import {setupApphierarchy, basicAppHierarchyCreator_WithFields_AndIndexes} from "./specHelpers"; import {permission} from "../src/authApi/permissions"; describe("aggregates", () => { it("should calculate correct totals, when no condition supplied", async () => { const {createInvoice, indexApi} = await setup(); await createInvoice(10); await createInvoice(20); await createInvoice(30); const result = await indexApi.aggregates("/Outstanding Invoices"); expect(result.all_invoices_by_type.Important.count).toBe(3); expect(result.all_invoices_by_type.Important.totalIncVat.max).toBe(30); expect(result.all_invoices_by_type.Important.totalIncVat.min).toBe(10); expect(result.all_invoices_by_type.Important.totalIncVat.sum).toBe(60); expect(result.all_invoices_by_type.Important.totalIncVat.mean).toBe(60 / 3); }); it("should split totals into correct groups", async () => { const {createInvoice, indexApi} = await setup(); await createInvoice(10, 0, "Important"); await createInvoice(20, 0, "NotImportant"); await createInvoice(30, 0, "NotImportant"); const result = await indexApi.aggregates("/Outstanding Invoices"); expect(result.all_invoices_by_type.Important.count).toBe(1); expect(result.all_invoices_by_type.NotImportant.count).toBe(2); expect(result.all_invoices_by_type.Important.totalIncVat.sum).toBe(10); expect(result.all_invoices_by_type.NotImportant.totalIncVat.sum).toBe(50); }); it("should include all when all match condition", async () => { const {createInvoice, indexApi} = await setup(); await createInvoice(10, 0, "Important", true); await createInvoice(10, 0, "Important", true); await createInvoice(10, 0, "Important", true); const result = await indexApi.aggregates("/Outstanding Invoices"); expect(result.written_off.Important.count).toBe(3); expect(result.written_off.Important.totalIncVat.sum).toBe(30); }); it("should add to '(none)' when group is blank, null or undefined", async () => { const {createInvoice, indexApi} = await setup(); await createInvoice(10, 0, "", true); await createInvoice(10, 0, null, true); const result = await indexApi.aggregates("/Outstanding Invoices"); expect(result.all_invoices_by_type["(none)"].count).toBe(2); expect(result.all_invoices_by_type["(none)"].totalIncVat.sum).toBe(20); }); it("should not include those that do not match condition", async () => { const {createInvoice, indexApi} = await setup(); await createInvoice(10, 0, "Important", true); await createInvoice(10, 0, "Important", true); await createInvoice(10, 0, "Important", false); const result = await indexApi.aggregates("/Outstanding Invoices"); expect(result.written_off.Important.count).toBe(2); expect(result.written_off.Important.totalIncVat.sum).toBe(20); }); it("should have 'all' group when no grouping supplied", async () => { const {createInvoice, indexApi} = await setup(); await createInvoice(10, 0, "Important", true); await createInvoice(20, 0, "Important", true); const result = await indexApi.aggregates("/Outstanding Invoices"); expect(result.all_invoices.all.count).toBe(2); }); it("should calculate correct totals, sharded index - all records", async () => { const {createInvoice, indexApi, invoicesByOutstandingKey} = await setup(); await createInvoice(10, 0, "Important"); await createInvoice(20, 20, "Important"); await createInvoice(30, 30, "Important"); const result = await indexApi.aggregates(invoicesByOutstandingKey); expect(result.all_invoices_by_type.Important.count).toBe(3); expect(result.all_invoices_by_type.Important.totalIncVat.max).toBe(30); expect(result.all_invoices_by_type.Important.totalIncVat.min).toBe(10); expect(result.all_invoices_by_type.Important.totalIncVat.sum).toBe(60); expect(result.all_invoices_by_type.Important.totalIncVat.mean).toBe(60 / 3); }); it("should calculate correct totals, sharded index - bounded by sharding", async () => { const {createInvoice, indexApi, invoicesByOutstandingKey} = await setup(); await createInvoice(10, 0, "Important"); await createInvoice(20, 20, "Important"); await createInvoice(30, 30, "Important"); const result = await indexApi.aggregates( invoicesByOutstandingKey, {totalIncVat:10, paidAmount:10}, {totalIncVat:10, paidAmount:10} ); expect(result.all_invoices_by_type.Important.count).toBe(2); expect(result.all_invoices_by_type.Important.totalIncVat.max).toBe(30); expect(result.all_invoices_by_type.Important.totalIncVat.min).toBe(20); expect(result.all_invoices_by_type.Important.totalIncVat.sum).toBe(50); expect(result.all_invoices_by_type.Important.totalIncVat.mean).toBe(50 / 2); }); it("should throw error when user user does not have permission", async () => { const {app, indexApi} = await setup(); app.removePermission(permission.readIndex.get("/customer_index")); let err; try { await indexApi.aggregates("/customer_index"); } catch(e) { err = e; } expect(err).toBeDefined(); expect(err.message.startsWith("Unauthorized")).toBeTruthy(); //expect(indexApi.aggregates("/customer_index")).rejects.toThrow(/Unauthorized/); }); it("should not depend on having any other permissions", async () => { const {app, indexApi} = await setup(); app.withOnlyThisPermission(permission.readIndex.get("/customer_index")); await indexApi.aggregates("/customer_index"); }); }); const setup = async () => { const {recordApi, app, indexApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields_AndIndexes); const customer = recordApi.getNew("/customers", "customer"); await recordApi.save(customer); const createInvoice = async (totalAmount=10, paidAmount=0, type="Important", writtenOff=false) => { const invoice = recordApi.getNew(`/customers/${customer.id}/invoices`, "invoice"); invoice.totalIncVat = totalAmount; invoice.paidAmount = paidAmount; invoice.invoiceType = type; invoice.isWrittenOff = writtenOff; return await recordApi.save(invoice); }; const invoicesByOutstandingKey = `/customers/${customer.id}/invoicesByOutstanding`; return {createInvoice, indexApi, invoicesByOutstandingKey, app}; }