UNPKG

jinaga

Version:

Data management for web and mobile applications.

412 lines (363 loc) 15.4 kB
import { Jinaga, JinagaTest } from "../../src"; import { Company, Employee, Office, OfficeClosed, OfficeReopened, President, User, model } from "../companyModel"; describe("specification query", () => { let creator: User; let company: Company; let office: Office; let closedOffice: Office; let reopenedOffice: Office; let president: President; let employee: Employee; let otherEmployee: Employee; let j: Jinaga; beforeEach(() => { creator = new User("--- PUBLIC KEY GOES HERE ---"); company = new Company(creator, "TestCo"); office = new Office(company, "TestOffice"); president = new President(office, new User("--- PRESIDENT PUBLIC KEY ---")); employee = new Employee(office, new User("--- EMPLOYEE PUBLIC KEY ---")); otherEmployee = new Employee(office, new User("--- OTHER EMPLOYEE PUBLIC KEY ---")); closedOffice = new Office(company, "ClosedOffice"); const closed = new OfficeClosed(closedOffice, new Date()); reopenedOffice = new Office(closedOffice.company, "ReopenedOffice"); const reopened = new OfficeReopened(new OfficeClosed(reopenedOffice, new Date())); j = JinagaTest.create({ initialState: [ creator, company, office, president, employee, otherEmployee, closedOffice, closed, reopenedOffice, reopened ] }); }); it("should query for successors using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(office), j.hash(closedOffice), j.hash(reopenedOffice) ]); }); it("should query for successors using successors", async () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(office), j.hash(closedOffice), j.hash(reopenedOffice) ]); }); it("should query for predecessors", async () => { const specification = model.given(Office).match((office, facts) => facts.ofType(Company) .join(company => company, office.company) ); const result = await j.query(specification, office); expect(result.length).toBe(1); expect(j.hash(result[0])).toBe(j.hash(company)); }); it("should query for multiple predecessors", async () => { const specification = model.given(Office).match((office, facts) => facts.ofType(User) .join(user => user, office.company.creator) ); const result = await j.query(specification, office); expect(result.length).toBe(1); expect(j.hash(result[0])).toBe(j.hash(creator)); }); it("should query for zig zag", async () => { const specification = model.given(Employee).match((employee, facts) => facts.ofType(President) .join(president => president.office, employee.office) ); const result = await j.query(specification, employee); expect(result.length).toBe(1); expect(j.hash(result[0])).toBe(j.hash(president)); }); it("should execute negative existential condition using successors", async () => { const specification = model.given(Company).match((company, facts) => company.successors(Office, office => office.company) .notExists(office => facts.ofType(OfficeClosed) .join(officeClosed => officeClosed.office, office) ) ); const result = await j.query(specification, company); expect(result.length).toBe(1); expect(j.hash(result[0])).toBe(j.hash(office)); }); it("should execute negative existential condition using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .notExists(office => facts.ofType(OfficeClosed) .join(officeClosed => officeClosed.office, office) ) ); const result = await j.query(specification, company); expect(result.length).toBe(1); expect(j.hash(result[0])).toBe(j.hash(office)); }); it("should execute positive existential condition using successors", async () => { const specification = model.given(Company).match((company, facts) => company.successors(Office, office => office.company) .exists(office => facts.ofType(OfficeClosed) .join(officeClosed => officeClosed.office, office) ) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(closedOffice), j.hash(reopenedOffice) ]); }); it("should execute positive existential condition using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .exists(office => facts.ofType(OfficeClosed) .join(officeClosed => officeClosed.office, office) ) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(closedOffice), j.hash(reopenedOffice) ]); }); it("should execute nested existential conditions using successors", async () => { const specification = model.given(Company).match((company, facts) => company.successors(Office, office => office.company) .notExists(office => facts.ofType(OfficeClosed) .join(officeClosed => officeClosed.office, office) .notExists(officeClosed => facts.ofType(OfficeReopened) .join(officeReopened => officeReopened.officeClosed, officeClosed) ) ) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(office), j.hash(reopenedOffice) ]); }); it("should execute nested existential conditions using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .notExists(office => facts.ofType(OfficeClosed) .join(officeClosed => officeClosed.office, office) .notExists(officeClosed => facts.ofType(OfficeReopened) .join(officeReopened => officeReopened.officeClosed, officeClosed) ) ) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(office), j.hash(reopenedOffice) ]); }); it("should match all employees using successors", async () => { const specification = model.given(Company).match((company, facts) => company.successors(Office, office => office.company) .selectMany(office => facts.ofType(Employee) .join(employee => employee.office, office) ) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(employee), j.hash(otherEmployee) ]); }); it("should match all employees using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Employee) .join(employee => employee.office.company, company) ); const result = await j.query(specification, company); expect(result.map(r => j.hash(r))).toEqual([ j.hash(employee), j.hash(otherEmployee) ]); }); it("should execute multiple path conditions using successors", async () => { const specification = model.given(Company, User).match((company, user, facts) => company.successors(Office, office => office.company) .selectMany(office => facts.ofType(Employee) .join(employee => employee.office, office) .join(employee => employee.user, user) ) ); const result = await j.query(specification, company, employee.user); expect(result.map(r => j.hash(r))).toEqual([ j.hash(employee) ]); }); it("should execute multiple path conditions using join", async () => { const specification = model.given(Company, User).match((company, user, facts) => facts.ofType(Employee) .join(employee => employee.office.company, company) .join(employee => employee.user, user) ); const result = await j.query(specification, company, employee.user); expect(result.map(r => j.hash(r))).toEqual([ j.hash(employee) ]); }); it("should execute a field projection using successors", async () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => office.identifier) ); const result = await j.query(specification, company); expect(result).toEqual([ "TestOffice", "ClosedOffice", "ReopenedOffice" ]); }); it("should execute a field projection using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => office.identifier) ); const result = await j.query(specification, company); expect(result).toEqual([ "TestOffice", "ClosedOffice", "ReopenedOffice" ]); }); it("should execute a composite projection using successors", async () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, company: company.identifier })) ); const result = await j.query(specification, company); expect(result).toEqual([ { identifier: "TestOffice", company: "TestCo" }, { identifier: "ClosedOffice", company: "TestCo" }, { identifier: "ReopenedOffice", company: "TestCo" } ]); }); it("should execute a composite projection using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, company: company.identifier })) ); const result = await j.query(specification, company); expect(result).toEqual([ { identifier: "TestOffice", company: "TestCo" }, { identifier: "ClosedOffice", company: "TestCo" }, { identifier: "ReopenedOffice", company: "TestCo" } ]); }); it("should execute a specification projection using successors", async () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, employees: office.successors(Employee, employee => employee.office) })) ); const result = await j.query(specification, company); expect(result.map(result => ({ identifier: result.identifier, employeeHashes: result.employees.map(employee => j.hash(employee)) }))).toEqual([ { identifier: "TestOffice", employeeHashes: [ j.hash(employee), j.hash(otherEmployee) ] }, { identifier: "ClosedOffice", employeeHashes: [] }, { identifier: "ReopenedOffice", employeeHashes: [] } ]); }); it("should execute a specification projection using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, employees: facts.ofType(Employee) .join(employee => employee.office, office) })) ); const result = await j.query(specification, company); expect(result.map(result => ({ identifier: result.identifier, employeeHashes: result.employees.map(employee => j.hash(employee)) }))).toEqual([ { identifier: "TestOffice", employeeHashes: [ j.hash(employee), j.hash(otherEmployee) ] }, { identifier: "ClosedOffice", employeeHashes: [] }, { identifier: "ReopenedOffice", employeeHashes: [] } ]); }); it("should execute a hash projection using join", async () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => j.hash(office)) ); const result = await j.query(specification, company); expect(result).toEqual([ j.hash(office), j.hash(closedOffice), j.hash(reopenedOffice) ]); }); it("should execute a hash projection using successors", async () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => j.hash(office)) ); const result = await j.query(specification, company); expect(result).toEqual([ j.hash(office), j.hash(closedOffice), j.hash(reopenedOffice) ]); }); });