Add tests
This commit is contained in:
parent
8c16c1908b
commit
333b415635
2 changed files with 106 additions and 4 deletions
95
packages/backend-core/src/cache/tests/user.spec.ts
vendored
Normal file
95
packages/backend-core/src/cache/tests/user.spec.ts
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import { User } from "@budibase/types"
|
||||||
|
import { tenancy } from "../.."
|
||||||
|
import { generator, structures } from "../../../tests"
|
||||||
|
import { DBTestConfiguration } from "../../../tests/extra"
|
||||||
|
import { getUsers } from "../user"
|
||||||
|
import { getGlobalDB, getGlobalDBName } from "../../context"
|
||||||
|
import _ from "lodash"
|
||||||
|
import { getDB } from "../../db"
|
||||||
|
import type * as TenancyType from "../../tenancy"
|
||||||
|
|
||||||
|
const config = new DBTestConfiguration()
|
||||||
|
|
||||||
|
// This mock is required to ensure that getTenantDB returns always as a singleton.
|
||||||
|
// This will allow us to spy on the db
|
||||||
|
const staticDb = getDB(getGlobalDBName(config.tenantId))
|
||||||
|
jest.mock("../../tenancy", (): typeof TenancyType => ({
|
||||||
|
...jest.requireActual("../../tenancy"),
|
||||||
|
getTenantDB: jest.fn().mockImplementation(() => staticDb),
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe("user cache", () => {
|
||||||
|
describe("getUsers", () => {
|
||||||
|
const users: User[] = []
|
||||||
|
beforeAll(async () => {
|
||||||
|
const userCount = 10
|
||||||
|
const userIds = generator.arrayOf(() => generator.guid(), {
|
||||||
|
min: userCount,
|
||||||
|
max: userCount,
|
||||||
|
})
|
||||||
|
|
||||||
|
await config.doInTenant(async () => {
|
||||||
|
const db = getGlobalDB()
|
||||||
|
for (const userId of userIds) {
|
||||||
|
const user = structures.users.user({ _id: userId })
|
||||||
|
await db.put(user)
|
||||||
|
users.push(user)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("when no user is in cache, all of them are retrieved from db", async () => {
|
||||||
|
const usersToRequest = _.sampleSize(users, 5)
|
||||||
|
|
||||||
|
const userIdsToRequest = usersToRequest.map(x => x._id!)
|
||||||
|
|
||||||
|
jest.spyOn(staticDb, "allDocs")
|
||||||
|
|
||||||
|
const results = await getUsers(userIdsToRequest, config.tenantId)
|
||||||
|
|
||||||
|
expect(results).toHaveLength(5)
|
||||||
|
expect(results).toEqual(
|
||||||
|
usersToRequest.map(u => ({
|
||||||
|
...u,
|
||||||
|
budibaseAccess: true,
|
||||||
|
_rev: expect.any(String),
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(tenancy.getTenantDB).toBeCalledTimes(1)
|
||||||
|
expect(tenancy.getTenantDB).toBeCalledWith(config.tenantId)
|
||||||
|
expect(staticDb.allDocs).toBeCalledTimes(1)
|
||||||
|
expect(staticDb.allDocs).toBeCalledWith({
|
||||||
|
keys: userIdsToRequest,
|
||||||
|
include_docs: true,
|
||||||
|
limit: 5,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("on a second all, all of them are retrieved from cache", async () => {
|
||||||
|
const usersToRequest = _.sampleSize(users, 5)
|
||||||
|
|
||||||
|
const userIdsToRequest = usersToRequest.map(x => x._id!)
|
||||||
|
|
||||||
|
jest.spyOn(staticDb, "allDocs")
|
||||||
|
|
||||||
|
await getUsers(userIdsToRequest, config.tenantId)
|
||||||
|
const resultsFromCache = await getUsers(userIdsToRequest, config.tenantId)
|
||||||
|
|
||||||
|
expect(resultsFromCache).toHaveLength(5)
|
||||||
|
expect(resultsFromCache).toEqual(
|
||||||
|
usersToRequest.map(u => ({
|
||||||
|
...u,
|
||||||
|
budibaseAccess: true,
|
||||||
|
_rev: expect.any(String),
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(staticDb.allDocs).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
15
packages/backend-core/src/cache/user.ts
vendored
15
packages/backend-core/src/cache/user.ts
vendored
|
@ -115,11 +115,18 @@ export async function getUsers(userIds: string[], tenantId: string) {
|
||||||
// try cache
|
// try cache
|
||||||
let usersFromCache = await client.bulkGet(userIds)
|
let usersFromCache = await client.bulkGet(userIds)
|
||||||
const missingUsersFromCache = userIds.filter(uid => !usersFromCache[uid])
|
const missingUsersFromCache = userIds.filter(uid => !usersFromCache[uid])
|
||||||
const usersFromDb = await populateUsersFromDB(missingUsersFromCache, tenantId)
|
const users = Object.values(usersFromCache)
|
||||||
for (const userToCache of usersFromDb) {
|
|
||||||
await client.store(userToCache._id, userToCache, EXPIRY_SECONDS)
|
if (missingUsersFromCache.length) {
|
||||||
|
const usersFromDb = await populateUsersFromDB(
|
||||||
|
missingUsersFromCache,
|
||||||
|
tenantId
|
||||||
|
)
|
||||||
|
for (const userToCache of usersFromDb) {
|
||||||
|
await client.store(userToCache._id, userToCache, EXPIRY_SECONDS)
|
||||||
|
}
|
||||||
|
users.push(...usersFromDb)
|
||||||
}
|
}
|
||||||
const users = [...Object.values(usersFromCache), ...usersFromDb]
|
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue