@@ -53,3 +53,187 @@ def test_quote_strips_extra_quotes():
53
53
54
54
def test_quotes_can_take_integers ():
55
55
assert utils .quote (1234 ) == '"1234"'
56
+
57
+
58
+ def test_sort_single_field_ascending ():
59
+ records = [
60
+ {"name" : "Charlie" , "age" : 25 },
61
+ {"name" : "Alice" , "age" : 30 },
62
+ {"name" : "Bob" , "age" : 20 },
63
+ ]
64
+ result = utils .sort_records (records , "name" )
65
+ expected = [
66
+ {"name" : "Alice" , "age" : 30 },
67
+ {"name" : "Bob" , "age" : 20 },
68
+ {"name" : "Charlie" , "age" : 25 },
69
+ ]
70
+ assert result == expected
71
+
72
+
73
+ def test_sort_single_field_descending ():
74
+ records = [
75
+ {"name" : "Charlie" , "age" : 25 },
76
+ {"name" : "Alice" , "age" : 30 },
77
+ {"name" : "Bob" , "age" : 20 },
78
+ ]
79
+ result = utils .sort_records (records , "-name" )
80
+ expected = [
81
+ {"name" : "Charlie" , "age" : 25 },
82
+ {"name" : "Bob" , "age" : 20 },
83
+ {"name" : "Alice" , "age" : 30 },
84
+ ]
85
+ assert result == expected
86
+
87
+
88
+ def test_sort_multiple_fields ():
89
+ records = [
90
+ {"name" : "Alice" , "age" : 30 },
91
+ {"name" : "Bob" , "age" : 25 },
92
+ {"name" : "Alice" , "age" : 20 },
93
+ ]
94
+ result = utils .sort_records (records , "name,-age" )
95
+ expected = [
96
+ {"name" : "Alice" , "age" : 30 },
97
+ {"name" : "Alice" , "age" : 20 },
98
+ {"name" : "Bob" , "age" : 25 },
99
+ ]
100
+ assert result == expected
101
+
102
+
103
+ def test_sort_missing_field ():
104
+ records = [
105
+ {"name" : "Charlie" , "age" : 25 },
106
+ {"name" : "Alice" },
107
+ {"name" : "Bob" , "age" : 20 },
108
+ ]
109
+ result = utils .sort_records (records , "age" )
110
+ expected = [
111
+ {"name" : "Bob" , "age" : 20 },
112
+ {"name" : "Charlie" , "age" : 25 },
113
+ {"name" : "Alice" }, # Missing "age" is treated as default
114
+ ]
115
+ assert result == expected
116
+
117
+
118
+ def test_sort_numeric_field_descending ():
119
+ records = [
120
+ {"name" : "Charlie" , "score" : 85 },
121
+ {"name" : "Alice" , "score" : 95 },
122
+ {"name" : "Bob" , "score" : 111 },
123
+ ]
124
+ result = utils .sort_records (records , "-score" )
125
+ expected = [
126
+ {"name" : "Bob" , "score" : 111 },
127
+ {"name" : "Alice" , "score" : 95 },
128
+ {"name" : "Charlie" , "score" : 85 },
129
+ ]
130
+ assert result == expected
131
+
132
+
133
+ def test_sort_mixed_numeric_and_string ():
134
+ records = [
135
+ {"name" : "Charlie" , "age" : 25 },
136
+ {"name" : "Alice" , "age" : 20 },
137
+ {"name" : "Bob" , "age" : 20 },
138
+ ]
139
+ result = utils .sort_records (records , "age,-name" )
140
+ expected = [
141
+ {"name" : "Bob" , "age" : 20 },
142
+ {"name" : "Alice" , "age" : 20 },
143
+ {"name" : "Charlie" , "age" : 25 },
144
+ ]
145
+ assert result == expected
146
+
147
+
148
+ def test_records_equal_identical_records ():
149
+ a = {"id" : 1 , "name" : "Alice" , "last_modified" : 123 , "schema" : "v1" }
150
+ b = {"id" : 1 , "name" : "Alice" , "last_modified" : 456 , "schema" : "v2" }
151
+ assert utils .records_equal (a , b )
152
+
153
+
154
+ def test_records_equal_different_records ():
155
+ a = {"id" : 1 , "name" : "Alice" , "last_modified" : 123 }
156
+ b = {"id" : 2 , "name" : "Bob" , "last_modified" : 456 }
157
+ assert not utils .records_equal (a , b )
158
+
159
+
160
+ def test_records_equal_missing_fields ():
161
+ a = {"id" : 1 , "name" : "Alice" , "last_modified" : 123 }
162
+ b = {"id" : 1 , "name" : "Alice" }
163
+ assert utils .records_equal (a , b )
164
+
165
+
166
+ def test_records_equal_extra_fields ():
167
+ a = {"id" : 1 , "name" : "Alice" , "extra" : "field" }
168
+ b = {"id" : 1 , "name" : "Alice" }
169
+ assert not utils .records_equal (a , b )
170
+
171
+
172
+ def test_records_equal_empty_records ():
173
+ a = {}
174
+ b = {}
175
+ assert utils .records_equal (a , b )
176
+
177
+
178
+ def test_records_equal_only_ignored_fields ():
179
+ a = {"last_modified" : 123 , "schema" : "v1" }
180
+ b = {"last_modified" : 456 , "schema" : "v2" }
181
+ assert utils .records_equal (a , b )
182
+
183
+
184
+ def test_collection_diff_create ():
185
+ src = [{"id" : 1 , "name" : "Alice" }]
186
+ dest = []
187
+ to_create , to_update , to_delete = utils .collection_diff (src , dest )
188
+ assert to_create == [{"id" : 1 , "name" : "Alice" }]
189
+ assert to_update == []
190
+ assert to_delete == []
191
+
192
+
193
+ def test_collection_diff_update ():
194
+ src = [{"id" : 1 , "name" : "Alice" }]
195
+ dest = [{"id" : 1 , "name" : "Bob" }]
196
+ to_create , to_update , to_delete = utils .collection_diff (src , dest )
197
+ assert to_create == []
198
+ assert to_update == [({"id" : 1 , "name" : "Bob" }, {"id" : 1 , "name" : "Alice" })]
199
+ assert to_delete == []
200
+
201
+
202
+ def test_collection_diff_delete ():
203
+ src = []
204
+ dest = [{"id" : 1 , "name" : "Alice" }]
205
+ to_create , to_update , to_delete = utils .collection_diff (src , dest )
206
+ assert to_create == []
207
+ assert to_update == []
208
+ assert to_delete == [{"id" : 1 , "name" : "Alice" }]
209
+
210
+
211
+ def test_collection_diff_mixed ():
212
+ src = [{"id" : 1 , "name" : "Alice" }, {"id" : 2 , "name" : "Bob" }, {"id" : 3 , "name" : "Charlie" }]
213
+ dest = [
214
+ {"id" : 2 , "name" : "Bob" },
215
+ {"id" : 3 , "name" : "CharlieUpdated" },
216
+ {"id" : 4 , "name" : "Dave" },
217
+ ]
218
+ to_create , to_update , to_delete = utils .collection_diff (src , dest )
219
+ assert to_create == [{"id" : 1 , "name" : "Alice" }]
220
+ assert to_update == [({"id" : 3 , "name" : "CharlieUpdated" }, {"id" : 3 , "name" : "Charlie" })]
221
+ assert to_delete == [{"id" : 4 , "name" : "Dave" }]
222
+
223
+
224
+ def test_collection_diff_no_changes ():
225
+ src = [{"id" : 1 , "name" : "Alice" }]
226
+ dest = [{"id" : 1 , "name" : "Alice" }]
227
+ to_create , to_update , to_delete = utils .collection_diff (src , dest )
228
+ assert to_create == []
229
+ assert to_update == []
230
+ assert to_delete == []
231
+
232
+
233
+ def test_collection_diff_empty_collections ():
234
+ src = []
235
+ dest = []
236
+ to_create , to_update , to_delete = utils .collection_diff (src , dest )
237
+ assert to_create == []
238
+ assert to_update == []
239
+ assert to_delete == []
0 commit comments