Skip to content

Commit 1e2d00e

Browse files
authored
chore(test): check that the response can contain unknown field (#4805)
1 parent d423821 commit 1e2d00e

File tree

16 files changed

+160
-139
lines changed

16 files changed

+160
-139
lines changed

.github/workflows/check.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ jobs:
378378
run: yarn cli cts generate ${{ matrix.client.language }} --language-version ${{ matrix.client.version }}
379379

380380
- name: Run unit CTS
381-
run: yarn cli cts run ${{ matrix.client.language }} --no-e2e
381+
run: yarn cli cts run ${{ matrix.client.language }} --no-e2e -v
382382

383383
- name: Run e2e CTS
384384
id: cts-e2e
-13
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
11
module github.com/algolia/algoliasearch-client-go/v4
22

33
go 1.21.11
4-
5-
require github.com/go-playground/validator/v10 v10.26.0
6-
7-
require (
8-
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
9-
github.com/go-playground/locales v0.14.1 // indirect
10-
github.com/go-playground/universal-translator v0.18.1 // indirect
11-
github.com/leodido/go-urn v1.4.0 // indirect
12-
golang.org/x/crypto v0.33.0 // indirect
13-
golang.org/x/net v0.34.0 // indirect
14-
golang.org/x/sys v0.30.0 // indirect
15-
golang.org/x/text v0.22.0 // indirect
16-
)
-28
Original file line numberDiff line numberDiff line change
@@ -1,28 +0,0 @@
1-
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2-
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
4-
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
5-
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
6-
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
7-
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
8-
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
9-
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
10-
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
11-
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
12-
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
13-
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
14-
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
15-
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
16-
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
18-
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
19-
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
20-
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
21-
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
22-
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
23-
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
24-
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
25-
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
26-
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
27-
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
28-
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

scripts/cts/testServer/algoliaMock.ts

+45
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,51 @@ function addRoutes(app: Express): void {
3737
processingTimeMS: 0,
3838
});
3939
});
40+
41+
// languages that just put the response in a map, there is no strict parsing or types to match.
42+
const isLaxLanguage = (lang: string) => {
43+
return lang === 'dart' || lang === 'javascript' || lang === 'python' || lang === 'php';
44+
};
45+
46+
app.get('/1/indexes/:indexName/settings', (req, res) => {
47+
const lang = req.params.indexName.match(/^cts_e2e_unknownField_(.*)$/)?.[1] as string;
48+
let unknown = {};
49+
if (!isLaxLanguage(lang)) {
50+
unknown = {
51+
unknownFieldNameThatWillNeverBeAddedToTheSpecIHope: 'hello',
52+
};
53+
}
54+
55+
res.json({
56+
minWordSizefor1Typo: 12,
57+
minWordSizefor2Typos: 13,
58+
hitsPerPage: 14,
59+
...unknown,
60+
});
61+
});
62+
63+
app.get('/1/indexes/:indexName/rules/:objectID', (req, res) => {
64+
const lang = req.params.indexName.match(/^cts_e2e_unknownFieldNested_(.*)$/)?.[1] as string;
65+
let unknown = {};
66+
if (!isLaxLanguage(lang)) {
67+
unknown = {
68+
unknownFieldNameThatWillNeverBeAddedToTheSpecIHope: 'hello',
69+
};
70+
}
71+
72+
res.json({
73+
objectID: req.params.objectID,
74+
consequence: {
75+
promote: [
76+
{
77+
objectID: '1',
78+
position: 10,
79+
...unknown,
80+
},
81+
],
82+
},
83+
});
84+
});
4085
}
4186

4287
export function algoliaMockServer(): Promise<Server> {

templates/go/client.mustache

-20
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ import (
1818
"slices"
1919
"time"
2020

21-
"github.com/go-playground/validator/v10"
22-
2321
"github.com/algolia/algoliasearch-client-go/v4/algolia/call"
2422
"github.com/algolia/algoliasearch-client-go/v4/algolia/compression"
2523
"github.com/algolia/algoliasearch-client-go/v4/algolia/transport"
@@ -284,24 +282,6 @@ func reportError(format string, a ...any) error {
284282
return fmt.Errorf(format, a...)
285283
}
286284

287-
// A wrapper for strict JSON decoding
288-
func newStrictDecoder(data []byte) *json.Decoder { //nolint:unused
289-
dec := json.NewDecoder(bytes.NewBuffer(data))
290-
dec.DisallowUnknownFields()
291-
return dec
292-
}
293-
294-
// A wrapper for validating a struct, returns nil if value is not a struct
295-
func validateStruct(v any) error { //nolint:unused
296-
err := validator.New().Struct(v)
297-
validationErrors, ok := err.(validator.ValidationErrors)
298-
if ok && len(validationErrors) > 0 {
299-
return validationErrors
300-
}
301-
302-
return nil
303-
}
304-
305285
// Set request body from an any
306286
func setBody(body any, c compression.Compression) (*bytes.Buffer, error) {
307287
if body == nil {

templates/go/model_oneof.mustache

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
2828
{{#vendorExtensions.x-has-discriminator}}
2929
// use discriminator value to speed up the lookup if possible, if not we will try every possibility
3030
var jsonDict map[string]any
31-
_ = newStrictDecoder(data).Decode(&jsonDict)
31+
_ = json.Unmarshal(data, &jsonDict)
3232
{{/vendorExtensions.x-has-discriminator}}
3333
{{#composedSchemas.oneOf}}
3434
{{#vendorExtensions.x-discriminator-fields.size}}
3535
if {{#vendorExtensions.x-discriminator-fields}}utils.HasKey(jsonDict, "{{.}}"){{^-last}} && {{/-last}}{{/vendorExtensions.x-discriminator-fields}} {
3636
{{/vendorExtensions.x-discriminator-fields.size}}
3737
// try to unmarshal data into {{#lambda.type-to-name}}{{{dataType}}}{{/lambda.type-to-name}}
38-
err = newStrictDecoder(data).Decode(&dst.{{#lambda.type-to-name}}{{{dataType}}}{{/lambda.type-to-name}})
39-
if err == nil && validateStruct(dst.{{#lambda.type-to-name}}{{{dataType}}}{{/lambda.type-to-name}}) == nil {
38+
err = json.Unmarshal(data, &dst.{{#lambda.type-to-name}}{{{dataType}}}{{/lambda.type-to-name}})
39+
if err == nil {
4040
return nil // found the correct type
4141
} else {
4242
dst.{{#lambda.type-to-name}}{{{dataType}}}{{/lambda.type-to-name}} = nil

templates/go/snippets/go.mod.mustache

-12
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,3 @@ go 1.21.11
55
replace github.com/algolia/algoliasearch-client-go/v4 => ../../../clients/algoliasearch-client-go
66

77
require github.com/algolia/algoliasearch-client-go/v4 v4.0.0
8-
9-
require (
10-
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
11-
github.com/go-playground/locales v0.14.1 // indirect
12-
github.com/go-playground/universal-translator v0.18.1 // indirect
13-
github.com/go-playground/validator/v10 v10.22.1 // indirect
14-
github.com/leodido/go-urn v1.4.0 // indirect
15-
golang.org/x/crypto v0.22.0 // indirect
16-
golang.org/x/net v0.24.0 // indirect
17-
golang.org/x/sys v0.19.0 // indirect
18-
golang.org/x/text v0.14.0 // indirect
19-
)

templates/kotlin/tests/client/tests.mustache

+2-6
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fun `{{#lambda.replaceBacktick}}{{{testName}}}{{/lambda.replaceBacktick}}`() = r
3737
assertEquals({{#match}}{{> tests/param_value}}{{/match}}, it.url.host);
3838
{{/testHost}}
3939
}{{/testResponse}}{{#testResponse}}
40-
{{#isHelper}}response = {
40+
response = {
4141
{{^match.isPrimitive}}
4242
assertNotNull(it)
4343
JSONAssert.assertEquals("""{{{match.value}}}""", Json.encodeToString(Json.encodeToJsonElement(it)), JSONCompareMode.STRICT)
@@ -50,11 +50,7 @@ fun `{{#lambda.replaceBacktick}}{{{testName}}}{{/lambda.replaceBacktick}}`() = r
5050
assertEquals({{#match}}{{> tests/param_value}}{{/match}}, it)
5151
{{/match.isNull}}
5252
{{/match.isPrimitive}}
53-
}{{/isHelper}}
54-
{{^isHelper}}response = {
55-
val response = Json.encodeToString(it)
56-
assertEquals({{#match}}{{> tests/param_value}}{{/match}}, response)
57-
}{{/isHelper}}
53+
}
5854
{{/testResponse}}
5955
)
6056
{{/isMethod}}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
{{#hasResponse}}let response{{#isGeneric}}: Response<{{#lambda.prefix}}{{{returnType}}}{{/lambda.prefix}}<{{#lambda.prefix}}Hit{{/lambda.prefix}}>>{{/isGeneric}} = {{> tests/method}}{{/hasResponse}}
2-
{{^hasResponse}}let _{{#isGeneric}}: Response<{{#lambda.prefix}}{{{returnType}}}{{/lambda.prefix}}<{{#lambda.prefix}}Hit{{/lambda.prefix}}>>{{/isGeneric}} = {{> tests/method}}{{/hasResponse}}
1+
{{#hasResponse}}let response{{#isGeneric}}: {{#useEchoRequester}}Response<{{/useEchoRequester}}{{#lambda.prefix}}{{{returnType}}}{{/lambda.prefix}}<{{#lambda.prefix}}Hit{{/lambda.prefix}}>{{#useEchoRequester}}>{{/useEchoRequester}}{{/isGeneric}} = {{> tests/method}}{{/hasResponse}}
2+
{{^hasResponse}}let _ = {{> tests/method}}{{/hasResponse}}
33
{{^isHelper}}
44
{{^isBenchmark}}
5-
let responseBodyData = try XCTUnwrap(response.bodyData)
65
{{#useEchoRequester}}
7-
let echoResponse = try CodableHelper.jsonDecoder.decode(EchoResponse.self, from: responseBodyData)
8-
{{/useEchoRequester}}
9-
{{^useEchoRequester}}
10-
let responseBodyJSON = try XCTUnwrap(responseBodyData.jsonString)
6+
let echoResponse = try CodableHelper.jsonDecoder.decode(EchoResponse.self, from: XCTUnwrap(response.bodyData))
117
{{/useEchoRequester}}
128
{{/isBenchmark}}
139
{{/isHelper}}

templates/swift/tests/client/tests.mustache

+2-5
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@
4141
{{#testResponse}}
4242
{{#isHelper}}
4343
{{^match.isPrimitive}}
44-
let comparableData = try XCTUnwrap("{{#lambda.escapeQuotes}}{{{match.value}}}{{/lambda.escapeQuotes}}".data(using: .utf8))
45-
try XCTLenientAssertEqual(received: CodableHelper.jsonEncoder.encode(response), expected: comparableData)
44+
try XCTLenientAssertEqual(received: response, expected: "{{#lambda.escapeQuotes}}{{{match.value}}}{{/lambda.escapeQuotes}}")
4645
{{/match.isPrimitive}}
4746
{{#match.isPrimitive}}
4847
{{#match.isNull}}
@@ -54,9 +53,7 @@
5453
{{/match.isPrimitive}}
5554
{{/isHelper}}
5655
{{^isHelper}}
57-
let comparableData = "{{#lambda.escapeQuotes}}{{{match.value}}}{{/lambda.escapeQuotes}}".data(using: .utf8)
58-
let comparableJSON = try XCTUnwrap(comparableData?.jsonString)
59-
XCTAssertEqual(comparableJSON, responseBodyJSON);
56+
XTCJSONEquals(received: response, expected: "{{#lambda.escapeQuotes}}{{{match.value}}}{{/lambda.escapeQuotes}}")
6057
{{/isHelper}}
6158
{{/testResponse}}
6259
{{#shouldScope}}

templates/swift/tests/e2e/e2e.mustache

+1-6
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,7 @@ final class {{client}}RequestsTestsE2E: XCTestCase {
6363
{{#response}}
6464
let response{{#isGeneric}}: Response<{{#lambda.prefix}}{{{returnType}}}{{/lambda.prefix}}<{{#lambda.prefix}}Hit{{/lambda.prefix}}>>{{/isGeneric}} = {{> tests/method}}
6565
{{#body}}
66-
let responseBody = try XCTUnwrap(response.body)
67-
let responseBodyData = try CodableHelper.jsonEncoder.encode(responseBody)
68-
69-
let expectedBodyData = try XCTUnwrap("{{#lambda.escapeJSON}}{{{body}}}{{/lambda.escapeJSON}}".data(using: .utf8))
70-
71-
XCTLenientAssertEqual(received: responseBodyData, expected: expectedBodyData)
66+
try XCTLenientAssertEqual(received: XCTUnwrap(response.body), expected: "{{#lambda.escapeJSON}}{{{body}}}{{/lambda.escapeJSON}}")
7267
{{/body}}
7368

7469
{{#statusCode}}

templates/swift/tests/method.mustache

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
try {{#isAsyncMethod}}await {{/isAsyncMethod}}client.{{method}}{{^isHelper}}{{^isGuide}}WithHTTPInfo{{/isGuide}}{{/isHelper}}({{#hasParams}}{{#parametersWithDataType}}{{> tests/generateParams }}{{^-last}}, {{/-last}}{{/parametersWithDataType}}{{/hasParams}}{{#hasRequestOptions}}{{#requestOptions}}, requestOptions: RequestOptions(
1+
try {{#isAsyncMethod}}await {{/isAsyncMethod}}client.{{method}}{{#useEchoRequester}}WithHTTPInfo{{/useEchoRequester}}({{#hasParams}}{{#parametersWithDataType}}{{> tests/generateParams }}{{^-last}}, {{/-last}}{{/parametersWithDataType}}{{/hasParams}}{{#hasRequestOptions}}{{#requestOptions}}, requestOptions: RequestOptions(
22
{{#headers}}
33
headers: [{{#parametersWithDataType}}"{{key}}": {{> tests/paramValue }}{{^-last}}, {{/-last}}{{/parametersWithDataType}}]{{#queryParameters}},{{/queryParameters}}
44
{{/headers}}

tests/CTS/client/search/api.json

+75
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,80 @@
224224
}
225225
}
226226
]
227+
},
228+
{
229+
"testName": "can handle unknown response fields",
230+
"autoCreateClient": false,
231+
"steps": [
232+
{
233+
"type": "createClient",
234+
"parameters": {
235+
"appId": "test-app-id",
236+
"apiKey": "test-api-key",
237+
"region": "us",
238+
"customHosts": [
239+
{
240+
"port": 6686
241+
}
242+
]
243+
}
244+
},
245+
{
246+
"type": "method",
247+
"method": "getSettings",
248+
"parameters": {
249+
"indexName": "cts_e2e_unknownField_${{language}}"
250+
},
251+
"expected": {
252+
"type": "response",
253+
"match": {
254+
"minWordSizefor1Typo": 12,
255+
"minWordSizefor2Typos": 13,
256+
"hitsPerPage": 14
257+
}
258+
}
259+
}
260+
]
261+
},
262+
{
263+
"testName": "can handle unknown response fields inside a nested oneOf",
264+
"autoCreateClient": false,
265+
"steps": [
266+
{
267+
"type": "createClient",
268+
"parameters": {
269+
"appId": "test-app-id",
270+
"apiKey": "test-api-key",
271+
"region": "us",
272+
"customHosts": [
273+
{
274+
"port": 6686
275+
}
276+
]
277+
}
278+
},
279+
{
280+
"type": "method",
281+
"method": "getRule",
282+
"parameters": {
283+
"indexName": "cts_e2e_unknownFieldNested_${{language}}",
284+
"objectID": "ruleObjectID"
285+
},
286+
"expected": {
287+
"type": "response",
288+
"match": {
289+
"objectID": "ruleObjectID",
290+
"consequence": {
291+
"promote": [
292+
{
293+
"objectID": "1",
294+
"position": 10
295+
}
296+
]
297+
}
298+
}
299+
}
300+
}
301+
]
227302
}
228303
]

tests/output/go/go.mod

-9
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@ require (
1515

1616
require (
1717
github.com/davecgh/go-spew v1.1.1 // indirect
18-
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
19-
github.com/go-playground/locales v0.14.1 // indirect
20-
github.com/go-playground/universal-translator v0.18.1 // indirect
21-
github.com/go-playground/validator/v10 v10.26.0 // indirect
22-
github.com/leodido/go-urn v1.4.0 // indirect
2318
github.com/pmezard/go-difflib v1.0.0 // indirect
24-
golang.org/x/crypto v0.33.0 // indirect
25-
golang.org/x/net v0.34.0 // indirect
26-
golang.org/x/sys v0.30.0 // indirect
27-
golang.org/x/text v0.22.0 // indirect
2819
gopkg.in/yaml.v3 v3.0.1 // indirect
2920
)

tests/output/go/go.sum

-20
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,13 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
4-
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
5-
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
6-
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
7-
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
8-
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
9-
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
10-
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
11-
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
12-
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
133
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
144
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
155
github.com/kinbiko/jsonassert v1.2.0 h1:+/JthIVXdIrThrOtSN9ry0mNtWKXMWuvxR0nU7gQ+tI=
166
github.com/kinbiko/jsonassert v1.2.0/go.mod h1:pCc3uudOt+lVAbkji9O0uw8MSVt4s+1ZJ0y8Ux2F1Og=
17-
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
18-
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
197
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
208
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
219
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
2210
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
23-
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
24-
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
25-
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
26-
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
27-
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
28-
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
29-
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
30-
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
3111
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
3212
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3313
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

0 commit comments

Comments
 (0)