Skip to content

Commit 0ab5f1c

Browse files
add next v9 test and improve fixture tooling (#14)
1 parent c14f21e commit 0ab5f1c

19 files changed

+284
-134
lines changed

fixtures/next-9/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

fixtures/next-9/config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'@harperdb/nextjs':
2+
package: '@harperdb/nextjs'
3+
files: '/*'

fixtures/next-9/next.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

fixtures/next-9/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "next-9",
3+
"private": true,
4+
"scripts": {
5+
"dev": "next dev",
6+
"build": "next build",
7+
"start": "next start",
8+
"lint": "next lint",
9+
"postinstall": "npm link @harperdb/nextjs"
10+
},
11+
"dependencies": {
12+
"@harperdb/nextjs": "*",
13+
"next": "^9.5.5",
14+
"react": "^16.14.0",
15+
"react-dom": "^16.14.0"
16+
}
17+
}

fixtures/next-9/pages/_app.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Head from 'next/head';
2+
3+
export default function App({ Component, pageProps }) {
4+
return (
5+
<>
6+
<Head>
7+
<title>HarperDB - Next.js v9 App</title>
8+
</Head>
9+
<Component {...pageProps} />
10+
</>
11+
);
12+
}

fixtures/next-9/pages/_document.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Document, { Html, Head, Main, NextScript } from 'next/document';
2+
3+
export default class MyDocument extends Document {
4+
render() {
5+
return (
6+
<Html>
7+
<Head />
8+
<body>
9+
<Main />
10+
<NextScript />
11+
</body>
12+
</Html>
13+
);
14+
}
15+
}

fixtures/next-9/pages/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Link from 'next/link';
2+
3+
export default function Index() {
4+
return (
5+
<div>
6+
<h1>Next.js v9</h1>
7+
<Link href="/page-2">Page 2</Link>
8+
</div>
9+
);
10+
}

fixtures/next-9/pages/page-2.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Link from 'next/link';
2+
3+
export default function Page2() {
4+
return (
5+
<div>
6+
<h1>Page 2</h1>
7+
<Link href="/">Home</Link>
8+
</div>
9+
);
10+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
"format:check": "npm run format -- --check",
3737
"format:fix": "npm run format -- --write",
3838
"pretest": "node util/scripts/pretest.js",
39-
"test": "playwright test --workers 3"
39+
"test": "playwright test --workers 3",
40+
"build-fixture": "node util/scripts/build-fixture-cli.js"
4041
},
4142
"dependencies": {
4243
"shell-quote": "^1.8.1"

playwright.config.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { defineConfig, devices } from '@playwright/test';
2-
3-
const NEXT_MAJORS = ['13', '14', '15'];
4-
const NODE_MAJORS = ['18', '20', '22'];
2+
import { VERSION_MATRIX } from './util/constants-and-names';
53

64
export default defineConfig({
75
testDir: 'test',
@@ -12,11 +10,11 @@ export default defineConfig({
1210
expect: {
1311
timeout: 30000,
1412
},
15-
projects: NEXT_MAJORS.flatMap((nextMajor) =>
16-
NODE_MAJORS.map((nodeMajor) => ({
13+
projects: [
14+
...VERSION_MATRIX.map(([nextMajor, nodeMajor]) => ({
1715
name: `Next.js v${nextMajor} - Node.js v${nodeMajor}`,
1816
use: { versions: { nextMajor, nodeMajor }, ...devices['Desktop Chrome'] },
1917
testMatch: [`test/next-${nextMajor}.test.js`],
20-
}))
21-
),
18+
})),
19+
],
2220
});

test/next-9.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { test, expect } from '../util/test-fixture.js';
2+
3+
test.describe.configure({ mode: 'serial' });
4+
5+
test('home page', async ({ nextApp, page }) => {
6+
await page.goto(nextApp.rest.toString());
7+
await expect(page.locator('h1')).toHaveText('Next.js v9');
8+
});
9+
10+
test('title', async ({ nextApp, page }) => {
11+
await page.goto(nextApp.rest.toString());
12+
await expect(page).toHaveTitle('HarperDB - Next.js v9 App');
13+
});
14+
15+
test('page 2', async ({ nextApp, page }) => {
16+
await page.goto(nextApp.rest.toString());
17+
await page.locator('a').click();
18+
await expect(page.locator('h1')).toHaveText('Page 2');
19+
});

util/build-fixture.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { spawn } from 'node:child_process';
2+
import { join } from 'node:path';
3+
import { DEBUG, ROOT, getNodeBaseImageName, getNextImageName } from './constants-and-names.js';
4+
import { CONTAINER_ENGINE } from './container-engine.js';
5+
import { CollectedTransform } from './collected-transform.js';
6+
7+
function validateResult(result) {
8+
const success = result.code === 0;
9+
10+
if (DEBUG || !success) {
11+
console.log(`Image \x1b[94m${result.name}\x1b[0m build process exited with: \x1b[35m${result.code}\x1b[0m\n`);
12+
result.stdout !== '' && console.log('\x1b[32mstdout\x1b[0m:\n' + result.stdout + '\n');
13+
result.stderr !== '' && console.log('\x1b[31mstderr\x1b[0m:\n' + result.stderr + '\n');
14+
}
15+
16+
if (!success) {
17+
process.exit(1);
18+
}
19+
}
20+
21+
function build(name, args, options = {}) {
22+
return new Promise((resolve, reject) => {
23+
const buildProcess = spawn(CONTAINER_ENGINE, args, { cwd: ROOT, stdio: ['ignore', 'pipe', 'pipe'], ...options });
24+
25+
const collectedStdout = buildProcess.stdout.pipe(new CollectedTransform());
26+
const collectedStderr = buildProcess.stderr.pipe(new CollectedTransform());
27+
28+
buildProcess.on('error', reject);
29+
buildProcess.on('close', (code) =>
30+
resolve({
31+
name,
32+
code,
33+
stdout: collectedStdout.output,
34+
stderr: collectedStderr.output,
35+
})
36+
);
37+
});
38+
}
39+
40+
export function buildNodeImage(nodeMajor, validate = true) {
41+
const buildPromise = build(getNodeBaseImageName(nodeMajor), [
42+
'build',
43+
'--build-arg',
44+
`NODE_MAJOR=${nodeMajor}`,
45+
'-t',
46+
getNodeBaseImageName(nodeMajor),
47+
'-f',
48+
join(ROOT, 'util', 'docker', 'base.dockerfile'),
49+
ROOT,
50+
]);
51+
52+
return validate ? buildPromise.then(validateResult) : buildPromise;
53+
}
54+
55+
export function buildNextImage(nextMajor, nodeMajor, validate = true) {
56+
const buildPromise = build(getNextImageName(nextMajor, nodeMajor), [
57+
'build',
58+
'--build-arg',
59+
`BASE_IMAGE=${getNodeBaseImageName(nodeMajor)}`,
60+
'--build-arg',
61+
`NEXT_MAJOR=${nextMajor}`,
62+
'-t',
63+
getNextImageName(nextMajor, nodeMajor),
64+
'-f',
65+
join(ROOT, 'util', 'docker', 'next.dockerfile'),
66+
ROOT,
67+
]);
68+
69+
return validate ? buildPromise.then(validateResult) : buildPromise;
70+
}

util/cache-bust.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

util/constants-and-names.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
import { join } from 'node:path';
22

3-
export const ROOT = join(import.meta.dirname, '..');
3+
export const DEBUG = process.env.DEBUG === '1';
44

5-
export const NEXT_MAJORS = ['13', '14', '15'];
5+
export const ROOT = join(import.meta.dirname, '..');
66

7-
export const NODE_MAJORS = ['18', '20', '22'];
7+
export const VERSION_MATRIX = [
8+
// Next.js v9
9+
['9', '16'],
10+
// Next.js v13
11+
['13', '18'],
12+
['13', '20'],
13+
['13', '22'],
14+
// Next.js v14
15+
['14', '18'],
16+
['14', '20'],
17+
['14', '22'],
18+
// Next.js v15
19+
['15', '18'],
20+
['15', '20'],
21+
['15', '22'],
22+
];
23+
24+
export const NEXT_MAJORS = new Set(VERSION_MATRIX.map(([nextMajor]) => nextMajor));
25+
export const NODE_MAJORS = new Set(VERSION_MATRIX.map(([_, nodeMajor]) => nodeMajor));
826

927
export const PORTS = ['9925', '9926'];
1028

util/docker/base.dockerfile

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33

44
ARG NODE_MAJOR
55

6-
FROM node:${NODE_MAJOR}
6+
FROM docker.io/node:${NODE_MAJOR}-slim
77

8+
EXPOSE 9925 9926
9+
10+
# Install utilities for the container
811
RUN apt-get update && apt-get install -y \
9-
curl \
12+
# List of tools to install
13+
# curl \
14+
# Clean Up
1015
&& rm -rf /var/lib/apt/lists/*
1116

1217
# Install HarperDB Globally
13-
RUN npm install -g harperdb
18+
RUN npm install -g harperdb@4.4.8
1419

1520
# Set HarperDB Environment Variables
1621
ENV TC_AGREEMENT=yes
@@ -23,25 +28,25 @@ ENV THREADS_COUNT=1
2328
ENV LOGGING_STDSTREAMS=true
2429
ENV LOGGING_LEVEL=debug
2530

26-
# Create components directory
27-
RUN mkdir -p /hdb/components
31+
RUN harperdb start
2832

2933
# Add base component
3034
COPY /fixtures/harperdb-base-component /hdb/components/harperdb-base-component
3135

3236
# Create the @harperdb/nextjs module directory so it can be linked locally
3337
RUN mkdir -p /@harperdb/nextjs
3438

35-
# Cache Bust copying project files
36-
ARG CACHE_BUST
37-
RUN echo "${CACHE_BUST}"
3839
COPY config.yaml extension.js cli.js package.json /@harperdb/nextjs/
3940

4041
WORKDIR /@harperdb/nextjs
42+
4143
# Install dependencies for the @harperdb/nextjs module
42-
RUN npm install
44+
RUN npm install --omit=dev
4345

4446
# Create link to the @harperdb/nextjs module
4547
RUN npm link
4648

47-
WORKDIR /
49+
WORKDIR /
50+
51+
# By default, run HarperDB when the container starts. This can be overridden by passing a different command to the container, or using a new CMD in a child Dockerfile.
52+
CMD harperdb run

util/docker/next.dockerfile

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@ FROM ${BASE_IMAGE}
77

88
ARG NEXT_MAJOR
99

10-
ARG CACHE_BUST
11-
RUN echo "${CACHE_BUST}"
1210
COPY fixtures/next-${NEXT_MAJOR} /hdb/components/next-${NEXT_MAJOR}
1311

1412
WORKDIR /hdb/components/next-${NEXT_MAJOR}
13+
14+
# Fixtures should automatically link the @harperdb/nextjs module via their postinstall script.
1515
RUN npm install
1616

1717
WORKDIR /
18-
19-
EXPOSE 9925 9926
20-
21-
CMD ["harperdb", "run"]

util/fixture.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
import { spawn, spawnSync } from 'node:child_process';
22
import { Transform } from 'node:stream';
33

4-
import { getNextImageName, getNextContainerName, NEXT_MAJORS, NODE_MAJORS, PORTS } from './constants-and-names.js';
4+
import {
5+
getNextImageName,
6+
getNextContainerName,
7+
NEXT_MAJORS,
8+
NODE_MAJORS,
9+
PORTS,
10+
DEBUG,
11+
} from './constants-and-names.js';
512
import { CONTAINER_ENGINE } from './container-engine.js';
613
import { CollectedTransform } from './collected-transform.js';
714

815
export class Fixture {
916
constructor({ autoSetup = true, debug = false, nextMajor, nodeMajor }) {
10-
if (!NEXT_MAJORS.includes(nextMajor)) {
17+
if (!NEXT_MAJORS.has(nextMajor)) {
1118
throw new Error(`nextMajor must be one of ${NEXT_MAJORS.join(', ')}`);
1219
}
1320
this.nextMajor = nextMajor;
1421

15-
if (!NODE_MAJORS.includes(nodeMajor)) {
22+
if (!NODE_MAJORS.has(nodeMajor)) {
1623
throw new Error(`nodeMajor must be one of ${NODE_MAJORS.join(', ')}`);
1724
}
1825
this.nodeMajor = nodeMajor;
1926

20-
this.debug = debug || process.env.DEBUG === '1';
27+
this.debug = debug || DEBUG;
2128

2229
this.imageName = getNextImageName(nextMajor, nodeMajor);
2330
this.containerName = getNextContainerName(nextMajor, nodeMajor);

0 commit comments

Comments
 (0)