Skip to content

Commit c61f121

Browse files
committed
fix e2e
1 parent 22a82cf commit c61f121

File tree

11 files changed

+176
-56
lines changed

11 files changed

+176
-56
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ jobs:
341341
id: task-status
342342
env:
343343
E2E_APP_CLERK_JS_DIR: ${{runner.temp}}
344+
E2E_APP_CLERK_UI_DIR: ${{runner.temp}}
344345
E2E_CLERK_VERSION: "latest"
345346
E2E_NEXTJS_VERSION: ${{ matrix.next-version }}
346347
E2E_PROJECT: ${{ matrix.test-project }}
@@ -386,6 +387,15 @@ jobs:
386387
pnpm config set minimum-release-age-exclude @clerk/*
387388
pnpm add @clerk/clerk-js
388389
390+
- name: Install @clerk/ui in os temp
391+
if: ${{ steps.task-status.outputs.affected == '1' }}
392+
working-directory: ${{runner.temp}}
393+
run: |
394+
mkdir clerk-ui && cd clerk-ui
395+
pnpm init
396+
pnpm config set minimum-release-age-exclude @clerk/*
397+
pnpm add @clerk/ui
398+
389399
- name: Copy components @clerk/astro
390400
if: ${{ matrix.test-name == 'astro' }}
391401
run: cd packages/astro && pnpm copy:components
@@ -420,6 +430,7 @@ jobs:
420430
run: pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS
421431
env:
422432
E2E_APP_CLERK_JS_DIR: ${{runner.temp}}
433+
E2E_APP_CLERK_UI_DIR: ${{runner.temp}}
423434
E2E_CLERK_VERSION: "latest"
424435
E2E_NEXTJS_VERSION: ${{ matrix.next-version }}
425436
E2E_PROJECT: ${{ matrix.test-project }}

.github/workflows/preview.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
turbo-signature: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
7878
turbo-team: ${{ vars.TURBO_TEAM }}
7979
turbo-token: ${{ secrets.TURBO_TOKEN }}
80-
registry-url: 'https://registry.npmjs.org'
80+
registry-url: "https://registry.npmjs.org"
8181

8282
- name: Build packages
8383
run: pnpm turbo build $TURBO_ARGS
@@ -101,12 +101,17 @@ jobs:
101101
run: |
102102
cp -r $GITHUB_WORKSPACE/packages/clerk-js/dist $FULL_TMP_FOLDER/public/clerk-js
103103
104+
- name: Copy ui/dist/browser into public/clerk-ui of test site
105+
run: |
106+
cp -r $GITHUB_WORKSPACE/packages/ui/dist/browser $FULL_TMP_FOLDER/public/clerk-ui
107+
104108
- name: Build with Vercel
105109
run: |
106110
cd $FULL_TMP_FOLDER
107111
vercel build --yes
108112
env:
109113
NEXT_PUBLIC_CLERK_JS_URL: /clerk-js/clerk.browser.js
114+
NEXT_PUBLIC_CLERK_UI_URL: /clerk-ui/ui.browser.js
110115

111116
- name: Deploy to Vercel (prebuilt)
112117
id: vercel-deploy

integration/constants.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ export const constants = {
2828
* Controls the path where clerk.browser.js is located on the disk.
2929
*/
3030
E2E_APP_CLERK_JS_DIR: process.env.E2E_APP_CLERK_JS_DIR,
31+
/**
32+
* Controls the URL the apps will load ui.browser.js from.
33+
* If this is set, clerk-ui will not be served automatically from the test runner.
34+
*/
35+
E2E_APP_CLERK_UI: process.env.E2E_APP_CLERK_UI,
36+
/**
37+
* Controls the path where ui.browser.js is located on the disk.
38+
*/
39+
E2E_APP_CLERK_UI_DIR: process.env.E2E_APP_CLERK_UI_DIR,
3140
/**
3241
* If CLEANUP=0 is used, the .tmp_integration directory will not be deleted.
3342
* This is useful for debugging locally.

integration/models/stateFile.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ type StateFile = Partial<{
3232
* The PID is used to teardown the http-server after the tests are done.
3333
*/
3434
clerkJsHttpServerPid: number;
35+
/**
36+
* This prop describes the pid of the http server that serves the clerk-ui hotloaded lib.
37+
* The http-server replaces the production clerk-ui delivery mechanism.
38+
* The PID is used to teardown the http-server after the tests are done.
39+
*/
40+
clerkUiHttpServerPid: number;
3541
}>;
3642

3743
const createStateFile = () => {
@@ -83,6 +89,16 @@ const createStateFile = () => {
8389
return read().clerkJsHttpServerPid;
8490
};
8591

92+
const setClerkUiHttpServerPid = (pid: number) => {
93+
const json = read();
94+
json.clerkUiHttpServerPid = pid;
95+
write(json);
96+
};
97+
98+
const getClerkUiHttpServerPid = () => {
99+
return read().clerkUiHttpServerPid;
100+
};
101+
86102
const debug = () => {
87103
const json = read();
88104
console.log('state file', JSON.stringify(json, null, 2));
@@ -94,6 +110,8 @@ const createStateFile = () => {
94110
getStandAloneApp,
95111
setClerkJsHttpServerPid,
96112
getClerkJsHttpServerPid,
113+
setClerkUiHttpServerPid,
114+
getClerkUiHttpServerPid,
97115
addLongRunningApp,
98116
getLongRunningApps,
99117
debug,

integration/presets/envs.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ const base = environmentConfig()
2727
.setEnvVariable('public', 'CLERK_KEYLESS_DISABLED', true)
2828
.setEnvVariable('public', 'CLERK_SIGN_IN_URL', '/sign-in')
2929
.setEnvVariable('public', 'CLERK_SIGN_UP_URL', '/sign-up')
30-
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');
30+
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
31+
.setEnvVariable('public', 'CLERK_UI_URL', constants.E2E_APP_CLERK_UI || 'http://localhost:18212/ui.browser.js');
3132

3233
const withKeyless = base
3334
.clone()
Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,34 @@
11
/* eslint-disable turbo/no-undeclared-env-vars */
22

3-
import os from 'node:os';
43
import path from 'node:path';
54

6-
import { constants } from '../constants';
75
import { stateFile } from '../models/stateFile';
8-
import { awaitableTreekill, fs, waitForServer } from '.';
9-
import { run } from './run';
6+
import { getTempDir, killHttpServer, startHttpServer } from './httpServer';
107

11-
export const startClerkJsHttpServer = async () => {
8+
export const startClerkJsHttpServer = async (): Promise<void> => {
129
if (process.env.E2E_APP_CLERK_JS) {
1310
return;
1411
}
15-
if (!process.env.CI) {
16-
await copyClerkJsToTempDir();
17-
}
18-
return serveFromTempDir();
19-
};
20-
21-
export const killClerkJsHttpServer = async () => {
22-
const clerkJsHttpServerPid = stateFile.getClerkJsHttpServerPid();
23-
if (clerkJsHttpServerPid) {
24-
console.log('Killing clerkJsHttpServer', clerkJsHttpServerPid);
25-
await awaitableTreekill(clerkJsHttpServerPid, 'SIGKILL');
26-
}
27-
};
2812

29-
// If we are running the tests locally, then clerk.browser.js should be built already
30-
// so we simply copy it from packages/clerk to the same location as CICD would install it
31-
const copyClerkJsToTempDir = async () => {
32-
const clerkJsTempDir = getClerkJsTempDir();
33-
await fs.remove(clerkJsTempDir);
34-
await fs.ensureDir(clerkJsTempDir);
35-
const packagesClerkJsDistPath = path.join(process.cwd(), 'packages/clerk-js/dist');
36-
fs.copySync(packagesClerkJsDistPath, clerkJsTempDir);
37-
};
13+
const clerkJsTempDir = getTempDir('clerk-js/node_modules/@clerk/clerk-js/dist', 'E2E_APP_CLERK_JS_DIR');
14+
const sourceDir = path.join(process.cwd(), 'packages/clerk-js/dist');
3815

39-
const serveFromTempDir = async () => {
40-
console.log('Serving clerkJs from temp dir');
41-
const port = 18211;
42-
const serverUrl = `http://localhost:${port}`;
43-
const now = Date.now();
44-
const stdoutFilePath = path.resolve(constants.TMP_DIR, `clerkJsHttpServer.${now}.log`);
45-
const stderrFilePath = path.resolve(constants.TMP_DIR, `clerkJsHttpServer.${now}.err.log`);
46-
const clerkJsTempDir = getClerkJsTempDir();
47-
const proc = run(`node_modules/.bin/http-server ${clerkJsTempDir} -d --gzip --cors -a localhost`, {
48-
cwd: process.cwd(),
49-
env: { PORT: port.toString() },
50-
detached: true,
51-
stdout: fs.openSync(stdoutFilePath, 'a'),
52-
stderr: fs.openSync(stderrFilePath, 'a'),
16+
const { pid } = await startHttpServer({
17+
name: 'clerkJs',
18+
port: 18211,
19+
sourceDir,
20+
targetTempDir: clerkJsTempDir,
21+
envVarOverride: 'E2E_APP_CLERK_JS',
22+
envVarDirOverride: 'E2E_APP_CLERK_JS_DIR',
23+
shouldCopyInLocal: true,
5324
});
54-
stateFile.setClerkJsHttpServerPid(proc.pid);
55-
await waitForServer(serverUrl, { log: console.log, maxAttempts: Infinity });
56-
console.log('clerk.browser.js is being served from', serverUrl);
25+
26+
stateFile.setClerkJsHttpServerPid(pid);
5727
};
5828

59-
// The location where the clerk.browser.js is served from
60-
// For simplicity, on CICD we install `@clerk/clerk-js` on osTemp
61-
// so the actual clerk.browser.file is at osTemp/clerk-js/node_modules/@clerk/clerk-js/dist
62-
// Locally, it's the osTemp/clerk-js/node_modules/@clerk/clerk-js/dist
63-
// You can override it by setting the `E2E_APP_CLERK_JS_DIR` env variable
64-
const getClerkJsTempDir = () => {
65-
const osTempDir = process.env.E2E_APP_CLERK_JS_DIR || os.tmpdir();
66-
return path.join(osTempDir, ...'clerk-js/node_modules/@clerk/clerk-js/dist'.split('/'));
29+
export const killClerkJsHttpServer = async (): Promise<void> => {
30+
const clerkJsHttpServerPid = stateFile.getClerkJsHttpServerPid();
31+
if (clerkJsHttpServerPid) {
32+
await killHttpServer(clerkJsHttpServerPid, 'clerkJs');
33+
}
6734
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* eslint-disable turbo/no-undeclared-env-vars */
2+
3+
import path from 'node:path';
4+
5+
import { stateFile } from '../models/stateFile';
6+
import { getTempDir, killHttpServer, startHttpServer } from './httpServer';
7+
8+
export const startClerkUiHttpServer = async (): Promise<void> => {
9+
if (process.env.E2E_APP_CLERK_UI) {
10+
return;
11+
}
12+
13+
const clerkUiTempDir = getTempDir('clerk-ui/node_modules/@clerk/ui/dist/browser', 'E2E_APP_CLERK_UI_DIR');
14+
const sourceDir = path.join(process.cwd(), 'packages/ui/dist/browser');
15+
16+
const { pid } = await startHttpServer({
17+
name: 'clerkUi',
18+
port: 18212,
19+
sourceDir,
20+
targetTempDir: clerkUiTempDir,
21+
envVarOverride: 'E2E_APP_CLERK_UI',
22+
envVarDirOverride: 'E2E_APP_CLERK_UI_DIR',
23+
shouldCopyInLocal: true,
24+
});
25+
26+
stateFile.setClerkUiHttpServerPid(pid);
27+
};
28+
29+
export const killClerkUiHttpServer = async (): Promise<void> => {
30+
const clerkUiHttpServerPid = stateFile.getClerkUiHttpServerPid();
31+
if (clerkUiHttpServerPid) {
32+
await killHttpServer(clerkUiHttpServerPid, 'clerkUi');
33+
}
34+
};

integration/scripts/httpServer.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* eslint-disable turbo/no-undeclared-env-vars */
2+
3+
import os from 'node:os';
4+
import path from 'node:path';
5+
6+
import { constants } from '../constants';
7+
import { awaitableTreekill, fs, waitForServer } from '.';
8+
import { run } from './run';
9+
10+
type HttpServerConfig = {
11+
name: string;
12+
port: number;
13+
sourceDir: string;
14+
targetTempDir: string;
15+
envVarOverride?: string;
16+
envVarDirOverride?: string;
17+
shouldCopyInLocal: boolean;
18+
};
19+
20+
const copyToTempDir = async (sourceDir: string, targetTempDir: string): Promise<void> => {
21+
await fs.remove(targetTempDir);
22+
await fs.ensureDir(targetTempDir);
23+
fs.copySync(sourceDir, targetTempDir);
24+
};
25+
26+
const serveFromTempDir = async (config: HttpServerConfig): Promise<{ pid: number; serverUrl: string }> => {
27+
console.log(`Serving ${config.name} from temp dir`);
28+
const serverUrl = `http://localhost:${config.port}`;
29+
const now = Date.now();
30+
const stdoutFilePath = path.resolve(constants.TMP_DIR, `${config.name}HttpServer.${now}.log`);
31+
const stderrFilePath = path.resolve(constants.TMP_DIR, `${config.name}HttpServer.${now}.err.log`);
32+
33+
const proc = run(`node_modules/.bin/http-server ${config.targetTempDir} -d --gzip --cors -a localhost`, {
34+
cwd: process.cwd(),
35+
env: { PORT: config.port.toString() },
36+
detached: true,
37+
stdout: fs.openSync(stdoutFilePath, 'a'),
38+
stderr: fs.openSync(stderrFilePath, 'a'),
39+
});
40+
41+
await waitForServer(serverUrl, { log: console.log, maxAttempts: Infinity });
42+
console.log(`${config.name} is being served from`, serverUrl);
43+
44+
return { pid: proc.pid, serverUrl };
45+
};
46+
47+
export const startHttpServer = async (config: HttpServerConfig): Promise<{ pid: number; serverUrl: string }> => {
48+
// Skip if override env var is provided
49+
if (config.envVarOverride && process.env[config.envVarOverride]) {
50+
return { pid: 0, serverUrl: process.env[config.envVarOverride] };
51+
}
52+
53+
// In local development, copy files to temp directory
54+
if (!process.env.CI && config.shouldCopyInLocal) {
55+
await copyToTempDir(config.sourceDir, config.targetTempDir);
56+
}
57+
58+
return serveFromTempDir(config);
59+
};
60+
61+
export const killHttpServer = async (pid: number, serverName: string): Promise<void> => {
62+
if (pid) {
63+
console.log(`Killing ${serverName}HttpServer`, pid);
64+
await awaitableTreekill(pid, 'SIGKILL');
65+
}
66+
};
67+
68+
export const getTempDir = (basePath: string, envVarOverride?: string): string => {
69+
const osTempDir = envVarOverride && process.env[envVarOverride] ? process.env[envVarOverride] : os.tmpdir();
70+
return path.join(osTempDir, ...basePath.split('/'));
71+
};

integration/scripts/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ export * from './setup';
1515
export * from './waitForServer';
1616
export { awaitableTreekill } from './awaitableTreekill';
1717
export { startClerkJsHttpServer, killClerkJsHttpServer } from './clerkJsServer';
18+
export { startClerkUiHttpServer, killClerkUiHttpServer } from './clerkUiServer';
19+
export { startHttpServer, killHttpServer, getTempDir } from './httpServer';

integration/tests/global.setup.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import { test as setup } from '@playwright/test';
22

33
import { constants } from '../constants';
44
import { appConfigs } from '../presets';
5-
import { fs, parseEnvOptions, startClerkJsHttpServer } from '../scripts';
5+
import { fs, parseEnvOptions, startClerkJsHttpServer, startClerkUiHttpServer } from '../scripts';
66

77
setup('start long running apps', async () => {
88
setup.setTimeout(90_000);
99

1010
await fs.ensureDir(constants.TMP_DIR);
1111

1212
await startClerkJsHttpServer();
13+
await startClerkUiHttpServer();
1314

1415
const { appIds } = parseEnvOptions();
1516
if (appIds.length) {

0 commit comments

Comments
 (0)