UNPKG

jinaga

Version:

Data management for web and mobile applications.

756 lines (694 loc) 28.6 kB
import { SpecificationOf } from "../../src"; import { Company, Office, OfficeClosed, OfficeReopened, President, User, UserName, model } from "../companyModel"; describe("given", () => { it("should parse an identity specification", () => { const specification = model.given(Company).select((company, facts) => company); expectSpecification(specification, ` (p1: Company) { } => p1`); }); it("should parse a successor join", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => u1`); }); it("should parse a successor join using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => u1`); }); it("should parse negative existential condition", () => { 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) ) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 !E { u2: Office.Closed [ u2->office: Office = u1 ] } ] } => u1`); }); it("should parse negative existential condition using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .notExists(office => office.successors(OfficeClosed, officeClosed => officeClosed.office)) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 !E { u2: Office.Closed [ u2->office: Office = u1 ] } ] } => u1`); }); it("should parse positive existential condition", () => { 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) ) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 E { u2: Office.Closed [ u2->office: Office = u1 ] } ] } => u1`); }); it("should parse positive existential condition using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .exists(office => office.successors(OfficeClosed, officeClosed => officeClosed.office)) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 E { u2: Office.Closed [ u2->office: Office = u1 ] } ] } => u1`); }); it("should parse nested negative existential condition", () => { const specification = model.given(Company).match((company, facts) => Office.inCompany(facts, company) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 !E { u2: Office.Closed [ u2->office: Office = u1 !E { u3: Office.Reopened [ u3->officeClosed: Office.Closed = u2 ] } ] } ] } => u1`); }); it("should parse nested negative existential condition using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .notExists(office => office.successors(OfficeClosed, officeClosed => officeClosed.office) .notExists(officeClosed => officeClosed.successors(OfficeReopened, officeReopened => officeReopened.officeClosed)) ) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 !E { u2: Office.Closed [ u2->office: Office = u1 !E { u3: Office.Reopened [ u3->officeClosed: Office.Closed = u2 ] } ] } ] } => u1`); }); it("should parse a field projection", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => office.identifier) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => u1.identifier`); }); it("should parse a field projection using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => office.identifier) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => u1.identifier`); }); it("should parse a composite projection with a field", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier }`); }); it("should parse a composite projection with a field using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier }`); }); it("should parse a composite projection with a collection", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, presidents: facts.ofType(President) .join(president => president.office, office) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => u2 }`); }); it("should parse a composite projection with a collection using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, presidents: office.successors(President, president => president.office) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => u2 }`); }); it("should parse a nested collection", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, presidents: facts.ofType(President) .join(president => president.office, office) .select(president => ({ president: president, names: facts.ofType(UserName) .join(userName => userName.user, president.user) .select(userName => userName.value) })) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => { names = { u3: User.Name [ u3->user: User = u2->user: User ] } => u3.value president = u2 } }`); }); it("should parse a nested collection using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, presidents: office.successors(President, president => president.office) .select(president => ({ president: president, names: president.user.successors(UserName, userName => userName.user) .select(userName => userName.value) })) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => { names = { u3: User.Name [ u3->user: User = u2->user: User ] } => u3.value president = u2 } }`); }); it("should parse multiple joins", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, presidents: facts.ofType(President) .join(president => president.office, office) .select(president => ({ president: president, names: facts.ofType(UserName) .join(userName => userName.user, president.user) .notExists(userName => facts.ofType(UserName) .join(next => next.prior, userName) .join(next => next.user, president.user) ) .select(userName => userName.value) })) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => { names = { u3: User.Name [ u3->user: User = u2->user: User !E { u4: User.Name [ u4->prior: User.Name = u3 u4->user: User = u2->user: User ] } ] } => u3.value president = u2 } }`); }); it("should parse multiple joins using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, presidents: office.successors(President, president => president.office) .select(president => ({ president: president, names: president.user.successors(UserName, userName => userName.user) .notExists(userName => userName.successors(UserName, next => next.prior) .join(next => next.user, president.user) ) .select(userName => userName.value) })) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => { names = { u3: User.Name [ u3->user: User = u2->user: User !E { u4: User.Name [ u4->prior: User.Name = u3 u4->user: User = u2->user: User ] } ] } => u3.value president = u2 } }`); }); it("should parse multiple joins in opposite order", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, presidents: facts.ofType(President) .join(president => president.office, office) .select(president => ({ president: president, names: facts.ofType(UserName) .join(userName => userName.user, president.user) .notExists(userName => facts.ofType(UserName) .join(next => next.user, president.user) .join(next => next.prior, userName) ) .select(userName => userName.value) })) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => { names = { u3: User.Name [ u3->user: User = u2->user: User !E { u4: User.Name [ u4->user: User = u2->user: User u4->prior: User.Name = u3 ] } ] } => u3.value president = u2 } }`); }); it("should parse multiple joins in opposite order using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, presidents: office.successors(President, president => president.office) .select(president => ({ president: president, names: president.user.successors(UserName, userName => userName.user) .notExists(userName => userName.successors(UserName, next => next.prior)) .select(userName => userName.value) })) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] } => { names = { u3: User.Name [ u3->user: User = u2->user: User !E { u4: User.Name [ u4->prior: User.Name = u3 ] } ] } => u3.value president = u2 } }`); }); it("should parse select many", () => { const specification = model.given(Company).match((company, facts) => facts.ofType(Office) .join(office => office.company, company) .select(office => ({ identifier: office.identifier, presidents: facts.ofType(President) .join(president => president.office, office) .selectMany(president => facts.ofType(User) .join(user => user, president.user) .select(user => ({ user: user, names: facts.ofType(UserName) .join(userName => userName.user, user) .select(userName => userName.value) })) ) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] u3: User [ u3 = u2->user: User ] } => { names = { u4: User.Name [ u4->user: User = u3 ] } => u4.value user = u3 } }`); }); it("should parse select many using successors syntax", () => { const specification = model.given(Company).match(company => company.successors(Office, office => office.company) .select(office => ({ identifier: office.identifier, presidents: office.successors(President, president => president.office) .selectMany(president => president.user.predecessor() .select(user => ({ user: user, names: user.successors(UserName, userName => userName.user) .select(userName => userName.value) })) ) })) ); expectSpecification(specification, ` (p1: Company) { u1: Office [ u1->company: Company = p1 ] } => { identifier = u1.identifier presidents = { u2: President [ u2->office: Office = u1 ] u3: User [ u3 = u2->user: User ] } => { names = { u4: User.Name [ u4->user: User = u3 ] } => u4.value user = u3 } }`); }); it("should parse multiple givens", () => { const specification = model.given(Company, User).match((company, user, facts) => facts.ofType(President) .join(president => president.office.company, company) .join(president => president.user, user) ); expectSpecification(specification, ` (p1: Company, p2: User) { u1: President [ u1->office: Office->company: Company = p1 u1->user: User = p2 ] } => u1`); }); it("should parse multiple givens using successors syntax", () => { const specification = model.given(Company, User).match((company, user) => company.successors(President, president => president.office.company) .join(president => president.user, user) ); expectSpecification(specification, ` (p1: Company, p2: User) { u1: President [ u1->office: Office->company: Company = p1 u1->user: User = p2 ] } => u1`); }); it("should parse a predecessor join using predecessor syntax", () => { const specification = model.given(Office).match(office => office.company.predecessor() ); expectSpecification(specification, ` (p1: Office) { u1: Company [ u1 = p1->company: Company ] } => u1`); }); it("should parse a predecessor join with field projection using predecessor syntax", () => { const specification = model.given(Office).match(office => office.company.predecessor() .select(company => company.identifier) ); expectSpecification(specification, ` (p1: Office) { u1: Company [ u1 = p1->company: Company ] } => u1.identifier`); }); it("should parse a predecessor join with composite projection using predecessor syntax", () => { const specification = model.given(Office).match((office, facts) => office.company.predecessor() .select(company => ({ identifier: company.identifier, creator: facts.ofType(User) .join(user => user, company.creator) })) ); expectSpecification(specification, ` (p1: Office) { u1: Company [ u1 = p1->company: Company ] } => { creator = { u2: User [ u2 = u1->creator: User ] } => u2 identifier = u1.identifier }`); }); it("should parse chained predecessor joins using predecessor syntax", () => { const specification = model.given(President).match(president => president.office.predecessor() .selectMany(office => office.company.predecessor()) ); expectSpecification(specification, ` (p1: President) { u1: Office [ u1 = p1->office: Office ] u2: Company [ u2 = u1->company: Company ] } => u2`); }); it("should parse a predecessor join with existential condition using predecessor syntax", () => { const specification = model.given(OfficeClosed).match(officeClosed => officeClosed.office.predecessor() .exists(office => office.company.predecessor()) ); expectSpecification(specification, ` (p1: Office.Closed) { u1: Office [ u1 = p1->office: Office E { u2: Company [ u2 = u1->company: Company ] } ] } => u1`); }); }); function expectSpecification<T, U>(specification: SpecificationOf<T, U>, expected: string) { expect("\n" + specification.toDescriptiveString(3)).toBe(expected + "\n"); }