@@ -58,7 +58,8 @@ type Call struct {
5858
5959// Snapshot holds the state of the snapshot being recorded, which can include multiple HTTP calls.
6060type Snapshot struct {
61- Calls []Call `json:"calls"`
61+ Partial bool `json:"partial,omitempty"`
62+ Calls []Call `json:"calls"`
6263
6364 // testName used to identify the snapshot file.
6465 testName string
@@ -79,19 +80,18 @@ type Snapshot struct {
7980 sseConns map [chan string ]struct {}
8081}
8182
82- // Finish
83- func (g * Snapshot ) Finish (t * testing.T ) {
84- t .Helper ()
85-
86- if ! g .updateMode {
87- if ! gock .IsDone () {
88- t .Fatalf ("Snapshot '%s' is not complete. Some requests were not mocked." , g .name )
83+ func (g * Snapshot ) sendMessage (msg string ) {
84+ for ch := range g .sseConns {
85+ select {
86+ case ch <- msg :
87+ default :
8988 }
90-
91- return
9289 }
90+ }
91+
92+ func (g * Snapshot ) saveToFile (t * testing.T ) {
93+ t .Helper ()
9394
94- // Update snapshot
9595 data , err := json .MarshalIndent (g , "" , " " )
9696 if err != nil {
9797 t .Fatalf ("Failed to marshal snapshot '%s': %v" , g .name , err )
@@ -105,6 +105,35 @@ func (g *Snapshot) Finish(t *testing.T) {
105105 }
106106}
107107
108+ func (g * Snapshot ) attemptToSavePartial (t * testing.T ) {
109+ t .Helper ()
110+
111+ if ! t .Failed () || ! g .updateMode || len (g .Calls ) == 0 {
112+ return
113+ }
114+
115+ g .sendMessage ("failedPartial" )
116+
117+ g .Partial = true
118+ g .saveToFile (t )
119+ }
120+
121+ // Finish
122+ func (g * Snapshot ) Finish (t * testing.T ) {
123+ t .Helper ()
124+
125+ if ! g .updateMode {
126+ if ! gock .IsDone () {
127+ t .Fatalf ("Snapshot '%s' is not complete. Some requests were not mocked." , g .name )
128+ }
129+
130+ return
131+ }
132+
133+ // Update snapshot
134+ g .saveToFile (t )
135+ }
136+
108137// file returns the path to the snapshot file.
109138func (g * Snapshot ) file () string {
110139 return filepath .Join (defaultSnapshotDirectory , strings .ReplaceAll (strings .ReplaceAll (g .testName + "-" + g .name , " " , "_" ), "/" , "_" )+ ".json" )
@@ -136,20 +165,15 @@ func (g *Snapshot) promptCall(req *http.Request, existingCall *Call) *Call {
136165 Headers : req .Header ,
137166 QueryParams : queryParams ,
138167 },
139- finalCall : finalCall ,
168+ finalCall : finalCall ,
140169 }
141170
142171 if existingCall != nil {
143172 g .pending .ExistingResponse = & existingCall .MockedCall
144173 }
145174
146175 // notify SSE clients
147- for ch := range g .sseConns {
148- select {
149- case ch <- "pending" :
150- default :
151- }
152- }
176+ g .sendMessage ("pending" )
153177
154178 g .mu .Unlock ()
155179
@@ -190,6 +214,11 @@ func MatchSnapshot(t *testing.T, snapshotName string) *Snapshot {
190214 t .Fatalf ("Failed to unmarshal snapshot '%s': %v" , snapshot .file (), err )
191215 }
192216
217+ if snapshot .Partial {
218+ snapshot .updateMode = true
219+ snapshot .Partial = false // reset partial flag for the new run
220+ }
221+
193222 if snapshot .updateMode {
194223 existingCalls = snapshot .Calls
195224 snapshot .Calls = make ([]Call , 0 )
@@ -209,6 +238,8 @@ func MatchSnapshot(t *testing.T, snapshotName string) *Snapshot {
209238 gock .Intercept ()
210239
211240 if snapshot .updateMode {
241+ t .Cleanup (func () { snapshot .attemptToSavePartial (t ) })
242+
212243 var existingCall * Call
213244 if len (existingCalls ) > 0 {
214245 existingCall = & existingCalls [0 ]
0 commit comments