Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nine-books-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@workflow/sveltekit": patch
---

Use hotUpdate for HMR in sveltekit
5 changes: 5 additions & 0 deletions .changeset/tiny-coins-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@workflow/nitro": patch
---

Add HMR to nitro integration
38 changes: 11 additions & 27 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,35 +178,18 @@ jobs:
- name: Run Initial Build
run: pnpm turbo run build --filter='!./workbench/*'

- name: Resolve symlinks for next dev to work
if: matrix.app.name == 'nextjs-webpack'
run: cd workbench/${{ matrix.app.name }} && ./resolve-symlinks.sh

- name: Run E2E Tests (Next.js)
if: matrix.app.name != 'nitro' && matrix.app.name != 'vite' && matrix.app.name != 'sveltekit'
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/next-dev.test.ts && pnpm run test:e2e
env:
APP_NAME: ${{ matrix.app.name }}
DEPLOYMENT_URL: "http://localhost:3000"
- name: Resolve symlinks
run: |
if [ -f "workbench/${{ matrix.app.name }}/resolve-symlinks.sh" ]; then
cd workbench/${{ matrix.app.name }} && ./resolve-symlinks.sh
fi

- name: Run E2E Tests (Nitro)
if: matrix.app.name == 'nitro'
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/e2e.test.ts
env:
APP_NAME: ${{ matrix.app.name }}
DEPLOYMENT_URL: "http://localhost:3000"
- name: Run E2E Tests (Vite)
if: matrix.app.name == 'vite'
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/e2e.test.ts
env:
APP_NAME: ${{ matrix.app.name }}
DEPLOYMENT_URL: "http://localhost:3000"
- name: Run E2E Tests (SvelteKit)
if: matrix.app.name == 'sveltekit'
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/e2e.test.ts
- name: Run E2E Tests
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/dev.test.ts && pnpm run test:e2e
env:
APP_NAME: ${{ matrix.app.name }}
DEPLOYMENT_URL: "http://localhost:3000"
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.port }}"
DEV_TEST_CONFIG: ${{ toJSON(matrix.app) }}

e2e-local-prod:
name: E2E Local Prod Tests (${{ matrix.app.name }} - ${{ matrix.app.canary && 'canary' || 'stable' }})
Expand Down Expand Up @@ -299,10 +282,11 @@ jobs:
$job = Start-Job -ScriptBlock { Set-Location $using:PWD; pnpm dev }
Start-Sleep -Seconds 15
cd ../..
pnpm vitest run packages/core/e2e/next-dev.test.ts
pnpm vitest run packages/core/e2e/dev.test.ts
pnpm run test:e2e
Stop-Job $job
shell: powershell
env:
APP_NAME: "nextjs-turbopack"
DEPLOYMENT_URL: "http://localhost:3000"
DEV_TEST_CONFIG: '{"generatedStepPath":"app/.well-known/workflow/v1/step/route.js","generatedWorkflowPath":"app/.well-known/workflow/v1/flow/route.js","apiFilePath":"app/api/chat/route.ts","apiFileImportPath":"../../..","port":3000}'
159 changes: 159 additions & 0 deletions packages/core/e2e/dev.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import fs from 'fs/promises';
import path from 'path';
import { afterEach, describe, expect, test } from 'vitest';
import { getWorkbenchAppPath } from './utils';

export interface DevTestConfig {
generatedStepPath: string;
generatedWorkflowPath: string;
apiFilePath: string;
apiFileImportPath: string;
/** The workflow file to modify for testing HMR. Defaults to '3_streams.ts' */
testWorkflowFile?: string;
}

function getConfigFromEnv(): DevTestConfig | null {
const envConfig = process.env.DEV_TEST_CONFIG;
if (envConfig) {
try {
return JSON.parse(envConfig);
} catch (e) {
console.error('Failed to parse DEV_TEST_CONFIG:', e);
}
}
return null;
}

export function createDevTests(config?: DevTestConfig) {
const finalConfig = config || getConfigFromEnv();
if (!finalConfig) {
throw new Error(
'No dev test config provided via parameter or DEV_TEST_CONFIG env var'
);
}
describe('dev e2e', () => {
const appPath = getWorkbenchAppPath();
const generatedStep = path.join(appPath, finalConfig.generatedStepPath);
const generatedWorkflow = path.join(
appPath,
finalConfig.generatedWorkflowPath
);
const testWorkflowFile = finalConfig.testWorkflowFile ?? '3_streams.ts';
const restoreFiles: Array<{ path: string; content: string }> = [];

afterEach(async () => {
await Promise.all(
restoreFiles.map(async (item) => {
if (item.content === '') {
await fs.unlink(item.path);
} else {
await fs.writeFile(item.path, item.content);
}
})
);
restoreFiles.length = 0;
});

test('should rebuild on workflow change', { timeout: 10_000 }, async () => {

Check failure on line 57 in packages/core/e2e/dev.test.ts

View workflow job for this annotation

GitHub Actions / E2E Windows Tests

packages/core/e2e/dev.test.ts > dev e2e > should rebuild on workflow change

Error: Test timed out in 10000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ packages/core/e2e/dev.test.ts:57:5
const workflowFile = path.join(appPath, 'workflows', testWorkflowFile);

const content = await fs.readFile(workflowFile, 'utf8');

await fs.writeFile(
workflowFile,
`${content}

export async function myNewWorkflow() {
'use workflow'
return 'hello world'
}
`
);
restoreFiles.push({ path: workflowFile, content });

while (true) {
try {
const workflowContent = await fs.readFile(generatedWorkflow, 'utf8');
expect(workflowContent).toContain('myNewWorkflow');
break;
} catch (_) {
await new Promise((res) => setTimeout(res, 1_000));
}
}
});

test('should rebuild on step change', { timeout: 10_000 }, async () => {

Check failure on line 85 in packages/core/e2e/dev.test.ts

View workflow job for this annotation

GitHub Actions / E2E Windows Tests

packages/core/e2e/dev.test.ts > dev e2e > should rebuild on step change

Error: Test timed out in 10000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ packages/core/e2e/dev.test.ts:85:5
const stepFile = path.join(appPath, 'workflows', testWorkflowFile);

const content = await fs.readFile(stepFile, 'utf8');

await fs.writeFile(
stepFile,
`${content}

export async function myNewStep() {
'use step'
return 'hello world'
}
`
);
restoreFiles.push({ path: stepFile, content });

while (true) {
try {
const workflowContent = await fs.readFile(generatedStep, 'utf8');
expect(workflowContent).toContain('myNewStep');
break;
} catch (_) {
await new Promise((res) => setTimeout(res, 1_000));
}
}
});

test(
'should rebuild on adding workflow file',
{ timeout: 10_000 },
async () => {
const workflowFile = path.join(appPath, 'workflows', 'new-workflow.ts');

await fs.writeFile(
workflowFile,
`export async function newWorkflowFile() {
'use workflow'
return 'hello world'
}
`
);
restoreFiles.push({ path: workflowFile, content: '' });
const apiFile = path.join(appPath, finalConfig.apiFilePath);

const apiFileContent = await fs.readFile(apiFile, 'utf8');
restoreFiles.push({ path: apiFile, content: apiFileContent });

await fs.writeFile(
apiFile,
`import '${finalConfig.apiFileImportPath}/workflows/new-workflow';
${apiFileContent}`
);

while (true) {
try {
const workflowContent = await fs.readFile(
generatedWorkflow,
'utf8'
);
expect(workflowContent).toContain('newWorkflowFile');
break;
} catch (_) {
await new Promise((res) => setTimeout(res, 1_000));
}
}
}
);
});
}

// Run tests with environment-based config if this file is executed directly
if (process.env.DEV_TEST_CONFIG) {
createDevTests();
}
134 changes: 0 additions & 134 deletions packages/core/e2e/next-dev.test.ts

This file was deleted.

10 changes: 9 additions & 1 deletion packages/nitro/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,18 @@ export default {

// Generate local bundles for dev and local prod
if (!isVercelDeploy) {
const builder = new LocalBuilder(nitro);
nitro.hooks.hook('build:before', async () => {
await new LocalBuilder(nitro).build();
await builder.build();
});

// Allows for HMR
if (nitro.options.dev) {
nitro.hooks.hook('dev:reload', async () => {
await builder.build();
});
}

addVirtualHandler(
nitro,
'/.well-known/workflow/v1/webhook/:token',
Expand Down
Loading