chore(M001/S01): auto-commit after complete-slice

This commit is contained in:
2026-03-24 12:27:04 +01:00
parent 9f03d123d0
commit 13d4e29336
22 changed files with 970 additions and 118 deletions
@@ -142,6 +142,61 @@ describe("correspondence Gmail import", () => {
});
mockedApi.post.mockImplementation((url: string, body?: any) => {
if (url === "/gmail/refresh-linked-threads") {
const hasReply = correspondenceMessages.some((message) => message.externalMessageId === "msg-2");
if (!hasReply && correspondenceMessages.some((message) => message.externalThreadId === "thread-1")) {
correspondenceMessages = [
...correspondenceMessages,
{
id: 701,
jobApplicationId: 42,
from: "Me",
content: "Following up on the role.",
subject: "Backend Developer follow-up",
channel: "Email",
date: new Date().toISOString(),
externalMessageId: "msg-2",
externalThreadId: "thread-1",
externalFrom: "user@example.test",
externalTo: "Maria Recruiter <maria@acme.test>",
},
];
return Promise.resolve({
data: {
jobApplicationId: body.jobApplicationId,
threadsChecked: 1,
imported: 1,
skipped: 1,
hasLinkedThreads: true,
refreshedAt: new Date().toISOString(),
threads: [
{
threadId: "thread-1",
imported: 1,
skipped: 1,
totalMessages: 2,
status: "imported-new-messages",
latestMessageDate: new Date().toISOString(),
},
],
},
} as any);
}
return Promise.resolve({
data: {
jobApplicationId: body.jobApplicationId,
threadsChecked: correspondenceMessages.some((message) => message.externalThreadId === "thread-1") ? 1 : 0,
imported: 0,
skipped: correspondenceMessages.some((message) => message.externalThreadId === "thread-1") ? correspondenceMessages.filter((message) => message.externalThreadId === "thread-1").length : 0,
hasLinkedThreads: correspondenceMessages.some((message) => message.externalThreadId === "thread-1"),
refreshedAt: new Date().toISOString(),
threads: correspondenceMessages.some((message) => message.externalThreadId === "thread-1")
? [{ threadId: "thread-1", imported: 0, skipped: correspondenceMessages.filter((message) => message.externalThreadId === "thread-1").length, totalMessages: correspondenceMessages.filter((message) => message.externalThreadId === "thread-1").length, status: "already-current", latestMessageDate: new Date().toISOString() }]
: [],
},
} as any);
}
if (url === "/gmail/import") {
correspondenceMessages = [
{
@@ -208,6 +263,34 @@ describe("correspondence Gmail import", () => {
expect(await screen.findByText(/to user@example\.test/i)).toBeInTheDocument();
});
test("automatically refreshes already-linked Gmail threads without manual re-import", async () => {
correspondenceMessages = [
{
id: 700,
jobApplicationId: 42,
from: "Company",
content: "Acme wants to schedule a call.",
subject: "Backend Developer interview",
channel: "Email",
date: new Date().toISOString(),
externalMessageId: "msg-1",
externalThreadId: "thread-1",
externalFrom: "Maria Recruiter <maria@acme.test>",
externalTo: "user@example.test",
},
];
renderDialog();
await waitFor(() => {
expect(mockedApi.post).toHaveBeenCalledWith("/gmail/refresh-linked-threads", { jobApplicationId: 42 });
});
expect(await screen.findByText(/backend developer follow-up/i)).toBeInTheDocument();
expect(await screen.findByText(/following up on the role\./i)).toBeInTheDocument();
expect((await screen.findAllByText(/thread thread-1/i)).length).toBeGreaterThan(0);
});
test("manual Gmail search override reloads job candidates with queryOverride", async () => {
renderDialog();