Skip to content

Commit 1ec7a2e

Browse files
add jest ensuring no duplicate calls are made in getFullWorkflowCached
1 parent 7a49983 commit 1ec7a2e

1 file changed

Lines changed: 160 additions & 0 deletions

File tree

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import flushPromises from "flush-promises";
2+
import { createPinia, setActivePinia } from "pinia";
3+
4+
import { getWorkflowFull } from "@/components/Workflow/workflows.services";
5+
import { useWorkflowStore } from "@/stores/workflowStore";
6+
7+
// Mock `getWorkflowFull` function
8+
jest.mock("@/components/Workflow/workflows.services", () => ({
9+
getWorkflowFull: jest.fn(),
10+
}));
11+
12+
const mockWorkflow = {
13+
id: "workflow-123",
14+
name: "Test Workflow",
15+
version: 1,
16+
steps: {},
17+
};
18+
19+
describe("useWorkflowStore", () => {
20+
let workflowStore: ReturnType<typeof useWorkflowStore>;
21+
22+
beforeEach(() => {
23+
setActivePinia(createPinia());
24+
workflowStore = useWorkflowStore();
25+
jest.clearAllMocks();
26+
});
27+
28+
describe("getFullWorkflowCached", () => {
29+
it("should fetch workflow when not cached", async () => {
30+
(getWorkflowFull as jest.Mock).mockResolvedValue(mockWorkflow);
31+
32+
const result = await workflowStore.getFullWorkflowCached("workflow-123", 1);
33+
await flushPromises();
34+
35+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
36+
expect(getWorkflowFull).toHaveBeenCalledWith("workflow-123", 1);
37+
expect(result).toEqual(mockWorkflow);
38+
});
39+
40+
it("should return cached workflow on subsequent calls", async () => {
41+
(getWorkflowFull as jest.Mock).mockResolvedValue(mockWorkflow);
42+
43+
// First call - should fetch
44+
const result1 = await workflowStore.getFullWorkflowCached("workflow-123", 1);
45+
await flushPromises();
46+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
47+
expect(result1).toEqual(mockWorkflow);
48+
49+
// Second call - should return cached
50+
const result2 = await workflowStore.getFullWorkflowCached("workflow-123", 1);
51+
await flushPromises();
52+
53+
// Still only one API call
54+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
55+
expect(result2).toEqual(mockWorkflow);
56+
});
57+
58+
it("should prevent duplicate concurrent requests for same workflow", async () => {
59+
// Create a promise that we can control when it resolves
60+
let resolveWorkflow: (value: any) => void;
61+
const workflowPromise = new Promise((resolve) => {
62+
resolveWorkflow = resolve;
63+
});
64+
(getWorkflowFull as jest.Mock).mockReturnValue(workflowPromise);
65+
66+
// Start two concurrent requests for the same workflow
67+
const promise1 = workflowStore.getFullWorkflowCached("workflow-123", 1);
68+
const promise2 = workflowStore.getFullWorkflowCached("workflow-123", 1);
69+
70+
// At this point, getWorkflowFull should only be called once
71+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
72+
73+
// Resolve the workflow promise
74+
resolveWorkflow!(mockWorkflow);
75+
await flushPromises();
76+
77+
// Both promises should resolve with the same workflow
78+
const [result1, result2] = await Promise.all([promise1, promise2]);
79+
expect(result1).toEqual(mockWorkflow);
80+
expect(result2).toEqual(mockWorkflow);
81+
82+
// Still only one API call
83+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
84+
});
85+
86+
it("should allow concurrent requests for different workflows", async () => {
87+
const mockWorkflow1 = { ...mockWorkflow, id: "workflow-1" };
88+
const mockWorkflow2 = { ...mockWorkflow, id: "workflow-2" };
89+
90+
(getWorkflowFull as jest.Mock).mockResolvedValueOnce(mockWorkflow1);
91+
(getWorkflowFull as jest.Mock).mockResolvedValueOnce(mockWorkflow2);
92+
93+
// Start concurrent requests for different workflows
94+
const [result1, result2] = await Promise.all([
95+
workflowStore.getFullWorkflowCached("workflow-1"),
96+
workflowStore.getFullWorkflowCached("workflow-2"),
97+
]);
98+
await flushPromises();
99+
100+
// Should make two separate API calls
101+
expect(getWorkflowFull).toHaveBeenCalledTimes(2);
102+
expect(result1).toEqual(mockWorkflow1);
103+
expect(result2).toEqual(mockWorkflow2);
104+
});
105+
106+
it("should allow concurrent requests for different versions of same workflow", async () => {
107+
const mockWorkflowV1 = { ...mockWorkflow, version: 1 };
108+
const mockWorkflowV2 = { ...mockWorkflow, version: 2 };
109+
110+
(getWorkflowFull as jest.Mock).mockResolvedValueOnce(mockWorkflowV1);
111+
(getWorkflowFull as jest.Mock).mockResolvedValueOnce(mockWorkflowV2);
112+
113+
// Start concurrent requests for different versions
114+
const [result1, result2] = await Promise.all([
115+
workflowStore.getFullWorkflowCached("workflow-123", 1),
116+
workflowStore.getFullWorkflowCached("workflow-123", 2),
117+
]);
118+
await flushPromises();
119+
120+
// Should make two separate API calls
121+
expect(getWorkflowFull).toHaveBeenCalledTimes(2);
122+
expect(result1).toEqual(mockWorkflowV1);
123+
expect(result2).toEqual(mockWorkflowV2);
124+
});
125+
126+
it("should deduplicate multiple concurrent requests", async () => {
127+
// Mock API response which we can resolve later
128+
let resolveWorkflow: (value: any) => void;
129+
const workflowPromise = new Promise((resolve) => {
130+
resolveWorkflow = resolve;
131+
});
132+
(getWorkflowFull as jest.Mock).mockReturnValue(workflowPromise);
133+
134+
// Start 5 concurrent requests
135+
const promises = [
136+
workflowStore.getFullWorkflowCached("workflow-123", 1),
137+
workflowStore.getFullWorkflowCached("workflow-123", 1),
138+
workflowStore.getFullWorkflowCached("workflow-123", 1),
139+
workflowStore.getFullWorkflowCached("workflow-123", 1),
140+
workflowStore.getFullWorkflowCached("workflow-123", 1),
141+
];
142+
143+
// Only one API call should be made
144+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
145+
146+
// Resolving the API call
147+
resolveWorkflow!(mockWorkflow);
148+
await flushPromises();
149+
150+
// All 5 promises should resolve with the same result
151+
const results = await Promise.all(promises);
152+
results.forEach((result) => {
153+
expect(result).toEqual(mockWorkflow);
154+
});
155+
156+
// Still only one API call total
157+
expect(getWorkflowFull).toHaveBeenCalledTimes(1);
158+
});
159+
});
160+
});

0 commit comments

Comments
 (0)