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
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ COPY . /usr/local/apache2/htdocs/

FROM base AS tests

# Install necessary packages for Playwright
RUN apt-get update && apt-get install -y \
libnss3 \
libatk-bridge2.0-0 \
libdrm2 \
libxkbcommon0 \
libgtk-3-0 \
libgbm1 \
libasound2 \
&& rm -rf /var/lib/apt/lists/*

# Install Playwright browsers
RUN npx playwright install chromium --with-deps

# Set default command to run BDD tests
CMD ["npm", "run", "test:bdd"]

Expand Down
48 changes: 48 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"markdown-it-attrs": "^4.3.1",
"mini-css-extract-plugin": "^2.9.1",
"moment": "^2.30.1",
"playwright": "^1.54.2",
"postcss-loader": "^8.1.1",
"sass": "^1.89.1",
"sass-loader": "^16.0.2",
Expand Down
85 changes: 71 additions & 14 deletions tests/staging/step_definitions/website_steps.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,78 @@
// Basic step definitions for BDD tests
// These are intentionally minimal placeholders to demonstrate the test framework setup
// Basic step definitions for BDD tests using Playwright
const { Given, When, Then, BeforeAll, AfterAll } = require('@cucumber/cucumber');
const { chromium } = require('playwright');

const { Given, When, Then } = require('@cucumber/cucumber');
let browser;
let context;
let page;

// This step definition is intentionally empty to show the framework works
// but tests still fail due to missing implementation
Given('the Staging site is started', function () {
// TODO: Implement step to start/verify staging site
return 'pending';
// Set up BASE_URL with default value for staging service in Docker network
const BASE_URL = process.env.BASE_URL || 'http://staging';

BeforeAll(async function () {
browser = await chromium.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
context = await browser.newContext({
// Increase timeout for slower Docker environments
timeout: 30000
});
});

AfterAll(async function () {
if (context) await context.close();
if (browser) await browser.close();
});

Given('the Staging site is started', async function () {
page = await context.newPage();

try {
// Verify that the BASE_URL can be reached (allow redirects)
const response = await page.goto(BASE_URL, {
waitUntil: 'networkidle',
timeout: 30000
});

if (!response || !response.ok()) {
throw new Error(`Failed to reach staging site at ${BASE_URL}. Status: ${response ? response.status() : 'No response'}`);
}
} catch (error) {
throw new Error(`Unable to connect to staging site at ${BASE_URL}: ${error.message}`);
}
});

When('the index page is visited', function () {
// TODO: Implement step to visit index page
return 'pending';
When('the index page is visited', async function () {
if (!page) {
throw new Error('Page not initialized. Make sure "Given the Staging site is started" step is executed first.');
}

// Navigate to the index page and ensure it loads without HTTP errors
const response = await page.goto(BASE_URL, {
waitUntil: 'networkidle',
timeout: 30000
});

if (!response || !response.ok()) {
throw new Error(`Index page failed to load. Status: ${response ? response.status() : 'No response'}`);
}

// Verify the page has loaded by checking for basic HTML structure
await page.waitForSelector('html', { timeout: 10000 });
});

Then('the Logo should be displayed in the top left corner', function () {
// TODO: Implement step to verify logo presence and position
return 'pending';
Then('the Logo should be displayed in the top left corner', async function () {
if (!page) {
throw new Error('Page not initialized. Make sure previous steps are executed first.');
}

// Check that favicon.png is somewhere nested under a <nav> element
// This covers both relative paths (favicon.png) and absolute URLs containing favicon.png
try {
const faviconInNav = await page.locator('nav img[src*="favicon.png"]').first();
await faviconInNav.waitFor({ state: 'visible', timeout: 10000 });
} catch (error) {
throw new Error('Logo (favicon.png) is not displayed in a nav element');
}
});