mirror of
https://github.com/dedicatedcode/reitti.git
synced 2026-01-09 17:37:57 -05:00
218 feature request end to end e2e frontend testing framework 2 (#477)
This commit is contained in:
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
e2e/
|
||||||
|
data/
|
||||||
|
docs/
|
||||||
|
scripts/
|
||||||
|
src/
|
||||||
124
.github/workflows/ci.yml
vendored
Normal file
124
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up JDK 25
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '25'
|
||||||
|
distribution: 'temurin'
|
||||||
|
cache: maven
|
||||||
|
|
||||||
|
- name: Install dependencies for acknowledgments script
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y jq curl
|
||||||
|
|
||||||
|
- name: Generate acknowledgments data
|
||||||
|
run: |
|
||||||
|
chmod +x scripts/generate-acknowledgments.sh
|
||||||
|
./scripts/generate-acknowledgments.sh
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: mvn verify -DskipTests
|
||||||
|
|
||||||
|
- name: Create bundle
|
||||||
|
run: mkdir staging && cp target/*.jar staging
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Cache Docker layers
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: docker-${{ runner.os }}-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
docker-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Build docker image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64
|
||||||
|
context: .
|
||||||
|
push: false
|
||||||
|
tags: dedicatedcode/reitti:latest
|
||||||
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
|
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||||
|
|
||||||
|
- name: Move Docker cache
|
||||||
|
run: |
|
||||||
|
rm -rf /tmp/.buildx-cache
|
||||||
|
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
||||||
|
|
||||||
|
- name: Start docker-compose
|
||||||
|
run: docker compose -f docker-compose.ci.yml up -d
|
||||||
|
working-directory: e2e
|
||||||
|
|
||||||
|
- name: Wait for app to be ready
|
||||||
|
run: |
|
||||||
|
timeout 60 bash -c 'until curl -f http://localhost:8080; do sleep 2; done'
|
||||||
|
working-directory: e2e
|
||||||
|
|
||||||
|
- name: Cache npm dependencies
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: e2e/node_modules
|
||||||
|
key: npm-${{ runner.os }}-${{ hashFiles('e2e/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
npm-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
working-directory: e2e
|
||||||
|
|
||||||
|
- name: Cache Playwright browsers
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.cache/ms-playwright
|
||||||
|
key: playwright-${{ runner.os }}-${{ hashFiles('e2e/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
playwright-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Install Playwright browsers
|
||||||
|
run: npx playwright install --with-deps
|
||||||
|
working-directory: e2e
|
||||||
|
|
||||||
|
- name: Run Playwright tests
|
||||||
|
run: CI=1 npx playwright test --project=chromium --project=firefox --project=webkit --project="Mobile Chrome" --project="Mobile Safari"
|
||||||
|
env:
|
||||||
|
BASE_URL: http://localhost:8080
|
||||||
|
working-directory: e2e
|
||||||
|
|
||||||
|
- name: Upload Playwright test results
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: playwright-test-results
|
||||||
|
path: e2e/test-results/
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- name: Upload Playwright report
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: playwright-report
|
||||||
|
path: e2e/playwright-report/
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- name: Stop docker-compose
|
||||||
|
run: docker compose -f docker-compose.ci.yml down
|
||||||
|
working-directory: e2e
|
||||||
|
if: always()
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,3 +32,6 @@ replay_pid*
|
|||||||
|
|
||||||
# Local docker-compose override
|
# Local docker-compose override
|
||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
/e2e/node_modules/
|
||||||
|
/e2e/playwright-report/
|
||||||
|
/e2e/test-results/
|
||||||
|
|||||||
59
e2e/docker-compose.ci.yml
Normal file
59
e2e/docker-compose.ci.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
services:
|
||||||
|
reitti:
|
||||||
|
image: dedicatedcode/reitti:latest
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
depends_on:
|
||||||
|
rabbitmq:
|
||||||
|
condition: service_healthy
|
||||||
|
postgis:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
volumes:
|
||||||
|
- reitti-data:/data/
|
||||||
|
environment:
|
||||||
|
POSTGIS_USER: reitti
|
||||||
|
POSTGIS_PASSWORD: reitti
|
||||||
|
POSTGIS_DB: reittidb
|
||||||
|
POSTGIS_HOST: postgis
|
||||||
|
postgis:
|
||||||
|
image: postgis/postgis:17-3.5-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: reitti
|
||||||
|
POSTGRES_PASSWORD: reitti
|
||||||
|
POSTGRES_DB: reittidb
|
||||||
|
volumes:
|
||||||
|
- postgis-data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U reitti -d reittidb"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
rabbitmq:
|
||||||
|
image: rabbitmq:3-management-alpine
|
||||||
|
environment:
|
||||||
|
RABBITMQ_DEFAULT_USER: reitti
|
||||||
|
RABBITMQ_DEFAULT_PASS: reitti
|
||||||
|
volumes:
|
||||||
|
- rabbitmq-data:/var/lib/rabbitmq
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
volumes:
|
||||||
|
postgis-data:
|
||||||
|
rabbitmq-data:
|
||||||
|
redis-data:
|
||||||
|
reitti-data:
|
||||||
195
e2e/package-lock.json
generated
Normal file
195
e2e/package-lock.json
generated
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
{
|
||||||
|
"name": "e2e-tests",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "e2e-tests",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@midleman/github-actions-reporter": "^1.10.1",
|
||||||
|
"@playwright/test": "^1.40.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/core": {
|
||||||
|
"version": "1.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||||
|
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/exec": "^1.1.1",
|
||||||
|
"@actions/http-client": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/exec": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/io": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/http-client": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tunnel": "^0.0.6",
|
||||||
|
"undici": "^5.25.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/io": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@fastify/busboy": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@midleman/github-actions-reporter": {
|
||||||
|
"version": "1.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@midleman/github-actions-reporter/-/github-actions-reporter-1.10.1.tgz",
|
||||||
|
"integrity": "sha512-G0kTVd8LyylE8fCvQd3CjNXbGAlCb5MO58sgKC1/PCqejz8OiVec8w5kprWFq+JRps4SkPtM4RImwO4iFHzbMQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "^1.10.0",
|
||||||
|
"ansi-to-html": "^0.7.2",
|
||||||
|
"marked": "^12.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/estruyf"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@playwright/test": "^1.42.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@playwright/test": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"playwright": "1.56.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"playwright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@playwright/test/node_modules/playwright": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"playwright-core": "1.56.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"playwright": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-to-html": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"entities": "^2.2.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"ansi-to-html": "bin/ansi-to-html"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/marked": {
|
||||||
|
"version": "12.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz",
|
||||||
|
"integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"marked": "bin/marked.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/playwright-core": {
|
||||||
|
"version": "1.56.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
|
||||||
|
"integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"playwright-core": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tunnel": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "5.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||||
|
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fastify/busboy": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
e2e/package.json
Normal file
27
e2e/package.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "e2e-tests",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Frontend tests",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "playwright test",
|
||||||
|
"test:headed": "playwright test --headed",
|
||||||
|
"test:debug": "playwright test --debug",
|
||||||
|
"test:ui": "playwright test --ui",
|
||||||
|
"docker:up": "docker compose up -d",
|
||||||
|
"docker:down": "docker compose down",
|
||||||
|
"test:docker": "npm run docker:up && sleep 5 && npm run test && npm run docker:down"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.40.0",
|
||||||
|
"@midleman/github-actions-reporter": "^1.10.1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"playwright",
|
||||||
|
"testing",
|
||||||
|
"frontend",
|
||||||
|
"date-picker"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
61
e2e/playwright.config.js
Normal file
61
e2e/playwright.config.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://playwright.dev/docs/test-configuration
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests',
|
||||||
|
/* 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: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: [["html"], ["@midleman/github-actions-reporter"]],
|
||||||
|
/* 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:8080',
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
/* Take screenshot on failure */
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 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'],
|
||||||
|
hasTouch: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Mobile Safari',
|
||||||
|
use: {
|
||||||
|
...devices['iPhone 12'],
|
||||||
|
hasTouch: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
37
e2e/tests/login.spec.js
Normal file
37
e2e/tests/login.spec.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {expect, test} from '@playwright/test';
|
||||||
|
|
||||||
|
test.describe('Login Page Tests', () => {
|
||||||
|
test.beforeEach(async ({page}) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
// Wait for fonts to load to ensure consistent rendering
|
||||||
|
await page.waitForFunction(() => {
|
||||||
|
return document.fonts.ready;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (await page.title() === 'Setup - Reitti') {
|
||||||
|
await page.locator('#password').fill('admin')
|
||||||
|
.then(() => page.keyboard.press('Enter'));
|
||||||
|
}
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should load Login Page', async ({page}) => {
|
||||||
|
// Check if the page loads with the expected title
|
||||||
|
await expect(page).toHaveTitle('Reitti - Login');
|
||||||
|
|
||||||
|
// Check if the main container is present
|
||||||
|
await expect(page.locator('#username')).toBeVisible();
|
||||||
|
await expect(page.locator('#password')).toBeVisible();
|
||||||
|
|
||||||
|
|
||||||
|
await page.locator('#username').fill('admin');
|
||||||
|
await page.locator('#password').fill('admin');
|
||||||
|
|
||||||
|
await page.locator('button:has-text("Login")').click();
|
||||||
|
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
await expect(page.locator('.navbar .nav-link.active')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -385,13 +385,13 @@ class SelectionManager {
|
|||||||
const clickedStart = getTimebandStart(itemData.date, timeband);
|
const clickedStart = getTimebandStart(itemData.date, timeband);
|
||||||
|
|
||||||
if (this.datePicker.options.singleDateMode) {
|
if (this.datePicker.options.singleDateMode) {
|
||||||
this.#handleTimebandSingleDateMode(clickedStart, timeband, itemData);
|
this.#handleTimebandSingleDateMode(clickedStart, timeband);
|
||||||
} else {
|
} else {
|
||||||
this.#handleTimebandRangeMode(clickedStart, timeband, itemData);
|
this.#handleTimebandRangeMode(clickedStart, timeband);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleTimebandSingleDateMode(clickedStart, timeband, itemData) {
|
#handleTimebandSingleDateMode(clickedStart, timeband) {
|
||||||
if (!this.selectedStartDate) {
|
if (!this.selectedStartDate) {
|
||||||
return this.#selectSingleTimebandDate(clickedStart, timeband);
|
return this.#selectSingleTimebandDate(clickedStart, timeband);
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ class SelectionManager {
|
|||||||
this.selectionTimeband = null;
|
this.selectionTimeband = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleTimebandRangeMode(clickedStart, timeband, itemData) {
|
#handleTimebandRangeMode(clickedStart, timeband) {
|
||||||
if (!this.selectedStartDate || (this.selectedStartDate && this.selectedEndDate)) {
|
if (!this.selectedStartDate || (this.selectedStartDate && this.selectedEndDate)) {
|
||||||
// Start new timeband range
|
// Start new timeband range
|
||||||
this.startTimebandRangeSelection(clickedStart, timeband);
|
this.startTimebandRangeSelection(clickedStart, timeband);
|
||||||
@@ -816,9 +816,6 @@ class DatePicker {
|
|||||||
this.render();
|
this.render();
|
||||||
this.#setupScrollListener();
|
this.#setupScrollListener();
|
||||||
this.#setupDelegatedItemEvents();
|
this.#setupDelegatedItemEvents();
|
||||||
if (this.options.startDate) {
|
|
||||||
this.setSelectedRange(this.options.startDate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#createContainer() {
|
#createContainer() {
|
||||||
@@ -1017,11 +1014,6 @@ class DatePicker {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#attachItemEvents(element, itemData, index) {
|
|
||||||
// Backward compatibility for custom renderers that expect direct events.
|
|
||||||
this.#prepareItemElement(element, itemData, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
#prepareItemElement(el, itemData, index) {
|
#prepareItemElement(el, itemData, index) {
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (!el.classList.contains('timeband-item')) {
|
if (!el.classList.contains('timeband-item')) {
|
||||||
@@ -1045,7 +1037,7 @@ class DatePicker {
|
|||||||
if (!data && el.dataset && el.dataset.time && this.itemByTime) {
|
if (!data && el.dataset && el.dataset.time && this.itemByTime) {
|
||||||
data = this.itemByTime.get(Number(el.dataset.time)) || null;
|
data = this.itemByTime.get(Number(el.dataset.time)) || null;
|
||||||
}
|
}
|
||||||
if (data) this.handleItemClick(data, Number.isNaN(idx) ? undefined : idx);
|
if (data) this.handleItemClick(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
this._onMouseOver = (e) => {
|
this._onMouseOver = (e) => {
|
||||||
@@ -1073,7 +1065,7 @@ class DatePicker {
|
|||||||
this.scrollContainer.addEventListener('mouseout', this._onMouseOut, { passive: true });
|
this.scrollContainer.addEventListener('mouseout', this._onMouseOut, { passive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleItemClick(itemData, index) {
|
handleItemClick(itemData) {
|
||||||
const sm = this.selectionManager;
|
const sm = this.selectionManager;
|
||||||
|
|
||||||
if (sm.isSelectingRange &&
|
if (sm.isSelectingRange &&
|
||||||
@@ -1200,7 +1192,6 @@ class DatePicker {
|
|||||||
// Already at max zoom out (YEAR)
|
// Already at max zoom out (YEAR)
|
||||||
this._wheelChainCount = 0;
|
this._wheelChainCount = 0;
|
||||||
this._wheelChainDir = 0;
|
this._wheelChainDir = 0;
|
||||||
return;
|
|
||||||
} else if (dir < 0) { // zoom in
|
} else if (dir < 0) { // zoom in
|
||||||
if (this.currentTimeband === TIMEBANDS.YEAR) {
|
if (this.currentTimeband === TIMEBANDS.YEAR) {
|
||||||
const target = new Date(date.getFullYear(), 0, 1);
|
const target = new Date(date.getFullYear(), 0, 1);
|
||||||
@@ -1215,7 +1206,6 @@ class DatePicker {
|
|||||||
// Already at max zoom in (DAY)
|
// Already at max zoom in (DAY)
|
||||||
this._wheelChainCount = 0;
|
this._wheelChainCount = 0;
|
||||||
this._wheelChainDir = 0;
|
this._wheelChainDir = 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2073,7 +2063,6 @@ class DatePicker {
|
|||||||
end: TimebandUtils.getItemRangeEnd(lastItem, this.currentTimeband)
|
end: TimebandUtils.getItemRangeEnd(lastItem, this.currentTimeband)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** UMD-style export **/
|
/** UMD-style export **/
|
||||||
|
|||||||
Reference in New Issue
Block a user