Skip to content

Commit

Permalink
proper working tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Pollak committed Sep 19, 2019
1 parent d9478fa commit 4dacd61
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 80 deletions.
18 changes: 13 additions & 5 deletions src/core/deserialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,19 @@ function deserializeStarProps(context, schema, propDef, obj, json) {
key + "': " + value)
obj[key] = value
} else if (propDef.pattern.test(key)) {
var value = deserializeObjectWithSchema(context, propDef, value, context.callback || GUARDED_NOOP, {})
// deserializeObjectWithSchema returns undefined on error
if (value !== undefined) {
obj[key] = value;
}
var value;
if (propDef.factory) {
value = deserializeObjectWithSchema(context, propDef, value, context.callback || GUARDED_NOOP, {})
// deserializeObjectWithSchema returns undefined on error
if (value !== undefined) {
obj[key] = value;
}
} else {
value = propDef.deserializer(value, context.callback || GUARDED_NOOP, context)
if (value !== SKIP) {
obj[key] = value;
}
}
}
}
}
Expand Down
64 changes: 12 additions & 52 deletions src/core/serialize.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/* eslint-disable no-console */
import { invariant, isPrimitive } from "../utils/utils"
import createModelSchema from "../api/createModelSchema"
import getDefaultModelSchema from "../api/getDefaultModelSchema"
import setDefaultModelSchema from "../api/setDefaultModelSchema"
import { SKIP, _defaultPrimitiveProp } from "../constants"

/**
* Serializes an object (graph) into json using the provided model schema.
* The model schema can be omitted if the object type has a default model schema associated with it.
Expand Down Expand Up @@ -39,11 +36,11 @@ export default function serialize(arg1, arg2) {
}

export function checkStarSchemaInvariant(propDef) {
invariant(propDef === true || propDef.pattern, "prop schema '*' can only be used with 'true'")
invariant(propDef === true || propDef.pattern, `prop schema '*' can only be used with 'true': ${JSON.stringify(propDef)}`)
}

export function serializeWithSchema(schema, obj) {
invariant(schema && typeof schema === "object", "Expected schema")
invariant(schema && typeof schema === "object" && schema.props, "Expected schema")
invariant(obj && typeof obj === "object", "Expected object")
var res
if (schema.extends)
Expand Down Expand Up @@ -80,58 +77,21 @@ export function serializeStarProps(schema, propDef, obj, target) {
if (isPrimitive(value)) {
target[key] = value
}
} else if (propDef.props) {
var jsonValue = serialize(propDef, value)
if (jsonValue === SKIP){
return
}
// todo: propDef.jsonname could be a transform function on key
target[key] = jsonValue
} else {
var jsonValue = serializeWithSchema(propDef, value)
if (jsonValue === SKIP) {
var jsonValue = propDef.serializer(value, key, obj)
if (jsonValue === SKIP){
return
}
// todo: propDef.jsonname could be a transform function on key
// todo: propDef.jsonname could be a transform function on key
target[key] = jsonValue
}
}
}
}

/**
* The `serializeAll` decorator can be used on a class to signal that all primitive properties should be serialized automatically.
*
* @example
* @serializeAll class Store {
* a = 3;
* b;
* }
*
* const store = new Store();
* store.c = 5;
* store.d = {};
* t.deepEqual(serialize(store), { a: 3, b: undefined, c: 5 });
*/
export function serializeAll(targetOrPattern, clazzOrSchema) {
let propSchema;
if (arguments.length === 1) {
invariant(arguments.length === 1 && typeof target === "function", "@serializeAll can only be used as class decorator")
propSchema = true;
} else {
invariant(typeof targetOrPattern === "object" && targetOrPattern.match, "@serializeAll pattern doesn't have match");
if (typeof clazzOrSchema === "function") {
clazzOrSchema = object(clazzOrSchema);
}
invariant(typeof clazzOrSchema === "object" && clazzOrSchema.serializer, "couldn't resolve schema");
propSchema = clazzOrSchema;
}

function result(target) {
var info = getDefaultModelSchema(target)
if (!info || !target.hasOwnProperty("serializeInfo")) {
info = createModelSchema(target, {})
setDefaultModelSchema(target, info)
}

getDefaultModelSchema(target).props["*"] = propSchema
return target
}
if (arguments.length === 1) {
return result();
}
return result;
}
50 changes: 50 additions & 0 deletions src/core/serializeAll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { invariant } from "../utils/utils"
import createModelSchema from "../api/createModelSchema"
import getDefaultModelSchema from "../api/getDefaultModelSchema"
import setDefaultModelSchema from "../api/setDefaultModelSchema"
import object from "../types/object"

/**
* The `serializeAll` decorator can be used on a class to signal that all primitive properties should be serialized automatically.
*
* @example
* @serializeAll class Store {
* a = 3;
* b;
* }
*
* const store = new Store();
* store.c = 5;
* store.d = {};
* t.deepEqual(serialize(store), { a: 3, b: undefined, c: 5 });
*/
export default function serializeAll(targetOrPattern, clazzOrSchema) {
let propSchema;
let invokeImmediately = false;
if (arguments.length === 1) {
invariant(typeof targetOrPattern === "function", "@serializeAll can only be used as class decorator");
propSchema = true;
invokeImmediately = true;
}
else {
invariant(typeof targetOrPattern === "object" && targetOrPattern.test, "@serializeAll pattern doesn't have test");
if (typeof clazzOrSchema === "function") {
clazzOrSchema = object(clazzOrSchema);
}
invariant(typeof clazzOrSchema === "object" && clazzOrSchema.serializer, "couldn't resolve schema");
propSchema = Object.assign({}, clazzOrSchema, {pattern: targetOrPattern})
}
function result(target) {
var info = getDefaultModelSchema(target);
if (!info || !target.hasOwnProperty("serializeInfo")) {
info = createModelSchema(target, {});
setDefaultModelSchema(target, info);
}
getDefaultModelSchema(target).props["*"] = propSchema;
return target;
}
if (invokeImmediately) {
return result(targetOrPattern);
}
return result;
}
3 changes: 2 additions & 1 deletion src/serializr.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export { default as serializable } from "./api/serializable"
/*
* ## Serialization and deserialization
*/
export { default as serialize, serializeAll } from "./core/serialize"
export { default as serialize } from "./core/serialize"
export { default as serializeAll } from "./core/serializeAll"
export { default as cancelDeserialize } from "./core/cancelDeserialize"
export { default as deserialize } from "./core/deserialize"
export { default as update } from "./core/update"
Expand Down
12 changes: 4 additions & 8 deletions test/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,10 @@ test("it should respect `*` : true (primitive) prop schemas", t => {
t.end()
})

test.only("it should respect `*` : schema prop schemas", t => {
var schema = {
factory: () => ({}),
pattern: /^\d.\d+$/,
props: {
x: optional(primitive())
}
}
test("it should respect `*` : schema prop schemas", t => {
var schema = Object.assign(_.createSimpleSchema({
x: optional(primitive()),
}), { pattern: /^\d.\d+$/ })

var s = _.createSimpleSchema({ "*" : schema} )
t.deepEqual(_.serialize(s, { "1.0": {x: 42}, "2.10": {x: 17 } }), { "1.0": {x: 42}, "2.10": {x: 17 } })
Expand Down
29 changes: 15 additions & 14 deletions test/typescript/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,28 +588,29 @@ test("[ts] @serializeAll", t => {
t.end()
})

class StarValue {
@serializable(optional())
public x?: number;
}

test("[ts] @serializeAll(schema)", t => {
class StarValue {
@serializable(optional())
public x?: number;
}

@serializeAll(/^\d\.\d+$/, StarValue)
class Store {
a = 3
b
class StoreWithStarSchema {
[key: string]: StarValue;
}

const store = new Store();
const store = new StoreWithStarSchema();
store["1.4"] = { x: 1 };
store["1.77"] = { };
(store as any).c = 5;
(store as any).d = {};

t.deepEqual(serialize(store), { a: 3, c: 5 })
t.deepEqual(serialize(store), { "1.4": {x: 1}, "1.77": {} })

const store2 = deserialize(Store, { a: 2, b: 3, c: 4 })
t.equal(store2.a, 2)
t.equal(store2.b, 3)
t.equal((store2 as any).c, 4)
const store2 = deserialize(StoreWithStarSchema, { "1.4": {x: 1}, "1.77": {}, c: 4 })
t.deepEqual(store["1.4"], { x: 1 })
t.deepEqual(store["1.77"], { })
t.equal((store2 as any).c, undefined)

t.end()
})

0 comments on commit 4dacd61

Please sign in to comment.