-
Notifications
You must be signed in to change notification settings - Fork 93
Expand file tree
/
Copy pathparameters_diff_by_location_test.go
More file actions
224 lines (186 loc) · 9.92 KB
/
parameters_diff_by_location_test.go
File metadata and controls
224 lines (186 loc) · 9.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package diff_test
import (
"testing"
"github.com/getkin/kin-openapi/openapi3"
"github.com/oasdiff/oasdiff/diff"
"github.com/oasdiff/oasdiff/load"
"github.com/stretchr/testify/require"
)
func TestParamNamesByLocation_Len(t *testing.T) {
require.Equal(t, 3, diff.ParamNamesByLocation{
"query": []string{"name"},
"header": []string{"id", "organization"},
}.Len())
}
func TestParamDiffByLocation_Len(t *testing.T) {
require.Equal(t, 3, diff.ParamDiffByLocation{
"query": diff.ParamDiffs{"query": &diff.ParameterDiff{}},
"header": diff.ParamDiffs{"id": &diff.ParameterDiff{}, "organization": &diff.ParameterDiff{}},
}.Len())
}
// Test for exploded parameter equivalence issue #711 - Forward direction (simple → exploded)
func TestExplodedParameterEquivalence(t *testing.T) {
loader := openapi3.NewLoader()
// Load the test specs
s1, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/base.yaml"))
require.NoError(t, err)
s2, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/exploded.yaml"))
require.NoError(t, err)
// Get the diff
d, _, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2)
require.NoError(t, err)
// Check that parameters are not flagged as deleted
if d != nil && d.PathsDiff != nil {
for _, pathItem := range d.PathsDiff.Modified {
if pathItem != nil && pathItem.OperationsDiff != nil {
for _, operationItem := range pathItem.OperationsDiff.Modified {
if operationItem != nil && operationItem.ParametersDiff != nil {
// Should not have deleted parameters - they should be recognized as equivalent
require.Empty(t, operationItem.ParametersDiff.Deleted, "Exploded parameters should not be flagged as deleted")
}
}
}
}
}
}
// Test for exploded parameter equivalence - Reverse direction (exploded → simple)
func TestExplodedParameterEquivalenceReverse(t *testing.T) {
loader := openapi3.NewLoader()
// Load the test specs in reverse order (exploded first, then simple)
s1, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/exploded.yaml"))
require.NoError(t, err)
s2, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/base.yaml"))
require.NoError(t, err)
// Get the diff
d, _, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2)
require.NoError(t, err)
// In the reverse direction, we should also see no deleted parameters
// The exploded parameter should be recognized as equivalent to the simple parameters
if d != nil && d.PathsDiff != nil {
for _, pathItem := range d.PathsDiff.Modified {
if pathItem != nil && pathItem.OperationsDiff != nil {
for _, operationItem := range pathItem.OperationsDiff.Modified {
if operationItem != nil && operationItem.ParametersDiff != nil {
// Should not have deleted parameters - the exploded parameter should map to simple parameters
require.Empty(t, operationItem.ParametersDiff.Deleted, "Simple parameters should not be flagged as deleted when equivalent exploded parameter exists")
// Should not have added parameters - the simple parameters should map to exploded parameter
require.Empty(t, operationItem.ParametersDiff.Added, "Simple parameters should not be flagged as added when equivalent exploded parameter exists")
}
}
}
}
}
}
// Test for partial exploded parameter conversion - where only some parameters are converted to exploded
func TestPartialExplodedParameterConversion(t *testing.T) {
loader := openapi3.NewLoader()
// Load the partial conversion test specs
s1, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/partial-base.yaml"))
require.NoError(t, err)
s2, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/partial-exploded.yaml"))
require.NoError(t, err)
// Get the diff
d, _, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2)
require.NoError(t, err)
// Check that only the exploded parameters are flagged as modified, not deleted/added
if d != nil && d.PathsDiff != nil {
for _, pathItem := range d.PathsDiff.Modified {
if pathItem != nil && pathItem.OperationsDiff != nil {
for _, operationItem := range pathItem.OperationsDiff.Modified {
if operationItem != nil && operationItem.ParametersDiff != nil {
// Should not have any deleted parameters - exploded equivalence should be recognized
require.Empty(t, operationItem.ParametersDiff.Deleted, "No parameters should be flagged as deleted in partial exploded conversion")
// Should not have any added parameters - exploded equivalence should be recognized
require.Empty(t, operationItem.ParametersDiff.Added, "No parameters should be flagged as added in partial exploded conversion")
// Should have modifications for the converted parameters (PageNumber, PageSize)
require.Contains(t, operationItem.ParametersDiff.Modified, "query")
queryMods := operationItem.ParametersDiff.Modified["query"]
require.Contains(t, queryMods, "PageNumber", "PageNumber should be flagged as modified (style change)")
require.Contains(t, queryMods, "PageSize", "PageSize should be flagged as modified (style change)")
// Should NOT have modifications for the unchanged parameters (SortBy, Order)
require.NotContains(t, queryMods, "SortBy", "SortBy should not be flagged as modified")
require.NotContains(t, queryMods, "Order", "Order should not be flagged as modified")
}
}
}
}
}
}
// TestParameterStyleDefaults tests that parameter style defaults are handled correctly
// according to OpenAPI specification: query/cookie default to "form", path/header default to "simple"
func TestParameterStyleDefaults(t *testing.T) {
// Test that path parameters with empty style don't incorrectly default to "form"
t.Run("path parameter with empty style should not be treated as exploded form", func(t *testing.T) {
loader := openapi3.NewLoader()
// Valid spec: path parameter without explicit style (should default to "simple")
s1, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/base.yaml"))
require.NoError(t, err)
s2, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/path-with-empty-style.yaml"))
require.NoError(t, err)
// The isExplodedObjectParam function should return false for this path parameter
// because path parameters default to "simple" style, not "form"
d, _, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2)
require.NoError(t, err)
require.NotNil(t, d)
// With our fix, path parameters should be correctly handled and not treated as exploded form
// This test mainly ensures the fix doesn't break and handles different parameter locations correctly
})
}
// TestIssue767_ExplodedParamWithSameNameProperty tests that an exploded object parameter
// is not mistakenly matched with a property inside its own schema.
// Regression test for issue #767 where a parameter named "query" with a property named "query"
// inside its schema was incorrectly matched as semantically equivalent to itself.
func TestIssue767_ExplodedParamWithSameNameProperty(t *testing.T) {
loader := openapi3.NewLoader()
// Load the same spec twice - should result in no diff
s1, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/issue-767.yml"))
require.NoError(t, err)
s2, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/issue-767.yml"))
require.NoError(t, err)
// Get the diff
d, _, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2)
require.NoError(t, err)
// The key assertion: identical specs should have no diff
// Before the fix, this incorrectly reported modifications because the "query" parameter
// was matched with its own "query" property
require.Nil(t, d, "Identical specs should result in no diff")
}
// TestExplodedParameterLocationMatching tests that parameters with the same name
// but different locations (In field) are NOT matched by exploded parameter logic.
// This test verifies the location check at parameters_diff_by_location.go:304
func TestExplodedParameterLocationMatching(t *testing.T) {
t.Run("parameters with same name but different locations should not match", func(t *testing.T) {
loader := openapi3.NewLoader()
// Base spec: has "userId" parameter in cookie location
s1, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/cross-location-base.yaml"))
require.NoError(t, err)
// Exploded spec: has exploded query parameter with "userId" property
s2, err := load.NewSpecInfo(loader, load.NewSource("../data/explode-params/cross-location-exploded.yaml"))
require.NoError(t, err)
// Get the diff
d, _, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2)
require.NoError(t, err)
// The key assertion: the cookie "userId" parameter should be DELETED and query exploded param ADDED
// because they should NOT match (different locations prevent matching)
if d != nil && d.PathsDiff != nil {
for _, pathItem := range d.PathsDiff.Modified {
if pathItem != nil && pathItem.OperationsDiff != nil {
for _, operationItem := range pathItem.OperationsDiff.Modified {
if operationItem != nil && operationItem.ParametersDiff != nil {
// Cookie "userId" should be flagged as deleted because location check prevents matching
require.NotEmpty(t, operationItem.ParametersDiff.Deleted["cookie"],
"Cookie 'userId' parameter should be deleted - it should NOT match query exploded 'userId' property")
require.Contains(t, operationItem.ParametersDiff.Deleted["cookie"], "userId",
"The deleted cookie parameter should be 'userId'")
// Query exploded parameter should be flagged as added
require.NotEmpty(t, operationItem.ParametersDiff.Added["query"],
"Query exploded parameter should be added since cookie param doesn't match")
require.Contains(t, operationItem.ParametersDiff.Added["query"], "userParams",
"The added query parameter should be 'userParams'")
}
}
}
}
}
})
}