632e66e21d
- Add configurable profile questions with conditional visibility, admin-only fields, user answers, and seeded onboarding/volunteer questions
- Add admin UI for managing profile questions and member profile answers
- Add volunteer level/profile data support across backend schemas, models, API, and migration
- Update dashboard/profile UI, super admin menu, membership service types, and related styling
- Add privacy policy, terms of service, cookie notice, and footer links
- Add frontend Vitest coverage for profile question logic
- Add backend pytest coverage for profile answer normalization and validation
- Update restart.sh to build, run frontend/backend unit tests, and restart only after tests pass
- Refresh README, quickstart, project structure, instructions, and Square docs to match current app features
- Protect feature flag reload behind super-admin access
- Restrict admin-triggered password resets so admins can only reset member accounts
- Replace email template HTML preview rendering with escaped text preview
- Update docs for feature flag reload access, password reset scope, and email template preview safety
-- test user questions are also made by AI and not very useful. but i didn't know what to put there so its good enough for a test
43 lines
1.8 KiB
TypeScript
43 lines
1.8 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
canEditProfileQuestion,
|
|
DependentProfileQuestion,
|
|
isProfileQuestionVisible,
|
|
ProfileQuestionAnswerValue
|
|
} from './profileQuestionLogic';
|
|
|
|
describe('profile question logic', () => {
|
|
it('keeps admin-managed questions read-only outside admin editing mode', () => {
|
|
const question = {
|
|
id: 1,
|
|
admin_only_edit: true,
|
|
can_edit: true
|
|
};
|
|
|
|
expect(canEditProfileQuestion(question, false)).toBe(false);
|
|
expect(canEditProfileQuestion(question, true)).toBe(true);
|
|
});
|
|
|
|
it('does not allow editing when the API marks a question read-only', () => {
|
|
expect(canEditProfileQuestion({ id: 1, admin_only_edit: false, can_edit: false }, true)).toBe(false);
|
|
});
|
|
|
|
it('shows dependent questions when boolean answers match', () => {
|
|
const parent: DependentProfileQuestion = { id: 1, depends_on_question_id: null, depends_on_value: null };
|
|
const child: DependentProfileQuestion = { id: 2, depends_on_question_id: 1, depends_on_value: 'true' };
|
|
const questionsById = new Map<number, DependentProfileQuestion>([[parent.id, parent], [child.id, child]]);
|
|
const answers: Record<number, ProfileQuestionAnswerValue> = { 1: true };
|
|
|
|
expect(isProfileQuestionVisible(child, questionsById, answers)).toBe(true);
|
|
});
|
|
|
|
it('hides dependent questions when select answers do not match', () => {
|
|
const parent: DependentProfileQuestion = { id: 1, depends_on_question_id: null, depends_on_value: null };
|
|
const child: DependentProfileQuestion = { id: 2, depends_on_question_id: 1, depends_on_value: 'completed' };
|
|
const questionsById = new Map<number, DependentProfileQuestion>([[parent.id, parent], [child.id, child]]);
|
|
const answers: Record<number, ProfileQuestionAnswerValue> = { 1: 'pending' };
|
|
|
|
expect(isProfileQuestionVisible(child, questionsById, answers)).toBe(false);
|
|
});
|
|
});
|