import Planka upstream

This commit is contained in:
xiaojibeier
2026-07-18 11:48:22 +08:00
commit c26fd3b190
1564 changed files with 214813 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
const BASE_URL = process.env.BASE_URL || 'http://localhost:1337';
const TIMEOUT = parseInt(process.env.TIMEOUT, 10) || 6000;
const PLAYWRIGHT = {
headless: process.env.PLAYWRIGHT_HEADLESS !== 'false',
slowMo: parseInt(process.env.PLAYWRIGHT_SLOW_MO, 10) || 1000,
};
export default {
BASE_URL,
TIMEOUT,
PLAYWRIGHT,
};
@@ -0,0 +1,24 @@
import { After, AfterAll, Before, BeforeAll, setDefaultTimeout } from '@cucumber/cucumber';
import { chromium } from 'playwright';
import Config from './Config.js';
setDefaultTimeout(Config.TIMEOUT);
BeforeAll(async () => {
global.browser = await chromium.launch(Config.PLAYWRIGHT);
});
Before(async () => {
global.context = await global.browser.newContext();
global.page = await global.context.newPage();
});
After(async () => {
await global.page.close();
await global.context.close();
});
AfterAll(async () => {
await global.browser.close();
});
@@ -0,0 +1,22 @@
Feature: Login
Background:
Given the user navigates to the login page
Scenario: User logs in with valid credentials
When the user logs in with email or username "demo" and password "demo" via the web UI
Then the user should be redirected to the home page
Scenario Outline: User logs in with invalid credentials
When the user logs in with email or username "<emailOrUsername>" and password "<password>" via the web UI
Then the user should see the message "<message>"
Examples:
| emailOrUsername | password | message |
| spiderman | spider123 | Invalid credentials |
| ironman | iron123 | Invalid credentials |
| aquaman | aqua123 | Invalid credentials |
Scenario: User logs out
Given the user is logged in with email or username "demo" and password "demo"
When the user logs out via the web UI
Then the user should be redirected to the login page
@@ -0,0 +1,19 @@
import Config from '../Config.js';
export default class HomePage {
constructor() {
this.url = Config.BASE_URL;
this.userActionSelector = 'div.menu > a:last-child';
this.logOutSelector = 'a:has-text("Log Out")';
}
async navigate() {
await page.goto(this.url);
}
async logout() {
await page.click(this.userActionSelector);
await page.click(this.logOutSelector);
}
}
@@ -0,0 +1,26 @@
import Config from '../Config.js';
export default class LoginPage {
constructor() {
this.url = `${Config.BASE_URL}/login`;
this.emailOrUsernameInputSelector = 'input[name="emailOrUsername"]';
this.passwordInputSelector = 'input[name="password"]';
this.logInButtonSelector = 'button.primary';
this.messageSelector = 'div.message > div.content > p';
}
async navigate() {
await page.goto(this.url);
}
async login(emailOrUsername, password) {
await page.fill(this.emailOrUsernameInputSelector, emailOrUsername);
await page.fill(this.passwordInputSelector, password);
await page.click(this.logInButtonSelector);
}
async getMessage() {
return page.innerText(this.messageSelector);
}
}
@@ -0,0 +1,60 @@
import assert from 'assert';
import { Given, Then, When } from '@cucumber/cucumber';
import { expect } from '@playwright/test';
import LoginPage from '../pages/LoginPage.js';
import HomePage from '../pages/HomePage.js';
const loginPage = new LoginPage();
const homePage = new HomePage();
// ---------- GIVEN ----------
Given('the user navigates to the login page', async () => {
await loginPage.navigate();
await expect(page).toHaveURL(loginPage.url);
});
Given(
'the user is logged in with email or username {string} and password {string}',
async (emailOrUsername, password) => {
await loginPage.navigate();
await loginPage.login(emailOrUsername, password);
await expect(page).toHaveURL(homePage.url);
},
);
// ---------- WHEN ----------
When(
'the user logs in with email or username {string} and password {string} via the web UI',
async (emailOrUsername, password) => {
await loginPage.login(emailOrUsername, password);
},
);
When('the user logs out via the web UI', async () => {
await homePage.logout();
});
// ---------- THEN ----------
Then('the user should be redirected to the home page', async () => {
await expect(page).toHaveURL(homePage.url);
});
Then('the user should be redirected to the login page', async () => {
await expect(page).toHaveURL(loginPage.url);
});
Then('the user should see the message {string}', async (expectedMessage) => {
const message = await loginPage.getMessage();
assert.strictEqual(
message,
expectedMessage,
`Expected message to be "${expectedMessage}", but received "${message}"`,
);
});
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# This script sets up symbolic links between the client dist files and the server directories
# Navigate to the root directory of the git repository
cd "$(git rev-parse --show-toplevel)" || { echo "Failed to navigate to the git repository root"; exit 1; }
# Store paths for the client dist, server public, and server views
CLIENT_PATH=$(pwd)/client/dist
SERVER_PUBLIC_PATH=$(pwd)/server/public
SERVER_VIEWS_PATH=$(pwd)/server/views
# Create symbolic links for the necessary client assets in the server's public and views directories
ln -s ${CLIENT_PATH}/favicon.ico ${SERVER_PUBLIC_PATH}/favicon.ico && echo "Linked favicon.ico successfully"
ln -s ${CLIENT_PATH}/logo192.png ${SERVER_PUBLIC_PATH}/logo192.png && echo "Linked logo192.png successfully"
ln -s ${CLIENT_PATH}/logo512.png ${SERVER_PUBLIC_PATH}/logo512.png && echo "Linked logo512.png successfully"
ln -s ${CLIENT_PATH}/manifest.json ${SERVER_PUBLIC_PATH}/manifest.json && echo "Linked manifest.json successfully"
ln -s ${CLIENT_PATH}/robots.txt ${SERVER_PUBLIC_PATH}/robots.txt && echo "Linked robots.txt successfully"
ln -s ${CLIENT_PATH}/assets ${SERVER_PUBLIC_PATH}/assets && echo "Linked assets folder successfully"
ln -s ${CLIENT_PATH}/index.ejs ${SERVER_VIEWS_PATH}/index.ejs && echo "Linked index.ejs successfully"
echo "Setup symbolic links completed successfully."