Skip to content

Commit

Permalink
Add e2e next template tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RoelLeijser committed Jan 28, 2025
1 parent 53eed8f commit c9c8712
Show file tree
Hide file tree
Showing 10 changed files with 1,253 additions and 34 deletions.
1 change: 1 addition & 0 deletions browser/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ publish
*/yarn-error.log
test-results
playwright-report
template-tests
*/nohup.out
*/yarn-error.log
lib/coverage
Expand Down
2 changes: 1 addition & 1 deletion browser/Earthfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
VERSION 0.7
PROJECT ontola/atomic-server
FROM node:20.8.0-bookworm
FROM node:22.13-bookworm # LTS
WORKDIR browser

all:
Expand Down
4 changes: 3 additions & 1 deletion browser/create-template/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ log('');
log(chalk.green('Done!'));

const endUsage = buildEndUsageString(args.values.template, args.positionals[0]);
console.log(endUsage);
log(endUsage);

process.exit(0);
2 changes: 1 addition & 1 deletion browser/create-template/templates/nextjs-site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
"generate-ontologies": "ad-generate ontologies"
"update-ontologies": "ad-generate ontologies"
},
"dependencies": {
"@t3-oss/env-nextjs": "^0.11.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
--theme-color-bg: #fff;
--theme-color-bg-1: #e3e3e3;
--theme-color-bg-2: #ededed;
--theme-color-accent: hsl(179, 58%, 37%);
--theme-color-accent: hsl(179, 58%, 32%);
--theme-color-alert: hsl(356, 53%, 50%);
--theme-color-text: #000;
--theme-color-text-light: #555555;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Metadata } from 'next';
import 'modern-css-reset/dist/reset.min.css';
import './globals.css';
import '@/app/globals.css';
import ProviderWrapper from '@/components/ProviderWrapper';
import VStack from '@/components/Layout/VStack';
import Navbar from '@/components/Navbar';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function TemplateListItem({
Image,
}: TemplateListItemProps): React.JSX.Element {
return (
<Wrapper onClick={() => onClick(id)}>
<Wrapper onClick={() => onClick(id)} data-testid='template-button'>
<Image />
<Content>
<span>{title}</span>
Expand Down
7 changes: 6 additions & 1 deletion browser/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"url": "https://github.com/atomicdata-dev/atomic-server/"
},
"devDependencies": {
"@playwright/test": "^1.48.1"
"@playwright/test": "^1.48.1",
"@types/kill-port": "^2.0.3"
},
"scripts": {
"playwright-install": "playwright install chromium",
Expand All @@ -22,5 +23,9 @@
"test-update": "playwright test --update-snapshots",
"test-new": "playwright codegen http://localhost:5173",
"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"
},
"dependencies": {
"@axe-core/playwright": "^4.10.1",
"kill-port": "^2.0.1"
}
}
162 changes: 162 additions & 0 deletions browser/e2e/tests/template.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { expect, test } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
import { execSync } from 'child_process';
import {
before,
makeDrivePublic,
newDrive,
signIn,
sideBarNewResourceTestId,
FRONTEND_URL,
} from './test-utils';
import fs from 'node:fs';
import { spawn, type ChildProcess } from 'node:child_process';
import path from 'node:path';
import kill from 'kill-port';

const TEMPLATE_DIR_NAME = 'template-tests';

test.describe.configure({ mode: 'serial' });

const waitForNextServer = (
childProcess: ChildProcess,
timeout = 30000,
): Promise<string> => {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
childProcess.kill(); // Kill the process if it times out
reject(new Error('Next.js server took too long to start.'));
}, timeout);

childProcess.stdout?.on('data', data => {
const message = data.toString();

const match = message.match(/http:\/\/localhost:\d+/);

if (match) {
clearTimeout(timeoutId); // Clear the timeout when resolved
resolve(match[0]); // Resolve with the URL
}
});

childProcess.stderr?.on('data', data => {
const errorMessage = data.toString();
console.error(`stderr: ${errorMessage}`);

if (errorMessage.includes('error')) {
clearTimeout(timeoutId); // Clear the timeout when rejecting
reject(
new Error(`Next.js server encountered an error: ${errorMessage}`),
);
}
});

childProcess.on('exit', code => {
clearTimeout(timeoutId); // Clear the timeout when the process exits

if (code !== 0) {
reject(new Error(`Next.js server process exited with code ${code}`));
}
});
});
};

test.describe('Create Next.js Template', () => {
test.beforeEach(before);

test('apply template', async ({ page }) => {
test.slow();
await signIn(page);
const drive = await newDrive(page);
await makeDrivePublic(page);

// Apply the template in data browser
await page.getByTestId(sideBarNewResourceTestId).click();
await expect(page).toHaveURL(`${FRONTEND_URL}/app/new`);

const button = page.getByTestId('template-button');
await button.click();

const applyTemplateButton = page.getByRole('button', {
name: 'Apply template',
});
await applyTemplateButton.click();

if (!fs.existsSync(TEMPLATE_DIR_NAME)) {
fs.mkdirSync(TEMPLATE_DIR_NAME);
}

execSync('pnpm link ../create-template');
execSync(
`pnpm exec create-template ${TEMPLATE_DIR_NAME}/nextjs-template --template nextjs-site --server-url ${drive.driveURL}`,
);
execSync(`pnpm install`, {
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
});
execSync('pnpm link ../../../cli', {
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
});
execSync('pnpm link ../../../lib', {
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
});
execSync('pnpm link ../../../react', {
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
});

execSync(`pnpm update-ontologies`, {
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,
});

const child = spawn('pnpm run build && pnpm start', {
cwd: `${TEMPLATE_DIR_NAME}/nextjs-template`,

shell: true,
});

try {
//start server
const url = await waitForNextServer(child);

// check if the server is running
const response = await page.goto(url);
expect(response?.status()).toBe(200);

// Check if home is following wcag AA standards
const homeScanResults = await new AxeBuilder({ page }).analyze();

expect(homeScanResults.violations).toEqual([]);

await expect(page.locator('body')).toContainText(
'This is a template site generated with @tomic/template.',
);

await page.goto(`${url}/blog`);

// Check if blog is following wcag AA standards
const blogScanResults = await new AxeBuilder({ page }).analyze();
expect(blogScanResults.violations).toEqual([]);

// Search for a blogpost
const searchInput = page.locator(
'input[aria-label="Search blogposts..."]',
);
await searchInput.fill('balloon');
await expect(page.locator('body')).toContainText('Balloon');
await expect(page.locator('body')).not.toContainText('coffee');
} finally {
child.kill();
}
});

test.afterEach(async () => {
const dirPath = path.join(__dirname, '..', TEMPLATE_DIR_NAME);

try {
await fs.promises.rm(dirPath, { recursive: true, force: true });
} catch (error) {
console.error(`Failed to delete ${TEMPLATE_DIR_NAME}:`, error);
}

await kill(3000);
});
});
Loading

0 comments on commit c9c8712

Please sign in to comment.