From 177005ed5e450f2088ba841a14051e77723a4ace Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 16 Jan 2025 16:53:21 +0000 Subject: [PATCH] Convert viewBuilder.spec.js to ts --- .../__snapshots__/viewBuilder.spec.js.snap | 147 --------------- .../view/tests/viewBuilder.spec.js | 75 -------- .../view/tests/viewBuilder.spec.ts | 174 ++++++++++++++++++ .../src/api/controllers/view/viewBuilder.ts | 20 +- packages/types/src/documents/app/view.ts | 4 +- 5 files changed, 192 insertions(+), 228 deletions(-) delete mode 100644 packages/server/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap delete mode 100644 packages/server/src/api/controllers/view/tests/viewBuilder.spec.js create mode 100644 packages/server/src/api/controllers/view/tests/viewBuilder.spec.ts diff --git a/packages/server/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap b/packages/server/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap deleted file mode 100644 index 80f2188e69..0000000000 --- a/packages/server/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap +++ /dev/null @@ -1,147 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`viewBuilder Calculate and filter creates a view with the calculation statistics and filter schema 1`] = ` -{ - "map": "function (doc) { - if ((doc.tableId === "14f1c4e94d6a47b682ce89d35d4c78b0" && !( - doc["myField"] === undefined || - doc["myField"] === null || - doc["myField"] === "" || - (Array.isArray(doc["myField"]) && doc["myField"].length === 0) - )) && (doc["age"] > 17)) { - emit(doc["_id"], doc["myField"]); - } - }", - "meta": { - "calculation": "stats", - "field": "myField", - "filters": [ - { - "condition": "MT", - "key": "age", - "value": 17, - }, - ], - "groupBy": undefined, - "schema": { - "avg": { - "type": "number", - }, - "count": { - "type": "number", - }, - "field": { - "type": "string", - }, - "max": { - "type": "number", - }, - "min": { - "type": "number", - }, - "sum": { - "type": "number", - }, - "sumsqr": { - "type": "number", - }, - }, - "tableId": "14f1c4e94d6a47b682ce89d35d4c78b0", - }, - "reduce": "_stats", -} -`; - -exports[`viewBuilder Calculate creates a view with the calculation statistics schema 1`] = ` -{ - "map": "function (doc) { - if ((doc.tableId === "14f1c4e94d6a47b682ce89d35d4c78b0" && !( - doc["myField"] === undefined || - doc["myField"] === null || - doc["myField"] === "" || - (Array.isArray(doc["myField"]) && doc["myField"].length === 0) - )) ) { - emit(doc["_id"], doc["myField"]); - } - }", - "meta": { - "calculation": "stats", - "field": "myField", - "filters": [], - "groupBy": undefined, - "schema": { - "avg": { - "type": "number", - }, - "count": { - "type": "number", - }, - "field": { - "type": "string", - }, - "max": { - "type": "number", - }, - "min": { - "type": "number", - }, - "sum": { - "type": "number", - }, - "sumsqr": { - "type": "number", - }, - }, - "tableId": "14f1c4e94d6a47b682ce89d35d4c78b0", - }, - "reduce": "_stats", -} -`; - -exports[`viewBuilder Filter creates a view with multiple filters and conjunctions 1`] = ` -{ - "map": "function (doc) { - if (doc.tableId === "14f1c4e94d6a47b682ce89d35d4c78b0" && (doc["Name"] === "Test" || doc["Yes"] > "Value")) { - emit(doc["_id"], doc["undefined"]); - } - }", - "meta": { - "calculation": undefined, - "field": undefined, - "filters": [ - { - "condition": "EQUALS", - "key": "Name", - "value": "Test", - }, - { - "condition": "MT", - "conjunction": "OR", - "key": "Yes", - "value": "Value", - }, - ], - "groupBy": undefined, - "schema": null, - "tableId": "14f1c4e94d6a47b682ce89d35d4c78b0", - }, -} -`; - -exports[`viewBuilder Group By creates a view emitting the group by field 1`] = ` -{ - "map": "function (doc) { - if (doc.tableId === "14f1c4e94d6a47b682ce89d35d4c78b0" ) { - emit(doc["age"], doc["score"]); - } - }", - "meta": { - "calculation": undefined, - "field": "score", - "filters": [], - "groupBy": "age", - "schema": null, - "tableId": "14f1c4e94d6a47b682ce89d35d4c78b0", - }, -} -`; diff --git a/packages/server/src/api/controllers/view/tests/viewBuilder.spec.js b/packages/server/src/api/controllers/view/tests/viewBuilder.spec.js deleted file mode 100644 index 7f4298b2ff..0000000000 --- a/packages/server/src/api/controllers/view/tests/viewBuilder.spec.js +++ /dev/null @@ -1,75 +0,0 @@ -const viewTemplate = require("../viewBuilder").default - -describe("viewBuilder", () => { - describe("Filter", () => { - it("creates a view with multiple filters and conjunctions", () => { - expect( - viewTemplate({ - name: "Test View", - tableId: "14f1c4e94d6a47b682ce89d35d4c78b0", - filters: [ - { - value: "Test", - condition: "EQUALS", - key: "Name", - }, - { - value: "Value", - condition: "MT", - key: "Yes", - conjunction: "OR", - }, - ], - }) - ).toMatchSnapshot() - }) - }) - - describe("Calculate", () => { - it("creates a view with the calculation statistics schema", () => { - expect( - viewTemplate({ - name: "Calculate View", - field: "myField", - calculation: "stats", - tableId: "14f1c4e94d6a47b682ce89d35d4c78b0", - filters: [], - }) - ).toMatchSnapshot() - }) - }) - - describe("Group By", () => { - it("creates a view emitting the group by field", () => { - expect( - viewTemplate({ - name: "Test Scores Grouped By Age", - tableId: "14f1c4e94d6a47b682ce89d35d4c78b0", - groupBy: "age", - field: "score", - filters: [], - }) - ).toMatchSnapshot() - }) - }) - - describe("Calculate and filter", () => { - it("creates a view with the calculation statistics and filter schema", () => { - expect( - viewTemplate({ - name: "Calculate View", - field: "myField", - calculation: "stats", - tableId: "14f1c4e94d6a47b682ce89d35d4c78b0", - filters: [ - { - value: 17, - condition: "MT", - key: "age", - }, - ], - }) - ).toMatchSnapshot() - }) - }) -}) diff --git a/packages/server/src/api/controllers/view/tests/viewBuilder.spec.ts b/packages/server/src/api/controllers/view/tests/viewBuilder.spec.ts new file mode 100644 index 0000000000..34526345f3 --- /dev/null +++ b/packages/server/src/api/controllers/view/tests/viewBuilder.spec.ts @@ -0,0 +1,174 @@ +import viewTemplate from "../viewBuilder" + +describe("viewBuilder", () => { + describe("Filter", () => { + it("creates a view with multiple filters and conjunctions", () => { + expect( + viewTemplate({ + field: "myField", + tableId: "tableId", + filters: [ + { + value: "Test", + condition: "EQUALS", + key: "Name", + }, + { + value: "Value", + condition: "MT", + key: "Yes", + conjunction: "OR", + }, + ], + }) + ).toEqual({ + map: `function (doc) { + if (doc.tableId === "tableId" && (doc["Name"] === "Test" || doc["Yes"] > "Value")) { + emit(doc["_id"], doc["myField"]); + } + }`, + meta: { + calculation: undefined, + field: "myField", + filters: [ + { + condition: "EQUALS", + key: "Name", + value: "Test", + }, + { + condition: "MT", + conjunction: "OR", + key: "Yes", + value: "Value", + }, + ], + groupBy: undefined, + schema: null, + tableId: "tableId", + }, + }) + }) + }) + + describe("Calculate", () => { + it("creates a view with the calculation statistics schema", () => { + expect( + viewTemplate({ + field: "myField", + calculation: "stats", + tableId: "tableId", + filters: [], + }) + ).toEqual({ + map: `function (doc) { + if ((doc.tableId === "tableId" && !( + doc["myField"] === undefined || + doc["myField"] === null || + doc["myField"] === "" || + (Array.isArray(doc["myField"]) && doc["myField"].length === 0) + )) ) { + emit(doc["_id"], doc["myField"]); + } + }`, + meta: { + calculation: "stats", + field: "myField", + filters: [], + groupBy: undefined, + schema: { + min: { type: "number" }, + max: { type: "number" }, + avg: { type: "number" }, + count: { type: "number" }, + sumsqr: { type: "number" }, + sum: { type: "number" }, + field: { type: "string" }, + }, + tableId: "tableId", + }, + reduce: "_stats", + }) + }) + }) + + describe("Group By", () => { + it("creates a view emitting the group by field", () => { + expect( + viewTemplate({ + tableId: "tableId", + groupBy: "age", + field: "score", + filters: [], + }) + ).toEqual({ + map: `function (doc) { + if (doc.tableId === "tableId" ) { + emit(doc["age"], doc["score"]); + } + }`, + meta: { + calculation: undefined, + field: "score", + filters: [], + groupBy: "age", + schema: null, + tableId: "tableId", + }, + }) + }) + }) + + describe("Calculate and filter", () => { + it("creates a view with the calculation statistics and filter schema", () => { + expect( + viewTemplate({ + field: "myField", + calculation: "stats", + tableId: "tableId", + filters: [ + { + value: 17, + condition: "MT", + key: "age", + }, + ], + }) + ).toEqual({ + map: `function (doc) { + if ((doc.tableId === "tableId" && !( + doc["myField"] === undefined || + doc["myField"] === null || + doc["myField"] === "" || + (Array.isArray(doc["myField"]) && doc["myField"].length === 0) + )) && (doc["age"] > 17)) { + emit(doc["_id"], doc["myField"]); + } + }`, + meta: { + calculation: "stats", + field: "myField", + filters: [ + { + condition: "MT", + key: "age", + value: 17, + }, + ], + groupBy: undefined, + schema: { + min: { type: "number" }, + max: { type: "number" }, + avg: { type: "number" }, + count: { type: "number" }, + sumsqr: { type: "number" }, + sum: { type: "number" }, + field: { type: "string" }, + }, + tableId: "tableId", + }, + reduce: "_stats", + }) + }) + }) +}) diff --git a/packages/server/src/api/controllers/view/viewBuilder.ts b/packages/server/src/api/controllers/view/viewBuilder.ts index 3df9df6657..2cedd1fc40 100644 --- a/packages/server/src/api/controllers/view/viewBuilder.ts +++ b/packages/server/src/api/controllers/view/viewBuilder.ts @@ -1,4 +1,4 @@ -import { ViewFilter, ViewTemplateOpts, DBView } from "@budibase/types" +import { ViewFilter, DBView } from "@budibase/types" const TOKEN_MAP: Record = { EQUALS: "===", @@ -120,7 +120,7 @@ function parseFilterExpression(filters: ViewFilter[]) { * @param groupBy - field to group calculation results on, if any */ function parseEmitExpression(field: string, groupBy: string) { - return `emit(doc["${groupBy || "_id"}"], doc["${field}"]);` + return `emit(doc["${groupBy}"], doc["${field}"]);` } /** @@ -135,7 +135,19 @@ function parseEmitExpression(field: string, groupBy: string) { * calculation: an optional calculation to be performed over the view data. */ export default function ( - { field, tableId, groupBy, filters = [], calculation }: ViewTemplateOpts, + { + field, + tableId, + groupBy, + filters = [], + calculation, + }: { + field: string + tableId: string + groupBy?: string + filters?: ViewFilter[] + calculation?: string + }, groupByMulti?: boolean ): DBView { // first filter can't have a conjunction @@ -168,7 +180,7 @@ export default function ( const parsedFilters = parseFilterExpression(filters) const filterExpression = parsedFilters ? `&& (${parsedFilters})` : "" - const emitExpression = parseEmitExpression(field, groupBy) + const emitExpression = parseEmitExpression(field, groupBy || "_id") const tableExpression = `doc.tableId === "${tableId}"` const coreExpression = statFilter ? `(${tableExpression} && ${statFilter})` diff --git a/packages/types/src/documents/app/view.ts b/packages/types/src/documents/app/view.ts index fd97cee409..a7fbf06377 100644 --- a/packages/types/src/documents/app/view.ts +++ b/packages/types/src/documents/app/view.ts @@ -6,10 +6,10 @@ import { DBView, SearchFilters } from "../../sdk" export type ViewTemplateOpts = { field: string tableId: string - groupBy: string + groupBy?: string filters: ViewFilter[] schema: any - calculation: string + calculation?: string groupByMulti?: boolean }