275 lines
8.5 KiB
TypeScript
275 lines
8.5 KiB
TypeScript
import { db } from '@/db/knex'
|
|
import { AllScopes } from '@/modules/core/helpers/mainConstants'
|
|
import { grantStreamPermissionsFactory } from '@/modules/core/repositories/streams'
|
|
import {
|
|
BasicTestWorkspace,
|
|
createTestWorkspace
|
|
} from '@/modules/workspaces/tests/helpers/creation'
|
|
import {
|
|
BasicTestUser,
|
|
createAuthTokenForUser,
|
|
createTestUsers
|
|
} from '@/test/authHelper'
|
|
import {
|
|
ActiveUserProjectsWorkspaceDocument,
|
|
CreateWorkspaceProjectDocument,
|
|
GetWorkspaceProjectsDocument,
|
|
GetWorkspaceTeamDocument,
|
|
MoveProjectToWorkspaceDocument
|
|
} from '@/test/graphql/generated/graphql'
|
|
import {
|
|
createTestContext,
|
|
testApolloServer,
|
|
TestApolloServer
|
|
} from '@/test/graphqlHelper'
|
|
import { beforeEachContext } from '@/test/hooks'
|
|
import { BasicTestStream, createTestStream } from '@/test/speckle-helpers/streamHelper'
|
|
import { Roles } from '@speckle/shared'
|
|
import { expect } from 'chai'
|
|
import cryptoRandomString from 'crypto-random-string'
|
|
|
|
const grantStreamPermissions = grantStreamPermissionsFactory({ db })
|
|
|
|
describe('Workspace project GQL CRUD', () => {
|
|
let apollo: TestApolloServer
|
|
|
|
const workspace: BasicTestWorkspace = {
|
|
id: '',
|
|
ownerId: '',
|
|
slug: cryptoRandomString({ length: 10 }),
|
|
name: 'My Test Workspace'
|
|
}
|
|
|
|
const serverAdminUser: BasicTestUser = {
|
|
id: '',
|
|
name: 'John Speckle',
|
|
email: 'john-speckle-workspace-project-admin@example.org',
|
|
role: Roles.Server.Admin
|
|
}
|
|
|
|
const serverMemberUser: BasicTestUser = {
|
|
id: '',
|
|
name: 'John Nobody',
|
|
email: 'john-nobody@example.org',
|
|
role: Roles.Server.User
|
|
}
|
|
|
|
before(async () => {
|
|
await beforeEachContext()
|
|
await createTestUsers([serverAdminUser, serverMemberUser])
|
|
const token = await createAuthTokenForUser(serverAdminUser.id, AllScopes)
|
|
apollo = await testApolloServer({
|
|
context: await createTestContext({
|
|
auth: true,
|
|
userId: serverAdminUser.id,
|
|
token,
|
|
role: serverAdminUser.role,
|
|
scopes: AllScopes
|
|
})
|
|
})
|
|
|
|
await createTestWorkspace(workspace, serverAdminUser)
|
|
|
|
const workspaceProjects = [
|
|
{ name: 'Workspace Project A', workspaceId: workspace.id },
|
|
{ name: 'Workspace Project B', workspaceId: workspace.id },
|
|
{ name: 'Workspace Project C', workspaceId: workspace.id }
|
|
]
|
|
|
|
await Promise.all(
|
|
workspaceProjects.map((input) =>
|
|
apollo.execute(CreateWorkspaceProjectDocument, { input })
|
|
)
|
|
)
|
|
})
|
|
|
|
describe('when specifying a workspace id during project creation', () => {
|
|
it('should create the project in that workspace', async () => {
|
|
const projectName = cryptoRandomString({ length: 6 })
|
|
|
|
const createRes = await apollo.execute(CreateWorkspaceProjectDocument, {
|
|
input: {
|
|
name: projectName,
|
|
workspaceId: workspace.id
|
|
}
|
|
})
|
|
|
|
const getRes = await apollo.execute(GetWorkspaceProjectsDocument, {
|
|
id: workspace.id
|
|
})
|
|
|
|
const workspaceProject = getRes.data?.workspace.projects.items.find(
|
|
(project) => project.name === projectName
|
|
)
|
|
|
|
expect(createRes).to.not.haveGraphQLErrors()
|
|
expect(getRes).to.not.haveGraphQLErrors()
|
|
expect(workspaceProject).to.exist
|
|
})
|
|
})
|
|
|
|
describe('when querying workspace projects', () => {
|
|
it('should return multiple projects', async () => {
|
|
const res = await apollo.execute(GetWorkspaceProjectsDocument, {
|
|
id: workspace.id
|
|
})
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(res.data?.workspace.projects.items.length).to.be.greaterThanOrEqual(3)
|
|
})
|
|
|
|
it('should respect limits', async () => {
|
|
const res = await apollo.execute(GetWorkspaceProjectsDocument, {
|
|
id: workspace.id,
|
|
limit: 1
|
|
})
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(res.data?.workspace.projects.items.length).to.equal(1)
|
|
})
|
|
|
|
it('should respect pagination', async () => {
|
|
const resA = await apollo.execute(GetWorkspaceProjectsDocument, {
|
|
id: workspace.id,
|
|
limit: 10
|
|
})
|
|
|
|
const resB = await apollo.execute(GetWorkspaceProjectsDocument, {
|
|
id: workspace.id,
|
|
limit: 10,
|
|
cursor: resA.data?.workspace.projects.cursor
|
|
})
|
|
|
|
const projectA = resA.data?.workspace.projects.items[0]
|
|
const projectB = resB.data?.workspace.projects.items[0]
|
|
|
|
expect(resA).to.not.haveGraphQLErrors()
|
|
expect(resB).to.not.haveGraphQLErrors()
|
|
expect(projectA).to.exist
|
|
expect(projectB).to.not.exist
|
|
expect(projectA?.name).to.not.equal(projectB?.name)
|
|
})
|
|
|
|
it('should respect search filters', async () => {
|
|
const res = await apollo.execute(GetWorkspaceProjectsDocument, {
|
|
id: workspace.id,
|
|
limit: 1,
|
|
filter: {
|
|
search: 'Workspace Project B'
|
|
}
|
|
})
|
|
|
|
const project = res.data?.workspace.projects.items[0]
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(project).to.exist
|
|
expect(project?.name).to.equal('Workspace Project B')
|
|
})
|
|
|
|
it('should return workspace info on project types', async () => {
|
|
const res = await apollo.execute(ActiveUserProjectsWorkspaceDocument, {})
|
|
|
|
const projects = res.data?.activeUser?.projects.items
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(projects).to.exist
|
|
expect(projects?.every((project) => project?.workspace?.id === workspace.id)).to
|
|
.be.true
|
|
})
|
|
})
|
|
|
|
describe('when moving a project to a workspace', () => {
|
|
const testProject: BasicTestStream = {
|
|
id: '',
|
|
ownerId: '',
|
|
name: 'Test Project',
|
|
isPublic: false
|
|
}
|
|
|
|
const targetWorkspace: BasicTestWorkspace = {
|
|
id: '',
|
|
ownerId: '',
|
|
slug: cryptoRandomString({ length: 10 }),
|
|
name: 'Target Workspace'
|
|
}
|
|
|
|
before(async () => {
|
|
await createTestWorkspace(targetWorkspace, serverAdminUser)
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
await createTestStream(testProject, serverAdminUser)
|
|
await grantStreamPermissions({
|
|
streamId: testProject.id,
|
|
userId: serverMemberUser.id,
|
|
role: Roles.Stream.Contributor
|
|
})
|
|
})
|
|
|
|
it('should move the project to the target workspace', async () => {
|
|
const res = await apollo.execute(MoveProjectToWorkspaceDocument, {
|
|
projectId: testProject.id,
|
|
workspaceId: targetWorkspace.id
|
|
})
|
|
|
|
const { workspaceId } =
|
|
res.data?.workspaceMutations.projects.moveToWorkspace ?? {}
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(workspaceId).to.equal(targetWorkspace.id)
|
|
})
|
|
|
|
it('should preserve project roles for project members', async () => {
|
|
const res = await apollo.execute(MoveProjectToWorkspaceDocument, {
|
|
projectId: testProject.id,
|
|
workspaceId: targetWorkspace.id
|
|
})
|
|
|
|
const { team } = res.data?.workspaceMutations.projects.moveToWorkspace ?? {}
|
|
|
|
const adminProjectRole = team?.find((role) => role.id === serverAdminUser.id)
|
|
const memberProjectRole = team?.find((role) => role.id === serverMemberUser.id)
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(adminProjectRole?.role).to.equal(Roles.Stream.Owner)
|
|
expect(memberProjectRole?.role).to.equal(Roles.Stream.Contributor)
|
|
})
|
|
|
|
it('should grant workspace roles to project members that are not already in the target workspace', async () => {
|
|
const resA = await apollo.execute(MoveProjectToWorkspaceDocument, {
|
|
projectId: testProject.id,
|
|
workspaceId: targetWorkspace.id
|
|
})
|
|
const resB = await apollo.execute(GetWorkspaceTeamDocument, {
|
|
workspaceId: targetWorkspace.id
|
|
})
|
|
|
|
const memberWorkspaceRole = resB.data?.workspace.team.items.find(
|
|
(role) => role.id === serverMemberUser.id
|
|
)
|
|
|
|
expect(resA).to.not.haveGraphQLErrors()
|
|
expect(resB).to.not.haveGraphQLErrors()
|
|
expect(memberWorkspaceRole?.role).to.equal(Roles.Workspace.Member)
|
|
})
|
|
|
|
it('should preserve workspace roles for project members that are already in the target workspace', async () => {
|
|
const resA = await apollo.execute(MoveProjectToWorkspaceDocument, {
|
|
projectId: testProject.id,
|
|
workspaceId: targetWorkspace.id
|
|
})
|
|
const resB = await apollo.execute(GetWorkspaceTeamDocument, {
|
|
workspaceId: targetWorkspace.id
|
|
})
|
|
|
|
const adminWorkspaceRole = resB.data?.workspace.team.items.find(
|
|
(role) => role.id === serverAdminUser.id
|
|
)
|
|
|
|
expect(resA).to.not.haveGraphQLErrors()
|
|
expect(resB).to.not.haveGraphQLErrors()
|
|
expect(adminWorkspaceRole?.role).to.equal(Roles.Workspace.Admin)
|
|
})
|
|
})
|
|
})
|