-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add contextual serialization test cases
- Loading branch information
Davide Caroselli
committed
Apr 20, 2024
1 parent
de9eded
commit 395dc71
Showing
1 changed file
with
106 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,21 @@ | ||
import {CircularReferenceError, Jsonthis, ToJsonOptions} from "./Jsonthis"; | ||
import {JsonField, JsonSchema, JsonTraversalState} from "./schema"; | ||
|
||
function sequelize(jsonthis: Jsonthis, ...models: any) { | ||
for (const model of models) { | ||
// This is the same construct used to support Sequelize models. | ||
jsonthis.registerGlobalSerializer(model, (value: any, state: JsonTraversalState, options?: ToJsonOptions) => { | ||
const data = Object.assign({}, value); | ||
const schema = JsonSchema.get(model); | ||
return jsonthis.toJson(data, options, state, schema); | ||
}); | ||
|
||
model.prototype.toJSON = function () { | ||
return jsonthis.toJson(this); | ||
} | ||
} | ||
} | ||
|
||
describe("Jsonthis class", () => { | ||
describe("registerGlobalSerializer method", () => { | ||
function dateSerializer(value: Date): string { | ||
|
@@ -292,27 +307,84 @@ describe("Jsonthis class", () => { | |
}); | ||
}); | ||
|
||
describe("with circular references", () => { | ||
class Node { | ||
public value: number; | ||
public next?: Node; | ||
describe("with context", () => { | ||
function contextualMaskEmail(value: string, state: JsonTraversalState, opts?: ToJsonOptions): string { | ||
const maskChar = opts?.context?.maskChar || "*"; | ||
return value.replace(/(?<=.).(?=[^@]*?.@)/g, maskChar); | ||
} | ||
|
||
const testCases = [ | ||
["simple Objects", false], | ||
["Sequelize models", true], | ||
]; | ||
|
||
constructor(value: number) { | ||
this.value = value; | ||
it.each(testCases)("on %s should serializer using context", (_, withSequelize) => { | ||
class User { | ||
id: number; | ||
@JsonField({serializer: contextualMaskEmail}) | ||
email: string = "[email protected]" | ||
|
||
constructor(id: number) { | ||
this.id = id; | ||
} | ||
} | ||
} | ||
|
||
function sequelize(jsonthis: Jsonthis, ...models: any) { | ||
for (const model of models) { | ||
// This is the same construct used to support Sequelize models. | ||
jsonthis.registerGlobalSerializer(model, (value: any, state: JsonTraversalState, options?: ToJsonOptions) => { | ||
const data = Object.assign({}, value); | ||
const schema = JsonSchema.get(model); | ||
return jsonthis.toJson(data, options, state, schema); | ||
}); | ||
const user = new User(1); | ||
|
||
const jsonthis = new Jsonthis(); | ||
if (withSequelize) sequelize(jsonthis, User); | ||
|
||
expect(jsonthis.toJson(user)).toStrictEqual({ | ||
id: 1, | ||
email: "j******[email protected]" | ||
}); | ||
|
||
expect(jsonthis.toJson(user, {context: {maskChar: "-"}})).toStrictEqual({ | ||
id: 1, | ||
email: "[email protected]" | ||
}); | ||
}); | ||
|
||
it.each(testCases)("on %s should pass context to nested objects", (_, withSequelize) => { | ||
class User { | ||
id: number; | ||
@JsonField({serializer: contextualMaskEmail}) | ||
email: string | ||
friend?: User; | ||
|
||
constructor(id: number, email: string) { | ||
this.id = id; | ||
this.email = email; | ||
} | ||
} | ||
} | ||
|
||
const user = new User(1, "[email protected]"); | ||
user.friend = new User(2, "[email protected]"); | ||
|
||
const jsonthis = new Jsonthis(); | ||
if (withSequelize) sequelize(jsonthis, User); | ||
|
||
expect(jsonthis.toJson(user)).toStrictEqual({ | ||
id: 1, | ||
email: "j******[email protected]", | ||
friend: { | ||
id: 2, | ||
email: "b*****[email protected]" | ||
} | ||
}); | ||
|
||
expect(jsonthis.toJson(user, {context: {maskChar: "-"}})).toStrictEqual({ | ||
id: 1, | ||
email: "[email protected]", | ||
friend: { | ||
id: 2, | ||
email: "[email protected]" | ||
} | ||
}); | ||
}); | ||
}); | ||
|
||
describe("with circular references", () => { | ||
function circularReferenceSerializer(ref: any) { | ||
return {"$ref": `$${ref.constructor.name}(${ref.value || ref.id})`} | ||
} | ||
|
@@ -325,6 +397,15 @@ describe("Jsonthis class", () => { | |
]; | ||
|
||
it.each(testCases)("on %s with direct circular reference", (_, withSequelize, withCRSerializer) => { | ||
class Node { | ||
public value: number; | ||
public next?: Node; | ||
|
||
constructor(value: number) { | ||
this.value = value; | ||
} | ||
} | ||
|
||
const node = new Node(1); | ||
node.next = new Node(2); | ||
node.next.next = node; | ||
|
@@ -348,6 +429,15 @@ describe("Jsonthis class", () => { | |
}); | ||
|
||
it.each(testCases)("on %s with nested circular reference", (_, withSequelize, withCRSerializer) => { | ||
class Node { | ||
public value: number; | ||
public next?: Node; | ||
|
||
constructor(value: number) { | ||
this.value = value; | ||
} | ||
} | ||
|
||
const node = new Node(1); | ||
node.next = new Node(2); | ||
node.next.next = new Node(3); | ||
|