From 2c5e9ff78470e04d7f8e877811c674c197a62a2e Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 3 May 2024 09:31:24 +0200 Subject: [PATCH] processOutputBBReference vs processOutputBBReferences --- .../rowProcessor/bbReferenceProcessor.ts | 99 +++++++++---------- .../tests/bbReferenceProcessor.spec.ts | 95 +++++++++++++++--- 2 files changed, 129 insertions(+), 65 deletions(-) diff --git a/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts b/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts index f26c29a0cd..ad6291dbc7 100644 --- a/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts +++ b/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts @@ -1,7 +1,6 @@ import { cache, db as dbCore } from "@budibase/backend-core" import { utils } from "@budibase/shared-core" import { - FieldType, BBReferenceFieldSubType, DocumentType, SEPARATOR, @@ -104,67 +103,30 @@ interface UserReferenceInfo { _id: string primaryDisplay: string email: string - firstName: string - lastName: string + firstName?: string + lastName?: string } -export function processOutputBBReferences( +export async function processOutputBBReference( value: string, - type: FieldType.BB_REFERENCE_SINGLE -): Promise -export function processOutputBBReferences( - value: string, - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType -): Promise - -export async function processOutputBBReferences( - value: string | string[], - type: FieldType.BB_REFERENCE | FieldType.BB_REFERENCE_SINGLE, - subtype?: BBReferenceFieldSubType -) { + subtype: BBReferenceFieldSubType.USER +): Promise { if (value === null || value === undefined) { // Already processed or nothing to process return value || undefined } - switch (type) { - case FieldType.BB_REFERENCE: { - const ids = - typeof value === "string" ? value.split(",").filter(id => !!id) : value - - switch (subtype) { - case undefined: - throw "Subtype must be defined" - case BBReferenceFieldSubType.USER: - case BBReferenceFieldSubType.USERS: { - const { users } = await cache.user.getUsers(ids) - if (!users.length) { - return undefined - } - - return users.map(u => ({ - _id: u._id, - primaryDisplay: u.email, - email: u.email, - firstName: u.firstName, - lastName: u.lastName, - })) - } - default: - throw utils.unreachable(subtype) - } - } - case FieldType.BB_REFERENCE_SINGLE: { - if (!value) { - return undefined - } + if (!value) { + return undefined + } + switch (subtype) { + case BBReferenceFieldSubType.USER: let user try { user = await cache.user.getUser(value as string) } catch (err: any) { - if (err.code !== 404) { + if (err.statusCode !== 404) { throw err } } @@ -173,15 +135,46 @@ export async function processOutputBBReferences( } return { - _id: user._id, + _id: user._id!, primaryDisplay: user.email, email: user.email, firstName: user.firstName, lastName: user.lastName, } - } - default: - throw utils.unreachable(type) + throw utils.unreachable(subtype) + } +} + +export async function processOutputBBReferences( + value: string, + subtype: BBReferenceFieldSubType +): Promise { + if (value === null || value === undefined) { + // Already processed or nothing to process + return value || undefined + } + + const ids = + typeof value === "string" ? value.split(",").filter(id => !!id) : value + + switch (subtype) { + case BBReferenceFieldSubType.USER: + case BBReferenceFieldSubType.USERS: { + const { users } = await cache.user.getUsers(ids) + if (!users.length) { + return undefined + } + + return users.map(u => ({ + _id: u._id!, + primaryDisplay: u.email, + email: u.email, + firstName: u.firstName, + lastName: u.lastName, + })) + } + default: + throw utils.unreachable(subtype) } } diff --git a/packages/server/src/utilities/rowProcessor/tests/bbReferenceProcessor.spec.ts b/packages/server/src/utilities/rowProcessor/tests/bbReferenceProcessor.spec.ts index a3c5cf8911..2825c9755d 100644 --- a/packages/server/src/utilities/rowProcessor/tests/bbReferenceProcessor.spec.ts +++ b/packages/server/src/utilities/rowProcessor/tests/bbReferenceProcessor.spec.ts @@ -4,6 +4,7 @@ import { BBReferenceFieldSubType, FieldType, User } from "@budibase/types" import { processInputBBReference, processInputBBReferences, + processOutputBBReference, processOutputBBReferences, } from "../bbReferenceProcessor" import { @@ -33,6 +34,12 @@ jest.mock("@budibase/backend-core", (): typeof backendCore => { const config = new DBTestConfiguration() describe("bbReferenceProcessor", () => { + const cacheGetUserSpy = backendCore.cache.user.getUser as jest.MockedFunction< + typeof backendCore.cache.user.getUser + > + const cacheGetUsersSpy = backendCore.cache.user + .getUsers as jest.MockedFunction + const users: User[] = [] beforeAll(async () => { const userCount = 10 @@ -57,9 +64,6 @@ describe("bbReferenceProcessor", () => { describe("processInputBBReference", () => { describe("subtype user", () => { - const cacheGetUserSpy = backendCore.cache.user - .getUser as jest.MockedFunction - it("validate valid string id", async () => { const user = _.sample(users) const userId = user!._id! @@ -118,9 +122,6 @@ describe("bbReferenceProcessor", () => { describe("processInputBBReferences", () => { describe("subtype user", () => { - const cacheGetUsersSpy = backendCore.cache.user - .getUsers as jest.MockedFunction - it("validate valid string id", async () => { const user = _.sample(users) const userId = user!._id! @@ -224,6 +225,41 @@ describe("bbReferenceProcessor", () => { }) }) + describe("processOutputBBReference", () => { + describe("subtype user", () => { + it("fetches user given a valid string id", async () => { + const user = _.sample(users)! + const userId = user._id! + + const result = await config.doInTenant(() => + processOutputBBReference(userId, BBReferenceFieldSubType.USER) + ) + + expect(result).toEqual({ + _id: user._id, + primaryDisplay: user.email, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + }) + expect(cacheGetUserSpy).toHaveBeenCalledTimes(1) + expect(cacheGetUserSpy).toHaveBeenCalledWith(userId) + }) + + it("returns undefined given an unexisting user", async () => { + const userId = generator.guid() + + const result = await config.doInTenant(() => + processOutputBBReference(userId, BBReferenceFieldSubType.USER) + ) + + expect(result).toBeUndefined() + expect(cacheGetUserSpy).toHaveBeenCalledTimes(1) + expect(cacheGetUserSpy).toHaveBeenCalledWith(userId) + }) + }) + }) + describe("processOutputBBReferences", () => { describe("subtype user", () => { it("fetches user given a valid string id", async () => { @@ -231,11 +267,7 @@ describe("bbReferenceProcessor", () => { const userId = user._id! const result = await config.doInTenant(() => - processOutputBBReferences( - userId, - FieldType.BB_REFERENCE, - BBReferenceFieldSubType.USER - ) + processOutputBBReferences(userId, BBReferenceFieldSubType.USER) ) expect(result).toEqual([ @@ -259,7 +291,6 @@ describe("bbReferenceProcessor", () => { const result = await config.doInTenant(() => processOutputBBReferences( [userId1, userId2].join(","), - FieldType.BB_REFERENCE, BBReferenceFieldSubType.USER ) ) @@ -279,6 +310,46 @@ describe("bbReferenceProcessor", () => { expect(cacheGetUsersSpy).toHaveBeenCalledTimes(1) expect(cacheGetUsersSpy).toHaveBeenCalledWith([userId1, userId2]) }) + + it("trims unexisting users user given a valid string id csv", async () => { + const [user1, user2] = _.sampleSize(users, 2) + const userId1 = user1._id! + const userId2 = user2._id! + + const unexistingUserId1 = generator.guid() + const unexistingUserId2 = generator.guid() + + const input = [ + unexistingUserId1, + userId1, + unexistingUserId2, + userId2, + ].join(",") + + const result = await config.doInTenant(() => + processOutputBBReferences(input, BBReferenceFieldSubType.USER) + ) + + expect(result).toHaveLength(2) + expect(result).toEqual( + expect.arrayContaining( + [user1, user2].map(u => ({ + _id: u._id, + primaryDisplay: u.email, + email: u.email, + firstName: u.firstName, + lastName: u.lastName, + })) + ) + ) + expect(cacheGetUsersSpy).toHaveBeenCalledTimes(1) + expect(cacheGetUsersSpy).toHaveBeenCalledWith([ + unexistingUserId1, + userId1, + unexistingUserId2, + userId2, + ]) + }) }) }) })