Skip to content

Commit 21196bb

Browse files
committed
refactor: add unit tests for dedupeTuples function
1 parent 527e525 commit 21196bb

File tree

2 files changed

+166
-2
lines changed

2 files changed

+166
-2
lines changed

src/components/compare/compare.utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export function getOperationTypesFromTwoVersions(
8989
return [prevVersion?.operationTypes || [], currVersion?.operationTypes || []]
9090
}
9191

92-
function dedupeTuples<T extends [object | undefined, object | undefined]>(
92+
export function dedupeTuples<T extends [object | undefined, object | undefined]>(
9393
tuples: T[],
9494
): T[] {
9595
const UNDEF: object = {}

test/compare.utils.test.ts

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { removeRedundantPartialPairs } from '../src/components/compare/compare.utils'
17+
import { dedupeTuples, removeRedundantPartialPairs } from '../src/components/compare/compare.utils'
1818

1919
describe('removeRedundantPartialPairs', () => {
2020
test('should return empty array when input is empty', () => {
@@ -182,3 +182,167 @@ describe('removeRedundantPartialPairs', () => {
182182
})
183183
})
184184

185+
describe('dedupeTuples', () => {
186+
test('should return empty array when input is empty', () => {
187+
const result = dedupeTuples([])
188+
expect(result).toEqual([])
189+
})
190+
191+
test('should return all tuples when there are no duplicates', () => {
192+
const objA = { id: 'A' }
193+
const objB = { id: 'B' }
194+
const objC = { id: 'C' }
195+
const objD = { id: 'D' }
196+
197+
const input: [object, object][] = [
198+
[objA, objB],
199+
[objC, objD],
200+
]
201+
202+
const result = dedupeTuples(input)
203+
expect(result).toEqual(input)
204+
})
205+
206+
test('should remove exact duplicate tuples (same object references)', () => {
207+
const objA = { id: 'A' }
208+
const objB = { id: 'B' }
209+
210+
const input: [object, object][] = [
211+
[objA, objB],
212+
[objA, objB], // Duplicate
213+
[objA, objB], // Duplicate
214+
]
215+
216+
const result = dedupeTuples(input)
217+
expect(result).toEqual([[objA, objB]])
218+
expect(result).toHaveLength(1)
219+
})
220+
221+
test('should handle tuples with undefined in first position', () => {
222+
const objB = { id: 'B' }
223+
const objD = { id: 'D' }
224+
225+
const input: [object | undefined, object][] = [
226+
[undefined, objB],
227+
[undefined, objD],
228+
[undefined, objB], // Duplicate
229+
]
230+
231+
const result = dedupeTuples(input)
232+
expect(result).toEqual([
233+
[undefined, objB],
234+
[undefined, objD],
235+
])
236+
expect(result).toHaveLength(2)
237+
})
238+
239+
test('should handle tuples with undefined in second position', () => {
240+
const objA = { id: 'A' }
241+
const objC = { id: 'C' }
242+
243+
const input: [object, object | undefined][] = [
244+
[objA, undefined],
245+
[objC, undefined],
246+
[objA, undefined], // Duplicate
247+
]
248+
249+
const result = dedupeTuples(input)
250+
expect(result).toEqual([
251+
[objA, undefined],
252+
[objC, undefined],
253+
])
254+
expect(result).toHaveLength(2)
255+
})
256+
257+
test('should remove multiple duplicate instances and keep only first occurrence', () => {
258+
const objA = { id: 'A' }
259+
const objB = { id: 'B' }
260+
const objC = { id: 'C' }
261+
const objD = { id: 'D' }
262+
263+
const input: [object, object][] = [
264+
[objA, objB],
265+
[objC, objD],
266+
[objA, objB], // Duplicate
267+
[objC, objD], // Duplicate
268+
[objA, objB], // Duplicate
269+
]
270+
271+
const result = dedupeTuples(input)
272+
expect(result).toEqual([
273+
[objA, objB],
274+
[objC, objD],
275+
])
276+
expect(result).toHaveLength(2)
277+
})
278+
279+
test('should use object identity - different objects with same content are NOT duplicates', () => {
280+
const objA1 = { id: 'A' }
281+
const objA2 = { id: 'A' } // Different object, same content
282+
const objB1 = { id: 'B' }
283+
const objB2 = { id: 'B' } // Different object, same content
284+
285+
const input: [object, object][] = [
286+
[objA1, objB1],
287+
[objA2, objB2], // NOT a duplicate - different object references
288+
[objA1, objB1], // Duplicate of first
289+
]
290+
291+
const result = dedupeTuples(input)
292+
expect(result).toEqual([
293+
[objA1, objB1],
294+
[objA2, objB2],
295+
])
296+
expect(result).toHaveLength(2)
297+
})
298+
299+
test('should handle mixed scenario with various combinations', () => {
300+
const objA = { id: 'A' }
301+
const objB = { id: 'B' }
302+
const objC = { id: 'C' }
303+
const objD = { id: 'D' }
304+
305+
const input: [object | undefined, object | undefined][] = [
306+
[objA, objB], // Unique
307+
[objC, objD], // Unique
308+
[objA, objB], // Duplicate of first
309+
[undefined, objB], // Unique (undefined in first position)
310+
[objA, undefined], // Unique (undefined in second position)
311+
[undefined, objB], // Duplicate
312+
[objA, undefined], // Duplicate
313+
[undefined, undefined],// Unique (both undefined)
314+
[objC, objD], // Duplicate
315+
[undefined, undefined],// Duplicate
316+
]
317+
318+
const result = dedupeTuples(input)
319+
expect(result).toEqual([
320+
[objA, objB],
321+
[objC, objD],
322+
[undefined, objB],
323+
[objA, undefined],
324+
[undefined, undefined],
325+
])
326+
expect(result).toHaveLength(5)
327+
})
328+
329+
test('should handle tuples where same object appears at different positions', () => {
330+
const objA = { id: 'A' }
331+
const objB = { id: 'B' }
332+
333+
const input: [object, object][] = [
334+
[objA, objB], // [A, B]
335+
[objB, objA], // [B, A] - NOT a duplicate (different positions)
336+
[objA, objB], // Duplicate of first
337+
[objB, objA], // Duplicate of second
338+
]
339+
340+
const result = dedupeTuples(input)
341+
expect(result).toEqual([
342+
[objA, objB],
343+
[objB, objA],
344+
])
345+
expect(result).toHaveLength(2)
346+
})
347+
})
348+

0 commit comments

Comments
 (0)