11import { expect } from "@playwright/test" ;
2+ import type { Page } from "@playwright/test" ;
23
34import { createTeamEventType } from "./fixtures/users" ;
45import { test } from "./lib/fixtures" ;
56
7+ async function testDuplicateAPICalls (
8+ page : Page ,
9+ url : string ,
10+ testDate ?: Date
11+ ) : Promise < { totalCalls : number ; trpcCalls : number ; apiV2Calls : number } > {
12+ const trpcCalls : string [ ] = [ ] ;
13+ const apiV2Calls : string [ ] = [ ] ;
14+
15+ if ( testDate ) {
16+ await page . clock . install ( { time : testDate } ) ;
17+ }
18+
19+ await page . route ( "**/api/trpc/slots/getSchedule**" , async ( route ) => {
20+ trpcCalls . push ( route . request ( ) . url ( ) ) ;
21+ await route . continue ( ) ;
22+ } ) ;
23+
24+ await page . route ( "**/api/v2/slots/available**" , async ( route ) => {
25+ apiV2Calls . push ( route . request ( ) . url ( ) ) ;
26+ await route . continue ( ) ;
27+ } ) ;
28+
29+ await page . goto ( url ) ;
30+ await page . waitForTimeout ( 5000 ) ;
31+
32+ return {
33+ totalCalls : trpcCalls . length + apiV2Calls . length ,
34+ trpcCalls : trpcCalls . length ,
35+ apiV2Calls : apiV2Calls . length ,
36+ } ;
37+ }
38+
639test . describe ( "Duplicate API Calls Prevention" , ( ) => {
740 test . afterEach ( ( { users } ) => users . deleteAll ( ) ) ;
841
9- test ( "should detect when schedule endpoints are called multiple times for individual user events" , async ( {
42+ test ( "should detect when schedule endpoints are called multiple times for individual user events - beginning of month " , async ( {
1043 page,
1144 users,
1245 } ) => {
1346 const user = await users . create ( ) ;
1447 const eventType = user . eventTypes . find ( ( e ) => e . slug === "30-min" ) ;
48+ const beginningOfMonth = new Date ( ) ;
49+ beginningOfMonth . setDate ( 5 ) ;
1550
16- const trpcCalls : string [ ] = [ ] ;
17- const apiV2Calls : string [ ] = [ ] ;
18-
19- // Intercept tRPC getSchedule calls - pattern matches /api/trpc/slots/getSchedule
20- await page . route ( "**/api/trpc/slots/getSchedule**" , async ( route ) => {
21- trpcCalls . push ( route . request ( ) . url ( ) ) ;
22- await route . continue ( ) ;
23- } ) ;
24-
25- await page . route ( "**/api/v2/slots/available**" , async ( route ) => {
26- apiV2Calls . push ( route . request ( ) . url ( ) ) ;
27- await route . continue ( ) ;
28- } ) ;
51+ const { totalCalls, trpcCalls, apiV2Calls } = await testDuplicateAPICalls (
52+ page ,
53+ `/${ user . username } /${ eventType ?. slug } ` ,
54+ beginningOfMonth
55+ ) ;
2956
30- await page . goto ( `/${ user . username } /${ eventType ?. slug } ` ) ;
57+ expect ( totalCalls ) . toBeGreaterThan ( 0 ) ;
58+ expect ( totalCalls ) . toBeLessThanOrEqual ( 1 ) ;
59+ expect ( trpcCalls ) . toBeLessThanOrEqual ( 1 ) ;
60+ expect ( apiV2Calls ) . toBeLessThanOrEqual ( 1 ) ;
61+ } ) ;
3162
32- await page . waitForTimeout ( 5000 ) ;
63+ test ( "should detect when schedule endpoints are called multiple times for individual user events - end of month" , async ( {
64+ page,
65+ users,
66+ } ) => {
67+ const user = await users . create ( ) ;
68+ const eventType = user . eventTypes . find ( ( e ) => e . slug === "30-min" ) ;
69+ const endOfMonth = new Date ( ) ;
70+ endOfMonth . setDate ( 20 ) ;
3371
34- const totalCalls = trpcCalls . length + apiV2Calls . length ;
72+ const { totalCalls, trpcCalls, apiV2Calls } = await testDuplicateAPICalls (
73+ page ,
74+ `/${ user . username } /${ eventType ?. slug } ` ,
75+ endOfMonth
76+ ) ;
3577
3678 expect ( totalCalls ) . toBeGreaterThan ( 0 ) ;
3779 expect ( totalCalls ) . toBeLessThanOrEqual ( 1 ) ;
38- expect ( trpcCalls . length ) . toBeLessThanOrEqual ( 1 ) ;
39- expect ( apiV2Calls . length ) . toBeLessThanOrEqual ( 1 ) ;
80+ expect ( trpcCalls ) . toBeLessThanOrEqual ( 1 ) ;
81+ expect ( apiV2Calls ) . toBeLessThanOrEqual ( 1 ) ;
4082 } ) ;
4183
42- test ( "should detect when schedule endpoints are called multiple times for team events" , async ( {
84+ test ( "should detect when schedule endpoints are called multiple times for team events - beginning of month " , async ( {
4385 page,
4486 users,
4587 } ) => {
@@ -50,6 +92,8 @@ test.describe("Duplicate API Calls Prevention", () => {
5092 teammates : [ { name : "teammate-1" } ] ,
5193 }
5294 ) ;
95+ const beginningOfMonth = new Date ( ) ;
96+ beginningOfMonth . setDate ( 5 ) ;
5397
5498 const { team } = await teamOwner . getFirstTeamMembership ( ) ;
5599 const teamEvent = await createTeamEventType (
@@ -58,32 +102,52 @@ test.describe("Duplicate API Calls Prevention", () => {
58102 { teamEventSlug : "team-event-test" , teamEventTitle : "Team Event Test" }
59103 ) ;
60104
61- const trpcCalls : string [ ] = [ ] ;
62- const apiV2Calls : string [ ] = [ ] ;
63-
64- await page . route ( "**/api/trpc/slots/getSchedule**" , async ( route ) => {
65- trpcCalls . push ( route . request ( ) . url ( ) ) ;
66- await route . continue ( ) ;
67- } ) ;
105+ const { totalCalls, trpcCalls, apiV2Calls } = await testDuplicateAPICalls (
106+ page ,
107+ `/team/${ team . slug } /${ teamEvent . slug } ` ,
108+ beginningOfMonth
109+ ) ;
68110
69- await page . route ( "**/api/v2/slots/available**" , async ( route ) => {
70- apiV2Calls . push ( route . request ( ) . url ( ) ) ;
71- await route . continue ( ) ;
72- } ) ;
111+ expect ( totalCalls ) . toBeGreaterThan ( 0 ) ;
112+ expect ( totalCalls ) . toBeLessThanOrEqual ( 1 ) ;
113+ expect ( trpcCalls ) . toBeLessThanOrEqual ( 1 ) ;
114+ expect ( apiV2Calls ) . toBeLessThanOrEqual ( 1 ) ;
115+ } ) ;
73116
74- await page . goto ( `/team/${ team . slug } /${ teamEvent . slug } ` ) ;
117+ test ( "should detect when schedule endpoints are called multiple times for team events - end of month" , async ( {
118+ page,
119+ users,
120+ } ) => {
121+ const teamOwner = await users . create (
122+ { name : "Team Owner" } ,
123+ {
124+ hasTeam : true ,
125+ teammates : [ { name : "teammate-1" } ] ,
126+ }
127+ ) ;
75128
76- await page . waitForTimeout ( 5000 ) ;
129+ const { team } = await teamOwner . getFirstTeamMembership ( ) ;
130+ const teamEvent = await createTeamEventType (
131+ { id : teamOwner . id } ,
132+ { id : team . id } ,
133+ { teamEventSlug : "team-event-test" , teamEventTitle : "Team Event Test" }
134+ ) ;
135+ const endOfMonth = new Date ( ) ;
136+ endOfMonth . setDate ( 20 ) ;
77137
78- const totalCalls = trpcCalls . length + apiV2Calls . length ;
138+ const { totalCalls, trpcCalls, apiV2Calls } = await testDuplicateAPICalls (
139+ page ,
140+ `/team/${ team . slug } /${ teamEvent . slug } ` ,
141+ endOfMonth
142+ ) ;
79143
80144 expect ( totalCalls ) . toBeGreaterThan ( 0 ) ;
81145 expect ( totalCalls ) . toBeLessThanOrEqual ( 1 ) ;
82- expect ( trpcCalls . length ) . toBeLessThanOrEqual ( 1 ) ;
83- expect ( apiV2Calls . length ) . toBeLessThanOrEqual ( 1 ) ;
146+ expect ( trpcCalls ) . toBeLessThanOrEqual ( 1 ) ;
147+ expect ( apiV2Calls ) . toBeLessThanOrEqual ( 1 ) ;
84148 } ) ;
85149
86- test ( "should detect when schedule endpoints are called multiple times for organization team events" , async ( {
150+ test ( "should detect when schedule endpoints are called multiple times for organization team events - beginning of month " , async ( {
87151 page,
88152 users,
89153 } ) => {
@@ -105,29 +169,55 @@ test.describe("Duplicate API Calls Prevention", () => {
105169 { id : team . id } ,
106170 { teamEventSlug : "org-team-event" , teamEventTitle : "Org Team Event" }
107171 ) ;
172+ const beginningOfMonth = new Date ( ) ;
173+ beginningOfMonth . setDate ( 5 ) ;
108174
109- const trpcCalls : string [ ] = [ ] ;
110- const apiV2Calls : string [ ] = [ ] ;
111-
112- await page . route ( "**/api/trpc/slots/getSchedule**" , async ( route ) => {
113- trpcCalls . push ( route . request ( ) . url ( ) ) ;
114- await route . continue ( ) ;
115- } ) ;
175+ const { totalCalls, trpcCalls, apiV2Calls } = await testDuplicateAPICalls (
176+ page ,
177+ `/org/${ org . slug } /${ team . slug } /${ teamEvent . slug } ` ,
178+ beginningOfMonth
179+ ) ;
116180
117- await page . route ( "**/api/v2/slots/available**" , async ( route ) => {
118- apiV2Calls . push ( route . request ( ) . url ( ) ) ;
119- await route . continue ( ) ;
120- } ) ;
181+ expect ( totalCalls ) . toBeGreaterThan ( 0 ) ;
182+ expect ( totalCalls ) . toBeLessThanOrEqual ( 1 ) ;
183+ expect ( trpcCalls ) . toBeLessThanOrEqual ( 1 ) ;
184+ expect ( apiV2Calls ) . toBeLessThanOrEqual ( 1 ) ;
185+ } ) ;
121186
122- await page . goto ( `/org/${ org . slug } /${ team . slug } /${ teamEvent . slug } ` ) ;
187+ test ( "should detect when schedule endpoints are called multiple times for organization team events - end of month" , async ( {
188+ page,
189+ users,
190+ } ) => {
191+ const orgOwner = await users . create (
192+ { name : "Org Owner" } ,
193+ {
194+ hasTeam : true ,
195+ teammates : [ { name : "teammate-1" } ] ,
196+ isOrg : true ,
197+ isOrgVerified : true ,
198+ hasSubteam : true ,
199+ }
200+ ) ;
123201
124- await page . waitForTimeout ( 5000 ) ;
202+ const { team } = await orgOwner . getFirstTeamMembership ( ) ;
203+ const { team : org } = await orgOwner . getOrgMembership ( ) ;
204+ const teamEvent = await createTeamEventType (
205+ { id : orgOwner . id } ,
206+ { id : team . id } ,
207+ { teamEventSlug : "org-team-event" , teamEventTitle : "Org Team Event" }
208+ ) ;
209+ const endOfMonth = new Date ( ) ;
210+ endOfMonth . setDate ( 20 ) ;
125211
126- const totalCalls = trpcCalls . length + apiV2Calls . length ;
212+ const { totalCalls, trpcCalls, apiV2Calls } = await testDuplicateAPICalls (
213+ page ,
214+ `/org/${ org . slug } /${ team . slug } /${ teamEvent . slug } ` ,
215+ endOfMonth
216+ ) ;
127217
128218 expect ( totalCalls ) . toBeGreaterThan ( 0 ) ;
129219 expect ( totalCalls ) . toBeLessThanOrEqual ( 1 ) ;
130- expect ( trpcCalls . length ) . toBeLessThanOrEqual ( 1 ) ;
131- expect ( apiV2Calls . length ) . toBeLessThanOrEqual ( 1 ) ;
220+ expect ( trpcCalls ) . toBeLessThanOrEqual ( 1 ) ;
221+ expect ( apiV2Calls ) . toBeLessThanOrEqual ( 1 ) ;
132222 } ) ;
133223} ) ;
0 commit comments