ede566eed9
* prep for new resources algo * typescriptifying stuff * minor types fix * migrate to resources col * repo & creation updated, WIP processing/retrieval * WIP invite processing * finished finalization refactor * project invite management * transformed all invites services * fixed up projects & core serverinvites resolvers * test fixes * WIP workspace create GQL & test * basic invite creation test works * a buncha working tests * more tests * cancelation tests * minor invite use refactor * invite retrieval tasks * invite use() works as expected * filtering out broken invites * enabled invite retrieval by token irregardless of who is it for * minor adjustments * tests fix * test config improvements * test env adjustment * extra test case * making resource access limits harder to ignore * linter fixes * eventBus type cleanup * better generic names * refactored serverinvites resource migration * fix(server): better error message in project invite edge case
126 lines
3.6 KiB
TypeScript
126 lines
3.6 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
import { ApolloServer } from 'apollo-server-express'
|
|
import { GraphQLResponse } from 'apollo-server-types'
|
|
import { DocumentNode } from 'graphql'
|
|
import { GraphQLContext, Nullable } from '@/modules/shared/helpers/typeHelper'
|
|
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
|
import { buildApolloServer } from '@/app'
|
|
import { addLoadersToCtx } from '@/modules/shared/middleware'
|
|
import { buildUnauthenticatedApolloServer } from '@/test/serverHelper'
|
|
import { Roles } from '@/modules/core/helpers/mainConstants'
|
|
import { AllScopes } from '@speckle/shared'
|
|
import { expect } from 'chai'
|
|
|
|
type TypedGraphqlResponse<R = Record<string, any>> = GraphQLResponse & {
|
|
data: Nullable<R>
|
|
}
|
|
|
|
/**
|
|
* Use this to execute GQL operations from tests against an Apollo instance and get
|
|
* a properly typed response
|
|
*/
|
|
export async function executeOperation<
|
|
R extends Record<string, any> = Record<string, any>,
|
|
V extends Record<string, any> = Record<string, any>
|
|
>(
|
|
apollo: ApolloServer,
|
|
query: DocumentNode,
|
|
variables?: V
|
|
): Promise<TypedGraphqlResponse<R>> {
|
|
return (await apollo.executeOperation({
|
|
query,
|
|
variables
|
|
})) as TypedGraphqlResponse<R>
|
|
}
|
|
|
|
/**
|
|
* Create a test context for a GraphQL request. Optionally override any of the default values.
|
|
* By default the context will be unauthenticated
|
|
*/
|
|
export const createTestContext = (
|
|
ctx?: Partial<Parameters<typeof addLoadersToCtx>[0]>
|
|
): GraphQLContext =>
|
|
addLoadersToCtx({
|
|
auth: false,
|
|
userId: undefined,
|
|
role: undefined,
|
|
token: undefined,
|
|
scopes: [],
|
|
stream: undefined,
|
|
err: undefined,
|
|
...(ctx || {})
|
|
})
|
|
|
|
/**
|
|
* Utilities that make it easier to test against an Apollo Server instance
|
|
*/
|
|
export const testApolloServer = async (params?: {
|
|
context?: GraphQLContext
|
|
/**
|
|
* If set, will create an authed context w/ all scopes and Server.User role for thies user id
|
|
*/
|
|
authUserId?: string
|
|
}) => {
|
|
const initialCtx: GraphQLContext | undefined = params?.authUserId
|
|
? createTestContext({
|
|
auth: true,
|
|
userId: params.authUserId,
|
|
role: Roles.Server.User,
|
|
token: 'asd',
|
|
scopes: AllScopes
|
|
})
|
|
: params?.context
|
|
|
|
const instance = initialCtx
|
|
? await buildApolloServer({
|
|
context: initialCtx
|
|
})
|
|
: await buildUnauthenticatedApolloServer()
|
|
|
|
/**
|
|
* Execute an operation against Apollo and get a properly typed response
|
|
*/
|
|
const execute = async <
|
|
R extends Record<string, any> = Record<string, any>,
|
|
V extends Record<string, any> = Record<string, any>
|
|
>(
|
|
query: TypedDocumentNode<R, V>,
|
|
variables: V,
|
|
options?: Partial<{
|
|
/**
|
|
* Optionally override the instance's context
|
|
*/
|
|
context: Parameters<typeof createTestContext>[0]
|
|
/**
|
|
* Whether to add an assertion that there were no GQL errors
|
|
*/
|
|
assertNoErrors: boolean
|
|
}>
|
|
): Promise<TypedGraphqlResponse<R>> => {
|
|
const realInstance = options?.context
|
|
? await buildApolloServer({
|
|
context: createTestContext({
|
|
...(initialCtx || {}),
|
|
...options.context
|
|
})
|
|
})
|
|
: instance
|
|
|
|
const res = (await realInstance.executeOperation({
|
|
query,
|
|
variables
|
|
})) as TypedGraphqlResponse<R>
|
|
|
|
if (options?.assertNoErrors) {
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
return { execute, server: instance }
|
|
}
|
|
|
|
export type TestApolloServer = Awaited<ReturnType<typeof testApolloServer>>
|
|
export type ExecuteOperationOptions = Parameters<TestApolloServer['execute']>[2]
|