diff --git a/packages/server/assets/workspacesCore/typedefs/workspaces.graphql b/packages/server/assets/workspacesCore/typedefs/workspaces.graphql index a7f4591d6..79ed58eba 100644 --- a/packages/server/assets/workspacesCore/typedefs/workspaces.graphql +++ b/packages/server/assets/workspacesCore/typedefs/workspaces.graphql @@ -605,6 +605,7 @@ extend type AdminQueries { input UserWorkspacesFilter { search: String + completed: Boolean } extend type Project { diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index e84941aea..3be59d664 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -4233,6 +4233,7 @@ export type UserUpdateInput = { }; export type UserWorkspacesFilter = { + completed?: InputMaybe; search?: InputMaybe; }; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index e1928c1bb..dac9da741 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -4213,6 +4213,7 @@ export type UserUpdateInput = { }; export type UserWorkspacesFilter = { + completed?: InputMaybe; search?: InputMaybe; }; diff --git a/packages/server/modules/workspaces/domain/operations.ts b/packages/server/modules/workspaces/domain/operations.ts index 36f96bdae..97bbbddba 100644 --- a/packages/server/modules/workspaces/domain/operations.ts +++ b/packages/server/modules/workspaces/domain/operations.ts @@ -65,6 +65,8 @@ export type GetWorkspaceBySlugOrId = (args: { export type GetWorkspaces = (args: { workspaceIds?: string[] userId?: string + search?: string + completed?: boolean }) => Promise export type GetAllWorkspaces = (args: { diff --git a/packages/server/modules/workspaces/graph/resolvers/workspaces.ts b/packages/server/modules/workspaces/graph/resolvers/workspaces.ts index 5c683eb34..855936608 100644 --- a/packages/server/modules/workspaces/graph/resolvers/workspaces.ts +++ b/packages/server/modules/workspaces/graph/resolvers/workspaces.ts @@ -59,7 +59,6 @@ import { getWorkspaceCollaboratorsFactory, getWorkspaceFactory, getWorkspaceRolesFactory, - getWorkspaceRolesForUserFactory, upsertWorkspaceFactory, upsertWorkspaceRoleFactory, getWorkspaceCollaboratorsTotalCountFactory, @@ -76,7 +75,9 @@ import { queryWorkspacesFactory, countWorkspacesFactory, countWorkspaceRoleWithOptionalProjectRoleFactory, - getPaginatedWorkspaceProjectsFactory + getPaginatedWorkspaceProjectsFactory, + getWorkspaceRolesForUserFactory, + getWorkspacesFactory } from '@/modules/workspaces/repositories/workspaces' import { buildWorkspaceInviteEmailContentsFactory, @@ -1846,18 +1847,20 @@ export = FF_WORKSPACES_MODULE_ENABLED return await listExpiredSsoSessions({ userId: context.userId }) }, - workspaces: async (_parent, _args, context) => { + workspaces: async (_parent, args, context) => { if (!context.userId) { throw new WorkspacesNotAuthorizedError() } const getWorkspaces = getWorkspacesForUserFactory({ - getWorkspace: getWorkspaceFactory({ db }), + getWorkspaces: getWorkspacesFactory({ db }), getWorkspaceRolesForUser: getWorkspaceRolesForUserFactory({ db }) }) const workspaces = await getWorkspaces({ - userId: context.userId + userId: context.userId, + search: args.filter?.search ?? undefined, + completed: args.filter?.completed ?? undefined }) // TODO: Pagination diff --git a/packages/server/modules/workspaces/repositories/workspaces.ts b/packages/server/modules/workspaces/repositories/workspaces.ts index 306d13059..8b3e912d3 100644 --- a/packages/server/modules/workspaces/repositories/workspaces.ts +++ b/packages/server/modules/workspaces/repositories/workspaces.ts @@ -52,6 +52,7 @@ import { import { WorkspaceInvalidRoleError } from '@/modules/workspaces/errors/workspace' import { WorkspaceAcl as DbWorkspaceAcl, + WorkspaceCreationState as DbWorkspaceCreationState, WorkspaceDomains, Workspaces, WorkspaceSeats @@ -149,9 +150,30 @@ const workspaceWithRoleBaseQuery = ({ export const getWorkspacesFactory = ({ db }: { db: Knex }): GetWorkspaces => - async ({ workspaceIds, userId }) => { + async ({ workspaceIds, userId, search, completed }) => { const q = workspaceWithRoleBaseQuery({ db, userId }) if (workspaceIds !== undefined) q.whereIn(Workspaces.col.id, workspaceIds) + + if (search) { + q.andWhere((builder) => { + builder + .where('name', 'ILIKE', `%${search}%`) + .orWhere('slug', 'ILIKE', `%${search}%`) + }) + } + + if (completed !== undefined) { + q.leftJoin( + DbWorkspaceCreationState.name, + Workspaces.col.id, + DbWorkspaceCreationState.col.workspaceId + ).andWhere((builder) => { + builder + .where({ [DbWorkspaceCreationState.col.completed]: completed }) + .orWhere({ [DbWorkspaceCreationState.col.completed]: null }) + }) + } + const results = await q return results } diff --git a/packages/server/modules/workspaces/services/retrieval.ts b/packages/server/modules/workspaces/services/retrieval.ts index da0a48bd5..a7546bc7c 100644 --- a/packages/server/modules/workspaces/services/retrieval.ts +++ b/packages/server/modules/workspaces/services/retrieval.ts @@ -1,11 +1,10 @@ import { FindEmailsByUserId } from '@/modules/core/domain/userEmails/operations' import { GetUserDiscoverableWorkspaces, - GetWorkspace, - GetWorkspaceRolesForUser + GetWorkspaceRolesForUser, + GetWorkspaces } from '@/modules/workspaces/domain/operations' import { Workspace } from '@/modules/workspacesCore/domain/types' -import { chunk, isNull } from 'lodash' type GetDiscoverableWorkspaceForUserArgs = { userId: string @@ -38,32 +37,29 @@ export const getDiscoverableWorkspacesForUserFactory = type GetWorkspacesForUserArgs = { userId: string + completed?: boolean + search?: string } export const getWorkspacesForUserFactory = ({ - getWorkspace, + getWorkspaces, getWorkspaceRolesForUser }: { - getWorkspace: GetWorkspace + getWorkspaces: GetWorkspaces getWorkspaceRolesForUser: GetWorkspaceRolesForUser }) => - async ({ userId }: GetWorkspacesForUserArgs): Promise => { + async ({ + userId, + completed, + search + }: GetWorkspacesForUserArgs): Promise => { const workspaceRoles = await getWorkspaceRolesForUser({ userId }) - const workspaces: Workspace[] = [] - - for (const workspaceRoleBatch of chunk(workspaceRoles, 20)) { - // TODO: Use `getWorkspaces`, which I saw Fabians already wrote in another PR - const workspacesBatch = await Promise.all( - workspaceRoleBatch.map(({ workspaceId }) => getWorkspace({ workspaceId })) - ) - workspaces.push( - ...workspacesBatch.filter( - (workspace): workspace is Workspace => !isNull(workspace) - ) - ) - } + const workspaceIds = workspaceRoles.map((workspace) => { + return workspace.workspaceId + }) + const workspaces = await getWorkspaces({ workspaceIds, completed, search }) return workspaces } diff --git a/packages/server/modules/workspaces/tests/helpers/creation.ts b/packages/server/modules/workspaces/tests/helpers/creation.ts index 529c3ecf3..e11078445 100644 --- a/packages/server/modules/workspaces/tests/helpers/creation.ts +++ b/packages/server/modules/workspaces/tests/helpers/creation.ts @@ -26,7 +26,8 @@ import { getWorkspaceDomainsFactory, storeWorkspaceDomainFactory, getWorkspaceBySlugFactory, - getWorkspaceRoleForUserFactory + getWorkspaceRoleForUserFactory, + upsertWorkspaceCreationStateFactory } from '@/modules/workspaces/repositories/workspaces' import { buildWorkspaceInviteEmailContentsFactory, @@ -107,7 +108,7 @@ import { getWorkspaceSeatTypeToProjectRoleMappingFactory, validateWorkspaceMemberProjectRoleFactory } from '@/modules/workspaces/services/projects' -import { isBoolean, isString } from 'lodash' +import { assign, isBoolean, isString } from 'lodash' import { captureCreatedInvite } from '@/test/speckle-helpers/inviteHelper' import { finalizeInvitedServerRegistrationFactory, @@ -127,6 +128,8 @@ import { validateStreamAccessFactory } from '@/modules/core/services/streams/access' import { authorizeResolver } from '@/modules/shared' +import { createRandomString } from '@/modules/core/helpers/testHelpers' +import { WorkspaceCreationState } from '@/modules/workspaces/domain/types' const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags() @@ -159,9 +162,16 @@ export const createTestWorkspace = async ( addPlan?: Partial> | boolean | WorkspacePlans addSubscription?: boolean regionKey?: string + addCreationState?: Pick } ) => { - const { domain, addPlan = true, regionKey, addSubscription } = options || {} + const { + domain, + addPlan = true, + regionKey, + addSubscription, + addCreationState + } = options || {} const useRegion = isMultiRegionTestMode() && regionKey if (!FF_WORKSPACES_MODULE_ENABLED) { @@ -295,6 +305,17 @@ export const createTestWorkspace = async ( }) } + if (addCreationState) { + const upsertWorkspaceState = upsertWorkspaceCreationStateFactory({ db }) + await upsertWorkspaceState({ + workspaceCreationState: { + workspaceId: newWorkspace.id, + state: addCreationState.state, + completed: addCreationState.completed + } + }) + } + const updateWorkspace = updateWorkspaceFactory({ validateSlug: validateSlugFactory({ getWorkspaceBySlug: getWorkspaceBySlugFactory({ db }) @@ -325,6 +346,19 @@ export const createTestWorkspace = async ( } } +export const buildBasicTestWorkspace = ( + overrides?: Partial +): BasicTestWorkspace => + assign( + { + id: createRandomString(), + name: createRandomString(), + slug: createRandomString(), + ownerId: '' + }, + overrides + ) + export const assignToWorkspace = async ( workspace: BasicTestWorkspace, user: BasicTestUser, diff --git a/packages/server/modules/workspaces/tests/integration/repositories.spec.ts b/packages/server/modules/workspaces/tests/integration/repositories.spec.ts index d6fadbca7..4b3536ac2 100644 --- a/packages/server/modules/workspaces/tests/integration/repositories.spec.ts +++ b/packages/server/modules/workspaces/tests/integration/repositories.spec.ts @@ -12,17 +12,24 @@ import { getWorkspaceWithDomainsFactory, countWorkspaceRoleWithOptionalProjectRoleFactory, getWorkspaceCollaboratorsFactory, - getWorkspaceBySlugFactory + getWorkspaceBySlugFactory, + getWorkspacesFactory } from '@/modules/workspaces/repositories/workspaces' import db from '@/db/knex' import cryptoRandomString from 'crypto-random-string' import { expect } from 'chai' import { Workspace, WorkspaceAcl } from '@/modules/workspacesCore/domain/types' import { expectToThrow } from '@/test/assertionHelper' -import { BasicTestUser, createTestUser, createTestUsers } from '@/test/authHelper' +import { + BasicTestUser, + buildBasicTestUser, + createTestUser, + createTestUsers +} from '@/test/authHelper' import { BasicTestWorkspace, assignToWorkspace, + buildBasicTestWorkspace, createTestWorkspace } from '@/modules/workspaces/tests/helpers/creation' import { @@ -46,6 +53,7 @@ import { createAndStoreTestWorkspaceFactory } from '@/test/speckle-helpers/works import { WorkspaceJoinRequests } from '@/modules/workspacesCore/helpers/db' const getWorkspace = getWorkspaceFactory({ db }) +const getWorkspaces = getWorkspacesFactory({ db }) const getWorkspaceBySlug = getWorkspaceBySlugFactory({ db }) const getWorkspaceCollaborators = getWorkspaceCollaboratorsFactory({ db }) const deleteWorkspace = deleteWorkspaceFactory({ db }) @@ -84,6 +92,23 @@ const createAndStoreTestUser = async (): Promise => { describe('Workspace repositories', () => { describe('getWorkspaceFactory creates a function, that', () => { + const testUserA = buildBasicTestUser() + const workspaceA1 = buildBasicTestWorkspace({ name: 'My House Workspace' }) + const workspaceA2 = buildBasicTestWorkspace({ name: 'My Garage Workspace' }) + + before(async () => { + const testUserB = buildBasicTestUser() + await createTestUsers([testUserA, testUserB]) + + const workspaceB = buildBasicTestWorkspace() + await createTestWorkspace(workspaceB, testUserB) + + await createTestWorkspace(workspaceA1, testUserA, { + addCreationState: { completed: true, state: {} } + }) + await createTestWorkspace(workspaceA2, testUserA) + }) + it('returns null if the workspace is not found', async () => { const workspace = await getWorkspace({ workspaceId: cryptoRandomString({ length: 10 }) @@ -91,6 +116,61 @@ describe('Workspace repositories', () => { expect(workspace).to.be.null }) // not testing get here, we're going to use that for testing upsert + + describe('getWorkspaces filters', () => { + it('is able to select them by name', async () => { + const workspaces = await getWorkspaces({ + userId: testUserA.id, + workspaceIds: [workspaceA1.id], + search: 'house' + }) + + expect(workspaces).to.have.lengthOf(1) + expect(workspaces[0].id).to.eq(workspaceA1.id) + }) + + it('is able to filter them out by name', async () => { + const workspaces = await getWorkspaces({ + userId: testUserA.id, + workspaceIds: [workspaceA1.id], + search: 'park' + }) + + expect(workspaces).to.have.lengthOf(0) + }) + + it('is able to filer them by completed status', async () => { + const workspaces = await getWorkspaces({ + userId: testUserA.id, + workspaceIds: [workspaceA1.id], + completed: true + }) + + expect(workspaces).to.have.lengthOf(1) + expect(workspaces[0].id).to.eq(workspaceA1.id) + }) + + it('is able to filer them out by completed status', async () => { + const workspaces = await getWorkspaces({ + userId: testUserA.id, + workspaceIds: [workspaceA1.id], + completed: false + }) + + expect(workspaces).to.have.lengthOf(0) + }) + + it('does not filter when there is no workspace_completed entry as safety mechanism', async () => { + const workspaces = await getWorkspaces({ + userId: testUserA.id, + workspaceIds: [workspaceA2.id], + completed: false + }) + + expect(workspaces).to.have.lengthOf(1) + expect(workspaces[0].id).to.eq(workspaceA2.id) + }) + }) }) describe('getWorkspaceBySlugFactory creates a function, that', () => { diff --git a/packages/server/modules/workspaces/tests/integration/workspaces.graph.spec.ts b/packages/server/modules/workspaces/tests/integration/workspaces.graph.spec.ts index 50a60c6c2..88bcd7914 100644 --- a/packages/server/modules/workspaces/tests/integration/workspaces.graph.spec.ts +++ b/packages/server/modules/workspaces/tests/integration/workspaces.graph.spec.ts @@ -7,6 +7,7 @@ import { } from '@/test/graphqlHelper' import { BasicTestUser, + buildBasicTestUser, createAuthTokenForUser, createTestUser, createTestUsers, @@ -35,11 +36,12 @@ import { WorkspaceEmbedOptionsDocument, ProjectEmbedOptionsDocument } from '@/test/graphql/generated/graphql' -import { beforeEachContext } from '@/test/hooks' +import { beforeEachContext, truncateTables } from '@/test/hooks' import { AllScopes } from '@/modules/core/helpers/mainConstants' import { assignToWorkspace, BasicTestWorkspace, + buildBasicTestWorkspace, createTestWorkspace, createWorkspaceInviteDirectly } from '@/modules/workspaces/tests/helpers/creation' @@ -76,6 +78,7 @@ import { itEach } from '@/test/assertionHelper' import { assignWorkspaceSeatFactory } from '@/modules/workspaces/services/workspaceSeat' import { createWorkspaceSeatFactory } from '@/modules/gatekeeper/repositories/workspaceSeat' import { WorkspaceSeatType } from '@/modules/gatekeeper/domain/billing' +import { Workspaces } from '@/modules/workspaces/helpers/db' const grantStreamPermissions = grantStreamPermissionsFactory({ db }) const validateAndCreateUserEmail = validateAndCreateUserEmailFactory({ @@ -700,16 +703,26 @@ describe('Workspaces GQL CRUD', () => { }) describe('query activeUser.workspaces', () => { - it('should return all workspaces for a user', async () => { - const testUser: BasicTestUser = { - id: '', - name: 'John Speckle', - email: 'foobar@example.org', - role: Roles.Server.Admin, - verified: true - } + const testUser = buildBasicTestUser({ role: Roles.Server.Admin }) + + before(async () => { + await truncateTables([Workspaces.name]) await createTestUser(testUser) + + await createTestWorkspace(buildBasicTestWorkspace(), testUser) + await createTestWorkspace( + buildBasicTestWorkspace({ + name: 'A loooooooooong name' + }), + testUser + ) + await createTestWorkspace(buildBasicTestWorkspace(), testUser, { + addCreationState: { completed: false, state: {} } + }) + }) + + it('should return all workspaces for a user', async () => { const testApollo: TestApolloServer = await testApolloServer({ context: await createTestContext({ auth: true, @@ -720,36 +733,53 @@ describe('Workspaces GQL CRUD', () => { }) }) - const workspace1: BasicTestWorkspace = { - id: '', - ownerId: '', - name: 'Workspace A', - slug: cryptoRandomString({ length: 10 }) - } - - const workspace2: BasicTestWorkspace = { - id: '', - ownerId: '', - name: 'Workspace A', - slug: cryptoRandomString({ length: 10 }) - } - - const workspace3: BasicTestWorkspace = { - id: '', - ownerId: '', - name: 'Workspace A', - slug: cryptoRandomString({ length: 10 }) - } - - await createTestWorkspace(workspace1, testUser) - await createTestWorkspace(workspace2, testUser) - await createTestWorkspace(workspace3, testUser) - const res = await testApollo.execute(GetActiveUserWorkspacesDocument, {}) expect(res).to.not.haveGraphQLErrors() - // TODO: this test depends on the previous tests + expect(res.data?.activeUser?.workspaces?.items?.length).to.equal(3) }) + + it('omits non complete workspaces on request', async () => { + const testApollo: TestApolloServer = await testApolloServer({ + context: await createTestContext({ + auth: true, + userId: testUser.id, + token: '', + role: testUser.role, + scopes: AllScopes + }) + }) + + const res = await testApollo.execute(GetActiveUserWorkspacesDocument, { + filter: { + completed: true + } + }) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.activeUser?.workspaces?.items?.length).to.equal(2) + }) + + it('filters by name workspaces on request', async () => { + const testApollo: TestApolloServer = await testApolloServer({ + context: await createTestContext({ + auth: true, + userId: testUser.id, + token: '', + role: testUser.role, + scopes: AllScopes + }) + }) + + const res = await testApollo.execute(GetActiveUserWorkspacesDocument, { + filter: { + search: 'loooooooooong' + } + }) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.activeUser?.workspaces?.items?.length).to.equal(1) + }) }) describe('query workspace.projects', () => { diff --git a/packages/server/modules/workspacesCore/helpers/db.ts b/packages/server/modules/workspacesCore/helpers/db.ts index 0c83e5ceb..ad002c663 100644 --- a/packages/server/modules/workspacesCore/helpers/db.ts +++ b/packages/server/modules/workspacesCore/helpers/db.ts @@ -30,6 +30,12 @@ export const WorkspaceDomains = buildTableHelper('workspace_domains', [ 'verified' ]) +export const WorkspaceCreationState = buildTableHelper('workspace_creation_state', [ + 'workspaceId', + 'completed', + 'state' +]) + export const WorkspaceJoinRequests = buildTableHelper('workspace_join_requests', [ 'workspaceId', 'userId', diff --git a/packages/server/test/authHelper.ts b/packages/server/test/authHelper.ts index c4ae62e90..8fe3a3a0d 100644 --- a/packages/server/test/authHelper.ts +++ b/packages/server/test/authHelper.ts @@ -1,6 +1,9 @@ import { db } from '@/db/knex' import { AllScopes, ServerRoles } from '@/modules/core/helpers/mainConstants' -import { createRandomEmail } from '@/modules/core/helpers/testHelpers' +import { + createRandomString, + createRandomEmail +} from '@/modules/core/helpers/testHelpers' import { UserRecord } from '@/modules/core/helpers/types' import { getServerInfoFactory } from '@/modules/core/repositories/server' import { @@ -37,7 +40,7 @@ import { createTestContext, testApolloServer } from '@/test/graphqlHelper' import { faker } from '@faker-js/faker' import { ServerScope, wait } from '@speckle/shared' import cryptoRandomString from 'crypto-random-string' -import { isArray, isNumber, omit, times } from 'lodash' +import { assign, isArray, isNumber, omit, times } from 'lodash' const getServerInfo = getServerInfoFactory({ db }) const findEmail = findEmailFactory({ db }) @@ -153,6 +156,17 @@ export type CreateTestUsersParams = { serial?: boolean } +export const buildBasicTestUser = (overrides?: Partial): BasicTestUser => + assign( + { + id: createRandomString(), + name: createRandomString(), + email: createRandomEmail(), + verified: true + }, + overrides + ) + /** * Create multiple users for tests and update them to include their ID */ diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 951a92b4e..005e66cd3 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -4214,6 +4214,7 @@ export type UserUpdateInput = { }; export type UserWorkspacesFilter = { + completed?: InputMaybe; search?: InputMaybe; }; @@ -6228,7 +6229,9 @@ export type UpdateWorkspaceMutationVariables = Exact<{ export type UpdateWorkspaceMutation = { __typename?: 'Mutation', workspaceMutations: { __typename?: 'WorkspaceMutations', update: { __typename?: 'Workspace', id: string, name: string, slug: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, readOnly: boolean, discoverabilityEnabled: boolean, role?: string | null } } }; -export type GetActiveUserWorkspacesQueryVariables = Exact<{ [key: string]: never; }>; +export type GetActiveUserWorkspacesQueryVariables = Exact<{ + filter?: InputMaybe; +}>; export type GetActiveUserWorkspacesQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', workspaces: { __typename?: 'WorkspaceCollection', items: Array<{ __typename?: 'Workspace', id: string, name: string, slug: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, readOnly: boolean, discoverabilityEnabled: boolean, role?: string | null }> } } | null }; @@ -6492,7 +6495,7 @@ export const GetWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"O export const GetWorkspaceBySlugDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaceBySlug"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceSlug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceBySlug"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceSlug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspace"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspaceCollaborator"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"discoverabilityEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"projectRoles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; export const GetActiveUserDiscoverableWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"getActiveUserDiscoverableWorkspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"discoverableWorkspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const UpdateWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceUpdateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"discoverabilityEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]} as unknown as DocumentNode; -export const GetActiveUserWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetActiveUserWorkspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspace"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"discoverabilityEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]} as unknown as DocumentNode; +export const GetActiveUserWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetActiveUserWorkspaces"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkspacesFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspace"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"discoverabilityEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]} as unknown as DocumentNode; export const UpdateWorkspaceRoleDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateWorkspaceRole"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceRoleUpdateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateRole"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspaceCollaborator"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"projectRoles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateWorkspaceProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateWorkspaceProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceProjectCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspaceProject"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspaceProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]} as unknown as DocumentNode; export const GetWorkspaceProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaceProjects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceProjectsFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TestWorkspaceProject"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestWorkspaceProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/server/test/graphql/workspaces.ts b/packages/server/test/graphql/workspaces.ts index 1c381e68a..ddf01d970 100644 --- a/packages/server/test/graphql/workspaces.ts +++ b/packages/server/test/graphql/workspaces.ts @@ -128,9 +128,9 @@ export const updateWorkspaceQuery = gql` ` export const getActiveUserWorkspacesQuery = gql` - query GetActiveUserWorkspaces { + query GetActiveUserWorkspaces($filter: UserWorkspacesFilter) { activeUser { - workspaces { + workspaces(filter: $filter) { items { ...TestWorkspace }