Files
srbhr--resume-matcher/apps/frontend/tests/interview-prep-view.test.tsx
T
wehub-resource-sync 5bdf4cc89a
Publish Docker Image / publish (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:36 +08:00

126 lines
3.8 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/react';
import { InterviewPrepView } from '@/components/builder/interview-prep-view';
import type { InterviewPrepData } from '@/components/common/resume_previewer_context';
vi.mock('@/lib/i18n', () => ({
useTranslations: () => ({
t: (key: string, params?: Record<string, string>) =>
params?.title ? `${key} ${params.title}` : key,
}),
}));
const interviewPrep: InterviewPrepData = {
role_fit_analysis: ['Backend API experience fits the role.'],
resume_questions: [
{
question: 'How did you build the API?',
focus_area: 'Backend architecture',
suggested_answer_points: ['Discuss resume-grounded API work.'],
},
],
project_follow_ups: [
{
question: 'What tradeoffs did you make in the matcher project?',
focus_area: 'Project tradeoffs',
suggested_answer_points: ['Explain real implementation choices.'],
},
],
skill_gaps: [
{
skill: 'Kubernetes',
why_it_matters: 'The JD mentions deployments.',
preparation_suggestion: 'Review basics without claiming experience.',
},
],
talking_points: ['Connect API work to the role.'],
};
describe('InterviewPrepView', () => {
it('renders an empty state and calls onGenerate', () => {
const onGenerate = vi.fn();
render(
<InterviewPrepView
interviewPrep={null}
isGenerating={false}
onGenerate={onGenerate}
isTailoredResume
/>
);
fireEvent.click(
screen.getByRole('button', { name: /builder\.generatePrompt\.generateButton/ })
);
expect(onGenerate).toHaveBeenCalledTimes(1);
});
it('renders loading and error states in the empty view', () => {
render(
<InterviewPrepView
interviewPrep={null}
isGenerating
error="Generation failed"
onGenerate={vi.fn()}
isTailoredResume
/>
);
expect(screen.getByText('Generation failed')).toBeInTheDocument();
expect(screen.getByText('common.generating')).toBeInTheDocument();
});
it('disables generation when job context is unavailable', () => {
const onGenerate = vi.fn();
render(
<InterviewPrepView
interviewPrep={null}
isGenerating={false}
error={null}
onGenerate={onGenerate}
isTailoredResume
canGenerate={false}
unavailableMessage="No saved job context"
/>
);
expect(screen.getByText('interviewPrep.unavailableTitle')).toBeInTheDocument();
expect(screen.getByText('No saved job context')).toBeInTheDocument();
expect(screen.queryByRole('button')).not.toBeInTheDocument();
});
it('renders generated interview prep sections', () => {
render(
<InterviewPrepView
interviewPrep={interviewPrep}
isGenerating={false}
onGenerate={vi.fn()}
isTailoredResume
/>
);
expect(screen.getByText('Backend API experience fits the role.')).toBeInTheDocument();
expect(screen.getByText('How did you build the API?')).toBeInTheDocument();
expect(
screen.getByText('What tradeoffs did you make in the matcher project?')
).toBeInTheDocument();
expect(screen.getByText('Kubernetes')).toBeInTheDocument();
expect(screen.getByText('Connect API work to the role.')).toBeInTheDocument();
});
it('shows a default unavailable message for generated prep when regeneration is blocked', () => {
render(
<InterviewPrepView
interviewPrep={interviewPrep}
isGenerating={false}
onGenerate={vi.fn()}
isTailoredResume
canGenerate={false}
/>
);
expect(screen.getByText('interviewPrep.missingContextDescription')).toBeInTheDocument();
expect(screen.getByText('Backend API experience fits the role.')).toBeInTheDocument();
});
});