mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
Merge remote-tracking branch 'origin/master' into 3505-feature-introduce-encrypted-jwts-in-backend-federation-communication
This commit is contained in:
commit
1b6d894bd3
158
.github/workflows/test_e2e.yml
vendored
158
.github/workflows/test_e2e.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
- name: Prepare test system
|
||||
run: |
|
||||
sudo chown runner:docker -R *
|
||||
bun install
|
||||
bun install --frozen-lockfile
|
||||
sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default
|
||||
|
||||
- name: Boot up test system | seed backend
|
||||
@ -40,9 +40,8 @@ jobs:
|
||||
cd backend
|
||||
cp .env.test_e2e .env
|
||||
cd ..
|
||||
bun turbo backend#build
|
||||
bun turbo frontend#build
|
||||
bun turbo backend#start frontend#start --env-mode=loose &
|
||||
bun turbo backend#build frontend#build --env-mode=loose
|
||||
bun turbo backend#start frontend#start --env-mode=loose &
|
||||
|
||||
- name: End-to-end tests | prepare
|
||||
run: |
|
||||
@ -106,3 +105,154 @@ jobs:
|
||||
with:
|
||||
name: backend-logs-pr-#${{ steps.pr.outputs.number }}
|
||||
path: /home/runner/work/gradido/gradido/logs/backend
|
||||
|
||||
end-to-end-tests-playwright:
|
||||
name: End-to-End Tests Playwright
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js version
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18.20.7'
|
||||
|
||||
- name: install bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Boot up test system | docker-compose mariadb mailserver
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach mariadb mailserver
|
||||
|
||||
- name: Prepare test system
|
||||
run: |
|
||||
sudo chown runner:docker -R *
|
||||
bun install --frozen-lockfile
|
||||
sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default
|
||||
|
||||
- name: Boot up test system | seed backend
|
||||
run: bun turbo seed
|
||||
|
||||
- name: copy test config
|
||||
run: |
|
||||
cd frontend
|
||||
cp .env.test_e2e .env
|
||||
cd ../backend
|
||||
cp .env.test_e2e .env
|
||||
|
||||
- name: Moving logs after seeding
|
||||
run: |
|
||||
mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed
|
||||
mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/
|
||||
|
||||
- name: Boot up test system | docker-compose backend, frontend
|
||||
run: |
|
||||
bun turbo backend#build frontend#build --env-mode=loose
|
||||
bun turbo backend#start frontend#start --env-mode=loose &
|
||||
|
||||
- name: End-to-end tests | prepare
|
||||
run: |
|
||||
cd e2e-tests/playwright/typescript
|
||||
bun install
|
||||
|
||||
- name: wait for frontend and backend to be ready
|
||||
run: |
|
||||
until nc -z 127.0.0.1 3000; do echo waiting for frontend; sleep 1; done;
|
||||
until nc -z 127.0.0.1 4000; do echo waiting for backend; sleep 1; done;
|
||||
|
||||
- name: Start local nginx webserver
|
||||
run: |
|
||||
sudo nginx -t
|
||||
sudo systemctl start nginx
|
||||
|
||||
- name: wait for nginx and mailserver to be ready
|
||||
run: |
|
||||
until nc -z 127.0.0.1 80; do echo waiting for nginx; sleep 1; done;
|
||||
until nc -z 127.0.0.1 1025; do echo waiting for mailserver; sleep 1; done;
|
||||
|
||||
- name: End-to-end tests | run tests
|
||||
id: e2e-tests
|
||||
run: |
|
||||
cd e2e-tests/playwright/typescript
|
||||
bun run test --project="Google Chrome"
|
||||
|
||||
- name: End-to-end tests | if tests failed, upload video
|
||||
id: e2e-video
|
||||
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cypress-videos-pr-#${{ steps.pr.outputs.number }}
|
||||
path: /home/runner/work/gradido/gradido/e2e-tests/playwright/typescript/test-results
|
||||
|
||||
end-to-end-tests-playwright-java:
|
||||
name: End-to-End Tests Playwright java
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js version
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18.20.7'
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: install bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Boot up test system | docker-compose mariadb mailserver
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach mariadb mailserver
|
||||
|
||||
- name: Prepare test system
|
||||
run: |
|
||||
sudo chown runner:docker -R *
|
||||
bun install
|
||||
sudo cp ./nginx/e2e-test.conf /etc/nginx/sites-available/default
|
||||
|
||||
- name: Boot up test system | seed backend
|
||||
run: bun turbo seed
|
||||
|
||||
- name: Moving logs after seeding
|
||||
run: |
|
||||
mkdir -p /home/runner/work/gradido/gradido/logs/backend/seed
|
||||
mv /home/runner/work/gradido/gradido/logs/backend/*.log /home/runner/work/gradido/gradido/logs/backend/seed/
|
||||
|
||||
- name: Boot up test system | docker-compose backend, frontend
|
||||
run: |
|
||||
cd backend
|
||||
cp .env.test_e2e .env
|
||||
cd ..
|
||||
bun turbo backend#build frontend#build --env-mode=loose
|
||||
bun turbo backend#start frontend#start --env-mode=loose &
|
||||
|
||||
- name: End-to-end tests | prepare
|
||||
run: |
|
||||
cd e2e-tests/playwright/typescript
|
||||
bun install
|
||||
|
||||
- name: wait for frontend and backend to be ready
|
||||
run: |
|
||||
until nc -z 127.0.0.1 3000; do echo waiting for frontend; sleep 1; done;
|
||||
until nc -z 127.0.0.1 4000; do echo waiting for backend; sleep 1; done;
|
||||
|
||||
- name: Start local nginx webserver
|
||||
run: |
|
||||
sudo nginx -t
|
||||
sudo systemctl start nginx
|
||||
|
||||
- name: wait for nginx and mailserver to be ready
|
||||
run: |
|
||||
until nc -z 127.0.0.1 80; do echo waiting for nginx; sleep 1; done;
|
||||
until nc -z 127.0.0.1 1025; do echo waiting for mailserver; sleep 1; done;
|
||||
|
||||
- name: End-to-end tests | run tests
|
||||
id: e2e-tests
|
||||
run: |
|
||||
cd e2e-tests/playwright/java
|
||||
mvn -B install -D skipTests --no-transfer-progress
|
||||
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
|
||||
mvn test
|
||||
@ -4,6 +4,7 @@ JWT_EXPIRES_IN=2m
|
||||
GDT_ACTIVE=false
|
||||
HUMHUB_ACTIVE=false
|
||||
GMS_ACTIVE=false
|
||||
USE_CRYPTO_WORKER=true
|
||||
|
||||
# Email
|
||||
EMAIL=true
|
||||
|
||||
@ -58,6 +58,7 @@ const run = async () => {
|
||||
const { con } = server
|
||||
await cleanDB()
|
||||
logger.info('##seed## clean database successful...')
|
||||
logger.info(`crypto worker enabled: ${CONFIG.USE_CRYPTO_WORKER}`)
|
||||
|
||||
// seed home community
|
||||
await writeHomeCommunityEntry()
|
||||
|
||||
2
e2e-tests/.gitignore
vendored
2
e2e-tests/.gitignore
vendored
@ -3,4 +3,4 @@ cypress/screenshots/
|
||||
cypress/videos/
|
||||
cypress/reports/
|
||||
cucumber-messages.ndjson
|
||||
|
||||
**/target
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
###############################################################################
|
||||
# Dockerfile to create a ready-to-use Playwright Docker image for end-to-end
|
||||
# testing.
|
||||
#
|
||||
# To avoid hardcoded versoning of Playwright, this Dockerfile is a custom
|
||||
# version of the ready-to-use Dockerfile privided by Playwright developement
|
||||
# (https://github.com/microsoft/playwright/blob/main/utils/docker/Dockerfile.focal)
|
||||
#
|
||||
# Here the latest stable versions of the browsers Chromium, Firefox, and Webkit
|
||||
# (Safari) are installed, icluding all dependencies based on Ubuntu specified by
|
||||
# Playwright developement.
|
||||
###############################################################################
|
||||
|
||||
FROM ubuntu:focal
|
||||
|
||||
# set a timezone for the Playwright browser dependency installation
|
||||
ARG TZ=Europe/Berlin
|
||||
|
||||
ARG DOCKER_WORKDIR=/tests/
|
||||
WORKDIR $DOCKER_WORKDIR
|
||||
|
||||
# package manager preparation
|
||||
RUN apt-get -qq update && apt-get install -qq -y curl gpg > /dev/null
|
||||
# for Node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
|
||||
# for Yarn
|
||||
RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||
|
||||
# install node v16 and Yarn
|
||||
RUN apt-get -qq update && apt-get install -qq -y nodejs yarn
|
||||
|
||||
COPY tests/package.json tests/yarn.lock $DOCKER_WORKDIR
|
||||
|
||||
# install Playwright with all dependencies
|
||||
# for the browsers chromium, firefox, and webkit
|
||||
RUN yarn install && yarn playwright install --with-deps
|
||||
|
||||
# clean up
|
||||
RUN rm -rf /var/lib/apt/lists/* && apt-get -qq clean
|
||||
|
||||
COPY tests/ $DOCKER_WORKDIR
|
||||
@ -1,24 +0,0 @@
|
||||
# Gradido End-to-End Testing with [Playwright](https://playwright.dev/) (CI-ready via Docker)
|
||||
|
||||
|
||||
A sample setup to show-case Playwright (using Typescript) as an end-to-end testing tool for Gradido runniing in a Docker container.
|
||||
Here we have a simple UI-based happy path login test running against the DEV system.
|
||||
|
||||
## Precondition
|
||||
Since dependencies and configurations for Github Actions integration is not set up yet, please run in root directory
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
to boot up the DEV system, before running the test.
|
||||
|
||||
## Execute the test
|
||||
|
||||
```bash
|
||||
# build a Docker image from the Dockerfile
|
||||
docker build -t gradido_e2e-tests-playwright .
|
||||
|
||||
# run the Docker container and execute the given tests
|
||||
docker run -it --network=host gradido_e2e-tests-playwright yarn playwright-e2e-tests
|
||||
```
|
||||
12
e2e-tests/playwright/java/Readme.md
Normal file
12
e2e-tests/playwright/java/Readme.md
Normal file
@ -0,0 +1,12 @@
|
||||
# gradido-e2e-tests-playwright with java
|
||||
|
||||
Experimental End-to-end tests with Playwright and Java
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Java 17
|
||||
- Maven
|
||||
- Playwright
|
||||
- Gradle
|
||||
- Git
|
||||
|
||||
52
e2e-tests/playwright/java/pom.xml
Normal file
52
e2e-tests/playwright/java/pom.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.gradido</groupId>
|
||||
<artifactId>gradido-e2e-tests-playwright</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<name>Gradido Playwright End-to-End Tests in Java</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.playwright</groupId>
|
||||
<artifactId>playwright</artifactId>
|
||||
<version>1.52.0</version>
|
||||
</dependency>
|
||||
<!-- JUnit Jupiter API & Engine -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<!-- References to interface static methods are allowed only at source level 1.8 or above -->
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M9</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Test*.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,69 @@
|
||||
package net.gradido.e2e.base;
|
||||
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.microsoft.playwright.BrowserContext;
|
||||
import com.microsoft.playwright.Playwright;
|
||||
import com.microsoft.playwright.Page;
|
||||
import com.microsoft.playwright.Tracing;
|
||||
import org.junit.jupiter.api.*;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
// Subclasses will inherit PER_CLASS behavior.
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class BaseTest {
|
||||
|
||||
protected Playwright playwright;
|
||||
protected Browser browser;
|
||||
|
||||
@BeforeAll
|
||||
void setUpAll() {
|
||||
playwright = Playwright.create();
|
||||
browser = playwright.chromium().launch();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
void tearDownAll() {
|
||||
playwright.close();
|
||||
}
|
||||
|
||||
// New instance for each test method.
|
||||
protected BrowserContext context;
|
||||
protected Page page;
|
||||
protected Path currentTracePath;
|
||||
|
||||
@BeforeEach
|
||||
void setUp(TestInfo testInfo) {
|
||||
context = browser.newContext(
|
||||
new Browser.NewContextOptions().setBaseURL("http://localhost:3000")
|
||||
);
|
||||
context.route("**/*", route -> {
|
||||
String url = route.request().url();
|
||||
|
||||
// we skip fontawesome and googleapis requests, we don't need them for functions test, but they cost time
|
||||
if (url.contains("use.fontawesome.com") || url.contains("fonts.googleapis.com")) {
|
||||
route.abort();
|
||||
return;
|
||||
}
|
||||
route.resume();
|
||||
});
|
||||
|
||||
// Start tracing before creating
|
||||
String testName = testInfo.getDisplayName().replaceAll("[^a-zA-Z0-9]", "");
|
||||
currentTracePath = Paths.get("target/traces/" + testName + ".zip");
|
||||
context.tracing().start(new Tracing.StartOptions()
|
||||
.setScreenshots(true)
|
||||
.setSnapshots(true)
|
||||
.setSources(true));
|
||||
page = context.newPage();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
// Stop tracing and export it into a zip archive.
|
||||
context.tracing().stop(new Tracing.StopOptions().setPath(currentTracePath));
|
||||
|
||||
page.close();
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package net.gradido.e2e.components;
|
||||
|
||||
import com.microsoft.playwright.Locator;
|
||||
import com.microsoft.playwright.Page;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class Toasts {
|
||||
public final Locator toastSlot;
|
||||
public final Locator toastTypeError;
|
||||
public final Locator toastTitle;
|
||||
public final Locator toastMessage;
|
||||
|
||||
public Toasts(Page page) {
|
||||
toastSlot = page.locator("#__BVID__toaster-container");
|
||||
toastTypeError = toastSlot.locator(".toast.text-bg-danger");
|
||||
toastTitle = toastTypeError.locator(".gdd-toaster-title");
|
||||
toastMessage = toastTypeError.locator(".gdd-toaster-body");
|
||||
}
|
||||
|
||||
public void assertErrorToastVisible() {
|
||||
toastTypeError.waitFor();
|
||||
assertTrue(toastTitle.isVisible());
|
||||
assertTrue(toastMessage.isVisible());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package net.gradido.e2e.pages;
|
||||
|
||||
import com.microsoft.playwright.Locator;
|
||||
import com.microsoft.playwright.Page;
|
||||
import com.microsoft.playwright.Response;
|
||||
|
||||
public class LoginPage {
|
||||
private final Page page;
|
||||
|
||||
private final Locator emailInput;
|
||||
private final Locator passwordInput;
|
||||
private final Locator submitButton;
|
||||
|
||||
public LoginPage(Page page) {
|
||||
this.page = page;
|
||||
emailInput = page.locator("input[name='email']");
|
||||
passwordInput = page.locator("input[name='password']");
|
||||
submitButton = page.locator("button[type='submit']");
|
||||
}
|
||||
|
||||
public void login(String email, String password) {
|
||||
emailInput.fill(email);
|
||||
passwordInput.fill(password);
|
||||
Response response = page.waitForResponse("**/graphql", () -> {
|
||||
submitButton.click();
|
||||
});
|
||||
}
|
||||
|
||||
public void navigate() {
|
||||
page.navigate("http://localhost:3000/login");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package net.gradido.e2e.tests;
|
||||
|
||||
import net.gradido.e2e.base.BaseTest;
|
||||
import net.gradido.e2e.pages.LoginPage;
|
||||
import net.gradido.e2e.components.Toasts;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class InvalidLoginTest extends BaseTest {
|
||||
private LoginPage loginPage;
|
||||
|
||||
@BeforeEach
|
||||
void initPageObjects() {
|
||||
loginPage = new LoginPage(page);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidUserSeesError() {
|
||||
loginPage.navigate();
|
||||
loginPage.login("peter@lustig.de", "wrongpass");
|
||||
Toasts toast = new Toasts(page);
|
||||
toast.assertErrorToastVisible();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package net.gradido.e2e.tests;
|
||||
|
||||
import net.gradido.e2e.base.BaseTest;
|
||||
import net.gradido.e2e.pages.LoginPage;
|
||||
import net.gradido.e2e.components.Toasts;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ValidLoginTest extends BaseTest {
|
||||
private LoginPage loginPage;
|
||||
|
||||
@BeforeEach
|
||||
void initPageObjects() {
|
||||
loginPage = new LoginPage(page);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validUserCanLogin() {
|
||||
loginPage.navigate();
|
||||
loginPage.login("peter@lustig.de", "Aa12345_");
|
||||
page.waitForURL("http://localhost:3000/overview");
|
||||
assertTrue(page.url().contains("/overview"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
junit.jupiter.execution.parallel.enabled = true
|
||||
junit.jupiter.execution.parallel.mode.default = same_thread
|
||||
junit.jupiter.execution.parallel.mode.classes.default = concurrent
|
||||
junit.jupiter.execution.parallel.config.strategy=dynamic
|
||||
junit.jupiter.execution.parallel.config.dynamic.factor=0.5
|
||||
@ -1,10 +0,0 @@
|
||||
import { FullConfig } from '@playwright/test';
|
||||
|
||||
async function globalSetup(config: FullConfig) {
|
||||
process.env.EMAIL = 'bibi@bloxberg.de';
|
||||
process.env.PASSWORD = 'Aa12345_';
|
||||
process.env.GMS_ACTIVE = false;
|
||||
process.env.HUMHUB_ACTIVE = false;
|
||||
}
|
||||
|
||||
export default globalSetup;
|
||||
@ -1,15 +0,0 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { LoginPage } from './models/login_page';
|
||||
import { WelcomePage } from './models/welcome_page';
|
||||
|
||||
|
||||
test('Gradido login test (happy path)', async ({ page }) => {
|
||||
const { EMAIL, PASSWORD } = process.env;
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.enterEmail(EMAIL);
|
||||
await loginPage.enterPassword(PASSWORD);
|
||||
await loginPage.submitLogin();
|
||||
// assertions
|
||||
await expect(page).toHaveURL('./overview');
|
||||
});
|
||||
@ -1,33 +0,0 @@
|
||||
import { expect, test, Locator, Page } from '@playwright/test';
|
||||
|
||||
export class LoginPage {
|
||||
readonly page: Page;
|
||||
readonly url: string;
|
||||
readonly emailInput: Locator;
|
||||
readonly passwordInput: Locator;
|
||||
readonly submitBtn: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.url = './login';
|
||||
this.emailInput = page.locator('id=Email-input-field');
|
||||
this.passwordInput = page.locator('id=Password-input-field');
|
||||
this.submitBtn = page.locator('text=Login');
|
||||
}
|
||||
|
||||
async goto() {
|
||||
await this.page.goto(this.url);
|
||||
}
|
||||
|
||||
async enterEmail(email: string) {
|
||||
await this.emailInput.fill(email);
|
||||
}
|
||||
|
||||
async enterPassword(password: string) {
|
||||
await this.passwordInput.fill(password);
|
||||
}
|
||||
|
||||
async submitLogin() {
|
||||
await this.submitBtn.click();
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
import { expect, Locator, Page } from '@playwright/test';
|
||||
|
||||
export class WelcomePage {
|
||||
readonly page: Page;
|
||||
readonly url: string;
|
||||
readonly profileLink: Locator;
|
||||
|
||||
constructor(page: Page){
|
||||
this.page = page;
|
||||
this.url = './overview';
|
||||
this.profileLink = page.locator('href=/profile');
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
globalSetup: require.resolve('./global-setup'),
|
||||
ignoreHTTPSErrors: true,
|
||||
locale: 'de-DE',
|
||||
reporter: process.env.CI ? 'github' : 'list',
|
||||
retries: 1,
|
||||
screenshot: 'only-on-failure',
|
||||
testDir: '.',
|
||||
timeout: 30000,
|
||||
trace: 'on-first-retry',
|
||||
video: 'never',
|
||||
viewport: { width: 1280, height: 720 },
|
||||
use: {
|
||||
baseURL: process.env.URL || 'http://127.0.0.1:3000',
|
||||
browserName: 'webkit',
|
||||
|
||||
},
|
||||
};
|
||||
export default config;
|
||||
7
e2e-tests/playwright/typescript/.gitignore
vendored
Normal file
7
e2e-tests/playwright/typescript/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
# Playwright
|
||||
node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
22
e2e-tests/playwright/typescript/components/Toasts.ts
Normal file
22
e2e-tests/playwright/typescript/components/Toasts.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import type { Locator, Page } from '@playwright/test'
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
export class Toasts {
|
||||
public readonly toastSlot: Locator
|
||||
public readonly toastTypeError: Locator
|
||||
public readonly toastTitle: Locator
|
||||
public readonly toastMessage: Locator
|
||||
|
||||
constructor(page: Page) {
|
||||
this.toastSlot = page.locator('#__BVID__toaster-container')
|
||||
this.toastTypeError = this.toastSlot.locator('.toast.text-bg-danger')
|
||||
this.toastTitle = this.toastTypeError.locator('.gdd-toaster-title')
|
||||
this.toastMessage = this.toastTypeError.locator('.gdd-toaster-body')
|
||||
}
|
||||
|
||||
async assertErrorToastVisible(): Promise<void> {
|
||||
await this.toastTypeError.waitFor({ state: 'visible' })
|
||||
expect(this.toastTitle).toBeVisible()
|
||||
expect(this.toastMessage).toBeVisible()
|
||||
}
|
||||
}
|
||||
1
e2e-tests/playwright/typescript/config/index.ts
Normal file
1
e2e-tests/playwright/typescript/config/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export const FRONTEND_URL = "http://localhost:3000"
|
||||
13
e2e-tests/playwright/typescript/package.json
Normal file
13
e2e-tests/playwright/typescript/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "typescript",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.53.1",
|
||||
"@types/node": "^24.0.7"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "playwright test --reporter=list"
|
||||
}
|
||||
}
|
||||
28
e2e-tests/playwright/typescript/pages/LoginPage.ts
Normal file
28
e2e-tests/playwright/typescript/pages/LoginPage.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import type { Locator, Page } from '@playwright/test'
|
||||
import { FRONTEND_URL } from '../config'
|
||||
|
||||
export class LoginPage {
|
||||
readonly page: Page
|
||||
readonly emailInput: Locator
|
||||
readonly passwordInput: Locator
|
||||
readonly submitButton: Locator
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page
|
||||
this.emailInput = page.locator('#email-input-field')
|
||||
this.passwordInput = page.locator('#password-input-field')
|
||||
this.submitButton = page.locator("button[type='submit']")
|
||||
}
|
||||
|
||||
async goto() {
|
||||
await this.page.goto(`${FRONTEND_URL}/login`)
|
||||
}
|
||||
|
||||
async login(email: string, password: string) {
|
||||
await this.emailInput.fill(email)
|
||||
await this.passwordInput.fill(password)
|
||||
const responsePromise = this.page.waitForResponse('**/graphql')
|
||||
await this.submitButton.click()
|
||||
await responsePromise
|
||||
}
|
||||
}
|
||||
82
e2e-tests/playwright/typescript/playwright.config.ts
Normal file
82
e2e-tests/playwright/typescript/playwright.config.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// import dotenv from 'dotenv';
|
||||
// import path from 'path';
|
||||
// dotenv.config({ path: path.resolve(__dirname, '.env') });
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: './tests',
|
||||
// Glob patterns or regular expressions that match test files.
|
||||
testMatch: '*',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: 2,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? '90%' : '75%',
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
// baseURL: 'http://localhost:3000',
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
video: 'on-first-retry',
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
// name: 'Mobile Chrome',
|
||||
// use: { ...devices['Pixel 5'] },
|
||||
// },
|
||||
// {
|
||||
// name: 'Mobile Safari',
|
||||
// use: { ...devices['iPhone 12'] },
|
||||
// },
|
||||
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||
// },
|
||||
{
|
||||
name: 'Google Chrome',
|
||||
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||
},
|
||||
],
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
// webServer: {
|
||||
// command: 'npm run start',
|
||||
// url: 'http://localhost:3000',
|
||||
// reuseExistingServer: !process.env.CI,
|
||||
// },
|
||||
});
|
||||
13
e2e-tests/playwright/typescript/tests/InvalidLoginTest.ts
Normal file
13
e2e-tests/playwright/typescript/tests/InvalidLoginTest.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { LoginPage } from '../pages/LoginPage'
|
||||
import { Toasts } from '../components/Toasts'
|
||||
|
||||
test('invalid login', async ({ page }) => {
|
||||
const loginPage = new LoginPage(page)
|
||||
await loginPage.goto()
|
||||
await loginPage.login('peter@lustig.de', 'wrongpass')
|
||||
|
||||
const toast = new Toasts(page)
|
||||
await toast.assertErrorToastVisible()
|
||||
await page.waitForTimeout(50)
|
||||
})
|
||||
11
e2e-tests/playwright/typescript/tests/ValidLoginTest.ts
Normal file
11
e2e-tests/playwright/typescript/tests/ValidLoginTest.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { LoginPage } from '../pages/LoginPage'
|
||||
import { FRONTEND_URL } from '../config'
|
||||
|
||||
test('valid login', async ({ page }) => {
|
||||
const loginPage = new LoginPage(page)
|
||||
await loginPage.goto()
|
||||
await loginPage.login('peter@lustig.de', 'Aa12345_')
|
||||
await page.waitForURL(`${FRONTEND_URL}/overview`)
|
||||
expect(page.url()).toContain('/overview')
|
||||
})
|
||||
41
e2e-tests/playwright/typescript/yarn.lock
Normal file
41
e2e-tests/playwright/typescript/yarn.lock
Normal file
@ -0,0 +1,41 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@playwright/test@^1.53.1":
|
||||
version "1.53.1"
|
||||
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.53.1.tgz#3ad5a2ce334b4a78390fd91e0a9d8423c09bc808"
|
||||
integrity sha512-Z4c23LHV0muZ8hfv4jw6HngPJkbbtZxTkxPNIg7cJcTc9C28N/p2q7g3JZS2SiKBBHJ3uM1dgDye66bB7LEk5w==
|
||||
dependencies:
|
||||
playwright "1.53.1"
|
||||
|
||||
"@types/node@^24.0.7":
|
||||
version "24.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.7.tgz#ee580f7850c7eabaeef61ef96b8d8c04fdf94f53"
|
||||
integrity sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==
|
||||
dependencies:
|
||||
undici-types "~7.8.0"
|
||||
|
||||
fsevents@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
playwright-core@1.53.1:
|
||||
version "1.53.1"
|
||||
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.53.1.tgz#0b6f7a2006ccb6126ffcc3e3b2fa9efda23b6638"
|
||||
integrity sha512-Z46Oq7tLAyT0lGoFx4DOuB1IA9D1TPj0QkYxpPVUnGDqHHvDpCftu1J2hM2PiWsNMoZh8+LQaarAWcDfPBc6zg==
|
||||
|
||||
playwright@1.53.1:
|
||||
version "1.53.1"
|
||||
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.53.1.tgz#86fb041b237a6868d163c87c4b9737fd1cac145e"
|
||||
integrity sha512-LJ13YLr/ocweuwxyGf1XNFWIU4M2zUSo149Qbp+A4cpwDjsxRPj7k6H25LBrEHiEwxvRbD8HdwvQmRMSvquhYw==
|
||||
dependencies:
|
||||
playwright-core "1.53.1"
|
||||
optionalDependencies:
|
||||
fsevents "2.3.2"
|
||||
|
||||
undici-types@~7.8.0:
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294"
|
||||
integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==
|
||||
1
frontend/.env.test_e2e
Normal file
1
frontend/.env.test_e2e
Normal file
@ -0,0 +1 @@
|
||||
GRAPHQL_URI=http://127.0.0.1:4000/graphql
|
||||
Loading…
x
Reference in New Issue
Block a user