Files
speckle-server/packages/server/modules/workspaces/tests/unit/services/join.spec.ts
T
Gergő Jedlicska da7f0dda0e gergo/web 2047 user joins the workspace event (#3412)
* feat(gatekeeper): add gatekeeper module feature flag

* feat(gatekeeper): add workspace pricing table domain

* feat(gatekeeper): add checkout session creation

* feat(gatekeeper): verify stripe signature

* wip(gatekeeper): checkout callbacks

* feat(gatekeeper): add unlimited and academia plan types

* refactor(envHelper): getStringFromEnv helper

* chore(gatekeeper): add future todos

* feat(gatekeeper): add productId to the subscription domain

* feat(gatekeeper): add in memory repositories

* feat(gatekeeper): add more errors

* feat(gatekeeper): complete checkout session service

* feat(gatekeeper): add stripe client implementation

* feat(gatekeeper): add checkout session completion webhook callback path

* feat(gendo): fix not needing env vars if gendo module is not enabled

* feat(gatekeeper): require a license for billing

* chore(gatekeeper): cleanup before testing

* feat(gatekeeper): subscriptionData parsing model

* ci: add billing integration and gatekeeper modules to test config

* test(gatekeeper): add checkout service tests

* feat(gatekeeper): make completeCheckout callback idempotent properly

* feat(gatekeeper): move to knex based repositories

* test(gatekeeper): billing repository tests

* feat(gatekeeper): add yearly billing cycle toggle

* feat(ci): add stripe integration context to test job

* feat(billingPage): conditionally render the checkout CTAs

* fix(gatekeeper): remove flaky test condition

* feat(helm): add billing integration feature flag

* WIP billing gql api

* feat(gatekeeper): cancel checkout session api

* feat(gatekeeper): handle existing checkout sessions, when trying to create a new one

* feat(gatekeeper): add workspace plans gql api

* feat(gatekeeper): handle cancelation and subscription updates

* fix(gatekeeper): scope initialization

* fix(gatekeeper): eliminate stripe client import sideeffect

* fix(gatekeeper): eliminate stripe client import sideeffect 2

* feat(gatekeeper): upsize subscription on workspace role change

* feat(shared): add command pattern implementation

* refactor(eventBus): remove return capabilities from the event bus

* refactor(workspaces): use new commandFactory in workspace resolver

* feat(core): facelift taskLock

* feat(gatekeeper): shedule subscription downscale

* feat(gatekeeper): manage subscription downscale

* feat(gatekeeper): get workspace subscriptions, that are about to expire

* feat(gatekeeper): manage subscription downscale

* fix(gatekeeper): do not update subscription to canceled subs

* ci: bump postgres and max connections

* feat(workspaces): fix command factory event bugs
2024-10-30 15:51:40 +01:00

139 lines
5.1 KiB
TypeScript

import { UserEmail } from '@/modules/core/domain/userEmails/types'
import { createRandomPassword } from '@/modules/core/helpers/testHelpers'
import {
WorkspaceJoinNotAllowedError,
WorkspaceNotDiscoverableError,
WorkspaceNotJoinableError
} from '@/modules/workspaces/errors/workspace'
import { joinWorkspaceFactory } from '@/modules/workspaces/services/join'
import { WorkspaceEvents } from '@/modules/workspacesCore/domain/events'
import {
WorkspaceAcl,
WorkspaceDomain,
WorkspaceWithDomains
} from '@/modules/workspacesCore/domain/types'
import { expectToThrow } from '@/test/assertionHelper'
import { Roles } from '@speckle/shared'
import { expect } from 'chai'
import { assign } from 'lodash'
const createTestWorkspaceWithDomains = (
arg?: Partial<WorkspaceWithDomains> | undefined
): WorkspaceWithDomains => {
const workspace: WorkspaceWithDomains = {
createdAt: new Date(),
updatedAt: new Date(),
name: createRandomPassword(),
slug: createRandomPassword(),
description: createRandomPassword(),
id: createRandomPassword(),
logo: null,
domains: [],
discoverabilityEnabled: false,
domainBasedMembershipProtectionEnabled: false,
defaultProjectRole: Roles.Stream.Contributor,
defaultLogoIndex: 0
}
if (arg) assign(workspace, arg)
return workspace
}
describe('Workspace join services', () => {
describe('joinWorkspaceFactory returns a function, that', () => {
it('throws an error if the workspace is not discoverable', async () => {
const userId = createRandomPassword()
const workspaceId = createRandomPassword()
const error = await expectToThrow(async () => {
await joinWorkspaceFactory({
getUserEmails: async () => [],
getWorkspaceWithDomains: async () => {
return createTestWorkspaceWithDomains()
},
upsertWorkspaceRole: async () => {
expect.fail()
},
emitWorkspaceEvent: async () => {
expect.fail()
}
})({ userId, workspaceId })
})
expect(error.message).to.be.equal(new WorkspaceNotDiscoverableError().message)
})
it('throws an error if the workspace has no verified domains', async () => {
const userId = createRandomPassword()
const workspaceId = createRandomPassword()
const error = await expectToThrow(async () => {
await joinWorkspaceFactory({
getUserEmails: async () => [],
getWorkspaceWithDomains: async () => {
return createTestWorkspaceWithDomains({
discoverabilityEnabled: true,
domains: [{ domain: 'example.com', verified: false }] as WorkspaceDomain[]
})
},
upsertWorkspaceRole: async () => {
expect.fail()
},
emitWorkspaceEvent: async () => {
expect.fail()
}
})({ userId, workspaceId })
})
expect(error.message).to.be.equal(new WorkspaceNotJoinableError().message)
})
it('throws an error if the user has no verified email matching the domains', async () => {
const userId = createRandomPassword()
const workspaceId = createRandomPassword()
const error = await expectToThrow(async () => {
await joinWorkspaceFactory({
getUserEmails: async () =>
[{ email: 'test@example.com', verified: false }] as UserEmail[],
getWorkspaceWithDomains: async () => {
return createTestWorkspaceWithDomains({
discoverabilityEnabled: true,
domains: [{ domain: 'example.com', verified: true }] as WorkspaceDomain[]
})
},
upsertWorkspaceRole: async () => {
expect.fail()
},
emitWorkspaceEvent: async () => {
expect.fail()
}
})({ userId, workspaceId })
})
expect(error.message).to.be.equal(new WorkspaceJoinNotAllowedError().message)
})
it('creates a workspace member role and emits workspace events', async () => {
const userId = createRandomPassword()
const workspaceId = createRandomPassword()
let storedWorkspaceRole: WorkspaceAcl | undefined = undefined
const firedEvents: string[] = []
await joinWorkspaceFactory({
getUserEmails: async () =>
[{ email: 'test@example.com', verified: true }] as UserEmail[],
getWorkspaceWithDomains: async () => {
return createTestWorkspaceWithDomains({
discoverabilityEnabled: true,
domains: [{ domain: 'example.com', verified: true }] as WorkspaceDomain[]
})
},
upsertWorkspaceRole: async (workspaceRole) => {
storedWorkspaceRole = workspaceRole
},
emitWorkspaceEvent: async ({ eventName }) => {
firedEvents.push(eventName)
}
})({ userId, workspaceId })
expect(storedWorkspaceRole!.userId).to.equal(userId)
expect(storedWorkspaceRole!.workspaceId).to.equal(workspaceId)
expect(storedWorkspaceRole!.role).to.equal(Roles.Workspace.Member)
expect(firedEvents).deep.equal([
WorkspaceEvents.JoinedFromDiscovery,
WorkspaceEvents.RoleUpdated
])
})
})
})