@@ -20,6 +20,7 @@ import {
2020 init ,
2121 retryOrTimeout ,
2222} from "./api.ts" ;
23+ import { clearEtags } from "./etags.js" ;
2324import { mockLoggingFunctions } from "./test-utils/logging.mock.ts" ;
2425import { getBranchName } from "./utils.ts" ;
2526
@@ -29,6 +30,7 @@ vi.mock("@actions/github");
2930interface MockResponse {
3031 data : any ;
3132 status : number ;
33+ headers : object ;
3234}
3335
3436function * mockPageIterator < T , P > (
@@ -66,6 +68,10 @@ const mockOctokit = {
6668 } ,
6769} ;
6870
71+ afterEach ( ( ) => {
72+ clearEtags ( ) ;
73+ } ) ;
74+
6975describe ( "API" , ( ) => {
7076 const {
7177 coreDebugLogMock,
@@ -119,6 +125,7 @@ describe("API", () => {
119125 Promise . resolve ( {
120126 data : undefined ,
121127 status : 204 ,
128+ headers : { } ,
122129 } ) ,
123130 ) ;
124131
@@ -147,6 +154,7 @@ describe("API", () => {
147154 Promise . resolve ( {
148155 data : undefined ,
149156 status : errorStatus ,
157+ headers : { } ,
150158 } ) ,
151159 ) ;
152160
@@ -176,6 +184,7 @@ describe("API", () => {
176184 return Promise . resolve ( {
177185 data : undefined ,
178186 status : 204 ,
187+ headers : { } ,
179188 } ) ;
180189 } ) ;
181190
@@ -219,6 +228,7 @@ describe("API", () => {
219228 Promise . resolve ( {
220229 data : mockData ,
221230 status : 200 ,
231+ headers : { } ,
222232 } ) ,
223233 ) ;
224234
@@ -246,6 +256,7 @@ describe("API", () => {
246256 Promise . resolve ( {
247257 data : undefined ,
248258 status : errorStatus ,
259+ headers : { } ,
249260 } ) ,
250261 ) ;
251262
@@ -268,6 +279,7 @@ describe("API", () => {
268279 Promise . resolve ( {
269280 data : [ ] ,
270281 status : 200 ,
282+ headers : { } ,
271283 } ) ,
272284 ) ;
273285
@@ -303,6 +315,7 @@ describe("API", () => {
303315 Promise . resolve ( {
304316 data : mockData ,
305317 status : 200 ,
318+ headers : { } ,
306319 } ) ,
307320 ) ;
308321
@@ -355,6 +368,7 @@ describe("API", () => {
355368 Promise . resolve ( {
356369 data : mockData ,
357370 status : 200 ,
371+ headers : { } ,
358372 } ) ,
359373 ) ;
360374
@@ -387,6 +401,7 @@ describe("API", () => {
387401 Promise . resolve ( {
388402 data : undefined ,
389403 status : errorStatus ,
404+ headers : { } ,
390405 } ) ,
391406 ) ;
392407
@@ -417,6 +432,7 @@ describe("API", () => {
417432 Promise . resolve ( {
418433 data : mockData ,
419434 status : 200 ,
435+ headers : { } ,
420436 } ) ,
421437 ) ;
422438
@@ -454,6 +470,7 @@ describe("API", () => {
454470 workflow_runs : [ ] ,
455471 } ,
456472 status : 200 ,
473+ headers : { } ,
457474 } ;
458475 return Promise . resolve ( mockResponse ) ;
459476 } ,
@@ -494,6 +511,7 @@ describe("API", () => {
494511 workflow_runs : [ ] ,
495512 } ,
496513 status : 200 ,
514+ headers : { } ,
497515 } ;
498516 return Promise . resolve ( mockResponse ) ;
499517 } ,
@@ -534,6 +552,7 @@ describe("API", () => {
534552 workflow_runs : [ ] ,
535553 } ,
536554 status : 200 ,
555+ headers : { } ,
537556 } ;
538557 return Promise . resolve ( mockResponse ) ;
539558 } ,
@@ -588,6 +607,7 @@ describe("API", () => {
588607 Promise . resolve ( {
589608 data : mockData ,
590609 status : 200 ,
610+ headers : { } ,
591611 } ) ,
592612 ) ;
593613
@@ -620,6 +640,7 @@ describe("API", () => {
620640 Promise . resolve ( {
621641 data : undefined ,
622642 status : errorStatus ,
643+ headers : { } ,
623644 } ) ,
624645 ) ;
625646
@@ -653,6 +674,7 @@ describe("API", () => {
653674 Promise . resolve ( {
654675 data : mockData ,
655676 status : 200 ,
677+ headers : { } ,
656678 } ) ,
657679 ) ;
658680
@@ -672,6 +694,64 @@ describe("API", () => {
672694 ` ,
673695 ) ;
674696 } ) ;
697+
698+ it ( "should send the etag from the previous response in the If-None-Match header" , async ( ) => {
699+ const mockData = {
700+ total_count : 1 ,
701+ jobs : [
702+ {
703+ id : 0 ,
704+ steps : undefined ,
705+ } ,
706+ ] ,
707+ } ;
708+ const etag =
709+ "37c2311495bbea359329d0bb72561bdb2b2fffea1b7a54f696b5a287e7ccad1e" ;
710+ let submittedEtag = null ;
711+ vi . spyOn (
712+ mockOctokit . rest . actions ,
713+ "listJobsForWorkflowRun" ,
714+ ) . mockImplementation ( ( { headers } ) => {
715+ if ( headers [ "If-None-Match" ] ) {
716+ submittedEtag = headers [ "If-None-Match" ] ;
717+ return Promise . resolve ( {
718+ data : null ,
719+ status : 304 ,
720+ headers : {
721+ etag : `W/"${ submittedEtag } "` ,
722+ } ,
723+ } ) ;
724+ }
725+ return Promise . resolve ( {
726+ data : mockData ,
727+ status : 200 ,
728+ headers : {
729+ etag : `W/"${ etag } "` ,
730+ } ,
731+ } ) ;
732+ } ) ;
733+
734+ // Behaviour
735+ // First API call will return 200 with an etag response header
736+ await fetchWorkflowRunJobSteps ( 0 ) ;
737+ expect ( submittedEtag ) . eq ( null ) ;
738+ // Second API call will return 304 because of If-None-Match header
739+ await expect ( fetchWorkflowRunJobSteps ( 0 ) ) . resolves . toStrictEqual ( [ ] ) ;
740+ expect ( submittedEtag ) . eq ( etag ) ;
741+
742+ // Logging
743+ assertOnlyCalled ( coreDebugLogMock ) ;
744+ expect ( coreDebugLogMock ) . toHaveBeenCalledTimes ( 2 ) ;
745+ expect ( coreDebugLogMock . mock . calls [ 0 ] ?. [ 0 ] ) . toMatchInlineSnapshot (
746+ `
747+ "Fetched Workflow Run Job Steps:
748+ Repository: owner/repo
749+ Workflow Run ID: 0
750+ Jobs Fetched: [0]
751+ Steps Fetched: []"
752+ ` ,
753+ ) ;
754+ } ) ;
675755 } ) ;
676756
677757 describe ( "fetchWorkflowRunUrl" , ( ) => {
@@ -683,6 +763,7 @@ describe("API", () => {
683763 Promise . resolve ( {
684764 data : mockData ,
685765 status : 200 ,
766+ headers : { } ,
686767 } ) ,
687768 ) ;
688769
@@ -696,6 +777,7 @@ describe("API", () => {
696777 Promise . resolve ( {
697778 data : undefined ,
698779 status : errorStatus ,
780+ headers : { } ,
699781 } ) ,
700782 ) ;
701783
0 commit comments