import {setupApphierarchy, basicAppHierarchyCreator_WithFields, basicAppHierarchyCreator_WithFields_AndIndexes} from "./specHelpers"; import {joinKey} from "../src/common"; import {some, isArray, isObjectLike} from "lodash"; describe("recordApi > create > reindex", () => { it("should add to default index, when record created", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = true; record.age = 9; record.createddate = new Date(); await recordApi.save(record); const items = await indexApi.listItems("/customer_index"); expect(items.length).toBe(1); expect(items[0].surname).toBe("Ledog"); expect(items[0].key).toBeDefined(); expect(items[0].key).toEqual(record.key); }); it("should add to index with filter, when record created and passes filter", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = false; record.age = 9; record.createddate = new Date(); await recordApi.save(record); const items = await indexApi.listItems("/deceased"); expect(items.length).toBe(1); expect(items[0].surname).toBe("Ledog"); expect(items[0].key).toBeDefined(); expect(items[0].key).toEqual(record.key); }); it("should not add to index with filter, when record created and fails filter", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = true; record.age = 9; record.createddate = new Date(); await recordApi.save(record); const items = await indexApi.listItems("/deceased"); expect(items.length).toBe(0); }); it("should be able to add to and list subcollection, after save (i.e. save initialiieses collection)", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const customer = recordApi.getNew("/customers", "customer"); await recordApi.save(customer); const invoicesCollectionKey = joinKey(customer.key, "invoices"); const invoice = recordApi.getNew(invoicesCollectionKey, "invoice"); invoice.totalIncVat = 10.5; invoice.createdDate = new Date(); await recordApi.save(invoice); const invoices = await indexApi.listItems( joinKey(customer.key, "invoice_index")); expect(isArray(invoices)).toBeTruthy(); expect(invoices.length).toBe(1); expect(invoices[0].totalIncVat).toBe(10.5); }); it("should add to global index, when required", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.age = 9; customer.isalive = true, customer.createdDate = new Date(); await recordApi.save(customer); const customers = await indexApi.listItems("/customersReference"); expect(isArray(customers)).toBeTruthy(); expect(customers.length).toBe(1); expect(customers[0].name).toBe("Ledog"); }); it("should add reference field to index and reparse", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner = recordApi.getNew("/partners", "partner"); partner.businessName = "ACME"; partner.phone = "098766e6"; await recordApi.save(partner); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.age = 9; customer.isalive = true, customer.createdDate = new Date(); customer.partner = partner; await recordApi.save(customer); const customers = await indexApi.listItems("/customer_index"); expect(customers.length).toBe(1); expect(isObjectLike(customer.partner)).toBeTruthy(); expect(customers[0].partner.key).toBe(partner.key); expect(customers[0].partner.name).toBe(partner.businessName); expect(customers[0].partner.phone).toBe(partner.phone); }); it("should add to reverse reference index, when required", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const referredByCustomer = recordApi.getNew("/customers", "customer"); referredByCustomer.surname = "Ledog"; referredByCustomer.age = 9; referredByCustomer.isalive = true, referredByCustomer.createdDate = new Date(); await recordApi.save(referredByCustomer); const referredCustomer = recordApi.getNew("/customers", "customer"); referredCustomer.surname = "Zeecat"; referredCustomer.age = 9; referredCustomer.isalive = true, referredCustomer.createdDate = new Date(); referredCustomer.referredBy = { key:referredByCustomer.key, value:referredByCustomer.surname}; await recordApi.save(referredCustomer); const customersReferredTo = await indexApi.listItems( joinKey(referredByCustomer.key, "referredToCustomers") ); expect(isArray(customersReferredTo)).toBeTruthy(); expect(customersReferredTo.length).toBe(1); expect(customersReferredTo[0].surname).toBe("Zeecat"); }); it("should add to sharded index, when record created, and should add into correct shards", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record1 = recordApi.getNew("/customers", "customer"); record1.surname = "Ledog"; await recordApi.save(record1); const record2 = recordApi.getNew("/customers", "customer"); record2.surname = "Zeecat"; await recordApi.save(record2); const items = await indexApi.listItems("/customersBySurname"); expect(items.length).toBe(2); expect(items[0].surname).toBe("Ledog"); expect(items[0].key).toEqual(record1.key); expect(items[1].surname).toBe("Zeecat"); expect(items[1].key).toEqual(record2.key); }); }); describe("recordApi > delete > reindex", () => { it("should remove from default index", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = true; record.age = 9; record.createddate = new Date(); await recordApi.save(record); await recordApi.delete(record.key); const itemsAfterDelete= await indexApi.listItems("/customer_index"); expect(itemsAfterDelete.length).toBe(0); }); it("should remove from sharded index", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record1 = recordApi.getNew("/customers", "customer"); record1.surname = "Ledog"; await recordApi.save(record1); const record2 = recordApi.getNew("/customers", "customer"); record2.surname = "Zeecat"; await recordApi.save(record2); await recordApi.delete(record1.key); const itemsAfterDelete= await indexApi.listItems("/customersBySurname"); expect(itemsAfterDelete.length).toBe(1); expect(itemsAfterDelete[0].surname).toBe("Zeecat"); }); it("should remove from all indexes", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const referredBy = recordApi.getNew("/customers", "customer"); referredBy.surname = "Zeecat"; await recordApi.save(referredBy); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = false; record.age = 9; record.createddate = new Date(); record.referredBy = { key: referredBy.key, value: referredBy.surname }; await recordApi.save(record); await recordApi.delete(record.key); const itemsAfterDelete= await indexApi.listItems("/customer_index"); expect(itemsAfterDelete.length).toBe(1); expect(itemsAfterDelete[0].surname).toBe("Zeecat"); const deceasedItemsAfterDelete= await indexApi.listItems("/deceased"); expect(deceasedItemsAfterDelete.length).toBe(0); const referredToItemsAfterDelete = await indexApi.listItems(`${referredBy.key}/referredToCustomers`); expect(referredToItemsAfterDelete.length).toBe(0); }); it("should only remove relevant record from all indexes", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = false; record.age = 9; record.createddate = new Date(); await recordApi.save(record); const otherRecord = recordApi.getNew("/customers", "customer"); otherRecord.surname = "Zeecat"; otherRecord.isalive = false; otherRecord.age = 12; record.createddate = new Date(); await recordApi.save(otherRecord); await recordApi.delete(record.key); const itemsAfterDelete= await indexApi.listItems("/customer_index"); expect(itemsAfterDelete.length).toBe(1); expect(itemsAfterDelete[0].surname).toBe("Zeecat"); const deceasedItemsAfterDelete= await indexApi.listItems("/deceased"); expect(deceasedItemsAfterDelete.length).toBe(1); expect(deceasedItemsAfterDelete[0].surname).toBe("Zeecat"); }); it("should remove from global index", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.age = 9; customer.isalive = true, customer.createdDate = new Date(); await recordApi.save(customer); await recordApi.delete(customer.key); const customers = await indexApi.listItems("/customersReference"); expect(isArray(customers)).toBeTruthy(); expect(customers.length).toBe(0); }); }); describe("recordApi > update > reindex", () => { it("should update values in indexes", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = false; record.age = 9; record.createddate = new Date(); await recordApi.save(record); const loadedRecord = await recordApi.load(record.key); loadedRecord.surname = "Zeedog"; await recordApi.save(loadedRecord); const itemsDefault = await indexApi.listItems("/customer_index"); expect(itemsDefault[0].surname).toBe("Zeedog"); expect(itemsDefault.length).toBe(1); }); it("should update values in sharded index", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; await recordApi.save(record); const loadedRecord = await recordApi.load(record.key); loadedRecord.surname = "Zeedog"; await recordApi.save(loadedRecord); const itemsDefault = await indexApi.listItems("/customersBySurname"); expect(itemsDefault[0].surname).toBe("Zeedog"); expect(itemsDefault.length).toBe(1); }); it("should only update values of relevant item", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const record = recordApi.getNew("/customers", "customer"); record.surname = "Ledog"; record.isalive = false; record.age = 9; record.createddate = new Date(); await recordApi.save(record); const otherRecord = recordApi.getNew("/customers", "customer"); otherRecord.surname = "Zeecat"; otherRecord.isalive = false; otherRecord.age = 12; record.createddate = new Date(); await recordApi.save(otherRecord); const loadedRecord = await recordApi.load(record.key); loadedRecord.surname = "Zeedog"; await recordApi.save(loadedRecord); const items = await indexApi.listItems("/customer_index"); const hasItemWithSurname = sn => some(items, i => i.surname === sn); expect(hasItemWithSurname("Zeedog")).toEqual(true); expect(hasItemWithSurname("Ledog")).toEqual(false); expect(hasItemWithSurname("Zeecat")).toEqual(true); expect(items.length).toBe(2); }); it("should update global index", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.age = 9; customer.isalive = true, customer.createdDate = new Date(); await recordApi.save(customer); const loadedCustomer = await recordApi.load(customer.key); loadedCustomer.surname = "Zeecat"; await recordApi.save(loadedCustomer); const customers = await indexApi.listItems("/customersReference"); expect(isArray(customers)).toBeTruthy(); expect(customers.length).toBe(1); expect(customers[0].name).toBe("Zeecat"); }); it("should remove from one reference index and add to another when field changed", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; await recordApi.save(partner1); const partner2 = recordApi.getNew("/partners", "partner"); partner2.businessName = "Big Corp ltd"; await recordApi.save(partner2); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; const customerSaved = await recordApi.save(customer); customerSaved.partner = { key: partner2.key, value: partner2.businessName }; await recordApi.save(customerSaved); const partner1Customer = await indexApi.listItems(`${partner1.key}/partnerCustomers`); expect(partner1Customer.length).toBe(0); const partner2Customer = await indexApi.listItems(`${partner2.key}/partnerCustomers`); expect(partner2Customer.length).toBe(1); }); it("should remove from reference index when reference blanked", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; await recordApi.save(partner1); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; const customerSaved = await recordApi.save(customer); customerSaved.partner = { key: "", value: "" }; await recordApi.save(customerSaved); const partner1Customer = await indexApi.listItems(`${partner1.key}/partnerCustomers`); expect(partner1Customer.length).toBe(0); }); it("should remove from reference index when filter no longer passes", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; await recordApi.save(partner1); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; const customerSaved = await recordApi.save(customer); customerSaved.isalive = false; await recordApi.save(customerSaved); const partner1Customer = await indexApi.listItems(`${partner1.key}/partnerCustomers`); expect(partner1Customer.length).toBe(0); }); it("should not add to reference index when filter does not pass", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; await recordApi.save(partner1); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; customer.isalive = false; await recordApi.save(customer); const partner1Customer = await indexApi.listItems(`${partner1.key}/partnerCustomers`); expect(partner1Customer.length).toBe(0); }); it("should remove from reference index, and not re-added when no longer passes filter, but reference is changed", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; await recordApi.save(partner1); const partner2 = recordApi.getNew("/partners", "partner"); partner2.businessName = "Big Corp ltd"; await recordApi.save(partner2); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; const customerSaved = await recordApi.save(customer); customerSaved.partner = { key: partner2.key, value: partner2.businessName }; customerSaved.isalive = false; await recordApi.save(customerSaved); const partner1Customer = await indexApi.listItems(`${partner1.key}/partnerCustomers`); expect(partner1Customer.length).toBe(0); const partner2Customer = await indexApi.listItems(`${partner2.key}/partnerCustomers`); expect(partner2Customer.length).toBe(0); }); it("should add to reference index, when reference is changed, and did not previsouly pass filter", async () => { const {recordApi, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; await recordApi.save(partner1); const partner2 = recordApi.getNew("/partners", "partner"); partner2.businessName = "Big Corp ltd"; await recordApi.save(partner2); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; customer.isalive = false; const customerSaved = await recordApi.save(customer); customerSaved.partner = { key: partner2.key, value: partner2.businessName }; customerSaved.isalive = true; await recordApi.save(customerSaved); const partner1Customer = await indexApi.listItems(`${partner1.key}/partnerCustomers`); expect(partner1Customer.length).toBe(0); const partner2Customer = await indexApi.listItems(`${partner2.key}/partnerCustomers`); expect(partner2Customer.length).toBe(1); }); }); describe("referenced object changed", () => { it("should update the reference", async () => { const { recordApi } = await setupApphierarchy(basicAppHierarchyCreator_WithFields); const partner1 = recordApi.getNew("/partners", "partner"); partner1.businessName = "ACME inc"; const savedPartner = await recordApi.save(partner1); const customer = recordApi.getNew("/customers", "customer"); customer.surname = "Ledog"; customer.partner = { key: partner1.key, value: partner1.businessName }; await recordApi.save(customer); savedPartner.businessName = "A.C.M.E Inc"; await recordApi.save(savedPartner); const updatedCustomer = await recordApi.load(customer.key); expect(updatedCustomer.partner.name).toBe(savedPartner.businessName); }); });