[web] optimize project lookup for tpds operations (#35466)

* [web] store ObjectIds in addUserToProject acceptance test helper

* [web] optimize project lookup for tpds operations

GitOrigin-RevId: 03db9fc450556072f177d56f640fcc6114b295d4
This commit is contained in:
Jakob Ackermann
2026-09-17 11:28:44 +00:00
committed by Copybot
parent dfd816801d
commit 8270641b42
7 changed files with 539 additions and 242 deletions
@@ -317,54 +317,8 @@ describe('ProjectGetter', function () {
})
})
describe('findUsersProjectsByName', function () {
it('should perform a case-insensitive search', async function (ctx) {
ctx.project1 = { _id: 1, name: 'find me!' }
ctx.project2 = { _id: 2, name: 'not me!' }
ctx.project3 = { _id: 3, name: 'FIND ME!' }
ctx.project4 = { _id: 4, name: 'Find Me!' }
ctx.Project.find.withArgs({ owner_ref: ctx.userId }).returns({
exec: sinon
.stub()
.resolves([ctx.project1, ctx.project2, ctx.project3, ctx.project4]),
})
const projects = await ctx.ProjectGetter.promises.findUsersProjectsByName(
ctx.userId,
ctx.project1.name
)
const projectNames = projects.map(project => project.name)
expect(projectNames).to.have.members([
ctx.project1.name,
ctx.project3.name,
ctx.project4.name,
])
})
it('should search collaborations as well', async function (ctx) {
ctx.project1 = { _id: 1, name: 'find me!' }
ctx.project2 = { _id: 2, name: 'FIND ME!' }
ctx.project3 = { _id: 3, name: 'Find Me!' }
ctx.project4 = { _id: 4, name: 'find ME!' }
ctx.project5 = { _id: 5, name: 'FIND me!' }
ctx.Project.find
.withArgs({ owner_ref: ctx.userId })
.returns({ exec: sinon.stub().resolves([ctx.project1]) })
ctx.CollaboratorsGetter.promises.getProjectsUserIsMemberOf.resolves({
readAndWrite: [ctx.project2],
readOnly: [ctx.project3],
tokenReadAndWrite: [ctx.project4],
tokenReadOnly: [ctx.project5],
})
const projects = await ctx.ProjectGetter.promises.findUsersProjectsByName(
ctx.userId,
ctx.project1.name
)
expect(projects.map(project => project.name)).to.have.members([
ctx.project1.name,
ctx.project2.name,
])
})
})
// findUsersProjectsByName is covered by the TpdsUpdateTests acceptance
// tests ("resolving a project by name").
describe('getUsersDeletedProjects', function () {
it('should look up the deleted projects by deletedProjectOwnerId', async function (ctx) {
@@ -65,13 +65,12 @@ describe('TpdsUpdateHandler', function () {
markAsDeletedByExternalSource: sinon.stub().resolves(),
},
}
ctx.CollaboratorsGetter = {
ProjectAccess: class {},
}
ctx.ProjectGetter = {
promises: {
findUsersProjectsByName: sinon.stub(),
findAllUsersProjects: sinon.stub().resolves({
owned: Object.values(ctx.projects),
readAndWrite: [],
}),
},
}
ctx.ProjectHelper = {
@@ -105,6 +104,13 @@ describe('TpdsUpdateHandler', function () {
default: ctx.Modules,
}))
vi.doMock(
'../../../../app/src/Features/Collaborators/CollaboratorsGetter',
() => ({
default: ctx.CollaboratorsGetter,
})
)
vi.doMock(
'../../../../app/src/Features/Notifications/NotificationsBuilder',
() => ({
@@ -148,45 +154,10 @@ describe('TpdsUpdateHandler', function () {
ctx.TpdsUpdateHandler = (await import(MODULE_PATH)).default
})
// Updates, deletes and resolves by project id are covered by the
// TpdsUpdateTests acceptance tests.
describe('getting an update', function () {
describe('byId', function () {
describe('with no matching project', function () {
beforeEach(function (ctx) {
ctx.projectId = new ObjectId().toString()
})
receiveUpdateById()
expectProjectNotCreated()
expectUpdateNotProcessed()
})
describe('with one matching active project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.active1._id.toString()
})
receiveUpdateById()
expectProjectNotCreated()
expectUpdateProcessed()
})
describe('with one matching archived project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.archived1._id.toString()
})
receiveUpdateById()
expectProjectNotCreated()
expectUpdateNotProcessed()
})
describe('with one matching trashed project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.trashed._id.toString()
})
receiveUpdateById()
expectProjectNotCreated()
expectUpdateNotProcessed()
})
})
describe('with no matching project', function () {
setupMatchingProjects([])
receiveUpdate()
@@ -246,44 +217,6 @@ describe('TpdsUpdateHandler', function () {
})
describe('getting a file delete', function () {
describe('byId', function () {
describe('with no matching project', function () {
beforeEach(function (ctx) {
ctx.projectId = new ObjectId().toString()
})
receiveFileDeleteById()
expectDeleteNotProcessed()
expectProjectNotDeleted()
})
describe('with one matching active project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.active1._id.toString()
})
receiveFileDeleteById()
expectDeleteProcessed()
expectProjectNotDeleted()
})
describe('with one matching archived project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.archived1._id.toString()
})
receiveFileDeleteById()
expectDeleteNotProcessed()
expectProjectNotDeleted()
})
describe('with one matching trashed project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.trashed._id.toString()
})
receiveFileDeleteById()
expectDeleteNotProcessed()
expectProjectNotDeleted()
})
})
describe('with no matching project', function () {
setupMatchingProjects([])
receiveFileDelete()
@@ -426,44 +359,6 @@ describe('TpdsUpdateHandler', function () {
})
describe('getting or creating a project', function () {
describe('byId', function () {
describe('with no matching project', function () {
beforeEach(function (ctx) {
ctx.projectId = new ObjectId().toString()
})
resolveProjectById()
expectProjectNotCreated()
expectNoProjectResolved()
})
describe('with one matching active project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.active1._id.toString()
})
resolveProjectById()
expectProjectNotCreated()
expectProjectResolved()
})
describe('with one matching archived project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.archived1._id.toString()
})
resolveProjectById()
expectProjectNotCreated()
expectNoProjectResolved()
})
describe('with one matching trashed project', function () {
beforeEach(function (ctx) {
ctx.projectId = ctx.projects.trashed._id.toString()
})
resolveProjectById()
expectProjectNotCreated()
expectNoProjectResolved()
})
})
describe('with no matching project', function () {
setupMatchingProjects([])
resolveProjectByName()
@@ -530,19 +425,6 @@ function receiveUpdate() {
})
}
function receiveUpdateById() {
beforeEach(async function (ctx) {
await ctx.TpdsUpdateHandler.promises.newUpdate(
ctx.userId,
ctx.projectId,
'', // projectName
ctx.path,
ctx.update,
ctx.source
)
})
}
function receiveFileDelete() {
beforeEach(async function (ctx) {
await ctx.TpdsUpdateHandler.promises.deleteUpdate(
@@ -555,18 +437,6 @@ function receiveFileDelete() {
})
}
function receiveFileDeleteById() {
beforeEach(async function (ctx) {
await ctx.TpdsUpdateHandler.promises.deleteUpdate(
ctx.userId,
ctx.projectId,
'', // projectName
ctx.path,
ctx.source
)
})
}
function receiveProjectDelete() {
beforeEach(async function (ctx) {
await ctx.TpdsUpdateHandler.promises.deleteUpdate(
@@ -601,17 +471,6 @@ function resolveProjectByName() {
})
}
function resolveProjectById() {
beforeEach(async function (ctx) {
ctx.resolvedProject =
await ctx.TpdsUpdateHandler.promises.getOrCreateProject(
ctx.userId,
ctx.projectId,
'' // projectName
)
})
}
/* Expectations */
function expectProjectCreated() {