|
|
@@ -1,6 +1,8 @@
|
|
|
-import { convertDateStringsToDates } from './axios';
|
|
|
+import type { DateConvertible } from './axios';
|
|
|
+import { convertStringsToDates } from './axios';
|
|
|
|
|
|
-describe('convertDateStringsToDates', () => {
|
|
|
+
|
|
|
+describe('convertStringsToDates', () => {
|
|
|
|
|
|
// Test case 1: Basic conversion in a flat object
|
|
|
test('should convert ISO date strings to Date objects in a flat object', () => {
|
|
|
@@ -15,9 +17,14 @@ describe('convertDateStringsToDates', () => {
|
|
|
createdAt: new Date(dateString),
|
|
|
name: 'Test Item',
|
|
|
};
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as Record<string, DateConvertible>;
|
|
|
+
|
|
|
expect(result.createdAt).toBeInstanceOf(Date);
|
|
|
- expect(result.createdAt.toISOString()).toEqual(dateString);
|
|
|
+
|
|
|
+ if (result.createdAt instanceof Date) {
|
|
|
+ expect(result.createdAt.toISOString()).toEqual(dateString);
|
|
|
+ }
|
|
|
+
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -53,11 +60,32 @@ describe('convertDateStringsToDates', () => {
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as {
|
|
|
+ data: {
|
|
|
+ item1: {
|
|
|
+ updatedAt: DateConvertible; // Assert 'updatedAt' later
|
|
|
+ value: number;
|
|
|
+ };
|
|
|
+ item2: {
|
|
|
+ nested: {
|
|
|
+ deletedAt: DateConvertible; // Assert 'deletedAt' later
|
|
|
+ isActive: boolean;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
expect(result.data.item1.updatedAt).toBeInstanceOf(Date);
|
|
|
- expect(result.data.item1.updatedAt.toISOString()).toEqual(dateString1);
|
|
|
- expect(result.data.item2.nested.deletedAt).toBeInstanceOf(Date);
|
|
|
- expect(result.data.item2.nested.deletedAt.toISOString()).toEqual(dateString2);
|
|
|
+
|
|
|
+ if (result.data.item1.updatedAt instanceof Date) {
|
|
|
+ expect(result.data.item1.updatedAt.toISOString()).toEqual(dateString1);
|
|
|
+ expect(result.data.item2.nested.deletedAt).toBeInstanceOf(Date);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (result.data.item2.nested.deletedAt instanceof Date) {
|
|
|
+ expect(result.data.item2.nested.deletedAt).toBeInstanceOf(Date);
|
|
|
+ expect(result.data.item2.nested.deletedAt.toISOString()).toEqual(dateString2);
|
|
|
+ }
|
|
|
+
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -73,22 +101,38 @@ describe('convertDateStringsToDates', () => {
|
|
|
{ id: 1, eventDate: new Date(dateString1) },
|
|
|
{ id: 2, eventDate: new Date(dateString2), data: { nestedProp: 'value' } },
|
|
|
];
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as [
|
|
|
+ { id: number, eventDate: DateConvertible},
|
|
|
+ { id: number, eventDate: DateConvertible, data: { nestedProp: string }},
|
|
|
+ ];
|
|
|
+
|
|
|
expect(result[0].eventDate).toBeInstanceOf(Date);
|
|
|
- expect(result[0].eventDate.toISOString()).toEqual(dateString1);
|
|
|
- expect(result[1].eventDate).toBeInstanceOf(Date);
|
|
|
- expect(result[1].eventDate.toISOString()).toEqual(dateString2);
|
|
|
+
|
|
|
+ if (result[0].eventDate instanceof Date) {
|
|
|
+ expect(result[0].eventDate.toISOString()).toEqual(dateString1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (result[1].eventDate instanceof Date) {
|
|
|
+ expect(result[1].eventDate).toBeInstanceOf(Date);
|
|
|
+ expect(result[1].eventDate.toISOString()).toEqual(dateString2);
|
|
|
+ }
|
|
|
+
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
// Test case 4: Array containing date strings directly (though less common for this function)
|
|
|
test('should handle arrays containing date strings directly', () => {
|
|
|
const dateString = '2023-06-20T18:00:00.000Z';
|
|
|
- const input = ['text', dateString, 123];
|
|
|
+ const input: [string, string, number] = ['text', dateString, 123];
|
|
|
const expected = ['text', new Date(dateString), 123];
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as DateConvertible[];
|
|
|
+
|
|
|
expect(result[1]).toBeInstanceOf(Date);
|
|
|
- expect(result[1].toISOString()).toEqual(dateString);
|
|
|
+
|
|
|
+ if (result[1] instanceof Date) {
|
|
|
+ expect(result[1].toISOString()).toEqual(dateString);
|
|
|
+ }
|
|
|
+
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -101,28 +145,28 @@ describe('convertDateStringsToDates', () => {
|
|
|
description: 'Some text',
|
|
|
};
|
|
|
const originalInput = JSON.parse(JSON.stringify(input)); // Deep copy to ensure no mutation
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input);
|
|
|
expect(result).toEqual(originalInput); // Should be deeply equal
|
|
|
- expect(result).toBe(input); // Confirm it mutated the original object
|
|
|
+ expect(result).not.toBe(input); // Confirm it mutated the original object
|
|
|
});
|
|
|
|
|
|
// Test case 6: Null, undefined, and primitive values
|
|
|
test('should return primitive values as is', () => {
|
|
|
- expect(convertDateStringsToDates(null)).toBeNull();
|
|
|
- expect(convertDateStringsToDates(undefined)).toBeUndefined();
|
|
|
- expect(convertDateStringsToDates(123)).toBe(123);
|
|
|
- expect(convertDateStringsToDates('hello')).toBe('hello');
|
|
|
- expect(convertDateStringsToDates(true)).toBe(true);
|
|
|
+ expect(convertStringsToDates(null)).toBeNull();
|
|
|
+ expect(convertStringsToDates(undefined)).toBeUndefined();
|
|
|
+ expect(convertStringsToDates(123)).toBe(123);
|
|
|
+ expect(convertStringsToDates('hello')).toBe('hello');
|
|
|
+ expect(convertStringsToDates(true)).toBe(true);
|
|
|
});
|
|
|
|
|
|
// Test case 7: Edge case - empty objects/arrays
|
|
|
test('should handle empty objects and arrays correctly', () => {
|
|
|
const emptyObject = {};
|
|
|
const emptyArray = [];
|
|
|
- expect(convertDateStringsToDates(emptyObject)).toEqual({});
|
|
|
- expect(convertDateStringsToDates(emptyArray)).toEqual([]);
|
|
|
- expect(convertDateStringsToDates(emptyObject)).toBe(emptyObject);
|
|
|
- expect(convertDateStringsToDates(emptyArray)).toEqual(emptyArray);
|
|
|
+ expect(convertStringsToDates(emptyObject)).toEqual({});
|
|
|
+ expect(convertStringsToDates(emptyArray)).toEqual([]);
|
|
|
+ expect(convertStringsToDates(emptyObject)).not.toBe(emptyObject);
|
|
|
+ expect(convertStringsToDates(emptyArray)).toEqual(emptyArray);
|
|
|
});
|
|
|
|
|
|
// Test case 8: Date string with different milliseconds (isoDateRegex without .000)
|
|
|
@@ -130,9 +174,14 @@ describe('convertDateStringsToDates', () => {
|
|
|
const dateString = '2023-01-15T10:00:00Z'; // No milliseconds
|
|
|
const input = { createdAt: dateString };
|
|
|
const expected = { createdAt: new Date(dateString) };
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as Record<string, DateConvertible>;
|
|
|
+
|
|
|
expect(result.createdAt).toBeInstanceOf(Date);
|
|
|
- expect(result.createdAt.toISOString()).toEqual('2023-01-15T10:00:00.000Z');
|
|
|
+
|
|
|
+ if (result.createdAt instanceof Date) {
|
|
|
+ expect(result.createdAt.toISOString()).toEqual('2023-01-15T10:00:00.000Z');
|
|
|
+ }
|
|
|
+
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -155,7 +204,14 @@ describe('convertDateStringsToDates', () => {
|
|
|
nestedDate: new Date(dateString),
|
|
|
},
|
|
|
};
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as {
|
|
|
+ prop1: DateConvertible,
|
|
|
+ prop2: null,
|
|
|
+ prop3: {
|
|
|
+ nestedNull: null,
|
|
|
+ nestedDate: DateConvertible
|
|
|
+ }
|
|
|
+ };
|
|
|
expect(result.prop1).toBeInstanceOf(Date);
|
|
|
expect(result.prop3.nestedDate).toBeInstanceOf(Date);
|
|
|
expect(result).toEqual(expected);
|
|
|
@@ -179,12 +235,23 @@ describe('convertDateStringsToDates', () => {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as {
|
|
|
+ id: number,
|
|
|
+ eventTime: DateConvertible,
|
|
|
+ details: {
|
|
|
+ lastActivity: DateConvertible
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
expect(result.eventTime).toBeInstanceOf(Date);
|
|
|
- expect(result.eventTime.toISOString()).toEqual(new Date(dateStringWithOffset).toISOString());
|
|
|
+ if (result.eventTime instanceof Date) {
|
|
|
+ expect(result.eventTime.toISOString()).toEqual(new Date(dateStringWithOffset).toISOString());
|
|
|
+ }
|
|
|
+
|
|
|
expect(result.details.lastActivity).toBeInstanceOf(Date);
|
|
|
- expect(result.details.lastActivity.toISOString()).toEqual(new Date('2025-06-12T05:00:00-04:00').toISOString());
|
|
|
+ if (result.details.lastActivity instanceof Date) {
|
|
|
+ expect(result.details.lastActivity.toISOString()).toEqual(new Date('2025-06-12T05:00:00-04:00').toISOString());
|
|
|
+ }
|
|
|
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
@@ -199,10 +266,13 @@ describe('convertDateStringsToDates', () => {
|
|
|
startTime: new Date(dateStringWithNegativeOffset),
|
|
|
};
|
|
|
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as Record<string, DateConvertible>;
|
|
|
|
|
|
expect(result.startTime).toBeInstanceOf(Date);
|
|
|
- expect(result.startTime.toISOString()).toEqual(new Date(dateStringWithNegativeOffset).toISOString());
|
|
|
+ if (result.startTime instanceof Date) {
|
|
|
+ expect(result.startTime.toISOString()).toEqual(new Date(dateStringWithNegativeOffset).toISOString());
|
|
|
+ }
|
|
|
+
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -216,10 +286,12 @@ describe('convertDateStringsToDates', () => {
|
|
|
zeroOffsetDate: new Date(dateStringWithZeroOffset),
|
|
|
};
|
|
|
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as Record<string, DateConvertible>;
|
|
|
|
|
|
expect(result.zeroOffsetDate).toBeInstanceOf(Date);
|
|
|
- expect(result.zeroOffsetDate.toISOString()).toEqual(new Date(dateStringWithZeroOffset).toISOString());
|
|
|
+ if (result.zeroOffsetDate instanceof Date) {
|
|
|
+ expect(result.zeroOffsetDate.toISOString()).toEqual(new Date(dateStringWithZeroOffset).toISOString());
|
|
|
+ }
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -233,10 +305,12 @@ describe('convertDateStringsToDates', () => {
|
|
|
detailedTime: new Date(dateStringWithMsAndOffset),
|
|
|
};
|
|
|
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as Record<string, DateConvertible>;
|
|
|
|
|
|
expect(result.detailedTime).toBeInstanceOf(Date);
|
|
|
- expect(result.detailedTime.toISOString()).toEqual(new Date(dateStringWithMsAndOffset).toISOString());
|
|
|
+ if (result.detailedTime instanceof Date) {
|
|
|
+ expect(result.detailedTime.toISOString()).toEqual(new Date(dateStringWithMsAndOffset).toISOString());
|
|
|
+ }
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
@@ -260,7 +334,14 @@ describe('convertDateStringsToDates', () => {
|
|
|
// Deep copy to ensure comparison is accurate since the function modifies in place
|
|
|
const expected = JSON.parse(JSON.stringify(input));
|
|
|
|
|
|
- const result = convertDateStringsToDates(input);
|
|
|
+ const result = convertStringsToDates(input) as {
|
|
|
+ date1: DateConvertible,
|
|
|
+ date2: DateConvertible,
|
|
|
+ date3: DateConvertible,
|
|
|
+ date4: DateConvertible,
|
|
|
+ date5: DateConvertible,
|
|
|
+ someOtherString: string,
|
|
|
+ };
|
|
|
|
|
|
// Assert that they remain strings (or whatever their original type was)
|
|
|
expect(typeof result.date1).toBe('string');
|
|
|
@@ -282,4 +363,104 @@ describe('convertDateStringsToDates', () => {
|
|
|
expect(result).toEqual(expected);
|
|
|
});
|
|
|
|
|
|
+
|
|
|
+ describe('test circular reference occurrences', () => {
|
|
|
+
|
|
|
+ // Test case 1: Circular references
|
|
|
+ test('should handle circular references without crashing and preserve the cycle', () => {
|
|
|
+ const dateString1 = '2023-02-20T12:30:00.000Z';
|
|
|
+ const dateString2 = '2023-03-01T08:00:00.000Z';
|
|
|
+ const dateString3 = '2023-04-05T14:15:00.000Z';
|
|
|
+
|
|
|
+ const input: any = {
|
|
|
+ data: {
|
|
|
+ item1: {
|
|
|
+ updatedAt: dateString1,
|
|
|
+ value: 10,
|
|
|
+ },
|
|
|
+ item2: {
|
|
|
+ nested1: {
|
|
|
+ deletedAt: dateString2,
|
|
|
+ isActive: false,
|
|
|
+ nested2: {
|
|
|
+ createdAt: dateString3,
|
|
|
+ parent: null as any,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ anotherItem: {
|
|
|
+ someValue: 42,
|
|
|
+ lastSeen: '2023-11-01T12:00:00Z',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // Create a circular reference
|
|
|
+ input.data.item2.nested1.nested2.parent = input;
|
|
|
+
|
|
|
+ const convertedOutput = convertStringsToDates(input) as {
|
|
|
+ data: {
|
|
|
+ item1: {
|
|
|
+ updatedAt: DateConvertible,
|
|
|
+ value: number,
|
|
|
+ },
|
|
|
+ item2: {
|
|
|
+ nested1: {
|
|
|
+ deletedAt: DateConvertible,
|
|
|
+ isActive: boolean,
|
|
|
+ nested2: {
|
|
|
+ createdAt: DateConvertible,
|
|
|
+ parent: any,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ anotherItem: {
|
|
|
+ someValue: number,
|
|
|
+ lastSeen: DateConvertible,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // Expect the function not to have thrown an error
|
|
|
+ expect(convertedOutput).toBeDefined();
|
|
|
+ expect(convertedOutput).toBeInstanceOf(Object);
|
|
|
+
|
|
|
+ // Check if circular reference is present
|
|
|
+ expect(convertedOutput.data.item2.nested1.nested2.parent).toBe(input);
|
|
|
+
|
|
|
+ // Check if the date conversion worked
|
|
|
+ expect(convertedOutput.data.item1.updatedAt).toBeInstanceOf(Date);
|
|
|
+ if (convertedOutput.data.item1.updatedAt instanceof Date) {
|
|
|
+ expect(convertedOutput.data.item1.updatedAt.toISOString()).toBe(dateString1);
|
|
|
+ }
|
|
|
+
|
|
|
+ expect(convertedOutput.data.item2.nested1.deletedAt).toBeInstanceOf(Date);
|
|
|
+ if (convertedOutput.data.item2.nested1.deletedAt instanceof Date) {
|
|
|
+ expect(convertedOutput.data.item2.nested1.deletedAt.toISOString()).toBe(dateString2);
|
|
|
+ }
|
|
|
+
|
|
|
+ expect(convertedOutput.data.item2.nested1.nested2.createdAt).toBeInstanceOf(Date);
|
|
|
+ if (convertedOutput.data.item2.nested1.nested2.createdAt instanceof Date) {
|
|
|
+ expect(convertedOutput.data.item2.nested1.nested2.createdAt.toISOString()).toBe(dateString3);
|
|
|
+ }
|
|
|
+
|
|
|
+ expect(convertedOutput.data.item2.anotherItem.lastSeen).toBeInstanceOf(Date);
|
|
|
+ if (convertedOutput.data.item2.anotherItem.lastSeen instanceof Date) {
|
|
|
+ expect(convertedOutput.data.item2.anotherItem.lastSeen.toISOString()).toBe(new Date(input.data.item2.anotherItem.lastSeen).toISOString());
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Test case 2: Direct self-reference
|
|
|
+ test('should work when encountering direct self-references', () => {
|
|
|
+ const obj: any = {};
|
|
|
+ obj.self = obj;
|
|
|
+ obj.createdAt = '2023-02-01T00:00:00Z';
|
|
|
+
|
|
|
+ const converted = convertStringsToDates(obj) as Record<string, DateConvertible>;
|
|
|
+
|
|
|
+ expect(converted).toBeDefined();
|
|
|
+ expect(converted.self).toBe(obj);
|
|
|
+ expect(converted.createdAt).toBeInstanceOf(Date);
|
|
|
+ });
|
|
|
+ });
|
|
|
});
|