Add tests for CoreApiClient stub issue (PR #18460) with clean tsconfig fix
Exclude test app src/ directories from SDK tsconfig.json instead of using a .d.ts hack. These directories contain standalone app code (with their own tsconfig.json) that should not be typechecked as SDK root files. - Exclude src/app-seeds/*/src/** and src/cli/__tests__/apps/*/src/** - Add check-core-client logic function that verifies CoreApiClient - Add E2E test asserting CoreApiClient has real query/mutation methods - Add app-build integration test documenting current stub behavior Made-with: Cursor
This commit is contained in:
+67
@@ -0,0 +1,67 @@
|
||||
import { readdir, rm } from 'node:fs/promises';
|
||||
import { join } from 'path';
|
||||
|
||||
import { appBuild } from '@/cli/public-operations/app-build';
|
||||
import { pathExists } from '@/cli/utilities/file/fs-utils';
|
||||
import { GENERATED_DIR, OUTPUT_DIR } from 'twenty-shared/application';
|
||||
|
||||
const APP_PATH = join(__dirname, '../..');
|
||||
|
||||
describe('rich-app app:build', () => {
|
||||
let buildResult: Awaited<ReturnType<typeof appBuild>>;
|
||||
|
||||
beforeAll(async () => {
|
||||
const generatedPath = join(
|
||||
APP_PATH,
|
||||
'node_modules',
|
||||
'twenty-sdk',
|
||||
GENERATED_DIR,
|
||||
);
|
||||
|
||||
await rm(generatedPath, { recursive: true, force: true });
|
||||
|
||||
buildResult = await appBuild({ appPath: APP_PATH });
|
||||
}, 60_000);
|
||||
|
||||
it('should complete build successfully', () => {
|
||||
expect(buildResult.success).toBe(true);
|
||||
});
|
||||
|
||||
it('should produce manifest in output directory', async () => {
|
||||
const manifestPath = join(APP_PATH, OUTPUT_DIR, 'manifest.json');
|
||||
|
||||
expect(await pathExists(manifestPath)).toBe(true);
|
||||
});
|
||||
|
||||
it('should produce built logic function files', async () => {
|
||||
const outputDir = join(APP_PATH, OUTPUT_DIR);
|
||||
const files = await readdir(outputDir, { recursive: true });
|
||||
const functionFiles = files
|
||||
.map((file) => file.toString())
|
||||
.filter((file) => file.endsWith('.function.mjs'))
|
||||
.sort();
|
||||
|
||||
expect(functionFiles.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// app:build only creates client stubs (empty CoreApiClient / MetadataApiClient)
|
||||
// because it doesn't sync with the server or generate the real API client.
|
||||
// Logic functions that use CoreApiClient will get an empty class at runtime.
|
||||
// When this is fixed, update this test to assert the client IS fully generated.
|
||||
// See: https://github.com/twentyhq/twenty/pull/18460
|
||||
it('should only produce client stubs (not a fully generated CoreApiClient)', async () => {
|
||||
const clientIndexPath = join(
|
||||
APP_PATH,
|
||||
'node_modules',
|
||||
'twenty-sdk',
|
||||
GENERATED_DIR,
|
||||
'core',
|
||||
'index.ts',
|
||||
);
|
||||
|
||||
const { readFile } = await import('node:fs/promises');
|
||||
const content = await readFile(clientIndexPath, 'utf-8');
|
||||
|
||||
expect(content).toBe('export class CoreApiClient {}\n');
|
||||
});
|
||||
});
|
||||
+20
@@ -76,4 +76,24 @@ describe('functionExecute E2E', () => {
|
||||
error: { code: 'FUNCTION_NOT_FOUND' },
|
||||
});
|
||||
});
|
||||
|
||||
// Verifies that CoreApiClient is fully generated (not just stubs) after
|
||||
// appGenerateClient. If app:build is used without client generation, the
|
||||
// bundled CoreApiClient would be an empty stub and this test would fail.
|
||||
// See: https://github.com/twentyhq/twenty/pull/18460
|
||||
it('should execute a function that uses CoreApiClient with real query/mutation methods', async () => {
|
||||
const result = await functionExecute({
|
||||
appPath: APP_PATH,
|
||||
functionName: 'check-core-client',
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
success: true,
|
||||
data: {
|
||||
functionName: 'check-core-client',
|
||||
status: 'SUCCESS',
|
||||
data: { hasQuery: true, hasMutation: true },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { CoreApiClient } from 'twenty-sdk/generated';
|
||||
import { defineLogicFunction } from '@/sdk';
|
||||
|
||||
export const CHECK_CORE_CLIENT_UNIVERSAL_IDENTIFIER =
|
||||
'b7c8d9e0-1a2b-4c3d-8e5f-6a7b8c9d0e1f';
|
||||
|
||||
const checkCoreClientHandler = () => {
|
||||
const client = new CoreApiClient();
|
||||
|
||||
return {
|
||||
hasQuery: typeof client.query === 'function',
|
||||
hasMutation: typeof client.mutation === 'function',
|
||||
};
|
||||
};
|
||||
|
||||
export default defineLogicFunction({
|
||||
universalIdentifier: CHECK_CORE_CLIENT_UNIVERSAL_IDENTIFIER,
|
||||
name: 'check-core-client',
|
||||
timeoutSeconds: 5,
|
||||
handler: checkCoreClientHandler,
|
||||
httpRouteTriggerSettings: {
|
||||
path: '/check-core-client',
|
||||
httpMethod: 'GET',
|
||||
isAuthRequired: false,
|
||||
},
|
||||
});
|
||||
@@ -36,6 +36,8 @@
|
||||
"src/front-component-renderer/host/generated/host-component-registry.ts",
|
||||
"src/front-component-renderer/remote/generated/remote-components.ts",
|
||||
"src/front-component-renderer/remote/generated/remote-elements.ts",
|
||||
"src/front-component-renderer/__stories__/**/*"
|
||||
"src/front-component-renderer/__stories__/**/*",
|
||||
"src/app-seeds/*/src/**/*",
|
||||
"src/cli/__tests__/apps/*/src/**/*"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user