6a1b28bc12
## What & why A single, consistent **workspace-creation step** for both multi-workspace and single-workspace self-host — collecting **name + logo** (and the **subdomain** in multi-workspace) — which **removes the duplicate name/logo prompt** that previously reappeared on the workspace subdomain (reported after #21641). ## Changes **One creation form for both modes** - With 0 workspaces, both multi-workspace and single-workspace route to the shared `SignInUpWorkspaceCreationForm`; `SignInUp` renders it for the `WorkspaceCreation` step regardless of domain/scope. - The subdomain field shows only in multi-workspace; single-workspace keeps its fixed address. **Logo on the creation step** - New scoped `uploadNewWorkspaceLogo(workspaceId, file)` mutation: the creator sets a logo on their just-created `PENDING_CREATION` workspace via the workspace-agnostic token (membership enforced — only the creator is a member at that point), reusing `uploadWorkspacePicture`. Upload size is capped via `settings.storage.maxFileSize` (also applied to the existing logo / profile-picture uploads). - The picked file is held locally (object-URL preview, revoked on unmount) and uploaded right after creation (non-fatal on failure). **Onboarding step → pure activation loader** - The old "Create your workspace" form (name + logo) is removed. The onboarding step now activates the pending workspace on mount and shows the loader, with a **Retry** action on failure. ## Testing - typecheck (front + server) ✅; oxlint + oxfmt clean on changed files ✅ - Unit tests: `auth.resolver.spec`, `useWorkspaceSubdomainField`, `SignInUpWorkspaceCreationForm` (multi + single-workspace), `useAuth` ✅ - Metadata GraphQL + `twenty-client-sdk` schema regenerated. Follow-up to #21641. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Xw37hR5seiCyWnppG9z4op --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
import { createRequire } from 'module';
|
|
const require = createRequire(import.meta.url);
|
|
|
|
const isCI = process.env.CI === 'true';
|
|
|
|
const jestConfig = {
|
|
// For more information please have a look to official docs https://jestjs.io/docs/configuration/#prettierpath-string
|
|
// Prettier v3 should be supported in jest v30 https://github.com/jestjs/jest/releases/tag/v30.0.0-alpha.1
|
|
prettierPath: null,
|
|
// to enable logs, comment out the following line
|
|
silent: true,
|
|
...(isCI && { reporters: ['./jest-failures-only-reporter.js'] }),
|
|
errorOnDeprecated: true,
|
|
clearMocks: true,
|
|
displayName: 'twenty-server',
|
|
rootDir: './',
|
|
testEnvironment: 'node',
|
|
setupFilesAfterEnv: ['./setupTests.ts'],
|
|
transformIgnorePatterns: [
|
|
// jsdom 29 pulls ESM-only transitive deps (parse5, entities, tough-cookie,
|
|
// @exodus/bytes via html-encoding-sniffer, @csstools/@asamuzakjp css engine).
|
|
// jest's CJS runtime can't load their `export` syntax, so let swc transform them.
|
|
'/node_modules/(?!(file-type|@file-type|strtok3|token-types|@borewit|@tokenizer|uint8array-extras|read-next-line|digest-fetch|md5|js-sha256|js-sha512|base-64|charenc|crypt|email-reply-parser|jsdom|html-encoding-sniffer|whatwg-encoding|@exodus|parse5|entities|tough-cookie|@csstools|@asamuzakjp|graphql-upload|fs-capacitor)/)',
|
|
],
|
|
testRegex: '.*\\.spec\\.ts$',
|
|
transform: {
|
|
// include .mjs so swc transforms ESM-only deps (e.g. jsdom's @csstools/* .mjs)
|
|
'^.+\\.(t|j|mj)s$': [
|
|
'@swc/jest',
|
|
{
|
|
jsc: {
|
|
parser: {
|
|
syntax: 'typescript',
|
|
tsx: false,
|
|
decorators: true,
|
|
},
|
|
transform: {
|
|
decoratorMetadata: true,
|
|
},
|
|
experimental: {
|
|
plugins: [
|
|
[
|
|
'@lingui/swc-plugin',
|
|
{
|
|
stripNonEssentialFields: false,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
moduleNameMapper: {
|
|
'^src/(.*)': '<rootDir>/src/$1',
|
|
'^test/(.*)': '<rootDir>/test/$1',
|
|
'^file-type$': require.resolve('file-type'),
|
|
},
|
|
moduleFileExtensions: ['js', 'mjs', 'json', 'ts'],
|
|
modulePathIgnorePatterns: ['<rootDir>/dist'],
|
|
fakeTimers: {
|
|
enableGlobally: true,
|
|
},
|
|
collectCoverageFrom: ['**/*.(t|j)s'],
|
|
coverageDirectory: '../coverage',
|
|
};
|
|
|
|
export default jestConfig;
|