diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7ce341f..aac5c05e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,14 +32,14 @@ jobs: --health-retries 5 steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Set up Go ${{ matrix.go-version }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - - name: Check out code into the Go module directory - uses: actions/checkout@v4 - - name: Set up Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 61c60c6a..f1c9f7ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,14 +12,14 @@ jobs: go-version: [ "1.22" ] steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Set up Go ${{ matrix.go-version }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - - name: Check out code into the Go module directory - uses: actions/checkout@v4 - - name: Copy swagger docs dummy file and Create dummy ui/dist/index.html run: mkdir ui/dist && touch ui/dist/index.html diff --git a/e2e/fixtures/login-page.ts b/e2e/fixtures/login-page.ts index 2f3bb099..58187df6 100644 --- a/e2e/fixtures/login-page.ts +++ b/e2e/fixtures/login-page.ts @@ -7,7 +7,7 @@ export class LoginPage { constructor(page: Page) { this.emailField = page.getByPlaceholder("Enter your email"); - this.passwordField = page.getByPlaceholder("Enter a password"); + this.passwordField = page.getByPlaceholder("Enter your password"); this.page = page; } diff --git a/e2e/package-lock.json b/e2e/package-lock.json index f855af79..41145782 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -9,35 +9,88 @@ "version": "0.0.0", "license": "Apache-2.0", "devDependencies": { + "@estruyf/github-actions-reporter": "^1.6.0", "@playwright/test": "^1.35.1", "pg": "^8.11.0", "prettier": "^3.0.3" } }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dev": true, + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", + "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "dev": true, + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@estruyf/github-actions-reporter": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@estruyf/github-actions-reporter/-/github-actions-reporter-1.6.0.tgz", + "integrity": "sha512-/psxlmgV70kPA9BE50nWYeBXlgt77FRzxdjT3WQDZ7gCCvjHx21Mh54Vlj+75TlxcJOU2LuB32c+1W6fyPrF6w==", + "dev": true, + "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/@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/@playwright/test": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz", - "integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.0.tgz", + "integrity": "sha512-Ebw0+MCqoYflop7wVKj711ccbNlrwTBCtjY5rlbiY9kHL2bCYxq+qltK6uPsVBGGAOb033H2VO0YobcQVxoW7Q==", "dev": true, "dependencies": { - "@types/node": "*", - "playwright-core": "1.35.1" + "playwright": "1.43.0" }, "bin": { "playwright": "cli.js" }, "engines": { "node": ">=16" - }, - "optionalDependencies": { - "fsevents": "2.3.2" } }, - "node_modules/@types/node": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz", - "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==", - "dev": true + "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/buffer-writer": { "version": "2.0.0", @@ -48,6 +101,15 @@ "node": ">=4" } }, + "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", @@ -62,6 +124,18 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/marked": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", + "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -159,10 +233,28 @@ "split2": "^4.1.0" } }, + "node_modules/playwright": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", + "integrity": "sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==", + "dev": true, + "dependencies": { + "playwright-core": "1.43.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, "node_modules/playwright-core": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz", - "integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.0.tgz", + "integrity": "sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -234,6 +326,36 @@ "node": ">= 10.x" } }, + "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.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -245,29 +367,73 @@ } }, "dependencies": { - "@playwright/test": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz", - "integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==", + "@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", "dev": true, "requires": { - "@types/node": "*", - "fsevents": "2.3.2", - "playwright-core": "1.35.1" + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "@actions/http-client": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", + "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "dev": true, + "requires": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "@estruyf/github-actions-reporter": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@estruyf/github-actions-reporter/-/github-actions-reporter-1.6.0.tgz", + "integrity": "sha512-/psxlmgV70kPA9BE50nWYeBXlgt77FRzxdjT3WQDZ7gCCvjHx21Mh54Vlj+75TlxcJOU2LuB32c+1W6fyPrF6w==", + "dev": true, + "requires": { + "@actions/core": "^1.10.0", + "ansi-to-html": "^0.7.2", + "marked": "^12.0.1" } }, - "@types/node": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz", - "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==", + "@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true }, + "@playwright/test": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.0.tgz", + "integrity": "sha512-Ebw0+MCqoYflop7wVKj711ccbNlrwTBCtjY5rlbiY9kHL2bCYxq+qltK6uPsVBGGAOb033H2VO0YobcQVxoW7Q==", + "dev": true, + "requires": { + "playwright": "1.43.0" + } + }, + "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, + "requires": { + "entities": "^2.2.0" + } + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", "dev": true }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -275,6 +441,12 @@ "dev": true, "optional": true }, + "marked": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", + "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", + "dev": true + }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -351,10 +523,20 @@ "split2": "^4.1.0" } }, + "playwright": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", + "integrity": "sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.43.0" + } + }, "playwright-core": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz", - "integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.0.tgz", + "integrity": "sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==", "dev": true }, "postgres-array": { @@ -396,6 +578,27 @@ "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", "dev": true }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true + }, + "undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "requires": { + "@fastify/busboy": "^2.0.0" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/e2e/package.json b/e2e/package.json index 2dbe1632..7d4c5779 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -12,6 +12,7 @@ "author": "Steven Weathers", "license": "Apache-2.0", "devDependencies": { + "@estruyf/github-actions-reporter": "^1.6.0", "@playwright/test": "^1.35.1", "pg": "^8.11.0", "prettier": "^3.0.3" diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index bebc095f..b7c9ce27 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -32,7 +32,7 @@ const config: PlaywrightTestConfig = { /* 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", + reporter: [["list"], ["html"], ["@estruyf/github-actions-reporter"]], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ diff --git a/e2e/tests/admin/admin.spec.ts b/e2e/tests/admin/admin.spec.ts index 4bf6a263..66d68613 100644 --- a/e2e/tests/admin/admin.spec.ts +++ b/e2e/tests/admin/admin.spec.ts @@ -8,8 +8,8 @@ test.describe("Admin page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/alerts.spec.ts b/e2e/tests/admin/alerts.spec.ts index 6782a21c..a28c092f 100644 --- a/e2e/tests/admin/alerts.spec.ts +++ b/e2e/tests/admin/alerts.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Alerts Page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/apikeys.spec.ts b/e2e/tests/admin/apikeys.spec.ts index 1d55559d..980631c3 100644 --- a/e2e/tests/admin/apikeys.spec.ts +++ b/e2e/tests/admin/apikeys.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin API Keys Page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/department.spec.ts b/e2e/tests/admin/department.spec.ts index 329c393e..9bbf80fd 100644 --- a/e2e/tests/admin/department.spec.ts +++ b/e2e/tests/admin/department.spec.ts @@ -11,8 +11,8 @@ test.describe("The Admin Department Page", () => { "bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa", ); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/organization.spec.ts b/e2e/tests/admin/organization.spec.ts index 0a21085b..f7d847dd 100644 --- a/e2e/tests/admin/organization.spec.ts +++ b/e2e/tests/admin/organization.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Organization Page", () => { await adminPage.goto("bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa"); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/organizations.spec.ts b/e2e/tests/admin/organizations.spec.ts index 47b21c8b..54aa2fb5 100644 --- a/e2e/tests/admin/organizations.spec.ts +++ b/e2e/tests/admin/organizations.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Organizations Page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/poker-games.spec.ts b/e2e/tests/admin/poker-games.spec.ts index 79c3d0be..2fe7d513 100644 --- a/e2e/tests/admin/poker-games.spec.ts +++ b/e2e/tests/admin/poker-games.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Poker Games Page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/team.spec.ts b/e2e/tests/admin/team.spec.ts index 0aae5288..29cbf563 100644 --- a/e2e/tests/admin/team.spec.ts +++ b/e2e/tests/admin/team.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Team Page", () => { await adminPage.goto("bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa"); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/teams.spec.ts b/e2e/tests/admin/teams.spec.ts index aeb529be..2ed9d3a0 100644 --- a/e2e/tests/admin/teams.spec.ts +++ b/e2e/tests/admin/teams.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Teams Page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/admin/users.spec.ts b/e2e/tests/admin/users.spec.ts index 2bae4b6b..f6438d63 100644 --- a/e2e/tests/admin/users.spec.ts +++ b/e2e/tests/admin/users.spec.ts @@ -8,8 +8,8 @@ test.describe("The Admin Users Page", () => { await adminPage.goto(); - const title = adminPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = adminPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/checkin.spec.ts b/e2e/tests/checkin.spec.ts index 4c6192be..2eaa8c58 100644 --- a/e2e/tests/checkin.spec.ts +++ b/e2e/tests/checkin.spec.ts @@ -7,8 +7,8 @@ test.describe("Team Checkin page", () => { const teamPage = new TeamCheckinPage(page); await teamPage.goto("bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa"); - const title = teamPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = teamPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/department.spec.ts b/e2e/tests/department.spec.ts index c1c743a6..216a76bf 100644 --- a/e2e/tests/department.spec.ts +++ b/e2e/tests/department.spec.ts @@ -10,8 +10,8 @@ test.describe("Department page", () => { "bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa", ); - const title = departmentPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = departmentPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/organization.spec.ts b/e2e/tests/organization.spec.ts index 74ecfd42..207c3165 100644 --- a/e2e/tests/organization.spec.ts +++ b/e2e/tests/organization.spec.ts @@ -6,8 +6,8 @@ test.describe("Organization Page", () => { const orgPage = new OrganizationPage(page); await orgPage.goto("bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa"); - const title = orgPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = orgPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); test("Registered user loads page successfully", async ({ diff --git a/e2e/tests/poker-games.spec.ts b/e2e/tests/poker-games.spec.ts index 325ba336..c57399ec 100644 --- a/e2e/tests/poker-games.spec.ts +++ b/e2e/tests/poker-games.spec.ts @@ -10,8 +10,8 @@ test.describe("Poker Games page", () => { const battlesPage = new PokerGamesPage(page); await battlesPage.goto(); - const title = battlesPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = battlesPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/profile.spec.ts b/e2e/tests/profile.spec.ts index 27d70825..2992857f 100644 --- a/e2e/tests/profile.spec.ts +++ b/e2e/tests/profile.spec.ts @@ -6,8 +6,8 @@ test.describe("User Profile page", () => { const profilePage = new ProfilePage(page); await profilePage.goto(); - const title = profilePage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = profilePage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); test("Guest user successfully loads", async ({ guestPage }) => { diff --git a/e2e/tests/retros.spec.ts b/e2e/tests/retros.spec.ts index b617d529..463264c6 100644 --- a/e2e/tests/retros.spec.ts +++ b/e2e/tests/retros.spec.ts @@ -10,8 +10,8 @@ test.describe("Retros page", () => { const retrosPage = new RetrosPage(page); await retrosPage.goto(); - const title = retrosPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = retrosPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/storyboards.spec.ts b/e2e/tests/storyboards.spec.ts index eb29ac2b..53671bb7 100644 --- a/e2e/tests/storyboards.spec.ts +++ b/e2e/tests/storyboards.spec.ts @@ -10,8 +10,8 @@ test.describe("Storyboards page", () => { const storyboardsPage = new StoryboardsPage(page); await storyboardsPage.goto(); - const title = storyboardsPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = storyboardsPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/e2e/tests/team.spec.ts b/e2e/tests/team.spec.ts index e836b5ff..a7069624 100644 --- a/e2e/tests/team.spec.ts +++ b/e2e/tests/team.spec.ts @@ -6,8 +6,8 @@ test.describe("Team page", () => { const teamPage = new TeamPage(page); await teamPage.goto("bbaf82ef-a2d3-4e9a-b824-5e56a03ac3aa"); - const title = teamPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = teamPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); test("Registered user loads team page", async ({ registeredPage }) => { diff --git a/e2e/tests/teams.spec.ts b/e2e/tests/teams.spec.ts index 26818866..3d739c96 100644 --- a/e2e/tests/teams.spec.ts +++ b/e2e/tests/teams.spec.ts @@ -8,8 +8,8 @@ test.describe("Teams page", () => { const teamsPage = new TeamsPage(page); await teamsPage.goto(); - const title = teamsPage.page.locator('[data-formtitle="login"]'); - await expect(title).toHaveText("Login"); + const loginForm = teamsPage.page.locator('form[name="login"]'); + await expect(loginForm).toBeVisible(); }); }); diff --git a/ui/src/components/auth/LoginForm.svelte b/ui/src/components/auth/LoginForm.svelte index e3388604..c10d919d 100644 --- a/ui/src/components/auth/LoginForm.svelte +++ b/ui/src/components/auth/LoginForm.svelte @@ -4,6 +4,7 @@ import LL from '../../i18n/i18n-svelte'; import SolidButton from '../global/SolidButton.svelte'; import TextInput from '../global/TextInput.svelte'; + import LockIcon from '../icons/LockIcon.svelte'; export let registerLink = ''; export let targetPage = appRoutes.landing; @@ -177,7 +178,7 @@ autocomplete="current-password" required class="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:placeholder-gray-300 dark:focus:border-indigo-400 dark:focus:ring-indigo-400 sm:text-sm" - placeholder="{$LL.passwordPlaceholder()}" + placeholder="{$LL.yourPasswordPlaceholder()}" bind:value="{password}" /> @@ -195,7 +196,7 @@ class="font-medium text-indigo-400 hover:text-indigo-500 cursor-pointer" on:click="{toggleForgotPassword}" > - {$LL.forgotPasswordCheckboxLabel()} + {$LL.forgotPassword()} {/if} @@ -207,18 +208,9 @@ class="group relative flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-700 dark:border-transparent dark:hover:bg-indigo-600 dark:focus:ring-indigo-400 dark:focus:ring-offset-2 disabled:cursor-wait disabled:opacity-50" > - + /> {$LL.login()} @@ -297,6 +289,16 @@ {#if forgotPassword}
+
+

+ {$LL.forgotPassword()} +

+

+ {$LL.forgotPasswordSubtext()} +

+
{/if} diff --git a/ui/src/components/icons/LockIcon.svelte b/ui/src/components/icons/LockIcon.svelte new file mode 100644 index 00000000..fd58421b --- /dev/null +++ b/ui/src/components/icons/LockIcon.svelte @@ -0,0 +1,17 @@ + + + diff --git a/ui/src/i18n/de/index.ts b/ui/src/i18n/de/index.ts index 8e0db1c6..efca3865 100644 --- a/ui/src/i18n/de/index.ts +++ b/ui/src/i18n/de/index.ts @@ -184,7 +184,9 @@ const de: Translation = { 'is designed and developed by {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'Der Source Code ist lizensiert {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Forgot Password', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Error getting alerts', getApikeysError: 'Error getting apikeys', getBattleError: @@ -391,7 +393,6 @@ const de: Translation = { selectTeam: 'Select a Team', selfHostedDesc: 'Alternatively you can {linkOpen}run it on your own server{linkClose}.', - sendResetEmail: 'Send Reset Email', sessionDuplicate: '{friendly|{false:Es existiert bereits eine Schlacht-Sitzung für Ihre ID, true:Es existiert bereits eine Partie-Sitzung für Ihre ID}}', showActiveBattles: @@ -580,7 +581,6 @@ const de: Translation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Registration is disabled.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/i18n/en/index.ts b/ui/src/i18n/en/index.ts index 56a60d65..d97a3f2b 100644 --- a/ui/src/i18n/en/index.ts +++ b/ui/src/i18n/en/index.ts @@ -183,7 +183,9 @@ const en: BaseTranslation = { 'is designed and developed by {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'The source code is licensed {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Forgot Password', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Error getting alerts', getApikeysError: 'Error getting apikeys', getBattleError: @@ -388,7 +390,6 @@ const en: BaseTranslation = { selectTeam: 'Select a Team', selfHostedDesc: 'Alternatively you can {linkOpen}run it on your own server{linkClose}.', - sendResetEmail: 'Send Reset Email', sessionDuplicate: '{friendly|{false:Duplicate battle session exists for your ID, true:Duplicate game session exists for your ID}}', showActiveBattles: @@ -570,7 +571,6 @@ const en: BaseTranslation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Registration is disabled.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/i18n/es/index.ts b/ui/src/i18n/es/index.ts index e13a8fea..121670ee 100644 --- a/ui/src/i18n/es/index.ts +++ b/ui/src/i18n/es/index.ts @@ -183,7 +183,9 @@ const es: Translation = { 'is designed and developed by {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'The source code is licensed {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Forgot Password', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Error getting alerts', getApikeysError: 'Error getting apikeys', getBattleError: @@ -388,7 +390,6 @@ const es: Translation = { selectTeam: 'Select a Team', selfHostedDesc: 'Alternatively you can {linkOpen}run it on your own server{linkClose}.', - sendResetEmail: 'Send Reset Email', sessionDuplicate: '{friendly|{false:Duplicate battle session exists for your ID, true:Duplicate game session exists for your ID}}', showActiveBattles: @@ -570,7 +571,6 @@ const es: Translation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Registration is disabled.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/i18n/fa/index.ts b/ui/src/i18n/fa/index.ts index 737fbfe2..1c51e843 100644 --- a/ui/src/i18n/fa/index.ts +++ b/ui/src/i18n/fa/index.ts @@ -183,7 +183,9 @@ const fa: Translation = { 'is designed and developed by {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'The source code is licensed {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Forgot Password', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Error getting alerts', getApikeysError: 'Error getting apikeys', getBattleError: @@ -388,7 +390,6 @@ const fa: Translation = { selectTeam: 'Select a Team', selfHostedDesc: 'Alternatively you can {linkOpen}run it on your own server{linkClose}.', - sendResetEmail: 'Send Reset Email', sessionDuplicate: '{friendly|{false:Duplicate battle session exists for your ID, true:Duplicate game session exists for your ID}}', showActiveBattles: @@ -570,7 +571,6 @@ const fa: Translation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Registration is disabled.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/i18n/fr/index.ts b/ui/src/i18n/fr/index.ts index 23858824..5245a422 100644 --- a/ui/src/i18n/fr/index.ts +++ b/ui/src/i18n/fr/index.ts @@ -188,7 +188,9 @@ const fr: Translation = { 'is designed and developed by {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'Le code source est sous licence {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Forgot Password', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Error getting alerts', getApikeysError: 'Error getting apikeys', getBattleError: @@ -396,7 +398,6 @@ const fr: Translation = { selectTeam: 'Select a Team', selfHostedDesc: 'Alternatively you can {linkOpen}run it on your own server{linkClose}.', - sendResetEmail: 'Send Reset Email', sessionDuplicate: '{friendly|{false:Un doublon de bataille existe pour votre ID, true:Un doublon de jeu existe pour votre ID}}', showActiveBattles: @@ -581,7 +582,6 @@ const fr: Translation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Registration is disabled.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/i18n/it/index.ts b/ui/src/i18n/it/index.ts index 1d91d5f0..94991e89 100644 --- a/ui/src/i18n/it/index.ts +++ b/ui/src/i18n/it/index.ts @@ -193,7 +193,9 @@ const it: Translation = { 'è progettato e sviluppato da {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'Il codice sorgente è concesso in licenza {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Password Dimenticata', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Errore durante il recupero degli avvisi', getApikeysError: 'Errore durante il recupero delle chiavi API', getBattleError: @@ -409,7 +411,6 @@ const it: Translation = { selectTeam: 'Seleziona un Team', selfHostedDesc: 'In alternativa, puoi {linkOpen}eseguirlo sul tuo server{linkClose}.', - sendResetEmail: 'Invia Email di Ripristino', sessionDuplicate: '{friendly|{false:Esiste già una sessione di battaglia duplicata per il tuo ID, true:Esiste una sessione di gioco duplicata per il tuo ID}}', showActiveBattles: @@ -600,7 +601,6 @@ const it: Translation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Registration is disabled.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/i18n/pt/index.ts b/ui/src/i18n/pt/index.ts index bae04176..581985bf 100644 --- a/ui/src/i18n/pt/index.ts +++ b/ui/src/i18n/pt/index.ts @@ -188,7 +188,9 @@ const pt: Translation = { 'é projetado e desenvolvido por {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'O código fonte é licenciado por {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Esqueceu a senha', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Erro ao obter alertas', getApikeysError: 'Erro ao obter chaves de API', getBattleError: @@ -398,7 +400,6 @@ const pt: Translation = { selectTeam: 'Selecione uma Equipe', selfHostedDesc: 'Alternativamente, você pode {linkOpen}executá-lo em seu próprio servidor{linkClose}.', - sendResetEmail: 'Enviar e-mail de redefinição', sessionDuplicate: '{friendly|{false:Existe uma sessão de batalha duplicada para o seu ID, true:Existe uma sessão de jogo duplicada para o seu ID}}', showActiveBattles: @@ -584,7 +585,6 @@ const pt: Translation = { reset: 'Redefinir', passwordResetError: 'Erro encontrado ao tentar redefinir a senha', resetPassword: 'Redefinir Senha', - forgotPasswordCheckboxLabel: 'Esqueceu sua Senha?', registerAsGuest: 'Registrar como Convidado', registrationDisabled: 'O cadastro está desativado.', userNamePlaceholder: 'Digite seu nome', diff --git a/ui/src/i18n/ru/index.ts b/ui/src/i18n/ru/index.ts index d01c322f..71519266 100644 --- a/ui/src/i18n/ru/index.ts +++ b/ui/src/i18n/ru/index.ts @@ -183,7 +183,9 @@ const ru: Translation = { 'is designed and developed by {authorOpen}Steven Weathers{authorClose}.', footerLicense: 'The source code is licensed {licenseOpen}Apache 2.0{licenseClose}.', - forgotPassword: 'Forgot Password', + forgotPassword: 'Forgot Your Password?', + forgotPasswordSubtext: `Don't fret! Just enter your email and we will send you instructions to reset your password.`, + returnToLogin: 'Return to Login', getAlertsError: 'Error getting alerts', getApikeysError: 'Error getting apikeys', getBattleError: @@ -388,7 +390,6 @@ const ru: Translation = { selectTeam: 'Select a Team', selfHostedDesc: 'Alternatively you can {linkOpen}run it on your own server{linkClose}.', - sendResetEmail: 'Send Reset Email', sessionDuplicate: '{friendly|{false:Duplicate battle session exists for your ID, true:Duplicate game session exists for your ID}}', showActiveBattles: @@ -570,7 +571,6 @@ const ru: Translation = { reset: 'Reset', passwordResetError: 'Error encountered attempting to reset password', resetPassword: 'Reset Password', - forgotPasswordCheckboxLabel: 'Forgot Password?', registerAsGuest: 'Register as Guest', registrationDisabled: 'Регистрация отключена.', userNamePlaceholder: 'Enter your name', diff --git a/ui/src/pages/user/Login.svelte b/ui/src/pages/user/Login.svelte index 1cd53d2c..6ebaeb1a 100644 --- a/ui/src/pages/user/Login.svelte +++ b/ui/src/pages/user/Login.svelte @@ -51,10 +51,7 @@
-

+

{$LL.login()}