Skip to content

Commit

Permalink
Add more tricky tests for circular-reference cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Davide Caroselli committed Apr 20, 2024
1 parent bdd003b commit fbf1ecf
Showing 1 changed file with 67 additions and 74 deletions.
141 changes: 67 additions & 74 deletions src/jsonthis.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,127 +313,123 @@ describe("Jsonthis class", () => {
}
}

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should throw an error when encountering a circular reference on %s", (_, withSequelize) => {
function circularReferenceSerializer(ref: any) {
return {"$ref": `$${ref.constructor.name}(${ref.value || ref.id})`}
}

const testCases = [
["simple Objects", false, false],
["simple Objects and custom C-REF serializer", false, true],
["Sequelize models", true, false],
["Sequelize models and custom C-REF serializer", true, true]
];

it.each(testCases)("on %s with direct circular reference", (_, withSequelize, withCRSerializer) => {
const node = new Node(1);
node.next = new Node(2);
node.next.next = node;

const jsonthis = new Jsonthis();
const jsonthis = new Jsonthis(withCRSerializer ? {circularReferenceSerializer} : {});
if (withSequelize) sequelize(jsonthis, Node);

expect(() => jsonthis.toJson(node)).toThrow(CircularReferenceError);
if (withCRSerializer) {
expect(() => jsonthis.toJson(node)).not.toThrow(CircularReferenceError);
expect(jsonthis.toJson(node)).toStrictEqual({
value: 1,
next: {
value: 2,
next: {"$ref": "$Node(1)"}
}
});
} else {
expect(() => jsonthis.toJson(node)).toThrow(CircularReferenceError);
}

});

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should throw an error when encountering a nested circular reference on %s", (_, withSequelize) => {
it.each(testCases)("on %s with nested circular reference", (_, withSequelize, withCRSerializer) => {
const node = new Node(1);
node.next = new Node(2);
node.next.next = new Node(3);
node.next.next.next = node;

const jsonthis = new Jsonthis();
if (withSequelize) sequelize(jsonthis, Node);

expect(() => jsonthis.toJson(node)).toThrow(CircularReferenceError);
});

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should handle circular references using the provided circularReferenceSerializer on %s", (_, withSequelize) => {
const node = new Node(1);
node.next = new Node(2);
node.next.next = node;

const jsonthis = new Jsonthis({
circularReferenceSerializer: function (node: Node) {
return {"$ref": `$${node.constructor.name}(${node.value})`}
}
});
const jsonthis = new Jsonthis(withCRSerializer ? {circularReferenceSerializer} : {});
if (withSequelize) sequelize(jsonthis, Node);

expect(jsonthis.toJson(node)).toStrictEqual({
value: 1,
next: {
value: 2,
if (withCRSerializer) {
expect(() => jsonthis.toJson(node)).not.toThrow(CircularReferenceError);
expect(jsonthis.toJson(node)).toStrictEqual({
value: 1,
next: {
"$ref": "$Node(1)"
value: 2,
next: {
value: 3,
next: {"$ref": "$Node(1)"}
}
}
}
});
});
} else {
expect(() => jsonthis.toJson(node)).toThrow(CircularReferenceError);
}
});

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should not throw CircularReferenceError encountering a nested duplicated property on %s", (_, withSequelize) => {
const date = new Date();

it.each(testCases)("on %s should be able to serialize a direct duplicated property", (_, withSequelize, withCRSerializer) => {
class User {
public id: number;
public registeredAt: Date;
public friend?: User;
public updatedAt: Date;

constructor(id: number, date: Date) {
constructor(id: number) {
this.id = id;
this.registeredAt = date;
this.registeredAt = this.updatedAt = new Date();
}
}

const user = new User(1, date);
user.friend = new User(2, date);
const user = new User(1);

const jsonthis = new Jsonthis();
const jsonthis = new Jsonthis(withCRSerializer ? {circularReferenceSerializer} : {});
if (withSequelize) sequelize(jsonthis, User);

expect(() => jsonthis.toJson(user)).not.toThrow(CircularReferenceError);
expect(jsonthis.toJson(user)).toStrictEqual({
id: 1,
registeredAt: date,
friend: {
id: 2,
registeredAt: date
}
registeredAt: user.registeredAt,
updatedAt: user.updatedAt
});
});

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should not throw CircularReferenceError encountering a duplicated property on %s", (_, withSequelize) => {
it.each(testCases)("on %s should be able to serialize a nested duplicated property", (_, withSequelize, withCRSerializer) => {
const date = new Date();

class User {
public id: number;
public registeredAt: Date;
public updatedAt: Date;
public friend?: User;

constructor(id: number) {
constructor(id: number, date: Date) {
this.id = id;
this.registeredAt = this.updatedAt = new Date();
this.registeredAt = date;
}
}

const user = new User(1);
const user = new User(1, date);
user.friend = new User(2, date);

const jsonthis = new Jsonthis();
const jsonthis = new Jsonthis(withCRSerializer ? {circularReferenceSerializer} : {});
if (withSequelize) sequelize(jsonthis, User);

expect(() => jsonthis.toJson(user)).not.toThrow(CircularReferenceError);
expect(jsonthis.toJson(user)).toStrictEqual({
id: 1,
registeredAt: user.registeredAt,
updatedAt: user.updatedAt
registeredAt: date,
friend: {
id: 2,
registeredAt: date
}
});
});

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should not throw CircularReferenceError encountering a Object referenced twice on %s", (_, withSequelize) => {
it.each(testCases)("on %s should be able to serialize an Object referenced twice", (_, withSequelize, withCRSerializer) => {
class User {
public id: number;
public roommate?: User;
Expand All @@ -447,7 +443,7 @@ describe("Jsonthis class", () => {
const user = new User(1);
user.roommate = user.friend = new User(2);

const jsonthis = new Jsonthis();
const jsonthis = new Jsonthis(withCRSerializer ? {circularReferenceSerializer} : {});
if (withSequelize) sequelize(jsonthis, User);

expect(() => jsonthis.toJson(user)).not.toThrow(CircularReferenceError);
Expand All @@ -458,10 +454,7 @@ describe("Jsonthis class", () => {
});
});

it.each([
["simple Objects", false],
["Sequelize models", true]
])("should not throw CircularReferenceError encountering a Object referenced twice in different trees on %s", (_, withSequelize) => {
it.each(testCases)("on %s should be able to serialize an Object referenced twice in different sub-trees", (_, withSequelize, withCRSerializer) => {
class User {
public id: number;
public roommate?: User;
Expand All @@ -477,7 +470,7 @@ describe("Jsonthis class", () => {
user.friend = new User(3);
user.roommate.friend = user.friend.friend = new User(4);

const jsonthis = new Jsonthis();
const jsonthis = new Jsonthis(withCRSerializer ? {circularReferenceSerializer} : {});
if (withSequelize) sequelize(jsonthis, User);

expect(() => jsonthis.toJson(user)).not.toThrow(CircularReferenceError);
Expand Down

0 comments on commit fbf1ecf

Please sign in to comment.