-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanalysis.spec.ts
More file actions
175 lines (154 loc) · 4.77 KB
/
analysis.spec.ts
File metadata and controls
175 lines (154 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* Analysis E2E tests with mocked LLM responses.
*/
import { test, expect } from "@playwright/test";
import path from "path";
import { registerUser } from "./helpers/auth";
const MOCK_ANALYSIS_RESPONSE = {
data: {
id: "mock-analysis-id",
resume_id: "r1",
jd_id: "j1",
resume_name: "sample.txt",
jd_name: "jd.txt",
score: 75,
results: {
score: 75,
categories: {
skills: {
score: 80,
matched: ["Python", "React"],
missing: ["Kubernetes"],
feedback: "Strong skills match.",
},
experience: {
score: 70,
matched: ["5 years"],
missing: ["Team lead"],
feedback: "Good experience.",
},
education: {
score: 85,
matched: ["CS degree"],
missing: [],
feedback: "Education matches well.",
},
keywords: {
score: 65,
matched: ["API", "microservices"],
missing: ["CI/CD"],
feedback: "Some keyword gaps.",
},
},
keyword_gaps: ["Kubernetes", "CI/CD"],
},
tips: [
{
priority: 1,
category: "skills",
suggestion: "Add Kubernetes experience",
section: "Skills",
},
],
llm_model: "gpt-4o-mini",
created_at: new Date().toISOString(),
},
error: null,
meta: {},
};
/** Upload a sample file as the given doc type. */
async function uploadFile(
page: import("@playwright/test").Page,
docType: "resume" | "job_description",
) {
await page.goto("/documents");
if (docType === "job_description") {
await page.getByRole("button", { name: "Job Description" }).click();
}
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles(path.join(__dirname, "fixtures", "sample.txt"));
await expect(page.getByText(/uploaded.*successfully/i)).toBeVisible({
timeout: 10000,
});
}
test.describe("Analysis", () => {
test("new analysis with doc selection shows results", async ({ page }) => {
await registerUser(page);
// Upload resume and JD
await uploadFile(page, "resume");
await uploadFile(page, "job_description");
// Mock the analysis API
await page.route("**/api/v1/analysis/match", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(MOCK_ANALYSIS_RESPONSE),
});
});
// Mock the get analysis endpoint
await page.route("**/api/v1/analysis/mock-analysis-id", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(MOCK_ANALYSIS_RESPONSE),
});
});
// Go to new analysis
await page.goto("/analysis/new");
// Select resume and JD
await page.getByText("Select a resume").click();
await page.getByRole("option").first().click();
await page.getByText("Select a job description").click();
await page.getByRole("option").first().click();
// Trigger analysis
await page.getByRole("button", { name: "Analyze Match" }).click();
// Should navigate to results
await expect(page).toHaveURL(/\/analysis\/mock-analysis-id/, {
timeout: 10000,
});
// Score gauge and categories should be visible
await expect(page.getByText("75")).toBeVisible();
await expect(
page.locator('[data-slot="card-title"]').filter({ hasText: "Skills" }),
).toBeVisible();
await expect(
page
.locator('[data-slot="card-title"]')
.filter({ hasText: "Experience" }),
).toBeVisible();
});
test("analysis result page shows score, categories, and tips", async ({
page,
}) => {
await registerUser(page);
// Mock the get analysis endpoint
await page.route("**/api/v1/analysis/mock-analysis-id", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(MOCK_ANALYSIS_RESPONSE),
});
});
await page.goto("/analysis/mock-analysis-id");
// Score gauge
await expect(page.getByText("75")).toBeVisible({ timeout: 5000 });
await expect(page.getByText("Match Score")).toBeVisible();
// Category cards
await expect(
page.locator('[data-slot="card-title"]').filter({ hasText: "Skills" }),
).toBeVisible();
await expect(
page
.locator('[data-slot="card-title"]')
.filter({ hasText: "Experience" }),
).toBeVisible();
await expect(
page.locator('[data-slot="card-title"]').filter({ hasText: "Education" }),
).toBeVisible();
await expect(
page.locator('[data-slot="card-title"]').filter({ hasText: "Keywords" }),
).toBeVisible();
// Tips
await expect(page.getByText("Add Kubernetes experience")).toBeVisible();
});
});