jinaga
Version:
Data management for web and mobile applications.
157 lines (133 loc) • 5.77 kB
text/typescript
import { computeHash, verifyHash } from '../../src/fact/hash';
import { dehydrateFact, Hydration } from '../../src/fact/hydrate';
import { JinagaTest } from '../../src/jinaga-test';
describe ('Hash', () => {
it('should be independent of field order', () => {
const hash1 = computeHash({
a: 'one',
b: 'two'
}, {});
const hash2 = computeHash({
b: 'two',
a: 'one'
}, {});
expect(hash1).toEqual(hash2);
});
it('should be independent of array order', () => {
const one = {
type: 'pred', hash: 'one'
};
const two = {
type: 'pred', hash: 'two'
};
const hash1 = computeHash({}, {
preds: [ one, two ]
});
const hash2 = computeHash({}, {
preds: [ two, one ]
});
expect(hash1).toEqual(hash2);
});
it('should verify hash', () => {
const records = dehydrateFact({
type: 'Child',
parent: {
type: 'Parent',
identifier: 'fee'
},
value: 'fum'
});
expect(verifyHash(records[0])).toBeTruthy();
expect(verifyHash(records[1])).toBeTruthy();
})
});
describe('Nullable Predecessors', () => {
it('should create fact with null predecessor and omit it from canonical form', () => {
// Given a fact with a null predecessor
const factWithNullPredecessor = {
type: 'ChildWithOptionalParent',
parent: null,
name: 'orphan'
};
// When dehydrating the fact
const records = dehydrateFact(factWithNullPredecessor);
// Then no exception should be thrown during creation
expect(records).toBeDefined();
expect(records.length).toBe(1);
// And the canonical form should omit the null predecessor
const record = records[0];
expect(record.predecessors).toEqual({});
expect(record.fields).toEqual({ name: 'orphan' });
expect(record.type).toBe('ChildWithOptionalParent');
// And deserialization should result in the property being undefined
const hydration = new Hydration(records);
const hydratedFact = hydration.hydrate({ type: record.type, hash: record.hash });
expect(hydratedFact.parent).toBeUndefined();
expect(hydratedFact.name).toBe('orphan');
expect(hydratedFact.type).toBe('ChildWithOptionalParent');
});
it('should create fact with undefined predecessor and omit it from canonical form', () => {
// Given a fact with an undefined predecessor
const factWithUndefinedPredecessor = {
type: 'ChildWithOptionalParent',
parent: undefined,
name: 'orphan'
};
// When dehydrating the fact
const records = dehydrateFact(factWithUndefinedPredecessor);
// Then no exception should be thrown during creation
expect(records).toBeDefined();
expect(records.length).toBe(1);
// And the canonical form should omit the undefined predecessor
const record = records[0];
expect(record.predecessors).toEqual({});
expect(record.fields).toEqual({ name: 'orphan' });
expect(record.type).toBe('ChildWithOptionalParent');
// And deserialization should result in the property being undefined
const hydration = new Hydration(records);
const hydratedFact = hydration.hydrate({ type: record.type, hash: record.hash });
expect(hydratedFact.parent).toBeUndefined();
expect(hydratedFact.name).toBe('orphan');
expect(hydratedFact.type).toBe('ChildWithOptionalParent');
});
});
describe('Fact Validation', () => {
it('should omit predecessor when fact contains null predecessor', async () => {
// Given a Jinaga instance
const j = JinagaTest.create({});
// When attempting to create a fact with a null predecessor
const factWithNullPredecessor = {
type: 'ChildWithNullParent',
parent: null,
name: 'non-parented child'
};
// Then the fact should be created, and the null predecessor should be omitted
const createdFact = await j.fact(factWithNullPredecessor);
expect(createdFact).toBeDefined();
expect(createdFact.type).toBe('ChildWithNullParent');
expect(createdFact.parent).toBeUndefined();
expect(createdFact.name).toBe('non-parented child');
});
});
describe("Fact with null predecessor", () => {
it("should create a fact and omit null predecessors in canonical form and deserialization", async () => {
// Given a Jinaga instance
const j = JinagaTest.create({});
const parent = await j.fact({
type: "Parent",
name: "Parent Fact"
});
// When attempting to create a fact with an array of predecessors that includes null
const factWithNullPredecessor = {
type: "ChildWithMultipleParents",
parents: [parent, null],
name: "missing-parent child"
};
// Then the fact should be created without throwing an error
const createdFact = await j.fact(factWithNullPredecessor);
expect(createdFact).toBeDefined();
expect(createdFact.type).toBe("ChildWithMultipleParents");
expect(createdFact.parents).toBeDefined();
expect(createdFact.parents.length).toBe(1); // Only the valid parent should be included
});
});