import { setupApphierarchy, basicAppHierarchyCreator_WithFields, stubEventHandler, } from "./specHelpers" import { events, isNonEmptyString } from "../src/common" import { permission } from "../src/authApi/permissions" import { getRecordInfo } from "../src/recordApi/recordInfo" describe("recordApi > save then load", () => { it("should save all field values on create new record", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" record.isalive = true record.age = 9 record.createddate = new Date() await recordApi.save(record) const saved = await recordApi.load(record.key) expect(saved.surname).toBe(record.surname) expect(saved.isalive).toBe(record.isalive) expect(saved.age).toBe(record.age) expect(saved.createddate).toEqual(record.createddate) }) it("should create values for fields when undefined", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.age = 9 record.createddate = new Date() await recordApi.save(record) const saved = await recordApi.load(record.key) expect(saved.surname).toBe(null) expect(saved.isalive).toBe(true) expect(saved.age).toBe(record.age) expect(saved.createddate).toEqual(record.createddate) }) it("loaded record isNew() always return false", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.age = 9 record.createddate = new Date() await recordApi.save(record) const saved = await recordApi.load(record.key) expect(saved.isNew).toBeDefined() expect(saved.isNew).toBe(false) }) it("loaded record id() and key() should work", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.age = 9 record.createddate = new Date() await recordApi.save(record) const saved = await recordApi.load(record.key) expect(saved.id).toBeDefined() expect(saved.id).toBe(record.id) expect(saved.key).toBeDefined() expect(saved.key).toBe(saved.key) }) it("loaded record type() should be a function", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.age = 9 record.createddate = new Date() await recordApi.save(record) const saved = await recordApi.load(record.key) expect(isNonEmptyString(saved.type)).toBeTruthy() expect(saved.type).toBe("customer") }) it("update existing should update field", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" record.isalive = true record.age = 9 record.createddate = new Date() await recordApi.save(record) const saved = await recordApi.load(record.key) saved.surname = "Zeedog" await recordApi.save(saved) const savedAgain = await recordApi.load(saved.key) expect(savedAgain.surname).toBe(saved.surname) }) it("should maintain referential integrity", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const referredByCustomer = recordApi.getNew("/customers", "customer") referredByCustomer.surname = "Ledog" referredByCustomer.age = 9 ;(referredByCustomer.isalive = true), (referredByCustomer.createdDate = new Date()) const savedReferredBy = 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 = referredByCustomer await recordApi.save(referredCustomer) savedReferredBy.surname = "Zeedog" await recordApi.save(savedReferredBy) const loadedReferredTo = await recordApi.load(referredCustomer.key) expect(loadedReferredTo.referredBy.surname).toBe("Zeedog") }) }) describe("save", () => { it("IsNew() should return false after save", async () => { const { recordApi } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" const savedRecord = await recordApi.save(record) expect(savedRecord.isNew).toBe(false) }) it("should publish onbegin and oncomplete events", async () => { const { recordApi, subscribe } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const handler = stubEventHandler() subscribe(events.recordApi.save.onBegin, handler.handle) subscribe(events.recordApi.save.onComplete, handler.handle) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" await recordApi.save(record) const onBegin = handler.getEvents(events.recordApi.save.onBegin) const onComplete = handler.getEvents(events.recordApi.save.onComplete) expect(onBegin.length).toBe(1) expect(onComplete.length).toBe(1) expect(onBegin[0].context.record).toBeDefined() expect(onBegin[0].context.record.key).toBe(record.key) expect(onComplete[0].context.record).toBeDefined() expect(onComplete[0].context.record.key).toBe(record.key) }) it("should publish create on create and update on update", async () => { const { recordApi, subscribe } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const handler = stubEventHandler() subscribe(events.recordApi.save.onRecordCreated, handler.handle) subscribe(events.recordApi.save.onRecordUpdated, handler.handle) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" const savedRecord = await recordApi.save(record) const onCreate = handler.getEvents(events.recordApi.save.onRecordCreated) expect(onCreate.length).toBe(1) expect(onCreate[0].context.record).toBeDefined() expect(onCreate[0].context.record.key).toBe(record.key) savedRecord.surname = "Zeecat" await recordApi.save(savedRecord) const onUpdate = handler.getEvents(events.recordApi.save.onRecordUpdated) expect(onUpdate.length).toBe(1) expect(onUpdate[0].context.old).toBeDefined() expect(onUpdate[0].context.old.key).toBe(record.key) expect(onUpdate[0].context.old.surname).toBe("Ledog") expect(onUpdate[0].context.new).toBeDefined() expect(onUpdate[0].context.new.key).toBe(record.key) expect(onUpdate[0].context.new.surname).toBe("Zeecat") }) it("should create folder and index for subcollection", async () => { const { recordApi, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" await recordApi.save(record) const recordDir = getRecordInfo(appHierarchy.root, record.key).dir expect( await recordApi._storeHandle.exists( `${recordDir}/invoice_index/index.csv` ) ).toBeTruthy() expect( await recordApi._storeHandle.exists(`${recordDir}/invoice_index`) ).toBeTruthy() expect( await recordApi._storeHandle.exists(`${recordDir}/invoices`) ).toBeTruthy() }) it("should create index folder and shardMap for sharded reverse reference index", async () => { const { recordApi, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" await recordApi.save(record) const recordDir = getRecordInfo(appHierarchy.root, record.key).dir expect( await recordApi._storeHandle.exists( `${recordDir}/referredToCustomers/shardMap.json` ) ).toBeTruthy() expect( await recordApi._storeHandle.exists(`${recordDir}/referredToCustomers`) ).toBeTruthy() }) it("should create folder for record", async () => { const { recordApi, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") record.surname = "Ledog" await recordApi.save(record) const recordDir = getRecordInfo(appHierarchy.root, record.key).dir expect(await recordApi._storeHandle.exists(`${recordDir}`)).toBeTruthy() expect( await recordApi._storeHandle.exists(`${recordDir}/record.json`) ).toBeTruthy() }) it("create should throw error, user user does not have permission", async () => { const { recordApi, app, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") app.removePermission( permission.createRecord.get(appHierarchy.customerRecord.nodeKey()) ) expect(recordApi.save(record)).rejects.toThrow(/Unauthorized/) }) it("create should not depend on having any other permissions", async () => { const { recordApi, app, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) app.withOnlyThisPermission( permission.createRecord.get(appHierarchy.customerRecord.nodeKey()) ) const record = recordApi.getNew("/customers", "customer") await recordApi.save(record) }) it("update should throw error, user user does not have permission", async () => { const { recordApi, app, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") app.removePermission( permission.updateRecord.get(appHierarchy.customerRecord.nodeKey()) ) const created = await recordApi.save(record) expect(recordApi.save(created)).rejects.toThrow(/Unauthorized/) }) it("update should not depend on having any other permissions", async () => { const { recordApi, app, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") const saved = await recordApi.save(record) app.withOnlyThisPermission( permission.updateRecord.get(appHierarchy.customerRecord.nodeKey()) ) await recordApi.save(saved) }) }) describe("recordApi > load", () => { it("should throw error when user user does not have permission", async () => { const { recordApi, app, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") const created = await recordApi.save(record) app.removePermission( permission.readRecord.get(appHierarchy.customerRecord.nodeKey()) ) expect(recordApi.load(created.key)).rejects.toThrow(/Unauthorized/) }) it("should not depend on having any other permissions", async () => { const { recordApi, app, appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) const record = recordApi.getNew("/customers", "customer") const saved = await recordApi.save(record) app.withOnlyThisPermission( permission.readRecord.get(appHierarchy.customerRecord.nodeKey()) ) await recordApi.load(saved.key) }) })