Skip to content

Commit d7640dc

Browse files
committed
Add e2e next template tests
1 parent 0c7df48 commit d7640dc

File tree

10 files changed

+230
-7
lines changed

10 files changed

+230
-7
lines changed

browser/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ publish
1313
*/yarn-error.log
1414
test-results
1515
playwright-report
16+
template-tests
1617
*/nohup.out
1718
*/yarn-error.log
1819
lib/coverage

browser/Earthfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
VERSION 0.7
22
PROJECT ontola/atomic-server
3-
FROM node:20.8.0-bookworm
3+
FROM node:22.13-bookworm # LTS
44
WORKDIR browser
55

66
all:

browser/create-template/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ log('');
6161
log(chalk.green('Done!'));
6262

6363
const endUsage = buildEndUsageString(args.values.template, args.positionals[0]);
64-
console.log(endUsage);
64+
log(endUsage);
65+
66+
process.exit(0);

browser/create-template/templates/nextjs-site/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"build": "next build",
88
"start": "next start",
99
"lint": "next lint",
10-
"generate-ontologies": "ad-generate ontologies"
10+
"update-ontologies": "ad-generate ontologies"
1111
},
1212
"dependencies": {
1313
"@t3-oss/env-nextjs": "^0.11.1",

browser/create-template/templates/nextjs-site/src/app/globals.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
--theme-color-bg: #fff;
33
--theme-color-bg-1: #e3e3e3;
44
--theme-color-bg-2: #ededed;
5-
--theme-color-accent: hsl(179, 58%, 37%);
5+
--theme-color-accent: hsl(179, 58%, 32%);
66
--theme-color-alert: hsl(356, 53%, 50%);
77
--theme-color-text: #000;
88
--theme-color-text-light: #555555;

browser/create-template/templates/nextjs-site/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Metadata } from 'next';
22
import 'modern-css-reset/dist/reset.min.css';
3-
import './globals.css';
3+
import '@/app/globals.css';
44
import ProviderWrapper from '@/components/ProviderWrapper';
55
import VStack from '@/components/Layout/VStack';
66
import Navbar from '@/components/Navbar';

browser/data-browser/src/components/Template/TemplateListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export function TemplateListItem({
1414
Image,
1515
}: TemplateListItemProps): React.JSX.Element {
1616
return (
17-
<Wrapper onClick={() => onClick(id)}>
17+
<Wrapper onClick={() => onClick(id)} data-testid='template-button'>
1818
<Image />
1919
<Content>
2020
<span>{title}</span>

browser/e2e/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"url": "https://github.com/atomicdata-dev/atomic-server/"
1313
},
1414
"devDependencies": {
15-
"@playwright/test": "^1.48.1"
15+
"@playwright/test": "^1.48.1",
16+
"@types/kill-port": "^2.0.3"
1617
},
1718
"scripts": {
1819
"playwright-install": "playwright install chromium",
@@ -22,5 +23,9 @@
2223
"test-update": "playwright test --update-snapshots",
2324
"test-new": "playwright codegen http://localhost:5173",
2425
"test-query": "PWDEBUG=1 DELETE_PREVIOUS_TEST_DRIVES=false playwright test \"e2e.spec.ts\" \"tables.spec.ts\" \"documents.spec.ts\" \"ontology.spec.ts\" \"search.spec.ts\" -g"
26+
},
27+
"dependencies": {
28+
"@axe-core/playwright": "^4.10.1",
29+
"kill-port": "^2.0.1"
2530
}
2631
}

browser/e2e/tests/template.spec.ts

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { expect, test } from '@playwright/test';
2+
import AxeBuilder from '@axe-core/playwright';
3+
import { execSync } from 'child_process';
4+
import {
5+
before,
6+
makeDrivePublic,
7+
newDrive,
8+
signIn,
9+
sideBarNewResourceTestId,
10+
FRONTEND_URL,
11+
} from './test-utils';
12+
import fs from 'node:fs';
13+
import { spawn, type ChildProcess } from 'node:child_process';
14+
import path from 'node:path';
15+
import kill from 'kill-port';
16+
17+
const TEMPLATE_DIR_NAME = 'template-tests';
18+
19+
test.describe.configure({ mode: 'serial' });
20+
21+
const waitForNextServer = (
22+
childProcess: ChildProcess,
23+
timeout = 30000,
24+
): Promise<string> => {
25+
return new Promise((resolve, reject) => {
26+
const timeoutId = setTimeout(() => {
27+
childProcess.kill(); // Kill the process if it times out
28+
reject(new Error('Next.js server took too long to start.'));
29+
}, timeout);
30+
31+
childProcess.stdout?.on('data', data => {
32+
const message = data.toString();
33+
34+
const match = message.match(/http:\/\/localhost:\d+/);
35+
36+
if (match) {
37+
clearTimeout(timeoutId); // Clear the timeout when resolved
38+
resolve(match[0]); // Resolve with the URL
39+
}
40+
});
41+
42+
childProcess.stderr?.on('data', data => {
43+
const errorMessage = data.toString();
44+
console.error(`stderr: ${errorMessage}`);
45+
46+
if (errorMessage.includes('error')) {
47+
clearTimeout(timeoutId); // Clear the timeout when rejecting
48+
reject(
49+
new Error(`Next.js server encountered an error: ${errorMessage}`),
50+
);
51+
}
52+
});
53+
54+
childProcess.on('exit', code => {
55+
clearTimeout(timeoutId); // Clear the timeout when the process exits
56+
57+
if (code !== 0) {
58+
reject(new Error(`Next.js server process exited with code ${code}`));
59+
}
60+
});
61+
});
62+
};
63+
64+
test.describe('Create Next.js Template', () => {
65+
test.beforeEach(before);
66+
67+
test('apply template', async ({ page }) => {
68+
test.slow();
69+
await signIn(page);
70+
const drive = await newDrive(page);
71+
await makeDrivePublic(page);
72+
73+
// Apply the template in data browser
74+
await page.getByTestId(sideBarNewResourceTestId).click();
75+
await expect(page).toHaveURL(`${FRONTEND_URL}/app/new`);
76+
77+
const button = page.getByTestId('template-button');
78+
await button.click();
79+
80+
const applyTemplateButton = page.getByRole('button', {
81+
name: 'Apply template',
82+
});
83+
await applyTemplateButton.click();
84+
85+
if (!fs.existsSync(TEMPLATE_DIR_NAME)) {
86+
fs.mkdirSync(TEMPLATE_DIR_NAME);
87+
}
88+
89+
execSync('pnpm link ../create-template');
90+
execSync(
91+
`pnpm exec create-template ${TEMPLATE_DIR_NAME}/nextjs-template --template nextjs-site --server-url ${drive.driveURL}`,
92+
);
93+
execSync(`pnpm install`, {
94+
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
95+
});
96+
execSync('pnpm link ../../../cli', {
97+
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
98+
});
99+
execSync('pnpm link ../../../lib', {
100+
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
101+
});
102+
execSync('pnpm link ../../../react', {
103+
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
104+
});
105+
106+
execSync(`pnpm update-ontologies`, {
107+
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
108+
});
109+
110+
const child = spawn('pnpm run build && pnpm start', {
111+
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
112+
113+
shell: true,
114+
});
115+
116+
try {
117+
//start server
118+
const url = await waitForNextServer(child);
119+
120+
// check if the server is running
121+
const response = await page.goto(url);
122+
expect(response?.status()).toBe(200);
123+
124+
// Check if home is following wcag AA standards
125+
const homeScanResults = await new AxeBuilder({ page }).analyze();
126+
127+
expect(homeScanResults.violations).toEqual([]);
128+
129+
await expect(page.locator('body')).toContainText(
130+
'This is a template site generated with @tomic/template.',
131+
);
132+
133+
await page.goto(`${url}/blog`);
134+
135+
// Check if blog is following wcag AA standards
136+
const blogScanResults = await new AxeBuilder({ page }).analyze();
137+
expect(blogScanResults.violations).toEqual([]);
138+
139+
// Search for a blogpost
140+
const searchInput = page.locator(
141+
'input[aria-label="Search blogposts..."]',
142+
);
143+
await searchInput.fill('balloon');
144+
await expect(page.locator('body')).toContainText('Balloon');
145+
await expect(page.locator('body')).not.toContainText('coffee');
146+
} finally {
147+
child.kill();
148+
}
149+
});
150+
151+
test.afterEach(async () => {
152+
const dirPath = path.join(__dirname, '..', TEMPLATE_DIR_NAME);
153+
154+
try {
155+
await fs.promises.rm(dirPath, { recursive: true, force: true });
156+
} catch (error) {
157+
console.error(`Failed to delete ${TEMPLATE_DIR_NAME}:`, error);
158+
}
159+
160+
await kill(3000);
161+
});
162+
});

browser/pnpm-lock.yaml

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)