Skip to content
Open
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
43 changes: 40 additions & 3 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ on:
push:
branches: [main]
pull_request:
workflow_call:
inputs:
node-version:
description: 'Node.js version'
required: false
type: string
default: 'all'
harper_ref:
description: 'HarperFast/harper ref to test against (branch, SHA, or tag). Empty = use pinned version.'
required: false
type: string
default: ''
workflow_dispatch:
inputs:
node-version:
Expand All @@ -16,6 +28,11 @@ on:
- '20'
- '22'
- '24'
harper_ref:
description: 'HarperFast/harper ref to test against (branch, SHA, or tag). Empty = use pinned version.'
required: false
type: string
default: ''

jobs:
generate-node-version-matrix:
Expand All @@ -31,10 +48,11 @@ jobs:
- name: Set Node versions
id: set-node-versions
run: |
if [ "${{ github.event.inputs.node-version }}" == "all" ] || [ -z "${{ github.event.inputs.node-version }}" ]; then
INPUT="${{ inputs.node-version }}"
if [ "$INPUT" == "all" ] || [ -z "$INPUT" ]; then
echo "node-versions=[20, 22, 24]" >> $GITHUB_OUTPUT
else
echo "node-versions=[${{ github.event.inputs.node-version }}]" >> $GITHUB_OUTPUT
echo "node-versions=[$INPUT]" >> $GITHUB_OUTPUT
fi

integration-tests:
Expand All @@ -59,6 +77,25 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Checkout harper override
if: ${{ inputs.harper_ref != '' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: HarperFast/harper
ref: ${{ inputs.harper_ref }}
path: harper-override

- name: Build and install harper override
if: ${{ inputs.harper_ref != '' }}
run: |
cd "$GITHUB_WORKSPACE/harper-override"
npm ci
npm run build
TARBALL=$(npm pack --json | jq -r '.[0].filename')
mv "$TARBALL" /tmp/harper-override.tgz
cd "$GITHUB_WORKSPACE"
npm install --save-dev /tmp/harper-override.tgz

- name: Build
run: npm run build

Expand All @@ -70,7 +107,7 @@ jobs:

- name: Run integration tests
run: npm run test:integration
timeout-minutes: 5
timeout-minutes: 15
env:
HARPER_INTEGRATION_TEST_LOG_DIR: /tmp/harper-test-logs
FORCE_COLOR: '1'
Expand Down
1 change: 1 addition & 0 deletions fixtures/next-16/.env.secrets
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MOCK_API_KEY=harper-secret-abc123
6 changes: 6 additions & 0 deletions fixtures/next-16/app/page.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
// force-dynamic so the injected secret is read at request time, proving
// loadEnv ran before Next.js rather than being baked in at build.
export const dynamic = 'force-dynamic';

export default async function Page() {
const apiKey = process.env.MOCK_API_KEY ?? 'not-set';
return (
<div>
<h1>Next.js v16</h1>
<p data-testid="api-key">{apiKey}</p>
</div>
);
}
11 changes: 11 additions & 0 deletions fixtures/next-16/config.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,13 @@
rest: true

# Startup secrets injection: loadEnv runs before @harperfast/nextjs, so
# MOCK_API_KEY is present in process.env before Next.js builds/starts.
loadEnv:
files: .env.secrets

# A plain Harper REST resource that must coexist with Next.js on the same port.
jsResource:
files: greeting.js

'@harperfast/nextjs':
package: '@harperfast/nextjs'
7 changes: 7 additions & 0 deletions fixtures/next-16/greeting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Resource } from 'harper';

export class Greeting extends Resource {
static async get() {
return { message: 'hello from harper' };
}
}
14 changes: 14 additions & 0 deletions integrationTests/next-16.pw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,17 @@ test('status endpoint returns 200', async ({ request, harper }) => {
const response = await request.get(`${harper.operationsAPIURL}/health`);
expect(response.status()).toBe(200);
});

// §5.3(c) — Harper REST API coexists with Next.js on the same port.
test('Harper REST API is reachable on the same port as Next.js', async ({ request, harper }) => {
const response = await request.get(`${harper.httpURL}/Greeting`);
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.message).toBe('hello from harper');
});

// §5.3(a) — Startup secrets injected via loadEnv before Next.js boots.
test('startup secrets are injected before Next.js boots', async ({ page, harper }) => {
await page.goto(harper.httpURL);
await expect(page.getByTestId('api-key')).toHaveText('harper-secret-abc123');
});
Loading