diff --git a/.github/workflows/RunE2ENightly.yml b/.github/workflows/RunE2ENightly.yml index ef001fac23..84f817c80c 100644 --- a/.github/workflows/RunE2ENightly.yml +++ b/.github/workflows/RunE2ENightly.yml @@ -2,56 +2,66 @@ name: Run E2E test nightly # This workflow is used to test our widgets nightly. on: - schedule: - # At 02:00 on every day-of-week. - - cron: "0 02 * * 1-5" + schedule: + # At 02:00 on every day-of-week. + - cron: "0 02 * * 1-5" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - e2e: - name: Run automated end-to-end tests nightly - runs-on: ubuntu-latest - - permissions: - packages: read - contents: read - - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 0 - - name: Setup pnpm - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 - - - name: Setup node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version-file: ".nvmrc" - cache: "pnpm" - - - name: Install dependencies - run: pnpm install - - - name: Install Playwright Browsers - run: pnpm exec playwright install --with-deps chromium - - - name: Executing E2E tests - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: pnpm -r --workspace-concurrency=1 --no-bail run e2e - - - name: Fixing files permissions - if: failure() - run: | - sudo find ${{ github.workspace }}/packages/* -type d -exec chmod 755 {} \; - sudo find ${{ github.workspace }}/packages/* -type f -exec chmod 644 {} \; - - - name: Archive test screenshot diff results - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - if: failure() - with: - name: test-screenshot-results - path: | - ${{ github.workspace }}/packages/**/**/test-results/**/*.png - ${{ github.workspace }}/packages/**/**/test-results/**/*.zip - if-no-files-found: error + e2e: + name: Run automated end-to-end tests nightly + runs-on: ubuntu-latest + + permissions: + packages: read + contents: read + + strategy: + fail-fast: false + matrix: + index: [0, 1, 2, 3] + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + - name: Setup pnpm + uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 + + - name: Setup node + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + node-version-file: ".nvmrc" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps chromium + + - name: Executing E2E tests + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: >- + node ./automation/run-e2e/bin/run-e2e-in-chunks.mjs --chunks 4 --index ${{ matrix.index }} --event-name ${{ github.event_name }} + + - name: Fixing files permissions + if: failure() + run: | + sudo find ${{ github.workspace }}/packages/* -type d -exec chmod 755 {} \; + sudo find ${{ github.workspace }}/packages/* -type f -exec chmod 644 {} \; + + - name: Archive test screenshot diff results + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + if: failure() + with: + name: test-screenshot-results-${{ matrix.index }} + path: | + ${{ github.workspace }}/packages/**/**/test-results/**/*.png + ${{ github.workspace }}/packages/**/**/test-results/**/*.zip + if-no-files-found: error diff --git a/automation/run-e2e/bin/migrate-spec.mjs b/automation/run-e2e/bin/migrate-spec.mjs new file mode 100644 index 0000000000..156151bdb1 --- /dev/null +++ b/automation/run-e2e/bin/migrate-spec.mjs @@ -0,0 +1,76 @@ +#!/usr/bin/env node + +/** + * Migrates E2E spec files to use shared fixtures and helpers. + * + * Usage: node migrate-spec.mjs [--dry-run] + * + * Transforms: + * 1. Replaces `import { test, expect } from "@playwright/test"` with shared fixtures + * 2. Removes afterEach logout blocks (fixture handles session cleanup) + * 3. Replaces `waitForLoadState("networkidle")` with `waitForMendixApp(page)` + */ + +import { readFileSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const args = process.argv.slice(2); +const dryRun = args.includes("--dry-run"); +const filePath = args.find(a => !a.startsWith("--")); + +if (!filePath) { + console.error("Usage: migrate-spec.mjs [--dry-run]"); + process.exit(1); +} + +const absPath = resolve(filePath); +let content = readFileSync(absPath, "utf-8"); +const original = content; +const changes = []; + +// 1. Replace import from @playwright/test with shared fixtures (handles both orderings) +const importPattern = + /import\s*\{\s*(?:test\s*,\s*expect|expect\s*,\s*test)\s*\}\s*from\s*["']@playwright\/test["'];?/g; +if (importPattern.test(content)) { + content = content.replace(importPattern, 'import { expect, test } from "@mendix/run-e2e/fixtures";'); + changes.push("Replaced @playwright/test import with shared fixtures"); +} + +// 2. Remove afterEach logout block (multiple patterns observed) +const afterEachPattern = + /\s*test\.afterEach\s*\(\s*["']Cleanup session["']\s*,\s*async\s*\(\s*\{\s*page\s*\}\s*\)\s*=>\s*\{[^}]*(?:window\.mx\.session\.logout|window\.mx\?\.session\?\.logout)[^}]*\}\s*\)\s*;?\n?/g; +if (afterEachPattern.test(content)) { + content = content.replace(afterEachPattern, "\n"); + changes.push("Removed afterEach session logout block (fixture handles this)"); +} + +// 3. Replace waitForLoadState("networkidle") with waitForMendixApp +const networkIdlePattern = /await\s+page\.waitForLoadState\s*\(\s*["']networkidle["']\s*\)\s*;?/g; +if (networkIdlePattern.test(content)) { + // Add helper import if not already present + if (!content.includes("@mendix/run-e2e/mendix-helpers")) { + const insertAfterImport = content.indexOf("\n", content.indexOf("import")); + if (insertAfterImport !== -1) { + content = + content.slice(0, insertAfterImport + 1) + + 'import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers";\n' + + content.slice(insertAfterImport + 1); + } + } + content = content.replace(networkIdlePattern, "await waitForMendixApp(page);"); + changes.push("Replaced waitForLoadState('networkidle') with waitForMendixApp(page)"); +} + +if (content === original) { + console.log(`No changes needed: ${absPath}`); + process.exit(0); +} + +if (dryRun) { + console.log(`[DRY RUN] Would apply to: ${absPath}`); + changes.forEach(c => console.log(` - ${c}`)); +} else { + writeFileSync(absPath, content, "utf-8"); + console.log(`Migrated: ${absPath}`); + changes.forEach(c => console.log(` - ${c}`)); +} diff --git a/automation/run-e2e/eslint.config.mjs b/automation/run-e2e/eslint.config.mjs index 016589e0fe..35f9a974e8 100644 --- a/automation/run-e2e/eslint.config.mjs +++ b/automation/run-e2e/eslint.config.mjs @@ -1,6 +1,7 @@ import { defineConfig } from "eslint/config"; import globals from "globals"; import js from "@eslint/js"; +import playwright from "eslint-plugin-playwright"; export default defineConfig([ { @@ -21,5 +22,14 @@ export default defineConfig([ rules: { "no-unused-vars": "warn" } + }, + { + files: ["**/e2e/**/*.spec.{,m,c}js"], + plugins: { playwright }, + rules: { + "playwright/no-wait-for-timeout": "error", + "playwright/no-networkidle": "warn", + "playwright/prefer-web-first-assertions": "warn" + } } ]); diff --git a/automation/run-e2e/lib/fixtures.mjs b/automation/run-e2e/lib/fixtures.mjs new file mode 100644 index 0000000000..9a3a6417cf --- /dev/null +++ b/automation/run-e2e/lib/fixtures.mjs @@ -0,0 +1,38 @@ +/* eslint-disable no-undef */ +import { test as base, expect } from "@playwright/test"; + +async function waitForMendixApp(page, timeout = 60_000) { + await page.waitForLoadState("domcontentloaded"); + await page.waitForFunction( + () => + Boolean(window.mx?.session) && + !document.querySelector(".mx-progress-indicator") && + document.querySelector(".mx-page") !== null, + undefined, + { timeout } + ); +} + +export { expect }; + +export const test = base.extend({ + mendixSession: [ + async ({ browser }, use) => { + const context = await browser.newContext(); + const page = await context.newPage(); + const originalGoto = page.goto.bind(page); + page.goto = async (url, options) => { + const response = await originalGoto(url, options); + await waitForMendixApp(page); + return response; + }; + await use({ context, page }); + await page.evaluate(() => window.mx?.session?.logout?.()).catch(() => {}); + await context.close(); + }, + { scope: "worker" } + ], + page: async ({ mendixSession }, use) => { + await use(mendixSession.page); + } +}); diff --git a/automation/run-e2e/lib/mendix-helpers.mjs b/automation/run-e2e/lib/mendix-helpers.mjs new file mode 100644 index 0000000000..b558f3ee04 --- /dev/null +++ b/automation/run-e2e/lib/mendix-helpers.mjs @@ -0,0 +1,57 @@ +/* eslint-disable no-undef */ +import { expect } from "@playwright/test"; + +export async function waitForMendixApp(page, timeout = 60_000) { + await page.waitForLoadState("domcontentloaded"); + await page.waitForFunction( + () => + Boolean(window.mx?.session) && + !document.querySelector(".mx-progress-indicator") && + document.querySelector(".mx-page") !== null, + undefined, + { timeout } + ); +} + +export async function waitForDataReady(page, timeout = 60_000) { + await waitForMendixApp(page, timeout); + await page.waitForLoadState("networkidle"); +} + +export async function waitForWidget(page, mxName, timeout = 15_000) { + const locator = page.locator(`.mx-name-${mxName}`); + await expect(locator).toBeVisible({ timeout }); + return locator; +} + +export async function waitForListData(page, mxName, minRows = 1, timeout = 15_000) { + const container = page.locator(`.mx-name-${mxName}`); + await expect(container).toBeVisible({ timeout }); + const rows = container.locator("[class*='item'], tr[class*='row'], [class*='gallery-item']"); + await expect(rows).toHaveCount(minRows, { timeout }); + return rows; +} + +export async function safeLogout(page) { + await page.evaluate(() => window.mx?.session?.logout?.()).catch(() => {}); +} + +export async function navigateToPage(page, path, timeout = 30_000) { + await page.goto(path); + await waitForMendixApp(page, timeout); +} + +export async function checkAccessibility(page, selector, options = {}) { + const AxeBuilder = (await import("@axe-core/playwright")).default; + let builder = new AxeBuilder({ page }).withTags(options.tags || ["wcag21aa"]); + if (selector) { + builder = builder.include(selector); + } + if (options.exclude) { + for (const sel of [].concat(options.exclude)) { + builder = builder.exclude(sel); + } + } + const results = await builder.analyze(); + expect(results.violations).toEqual([]); +} diff --git a/automation/run-e2e/package.json b/automation/run-e2e/package.json index 1dac43dbee..cb81bba618 100644 --- a/automation/run-e2e/package.json +++ b/automation/run-e2e/package.json @@ -12,6 +12,11 @@ "run-e2e": "bin/run-e2e.mjs" }, "type": "module", + "exports": { + "./fixtures": "./lib/fixtures.mjs", + "./mendix-helpers": "./lib/mendix-helpers.mjs", + "./playwright.config.cjs": "./playwright.config.cjs" + }, "scripts": { "format": "prettier --ignore-path ./node_modules/@mendix/prettier-config-web-widgets/global-prettierignore --write .", "lint": "eslint .", diff --git a/automation/run-e2e/playwright.config.cjs b/automation/run-e2e/playwright.config.cjs index 0c80130f21..64275de14d 100644 --- a/automation/run-e2e/playwright.config.cjs +++ b/automation/run-e2e/playwright.config.cjs @@ -9,11 +9,13 @@ module.exports = defineConfig({ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, + /* Filter tests by tag: E2E_SUITE=smoke runs only @smoke-tagged tests */ + grep: process.env.E2E_SUITE === "smoke" ? /@smoke/ : undefined, /* Retry on CI only */ retries: process.env.CI ? 2 : 0, - /* Use 4 workers on CI – the runner has multiple cores and each widget's tests - * are independent, so parallel execution cuts per-widget runtime significantly. */ - workers: process.env.CI ? 4 : undefined, + /* Worker-scoped session: each worker holds 1 Mendix session. Safe up to 4 workers + * against the 5-session developer license (leaves 1 headroom). */ + workers: process.env.CI ? 4 : 4, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: [ ["list"], @@ -35,11 +37,20 @@ module.exports = defineConfig({ reuseExistingServer: !process.env.CI } ], */ + expect: { + toHaveScreenshot: { + animations: "disabled", + threshold: 0.1 + } + }, /* 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: process.env.URL ? process.env.URL : "http://127.0.0.1:8080", + actionTimeout: 10_000, + navigationTimeout: 30_000, + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", diff --git a/packages/pluggableWidgets/accessibility-helper-web/e2e/AccessibilityHelper.spec.js b/packages/pluggableWidgets/accessibility-helper-web/e2e/AccessibilityHelper.spec.js index ee408a512c..12467203d1 100644 --- a/packages/pluggableWidgets/accessibility-helper-web/e2e/AccessibilityHelper.spec.js +++ b/packages/pluggableWidgets/accessibility-helper-web/e2e/AccessibilityHelper.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("with single target", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("sets attributes when condition is true", async ({ page }) => { @@ -63,7 +59,7 @@ test.describe("with single target", () => { test("sets attributes when condition is true", async ({ page }) => { await page.click(".mx-name-actionButton2"); await page.click(".mx-name-actionButton2"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons2 input:first-child"); await expect(page.locator(".mx-name-text3")).toHaveAttribute("trueCondition", "true"); @@ -72,7 +68,7 @@ test.describe("with single target", () => { test("hides attributes when condition is false", async ({ page }) => { await page.click(".mx-name-actionButton2"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons2 input:first-child"); await expect(page.locator(".mx-name-text3")).not.toHaveAttribute("a11yhelper", "a11yhelper"); @@ -81,7 +77,7 @@ test.describe("with single target", () => { test("updates target attributes when attributes are expression", async ({ page }) => { await page.click(".mx-name-actionButton2"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons2 input:first-child"); await page.locator(".mx-name-textBox1 input").fill("test", { force: true }); @@ -94,7 +90,7 @@ test.describe("with single target", () => { test("updates target attributes using a NF", async ({ page }) => { await page.click(".mx-name-actionButton2"); await page.click(".mx-name-actionButton2"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons1 input:first-child"); @@ -107,7 +103,7 @@ test.describe("with single target", () => { test("sets target attributes even though target's props changed eg: textinput", async ({ page }) => { await page.click(".mx-name-actionButton2"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons1 input:first-child"); await page.locator(".mx-name-textBox1 input").fill("test", { force: true }); @@ -123,7 +119,7 @@ test.describe("with single target", () => { }) => { await page.click(".mx-name-actionButton2"); await page.click(".mx-name-actionButton2"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons2 input:first-child"); await page.click(".mx-name-radioButtons1 input:first-child"); diff --git a/packages/pluggableWidgets/accordion-web/e2e/Accordion.spec.js b/packages/pluggableWidgets/accordion-web/e2e/Accordion.spec.js index 655458645d..8103ec4bcb 100644 --- a/packages/pluggableWidgets/accordion-web/e2e/Accordion.spec.js +++ b/packages/pluggableWidgets/accordion-web/e2e/Accordion.spec.js @@ -1,9 +1,10 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Accordion", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if all accordion elements are rendered as expected", async ({ diff --git a/packages/pluggableWidgets/badge-button-web/e2e/dataTypes.spec.js b/packages/pluggableWidgets/badge-button-web/e2e/dataTypes.spec.js index 31530b91bf..73d2116f43 100644 --- a/packages/pluggableWidgets/badge-button-web/e2e/dataTypes.spec.js +++ b/packages/pluggableWidgets/badge-button-web/e2e/dataTypes.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("BadgeButton different data types", () => { test.beforeEach(async ({ page }) => { await page.goto("p/dataTypes"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays correctly string data", async ({ page }) => { diff --git a/packages/pluggableWidgets/badge-button-web/e2e/differentViews.spec.js b/packages/pluggableWidgets/badge-button-web/e2e/differentViews.spec.js index 07ebd7553a..c86440a6ed 100644 --- a/packages/pluggableWidgets/badge-button-web/e2e/differentViews.spec.js +++ b/packages/pluggableWidgets/badge-button-web/e2e/differentViews.spec.js @@ -1,9 +1,5 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; // Conditional flag added to skip these tests when running on react client, because those widgets aren't supported in the react client test.skip(process.env.MODERN_CLIENT === true, () => { @@ -11,7 +7,7 @@ test.skip(process.env.MODERN_CLIENT === true, () => { test.describe("listen to grid", () => { test.beforeEach(async ({ page }) => { await page.goto("p/listenToGrid"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays correctly when listening a data grid", async ({ page }) => { @@ -26,7 +22,7 @@ test.skip(process.env.MODERN_CLIENT === true, () => { test.describe("listview", () => { test.beforeEach(async ({ page }) => { await page.goto("p/listView"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays correctly in a list view", async ({ page }) => { @@ -46,7 +42,7 @@ test.skip(process.env.MODERN_CLIENT === true, () => { test.describe("template grid", () => { test.beforeEach(async ({ page }) => { await page.goto("p/templateGrid"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays correctly in a template grid", async ({ page }) => { @@ -67,7 +63,7 @@ test.skip(process.env.MODERN_CLIENT === true, () => { test.describe("tab container", () => { test.beforeEach(async ({ page }) => { await page.goto("p/tabContainer"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays correctly in default tab", async ({ page }) => { diff --git a/packages/pluggableWidgets/badge-button-web/e2e/onClick.spec.js b/packages/pluggableWidgets/badge-button-web/e2e/onClick.spec.js index 32e411e6ce..b7f0e30f72 100644 --- a/packages/pluggableWidgets/badge-button-web/e2e/onClick.spec.js +++ b/packages/pluggableWidgets/badge-button-web/e2e/onClick.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("BadgeButton on click", () => { test.describe("call microflow", () => { test.beforeEach(async ({ page }) => { await page.goto("p/events"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays a dialog", async ({ page }) => { diff --git a/packages/pluggableWidgets/badge-button-web/e2e/render.spec.js b/packages/pluggableWidgets/badge-button-web/e2e/render.spec.js index ac3f0f67bf..280696e6bc 100644 --- a/packages/pluggableWidgets/badge-button-web/e2e/render.spec.js +++ b/packages/pluggableWidgets/badge-button-web/e2e/render.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("BadgeButton", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("displays correctly dynamic data", async ({ page }) => { diff --git a/packages/pluggableWidgets/badge-web/e2e/badge.spec.js b/packages/pluggableWidgets/badge-web/e2e/badge.spec.js index bd0c266b44..272be74ba9 100644 --- a/packages/pluggableWidgets/badge-web/e2e/badge.spec.js +++ b/packages/pluggableWidgets/badge-web/e2e/badge.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.beforeEach(async ({ page }) => { await page.goto("/"); diff --git a/packages/pluggableWidgets/badge-web/e2e/dataTypes.spec.js b/packages/pluggableWidgets/badge-web/e2e/dataTypes.spec.js index f9bdfd29be..f95f0f9822 100644 --- a/packages/pluggableWidgets/badge-web/e2e/dataTypes.spec.js +++ b/packages/pluggableWidgets/badge-web/e2e/dataTypes.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("Badge different data types", () => { test.beforeEach(async ({ page }) => { diff --git a/packages/pluggableWidgets/badge-web/e2e/onClick.spec.js b/packages/pluggableWidgets/badge-web/e2e/onClick.spec.js index fd9d31a5aa..25e4d81ff8 100644 --- a/packages/pluggableWidgets/badge-web/e2e/onClick.spec.js +++ b/packages/pluggableWidgets/badge-web/e2e/onClick.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("badge-web", () => { test.beforeEach(async ({ page }) => { diff --git a/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js b/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js index 573fa34389..433adf2aea 100644 --- a/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js +++ b/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("BarcodeGenerator", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("renders barcode generator widget", async ({ page }) => { diff --git a/packages/pluggableWidgets/carousel-web/e2e/Carousel.spec.js b/packages/pluggableWidgets/carousel-web/e2e/Carousel.spec.js index 6d08a9cf70..d5dcf12d30 100644 --- a/packages/pluggableWidgets/carousel-web/e2e/Carousel.spec.js +++ b/packages/pluggableWidgets/carousel-web/e2e/Carousel.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("Carousel", () => { test.beforeEach(async ({ page }) => { diff --git a/packages/pluggableWidgets/checkbox-radio-selection-web/e2e/SelectionControls.spec.js b/packages/pluggableWidgets/checkbox-radio-selection-web/e2e/SelectionControls.spec.js index 310453dd54..f567dbce25 100644 --- a/packages/pluggableWidgets/checkbox-radio-selection-web/e2e/SelectionControls.spec.js +++ b/packages/pluggableWidgets/checkbox-radio-selection-web/e2e/SelectionControls.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("checkbox-radio-selection-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/checkboxradioselection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-actionButton1"); }); @@ -34,7 +30,7 @@ test.describe("checkbox-radio-selection-web", () => { test("renders checkbox radio selection using static values", async ({ page }) => { await page.reload(); await page.click(".mx-name-actionButton1", { timeout: 10000 }); - await page.waitForLoadState("networkidle", { timeout: 10000 }); + await waitForMendixApp(page); const tabPage2 = page.getByRole("tab", { name: "Page 2" }); await expect(tabPage2).toBeVisible({ timeout: 10000 }); await tabPage2.click(); @@ -46,7 +42,7 @@ test.describe("checkbox-radio-selection-web", () => { test("renders checkbox radio selection using database", async ({ page }) => { await page.reload(); await page.click(".mx-name-actionButton1", { timeout: 10000 }); - await page.waitForLoadState("networkidle", { timeout: 10000 }); + await waitForMendixApp(page); const tabPage2 = page.getByRole("tab", { name: "Page 2" }); await expect(tabPage2).toBeVisible({ timeout: 10000 }); await tabPage2.click(); @@ -59,7 +55,7 @@ test.describe("checkbox-radio-selection-web", () => { test("handles radio button selection", async ({ page }) => { await page.reload(); await page.click(".mx-name-actionButton1", { timeout: 10000 }); - await page.waitForLoadState("networkidle", { timeout: 10000 }); + await waitForMendixApp(page); const tabPage2 = page.getByRole("tab", { name: "Page 2" }); await expect(tabPage2).toBeVisible({ timeout: 10000 }); await tabPage2.click(); diff --git a/packages/pluggableWidgets/color-picker-web/e2e/ColorPicker.spec.js b/packages/pluggableWidgets/color-picker-web/e2e/ColorPicker.spec.js index 7471a92b45..4f60c20816 100644 --- a/packages/pluggableWidgets/color-picker-web/e2e/ColorPicker.spec.js +++ b/packages/pluggableWidgets/color-picker-web/e2e/ColorPicker.spec.js @@ -1,9 +1,5 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("color-picker-web", () => { test.describe("render a picker of mode", () => { @@ -11,7 +7,7 @@ test.describe("color-picker-web", () => { const isFirefox = browserName === "firefox"; await page.goto("/p/modePage"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); if (!isFirefox) { const colorPicker = await page.locator(".mx-name-colorPicker3 .widget-color-picker-inner"); @@ -28,7 +24,7 @@ test.describe("color-picker-web", () => { test("input box", async ({ page }) => { await page.goto("/p/modePage"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-tabPage2"); const inputBox = await page.locator(".mx-name-colorPicker17 input"); await expect(inputBox).toHaveValue("#4caf50"); @@ -36,7 +32,7 @@ test.describe("color-picker-web", () => { test("inline", async ({ page }) => { await page.goto("/p/modePage"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-tabPage3"); const inlinePicker = await page.locator(".mx-name-colorPicker27 .sketch-picker"); await expect(inlinePicker).toBeVisible(); @@ -46,7 +42,7 @@ test.describe("color-picker-web", () => { test.describe("renders a picker of type", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/modePage"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-tabPage3"); }); @@ -109,14 +105,14 @@ test.describe("color-picker-web", () => { test.describe("renders with color format as", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/colorFormat"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.fixme("hex", async ({ page }) => { const hexInput = await page.locator(".mx-name-colorPicker24 input"); await expect(hexInput).toBeVisible(); await page.reload(); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(hexInput).toBeVisible({ timeout: 10000 }); await expect(hexInput).toBeEnabled({ timeout: 10000 }); await expect(hexInput).toBeEditable({ timeout: 10000 }); diff --git a/packages/pluggableWidgets/column-chart-web/e2e/ColumnChart.spec.js b/packages/pluggableWidgets/column-chart-web/e2e/ColumnChart.spec.js index 519940893c..ee0b977966 100644 --- a/packages/pluggableWidgets/column-chart-web/e2e/ColumnChart.spec.js +++ b/packages/pluggableWidgets/column-chart-web/e2e/ColumnChart.spec.js @@ -1,16 +1,12 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("column-chart-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButton1").click(); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("column color", () => { @@ -18,8 +14,7 @@ test.describe("column-chart-web", () => { const defaultColorContainer = page.locator(".mx-name-containerDefaultColor .widget-chart"); await defaultColorContainer.scrollIntoViewIfNeeded(); await expect(defaultColorContainer).toBeVisible({ timeout: 10000 }); - // Ensure the chart is fully rendered before taking a screenshot - await page.waitForTimeout(1000); // Wait for 1 second + await expect(defaultColorContainer.locator(".plot-container")).toBeVisible(); await expect(defaultColorContainer).toHaveScreenshot(`columnChartDefaultColor.png`); }); @@ -27,8 +22,7 @@ test.describe("column-chart-web", () => { const customColorContainer = page.locator(".mx-name-containerCustomColor .widget-chart"); await customColorContainer.scrollIntoViewIfNeeded(); await expect(customColorContainer).toBeVisible({ timeout: 10000 }); - // Ensure the chart is fully rendered before taking a screenshot - await page.waitForTimeout(1000); // Wait for 1 second + await expect(customColorContainer.locator(".plot-container")).toBeVisible(); await expect(customColorContainer).toHaveScreenshot(`columnChartCustomColor.png`); }); }); @@ -38,8 +32,7 @@ test.describe("column-chart-web", () => { const groupContainer = page.locator(".mx-name-containerGroup .widget-chart"); await groupContainer.scrollIntoViewIfNeeded(); await expect(groupContainer).toBeVisible({ timeout: 10000 }); - // Ensure the chart is fully rendered before taking a screenshot - await page.waitForTimeout(1000); // Wait for 1 second + await expect(groupContainer.locator(".plot-container")).toBeVisible(); await expect(groupContainer).toHaveScreenshot(`columnChartGrouped.png`); }); @@ -47,8 +40,7 @@ test.describe("column-chart-web", () => { const stackContainer = page.locator(".mx-name-containerStack .widget-chart"); await stackContainer.scrollIntoViewIfNeeded(); await expect(stackContainer).toBeVisible({ timeout: 10000 }); - // Ensure the chart is fully rendered before taking a screenshot - await page.waitForTimeout(1000); // Wait for 1 second + await expect(stackContainer.locator(".plot-container")).toBeVisible(); await expect(stackContainer).toHaveScreenshot(`columnChartStacked.png`); }); }); diff --git a/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js b/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js index 5a3fefae3e..f9e2729342 100644 --- a/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js +++ b/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js @@ -1,16 +1,12 @@ -import { expect, test } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { expect, test } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("combobox-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/combobox"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-actionButton1"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("data source types", () => { diff --git a/packages/pluggableWidgets/datagrid-date-filter-web/e2e/DataGridDateFilter.spec.js b/packages/pluggableWidgets/datagrid-date-filter-web/e2e/DataGridDateFilter.spec.js index c1cf7196d4..650e6984dc 100644 --- a/packages/pluggableWidgets/datagrid-date-filter-web/e2e/DataGridDateFilter.spec.js +++ b/packages/pluggableWidgets/datagrid-date-filter-web/e2e/DataGridDateFilter.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("datagrid-date-filter-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("visual testing:", () => { @@ -22,15 +18,14 @@ test.describe("datagrid-date-filter-web", () => { }); }); - test.fixme( - "compares with a screenshot baseline and checks if date picker element is rendered as expected", - async ({ page }) => { - const datagrid = page.locator(".mx-name-datagrid1"); - const datePickerButton = datagrid.locator(".btn-calendar").first(); - await datePickerButton.click(); - await expect(datagrid).toHaveScreenshot(`dataGridDateFilterDatePicker.png`); - } - ); + test.fixme("compares with a screenshot baseline and checks if date picker element is rendered as expected", async ({ + page + }) => { + const datagrid = page.locator(".mx-name-datagrid1"); + const datePickerButton = datagrid.locator(".btn-calendar").first(); + await datePickerButton.click(); + await expect(datagrid).toHaveScreenshot(`dataGridDateFilterDatePicker.png`); + }); test("filters a typed date", async ({ page }) => { const datagrid = page.locator(".mx-name-datagrid1"); @@ -90,7 +85,7 @@ test.describe("datagrid-date-filter-web", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilter.spec.js b/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilter.spec.js index 563023ae42..8eff6360f8 100644 --- a/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilter.spec.js +++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilter.spec.js @@ -1,15 +1,11 @@ -import { expect, test } from "@playwright/test"; +import { expect, test } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("datagrid-dropdown-filter-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("visual testing:", () => { @@ -18,9 +14,7 @@ test.describe("datagrid-dropdown-filter-web", () => { }) => { const dataGrid = await page.locator(".mx-name-datagrid1"); await expect(dataGrid).toBeVisible(); - await expect(page).toHaveScreenshot(`dataGridDropDownFilter-${process.env.BROWSER_NAME}.png`, { - threshold: 0.1 - }); + await expect(page).toHaveScreenshot(`dataGridDropDownFilter-${process.env.BROWSER_NAME}.png`); }); }); @@ -29,7 +23,7 @@ test.describe("datagrid-dropdown-filter-web", () => { await page.locator(".mx-name-datagrid1 .mx-name-dataGridDrop_downFilter1").click({ delay: 100 }); await page.waitForSelector(".widget-dropdown-filter-menu-slot > ul > li:nth-child(1)"); await page.locator(".widget-dropdown-filter-menu-slot > ul > li:nth-child(1)").click({ delay: 100 }); - await page.waitForTimeout(300); // wait for filter to apply + await expect(page.locator(".mx-name-datagrid1 .tr")).toHaveCount(1); await page.locator('.mx-name-datagrid1 .th[title="Age"]').click({ delay: 100 }); const cells = await page.$$eval(".mx-name-datagrid1 .td", elements => elements.map(element => element.textContent) @@ -43,7 +37,7 @@ test.describe("datagrid-dropdown-filter-web", () => { await page.locator(".widget-dropdown-filter-menu-slot > ul > li:nth-child(1)").click({ delay: 100 }); await page.waitForSelector(".widget-dropdown-filter-menu-slot > ul > li:nth-child(2)"); await page.locator(".widget-dropdown-filter-menu-slot > ul > li:nth-child(2)").click({ delay: 100 }); - await page.waitForTimeout(300); // wait for filter to apply + await expect(page.locator(".mx-name-datagrid1 .tr")).toHaveCount(2); await page.locator('.mx-name-datagrid1 .th[title="Age"]').click({ delay: 100 }); const cells = await page.$$eval(".mx-name-datagrid1 .td", elements => elements.map(element => element.textContent) @@ -77,7 +71,7 @@ test.describe("datagrid-dropdown-filter-web", () => { test.describe("with Default value", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/filter_init_condition"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("in single mode, set init condition for boolean", async ({ page }) => { @@ -194,7 +188,7 @@ test.describe("with Default value", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilterAssociation.spec.js b/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilterAssociation.spec.js index 4ffcbe7119..234f32310d 100644 --- a/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilterAssociation.spec.js +++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/e2e/DataGridDropDownFilterAssociation.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("datagrid-dropdown-filter-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/associations-filter"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("single select", () => { diff --git a/packages/pluggableWidgets/datagrid-number-filter-web/e2e/DataGridNumberFilter.spec.js b/packages/pluggableWidgets/datagrid-number-filter-web/e2e/DataGridNumberFilter.spec.js index a44b536a93..6817780dc1 100644 --- a/packages/pluggableWidgets/datagrid-number-filter-web/e2e/DataGridNumberFilter.spec.js +++ b/packages/pluggableWidgets/datagrid-number-filter-web/e2e/DataGridNumberFilter.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("datagrid-number-filter-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("visual testing:", () => { @@ -18,9 +14,7 @@ test.describe("datagrid-number-filter-web", () => { }) => { const dataGrid = await page.locator(".mx-name-datagrid1"); await expect(dataGrid).toBeVisible(); - await expect(page).toHaveScreenshot(`dataGridNumberFilter.png`, { - threshold: 0.1 - }); + await expect(page).toHaveScreenshot(`dataGridNumberFilter.png`); }); }); @@ -42,7 +36,7 @@ test.describe("datagrid-number-filter-web", () => { const expected = [`First nameYear${NBSP}`, "Delia1987", "Lizzie1987"]; await page.goto("/p/filter_init_condition"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const rows = await page.locator(".mx-name-dataGrid21 [role=row]"); for (let i = 0; i < rows.length; i++) { @@ -57,7 +51,7 @@ test.describe("datagrid-number-filter-web", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) diff --git a/packages/pluggableWidgets/datagrid-text-filter-web/e2e/DataGridTextFilter.spec.js b/packages/pluggableWidgets/datagrid-text-filter-web/e2e/DataGridTextFilter.spec.js index 8be396ba9a..5645949ed9 100644 --- a/packages/pluggableWidgets/datagrid-text-filter-web/e2e/DataGridTextFilter.spec.js +++ b/packages/pluggableWidgets/datagrid-text-filter-web/e2e/DataGridTextFilter.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("datagrid-text-filter-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("visual testing:", () => { @@ -18,9 +14,7 @@ test.describe("datagrid-text-filter-web", () => { }) => { const dataGrid = await page.locator(".mx-name-datagrid1"); await expect(dataGrid).toBeVisible(); - await expect(page).toHaveScreenshot(`dataGridTextFilter.png`, { - threshold: 0.1 - }); + await expect(page).toHaveScreenshot(`dataGridTextFilter.png`); }); }); @@ -51,7 +45,7 @@ test.describe("datagrid-text-filter-web", () => { const expected = [`First name${NBSP}`, "Betty"]; await page.goto("/p/filter_init_condition"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const rows = await page.locator(".mx-name-dataGrid21 [role=row]"); for (let i = 0; i < rows.length; i++) { @@ -66,7 +60,7 @@ test.describe("datagrid-text-filter-web", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js index 8fb49539d6..ab93e490c0 100644 --- a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js +++ b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js @@ -1,19 +1,15 @@ import AxeBuilder from "@axe-core/playwright"; -import { expect, test } from "@playwright/test"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; +import { expect, test } from "@mendix/run-e2e/fixtures"; import path from "path"; import * as XLSX from "xlsx"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("datagrid-web export to Excel", () => { test("check if export to Excel generates correct output", async ({ page }) => { const downloadedFilename = path.join("./e2e/downloads/", "testFilename.xlsx"); await page.goto("/p/export-excel"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-dataGridExportExcel").waitFor({ state: "visible", timeout: 15000 }); // Start waiting for download before clicking. const downloadPromise = page.waitForEvent("download"); @@ -47,7 +43,7 @@ test.describe("datagrid-web export to Excel", () => { test.describe("capabilities: sorting", () => { test("applies the default sort order from the data source option", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1 .column-header").nth(1)).toHaveText("First Name"); await expect(page.locator(".mx-name-datagrid1 .column-header").nth(1).locator("svg")).toHaveAttribute( "data-icon", @@ -58,7 +54,7 @@ test.describe("capabilities: sorting", () => { test("changes order of data to ASC when clicking sort option", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1 .column-header").nth(1)).toHaveText("First Name"); await expect(page.locator(".mx-name-datagrid1 .column-header").nth(1).locator("svg")).toHaveAttribute( "data-icon", @@ -74,7 +70,7 @@ test.describe("capabilities: sorting", () => { test("changes order of data to DESC when clicking sort option", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1 .column-header").nth(1)).toHaveText("First Name"); await page.locator(".mx-name-datagrid1 .column-header").nth(1).click(); await page.locator(".mx-name-datagrid1 .column-header").nth(1).click(); @@ -89,7 +85,7 @@ test.describe("capabilities: sorting", () => { test.describe("capabilities: hiding", () => { test("hides a selected column", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1 .column-header").first()).toHaveText("Age"); await page.locator(".mx-name-datagrid1 .column-selector-button").click(); await page.locator(".column-selectors > li").first().click(); @@ -98,7 +94,7 @@ test.describe("capabilities: hiding", () => { test("hide column saved on configuration attribute capability", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); // hide first column await page.locator(".mx-name-datagrid5 .column-selector-button").click(); @@ -127,7 +123,7 @@ test.describe("capabilities: hiding", () => { }); test("hide column by default enabled", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid6 .column-header").first()).toHaveText("First Name"); await page.locator(".mx-name-datagrid6 .column-selector-button").click(); await page.locator(".column-selectors > li").first().click(); @@ -136,7 +132,7 @@ test.describe("capabilities: hiding", () => { test("do not allow to hide last visible column", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1 .column-header").first()).toBeVisible(); await page.locator(".mx-name-datagrid1 .column-selector-button").click(); await expect(page.locator(".column-selectors input:checked")).toHaveCount(4); @@ -158,7 +154,7 @@ test.describe("capabilities: hiding", () => { test.describe("capabilities: onClick action", () => { test("check the context", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1 .td").first()).toHaveText("12"); await page.locator(".mx-name-datagrid1 .td").first().click(); await expect(page.locator(".mx-name-AgeTextBox input")).toHaveValue("12"); @@ -168,7 +164,7 @@ test.describe("capabilities: onClick action", () => { test.describe("manual column width", () => { test("compares with a screenshot baseline and checks the column width is with correct size", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-datagrid7").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-datagrid7")).toHaveScreenshot(`dataGridColumnContent.png`); }); @@ -179,7 +175,7 @@ test.describe("visual testing:", () => { page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-datagrid1")).toBeVisible(); await expect(page.locator(".mx-name-datagrid1")).toHaveScreenshot(`datagrid.png`); }); @@ -188,7 +184,7 @@ test.describe("visual testing:", () => { page }) => { await page.goto("/p/virtual-scrolling"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-dataGrid21")).toBeVisible(); await page.locator(".mx-name-dataGrid21 .mx-name-textFilter1 .filter-selector-content .btn").click(); await expect(page.locator(".mx-page")).toHaveScreenshot(`datagrid-virtual-scrolling.png`); @@ -198,7 +194,7 @@ test.describe("visual testing:", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) .exclude(".mx-name-navigationTree3") diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/dataGridColumnContent-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/dataGridColumnContent-chromium-darwin.png index 92867e6031..673ebb3c56 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/dataGridColumnContent-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/dataGridColumnContent-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-chromium-darwin.png index ae3e48941f..fd6c2baa10 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-virtual-scrolling-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-virtual-scrolling-chromium-darwin.png index 6162d85287..6a6acd91fb 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-virtual-scrolling-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js-snapshots/datagrid-virtual-scrolling-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js index b5ee1fd855..d4e3e14eca 100644 --- a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js +++ b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js @@ -1,17 +1,13 @@ -import { expect, test } from "@playwright/test"; +import { expect, test } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("datagrid-web selection", async () => { test("applies checkbox single selection checkbox", async ({ page }) => { const singleSelectionCheckbox = page.locator(".mx-name-dgSingleSelectionCheckbox"); await page.goto("/p/single-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(singleSelectionCheckbox).toBeVisible(); await singleSelectionCheckbox.locator("input").first().click(); await expect(page).toHaveScreenshot(`datagridSingleSelectionCheckbox.png`); @@ -21,7 +17,7 @@ test.describe("datagrid-web selection", async () => { const singleSelectionRowClick = page.locator(".mx-name-dgSingleSelectionRowClick"); await page.goto("/p/single-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(singleSelectionRowClick).toBeVisible(); await singleSelectionRowClick .locator(".td") @@ -34,7 +30,7 @@ test.describe("datagrid-web selection", async () => { const multiSelectionCheckbox = page.locator(".mx-name-dgMultiSelectionCheckbox"); await page.goto("/p/multi-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(multiSelectionCheckbox).toBeVisible(); await multiSelectionCheckbox.locator("input").first().click(); await multiSelectionCheckbox.locator("input").nth(1).click(); @@ -45,7 +41,7 @@ test.describe("datagrid-web selection", async () => { const multiSelectionRowClick = page.locator(".mx-name-dgMultiSelectionRowClick"); await page.goto("/p/multi-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(multiSelectionRowClick).toBeVisible(); await multiSelectionRowClick.locator(".td").first().click({ force: true }); await multiSelectionRowClick @@ -57,7 +53,7 @@ test.describe("datagrid-web selection", async () => { test("checks single selection accessibility with sr-only text", async ({ page }) => { await page.goto("/p/single-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const singleSelectionCheckbox = page.locator(".mx-name-dgSingleSelectionCheckbox"); await singleSelectionCheckbox.waitFor(); @@ -88,7 +84,7 @@ test.describe("datagrid-web selection", async () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/p/multi-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-dgMultiSelectionCheckbox").waitFor(); const accessibilityScanResults = await new AxeBuilder({ page }) diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionCheckbox-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionCheckbox-chromium-darwin.png index 08f5bae7b3..42256da53f 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionCheckbox-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionCheckbox-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionRowClick-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionRowClick-chromium-darwin.png index 62e64aa1d2..fcda58a266 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionRowClick-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridMultiSelectionRowClick-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionCheckbox-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionCheckbox-chromium-darwin.png index 39bba7ec1b..56f8f54644 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionCheckbox-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionCheckbox-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionRowClick-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionRowClick-chromium-darwin.png index cbe1fc9a95..95069e211e 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionRowClick-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/DataGridSelection.spec.js-snapshots/datagridSingleSelectionRowClick-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js index 9834a8ae48..c6ff286e19 100644 --- a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js +++ b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js @@ -1,9 +1,5 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test("datagrid-web filtering integration", async ({ page }) => { const rows = async () => { @@ -13,7 +9,7 @@ test("datagrid-web filtering integration", async ({ page }) => { const rowCount = await rows(); await page.goto("/p/filtering-integration"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(rowCount).toHaveCount(51); diff --git a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png index f9e0b93ff5..cb4c4c4b3c 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringMulti.spec.js b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringMulti.spec.js index a622b7e272..f818cee362 100644 --- a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringMulti.spec.js +++ b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringMulti.spec.js @@ -1,9 +1,5 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("datagrid-web filtering multi select", () => { test("filter rows where enum attribute equal to one of selected values", async ({ page }) => { @@ -15,7 +11,7 @@ test.describe("datagrid-web filtering multi select", () => { const enumSelect = () => page.locator(".mx-name-drop_downFilter1[role=combobox]"); const rowCount = await rows(); await page.goto("/p/filtering-multi"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(rowCount).toHaveCount(11); await expect(await column(2).first()).toHaveText("Black"); await expect(await column(2).last()).toHaveText("Blue"); @@ -25,10 +21,7 @@ test.describe("datagrid-web filtering multi select", () => { await option("Blush").click({ delay: 20 }); await expect(await rows()).toHaveCount(8); await page.getByRole("columnheader", { name: "Color (enum)" }).getByRole("combobox").click({ delay: 20 }); - const columnText = await column(2).allTextContents(); - await expect(columnText).toEqual( - expect.arrayContaining(["Pink", "Pink", "Pink", "Blush", "Blush", "Pink", "Pink"]) - ); + await expect(column(2)).toContainText(["Pink", "Pink", "Pink", "Blush", "Blush", "Pink", "Pink"]); }); test("filter rows where ReferenceSet contains at least one of selected objects", async ({ page }) => { @@ -50,7 +43,7 @@ test.describe("datagrid-web filtering multi select", () => { "Environmental scientistPublic librarianMaterials specialist" ]; await page.goto("/p/filtering-multi"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(await column(3).first()).toHaveText(expectedColumnText[0]); await roleSelect().click(); await option("Economist").click({ delay: 20 }); @@ -58,11 +51,7 @@ test.describe("datagrid-web filtering multi select", () => { await option("Public librarian").click({ delay: 20 }); await expect(await rows()).toHaveCount(10); await roleSelect().click({ delay: 20 }); - await page.waitForTimeout(300); - const columnTexts = await column(3).allTextContents(); - expectedColumnText.forEach((text, index) => { - expect(columnTexts[index]).toBe(text); - }); + await expect(column(3)).toHaveText(expectedColumnText); }); test("filter rows where Reference equal to one of selected objects", async ({ page }) => { @@ -75,7 +64,7 @@ test.describe("datagrid-web filtering multi select", () => { const rowCount = await rows(); await page.goto("/p/filtering-multi"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(rowCount).toHaveCount(11); await expect(await column(4).first()).toHaveText("W.R. Berkley Corporation"); await expect(await column(4).last()).toHaveText("PETsMART Inc"); @@ -85,10 +74,12 @@ test.describe("datagrid-web filtering multi select", () => { await option("ALLETE, Inc.").click({ delay: 20 }); await expect(await rows()).toHaveCount(6); await page.getByRole("columnheader", { name: "Company" }).getByRole("combobox").click({ delay: 20 }); - await page.waitForTimeout(300); - const columnText = await column(4).allTextContents(); - expect(columnText).toEqual( - expect.arrayContaining(["ALLETE, Inc.", "FMC Corp", "ALLETE, Inc.", "ALLETE, Inc.", "ALLETE, Inc."]) - ); + await expect(column(4)).toContainText([ + "ALLETE, Inc.", + "FMC Corp", + "ALLETE, Inc.", + "ALLETE, Inc.", + "ALLETE, Inc." + ]); }); }); diff --git a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringSingle.spec.js b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringSingle.spec.js index b420086f22..508f48e657 100644 --- a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringSingle.spec.js +++ b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringSingle.spec.js @@ -1,14 +1,10 @@ -import { expect, test } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { expect, test } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("datagrid-web filtering single select", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/filtering-single"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if all datagrid and filter elements are rendered as expected", async ({ @@ -20,33 +16,22 @@ test.describe("datagrid-web filtering single select", () => { }); test("filter rows that have Yes in Pets column", async ({ page }) => { - const rows = async () => { - return page.locator('.mx-name-dataGrid21 [role="row"]'); - }; const column = n => page.locator(`[role="gridcell"]:nth-child(${n})`); const option = label => page.locator(`[role="option"]:has-text("${label}")`); const booleanSelect = () => page.locator('.mx-name-drop_downFilter2[role="combobox"]'); await booleanSelect().click(); await option("Yes").click({ delay: 1 }); - const rowCount = await rows(); - await expect(rowCount).toHaveCount(11); - const columnTexts = await column(3).allTextContents(); - columnTexts.forEach(text => expect(text).toBe("Yes")); + await expect(column(3)).toHaveText(["Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes"]); }); test("filter rows that have No in Pets column", async ({ page }) => { - const rows = async () => { - return page.locator('.mx-name-dataGrid21 [role="row"]'); - }; const column = n => page.locator(`[role="gridcell"]:nth-child(${n})`); const booleanSelect = () => page.locator('.mx-name-drop_downFilter2[role="combobox"]'); await booleanSelect().click(); - await page.getByRole("option", { name: "No", exact: true }).click(); - const rowCount = await rows(); - await expect(rowCount).toHaveCount(11); + await expect(column(3).first()).toHaveText("No"); const columnTexts = await column(3).allTextContents(); columnTexts.forEach(text => expect(text).toBe("No")); }); diff --git a/packages/pluggableWidgets/dropdown-sort-web/e2e/DropDownSort.spec.js b/packages/pluggableWidgets/dropdown-sort-web/e2e/DropDownSort.spec.js index 1028fd1c03..01f36317a4 100644 --- a/packages/pluggableWidgets/dropdown-sort-web/e2e/DropDownSort.spec.js +++ b/packages/pluggableWidgets/dropdown-sort-web/e2e/DropDownSort.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("dropdown-sort-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("shows the descending order", async ({ page }) => { @@ -31,7 +27,7 @@ test.describe("dropdown-sort-web", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) diff --git a/packages/pluggableWidgets/fieldset-web/e2e/Fieldset.spec.js b/packages/pluggableWidgets/fieldset-web/e2e/Fieldset.spec.js index 1faaeff61e..fad7b24dbb 100644 --- a/packages/pluggableWidgets/fieldset-web/e2e/Fieldset.spec.js +++ b/packages/pluggableWidgets/fieldset-web/e2e/Fieldset.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Fieldset", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/configuration-combinations"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("renders content and legend", async ({ page }) => { diff --git a/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js b/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js index 4298bbdee9..7f11b55380 100644 --- a/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js +++ b/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("gallery-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("capabilities: sorting", () => { @@ -34,7 +30,7 @@ test.describe("gallery-web", () => { const textFilter = ".mx-name-gallery1 .form-control"; await page.locator(textFilter).first().fill("Leo"); - await page.waitForTimeout(1000); // wait for filter to apply + await expect(page.locator(".widget-gallery-item")).toHaveCount(1); await expect(page.locator(gallery)).toHaveScreenshot(`galleryTextFilter.png`); }); @@ -61,7 +57,7 @@ test.describe("gallery-web", () => { await dropdown.click({ delay: 1 }); await dropdown.getByRole("listbox").getByRole("option", { name: "QA Engineer" }).click({ delay: 1 }); - await page.waitForTimeout(1000); // wait for filter to apply + await expect(page.locator(".widget-gallery-item")).toHaveCount(1); await expect(gallery).toHaveScreenshot(`galleryDropdownFilter.png`); }); }); @@ -90,7 +86,7 @@ test.describe("gallery-web", () => { test.describe("a11y testing:", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks accessibility violations", async ({ page }) => { diff --git a/packages/pluggableWidgets/gallery-web/e2e/GallerySelection.spec.js b/packages/pluggableWidgets/gallery-web/e2e/GallerySelection.spec.js index 3e5f97f97e..573cfd4223 100644 --- a/packages/pluggableWidgets/gallery-web/e2e/GallerySelection.spec.js +++ b/packages/pluggableWidgets/gallery-web/e2e/GallerySelection.spec.js @@ -1,16 +1,12 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("gallery-web", () => { test.describe("capabilities: selection", () => { test("applies single select", async ({ page }) => { await page.goto("/p/single-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-gallery1")).toBeVisible(); await page.locator(".mx-name-image1").first().click(); await page.locator(".mx-name-feedback1").isHidden(); @@ -19,7 +15,7 @@ test.describe("gallery-web", () => { test("applies multi select", async ({ page }) => { await page.goto("/p/multi-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-gallery1")).toBeVisible(); await page.keyboard.down("Shift"); await page.locator(".mx-name-image1").nth(0).click(); @@ -33,7 +29,7 @@ test.describe("gallery-web", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/p/multi-selection"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-gallery1").waitFor(); const accessibilityScanResults = await new AxeBuilder({ page }) diff --git a/packages/pluggableWidgets/heatmap-chart-web/e2e/HeatMapChart.spec.js b/packages/pluggableWidgets/heatmap-chart-web/e2e/HeatMapChart.spec.js index 0e47cc6b38..29ed56e8b0 100644 --- a/packages/pluggableWidgets/heatmap-chart-web/e2e/HeatMapChart.spec.js +++ b/packages/pluggableWidgets/heatmap-chart-web/e2e/HeatMapChart.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("heatmap-chart-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("heatmap color", { viewport: { height: 720, width: 1280 } }, async () => { @@ -18,10 +14,7 @@ test.describe("heatmap-chart-web", () => { await customColorContainer.scrollIntoViewIfNeeded(); await expect(customColorContainer.locator(".mx-react-plotly-chart")).toBeVisible({ timeout: 5000 }); await expect(customColorContainer.locator("g.colorbar")).toBeVisible({ timeout: 5000 }); - await page.waitForTimeout(500); - await expect(customColorContainer).toHaveScreenshot(`heatmapChartCustomColor.png`, { - threshold: 0.5 - }); + await expect(customColorContainer).toHaveScreenshot(`heatmapChartCustomColor.png`); }); }); @@ -32,10 +25,7 @@ test.describe("heatmap-chart-web", () => { await ascendingContainer.scrollIntoViewIfNeeded(); await expect(ascendingContainer.locator(".mx-react-plotly-chart")).toBeVisible({ timeout: 5000 }); await expect(ascendingContainer.locator("g.colorbar")).toBeVisible({ timeout: 5000 }); - await page.waitForTimeout(500); - await expect(ascendingContainer).toHaveScreenshot(`heatmapChartAscending.png`, { - threshold: 0.5 - }); + await expect(ascendingContainer).toHaveScreenshot(`heatmapChartAscending.png`); }); test("renders heatmap chart with descending order and compares with a screenshot baseline", async ({ @@ -46,10 +36,7 @@ test.describe("heatmap-chart-web", () => { await descendingContainer.scrollIntoViewIfNeeded(); await expect(descendingContainer.locator(".mx-react-plotly-chart")).toBeVisible({ timeout: 5000 }); await expect(descendingContainer.locator("g.colorbar")).toBeVisible({ timeout: 5000 }); - await page.waitForTimeout(500); - await expect(descendingContainer).toHaveScreenshot(`heatmapChartDescending.png`, { - threshold: 0.5 - }); + await expect(descendingContainer).toHaveScreenshot(`heatmapChartDescending.png`); }); }); }); diff --git a/packages/pluggableWidgets/image-web/e2e/dataTypes.spec.js b/packages/pluggableWidgets/image-web/e2e/dataTypes.spec.js index 0674fbe55c..dd7368232f 100644 --- a/packages/pluggableWidgets/image-web/e2e/dataTypes.spec.js +++ b/packages/pluggableWidgets/image-web/e2e/dataTypes.spec.js @@ -1,9 +1,5 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Image viewer", () => { const dynamicImage = @@ -13,7 +9,7 @@ test.describe("Image viewer", () => { test("loads an image from a dynamic url", async ({ page }) => { await page.goto("/p/dynamicUrl"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const imageElement = await page.locator(".mx-name-imageRender1 img"); await expect(imageElement).toHaveAttribute("src", dynamicImage); }); @@ -21,7 +17,7 @@ test.describe("Image viewer", () => { // todo: unskip once we figure out why this spec is failing. test.skip("loads an image from a dynamic url association", async ({ page }) => { await page.goto("/p/dynamicUrlAssociation"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const imageElement = await page.locator(".mx-name-image1 img"); await expect(imageElement).toHaveAttribute("src", dynamicImage); }); @@ -29,21 +25,21 @@ test.describe("Image viewer", () => { // todo: unskip once we figure out why this spec is failing. test.skip("loads no image when no image url is specified", async ({ page }) => { await page.goto("/p/emptyUrl"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const imageElement = await page.locator(".mx-name-image1.hidden img"); await expect(imageElement).toHaveAttribute("src", dynamicImageNoUrl); }); test("loads an image from a static image", async ({ page }) => { await page.goto("/p/staticImage"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const imageElement = await page.locator(".mx-name-image1 img"); await expect(imageElement).toHaveAttribute("src", /ImageViewer\$Images\$landscape_2\.png/); }); test("loads an image from a static URL", async ({ page }) => { await page.goto("/p/staticUrl"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const imageElement = await page.locator(".mx-name-image1 img"); await expect(imageElement).toHaveAttribute("src", staticUrl); }); diff --git a/packages/pluggableWidgets/image-web/e2e/differentViews.spec.js b/packages/pluggableWidgets/image-web/e2e/differentViews.spec.js index 32526e5af2..51c4c34b46 100644 --- a/packages/pluggableWidgets/image-web/e2e/differentViews.spec.js +++ b/packages/pluggableWidgets/image-web/e2e/differentViews.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; // Conditional flag added to skip these tests when running on react client, because those widgets aren't supported in the react client test.describe.skip(process.env.MODERN_CLIENT === true, () => { diff --git a/packages/pluggableWidgets/image-web/e2e/onClick.spec.js b/packages/pluggableWidgets/image-web/e2e/onClick.spec.js index 21b467af34..986f0f9bb9 100644 --- a/packages/pluggableWidgets/image-web/e2e/onClick.spec.js +++ b/packages/pluggableWidgets/image-web/e2e/onClick.spec.js @@ -1,9 +1,5 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Image viewer", () => { const dynamicImage = @@ -11,7 +7,7 @@ test.describe("Image viewer", () => { test("triggers a Microflow on click", async ({ page }) => { await page.goto("/p/onClickMicroflow"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-image1"); const modalDialog = await page.locator(".modal-dialog"); await expect(modalDialog).toContainText("You clicked this image"); @@ -19,7 +15,7 @@ test.describe("Image viewer", () => { test("triggers a Nanoflow on click", async ({ page }) => { await page.goto("/p/onClickNanoflow"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-image1"); const modalDialog = await page.locator(".modal-dialog"); await expect(modalDialog).toContainText(dynamicImage); @@ -27,7 +23,7 @@ test.describe("Image viewer", () => { test("opens a Page on click", async ({ page }) => { await page.goto("/p/onClickShowPage"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-image1"); const modalDialog = await page.locator(".modal-dialog"); const caption = await modalDialog.locator("#mxui_widget_Window_0_caption"); @@ -36,7 +32,7 @@ test.describe("Image viewer", () => { test("shows full screen image on click", async ({ page }) => { await page.goto("/p/onClickOpenFullScreen"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-name-imageRender1"); const lightboxImage = await page.locator(".mx-image-viewer-lightbox img"); await expect(lightboxImage).toHaveAttribute("src", /ImageViewer\$Images\$landscape_2\.png/); diff --git a/packages/pluggableWidgets/language-selector-web/e2e/LanguageSelector.spec.js b/packages/pluggableWidgets/language-selector-web/e2e/LanguageSelector.spec.js index bd8cc58cde..1cb8295bbc 100644 --- a/packages/pluggableWidgets/language-selector-web/e2e/LanguageSelector.spec.js +++ b/packages/pluggableWidgets/language-selector-web/e2e/LanguageSelector.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - test.describe("language-selector-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks if all elements are rendered as expected", async ({ page }) => { @@ -33,7 +29,7 @@ test.describe("language-selector-web", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(["wcag21aa"]) .disableRules([ diff --git a/packages/pluggableWidgets/line-chart-web/e2e/LineChart.spec.js b/packages/pluggableWidgets/line-chart-web/e2e/LineChart.spec.js index 9cda7070b5..dc15accbc0 100644 --- a/packages/pluggableWidgets/line-chart-web/e2e/LineChart.spec.js +++ b/packages/pluggableWidgets/line-chart-web/e2e/LineChart.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("line-chart-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("line style", () => { diff --git a/packages/pluggableWidgets/maps-web/e2e/google.spec.js b/packages/pluggableWidgets/maps-web/e2e/google.spec.js index 844b95a31c..eb17e37dc3 100644 --- a/packages/pluggableWidgets/maps-web/e2e/google.spec.js +++ b/packages/pluggableWidgets/maps-web/e2e/google.spec.js @@ -1,24 +1,17 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Google Maps", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); - test("compares with a screenshot baseline and checks if basemap is correct", async ({ page }) => { + test("renders basemap with markers", async ({ page }) => { const $mapsElement = page.locator(".widget-google-maps"); await expect($mapsElement).toBeVisible(); - await expect($mapsElement).toHaveScreenshot(`googleMaps.png`, { - maxDiffPixels: 15000, - threshold: 0.3, - animations: "disabled" - }); + const canvas = $mapsElement.locator("canvas, .gm-style > div"); + await expect(canvas.first()).toBeVisible(); }); test("checks the rendering", async ({ page }) => { diff --git a/packages/pluggableWidgets/maps-web/e2e/here.spec.js b/packages/pluggableWidgets/maps-web/e2e/here.spec.js index 3e6017891d..19f1b4d850 100644 --- a/packages/pluggableWidgets/maps-web/e2e/here.spec.js +++ b/packages/pluggableWidgets/maps-web/e2e/here.spec.js @@ -1,25 +1,21 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Here Maps", () => { test.describe("rendering", () => { - test("compares with a screenshot baseline and checks if basemap is correct", async ({ page }) => { + test("renders basemap correctly", async ({ page }) => { await page.goto("p/here-static"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const mapElement = await page.locator(".widget-maps"); await expect(mapElement).toBeVisible(); - await expect(mapElement).toHaveScreenshot("hereMaps.png", { maxDiffPixels: 4000 }); + await expect(mapElement).toHaveScreenshot("hereMaps.png"); }); }); test.describe("mixed rendering", () => { test("checks the rendering", async ({ page }) => { await page.goto("p/here"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const mapElement = await page.locator(".widget-leaflet-maps"); await expect(mapElement).toBeVisible(); }); @@ -36,7 +32,7 @@ test.describe("Here Maps", () => { test.describe("static locations", () => { test("checks the rendering", async ({ page }) => { await page.goto("p/here-static"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const mapElement = await page.locator(".widget-leaflet-maps"); await expect(mapElement).toBeVisible(); }); @@ -54,7 +50,7 @@ test.describe("Here Maps", () => { test.describe("datasource locations", () => { test.beforeEach(async ({ page }) => { await page.goto("p/here-datasource"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -74,7 +70,7 @@ test.describe("Here Maps", () => { test.describe("on click", () => { test.beforeEach(async ({ page }) => { await page.goto("p/here-onclick"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("should click on first marker", async ({ page }) => { diff --git a/packages/pluggableWidgets/maps-web/e2e/mapbox.spec.js b/packages/pluggableWidgets/maps-web/e2e/mapbox.spec.js index 6fe583b481..b674d1a5d1 100644 --- a/packages/pluggableWidgets/maps-web/e2e/mapbox.spec.js +++ b/packages/pluggableWidgets/maps-web/e2e/mapbox.spec.js @@ -1,28 +1,24 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Mapbox Maps", () => { test.describe("rendering", () => { test.beforeEach(async ({ page }) => { await page.goto("p/mapbox-static"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if basemap is correct", async ({ page }) => { const mapElement = await page.locator(".widget-maps"); await expect(mapElement).toBeVisible(); - await expect(mapElement).toHaveScreenshot("mapboxMaps.png", { maxDiffPixels: 4000 }); + await expect(mapElement).toHaveScreenshot("mapboxMaps.png"); }); }); test.describe("mixed rendering", () => { test.beforeEach(async ({ page }) => { await page.goto("p/mapbox"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -41,7 +37,7 @@ test.describe("Mapbox Maps", () => { test.describe("static locations", () => { test.beforeEach(async ({ page }) => { await page.goto("p/mapbox-static"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -61,7 +57,7 @@ test.describe("Mapbox Maps", () => { test.describe("datasource locations", () => { test.beforeEach(async ({ page }) => { await page.goto("p/mapbox-datasource"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -81,7 +77,7 @@ test.describe("Mapbox Maps", () => { test.describe("on click", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/mapbox-onclick"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("should click on first marker", async ({ page }) => { diff --git a/packages/pluggableWidgets/maps-web/e2e/openstreet.spec.js b/packages/pluggableWidgets/maps-web/e2e/openstreet.spec.js index 731075a10b..07d17171d7 100644 --- a/packages/pluggableWidgets/maps-web/e2e/openstreet.spec.js +++ b/packages/pluggableWidgets/maps-web/e2e/openstreet.spec.js @@ -1,28 +1,24 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("OpenStreet Maps", () => { test.describe("rendering", () => { test.beforeEach(async ({ page }) => { await page.goto("p/osm-static"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if basemap is correct", async ({ page }) => { const mapElement = await page.locator(".widget-maps"); await expect(mapElement).toBeVisible(); - await expect(mapElement).toHaveScreenshot("osmMaps.png", { maxDiffPixels: 4000 }); + await expect(mapElement).toHaveScreenshot("osmMaps.png"); }); }); test.describe("mixed rendering", () => { test.beforeEach(async ({ page }) => { await page.goto("p/osm"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -41,7 +37,7 @@ test.describe("OpenStreet Maps", () => { test.describe("static locations", () => { test.beforeEach(async ({ page }) => { await page.goto("p/osm-static"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -60,7 +56,7 @@ test.describe("OpenStreet Maps", () => { test.describe("datasource locations", () => { test.beforeEach(async ({ page }) => { await page.goto("p/osm-datasource"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("checks the rendering", async ({ page }) => { @@ -79,7 +75,7 @@ test.describe("OpenStreet Maps", () => { test.describe("on click", () => { test.beforeEach(async ({ page }) => { await page.goto("p/osm-onclick"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("should click on first marker", async ({ page }) => { diff --git a/packages/pluggableWidgets/markdown-web/e2e/Markdown.spec.js b/packages/pluggableWidgets/markdown-web/e2e/Markdown.spec.js index aea6cdeb13..5a5c9fc3ca 100644 --- a/packages/pluggableWidgets/markdown-web/e2e/Markdown.spec.js +++ b/packages/pluggableWidgets/markdown-web/e2e/Markdown.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("markdown-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("contents", () => { diff --git a/packages/pluggableWidgets/pie-doughnut-chart-web/e2e/PieChart.spec.js b/packages/pluggableWidgets/pie-doughnut-chart-web/e2e/PieChart.spec.js index 903d598a4c..67c91e1f3f 100644 --- a/packages/pluggableWidgets/pie-doughnut-chart-web/e2e/PieChart.spec.js +++ b/packages/pluggableWidgets/pie-doughnut-chart-web/e2e/PieChart.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("pie-doughnut-chart-web", () => { test.describe("pie color", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test( @@ -19,7 +15,7 @@ test.describe("pie-doughnut-chart-web", () => { await containerSliceColor.scrollIntoViewIfNeeded(); await expect(containerSliceColor).toBeVisible({ timeout: 15000 }); await containerSliceColor.scrollIntoViewIfNeeded(); - await expect(containerSliceColor).toHaveScreenshot("pieChartDefaultColor.png", { threshold: 0.5 }); + await expect(containerSliceColor).toHaveScreenshot("pieChartDefaultColor.png"); }, { retry: 3 } ); @@ -28,7 +24,7 @@ test.describe("pie-doughnut-chart-web", () => { test.describe("column format", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test( @@ -36,7 +32,7 @@ test.describe("pie-doughnut-chart-web", () => { async ({ page }) => { const containerPieFormat = await page.locator(".mx-name-containerPieFormat"); await containerPieFormat.scrollIntoViewIfNeeded(); - await expect(containerPieFormat).toHaveScreenshot("pieChartPieFormat.png", { threshold: 0.5 }); + await expect(containerPieFormat).toHaveScreenshot("pieChartPieFormat.png"); }, { retry: 3 } ); @@ -44,7 +40,7 @@ test.describe("pie-doughnut-chart-web", () => { test("renders pie chart with doughnut format and compares with a screenshot baseline", async ({ page }) => { const containerDoughnutFormat = await page.locator(".mx-name-containerDoughnutFormat"); await containerDoughnutFormat.scrollIntoViewIfNeeded(); - await expect(containerDoughnutFormat).toHaveScreenshot("pieChartDoughnutFormat.png", { threshold: 0.5 }); + await expect(containerDoughnutFormat).toHaveScreenshot("pieChartDoughnutFormat.png"); }); }); }); diff --git a/packages/pluggableWidgets/popup-menu-web/e2e/PopupMenu.spec.js b/packages/pluggableWidgets/popup-menu-web/e2e/PopupMenu.spec.js index a4b1778998..c6d9f2ef1f 100644 --- a/packages/pluggableWidgets/popup-menu-web/e2e/PopupMenu.spec.js +++ b/packages/pluggableWidgets/popup-menu-web/e2e/PopupMenu.spec.js @@ -1,15 +1,11 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Popup-menu-web", () => { test.describe("using basic option", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the top left position", async ({ @@ -17,7 +13,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton10"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuTopLeft.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuTopLeft.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the left position", async ({ @@ -25,7 +21,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton12"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuLeft.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuLeft.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the top position", async ({ @@ -33,7 +29,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton15"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuTop.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuTop.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the top right position", async ({ @@ -41,7 +37,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton13"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuTopRight.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuTopRight.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the right position", async ({ @@ -49,7 +45,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton14"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuRight.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuRight.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the bottom right position", async ({ @@ -57,7 +53,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton20"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuBottomRight.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuBottomRight.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the bottom left position", async ({ @@ -65,7 +61,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton18"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuBottomLeft.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuBottomLeft.png`); }); test("compares with a screenshot baseline and checks if popupmenu is rendered in the bottom position", async ({ @@ -73,12 +69,12 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton19"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`popUpMenuBottom.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`popUpMenuBottom.png`); }); test("shows a new menu list when on hover is triggered", async ({ page }) => { await page.click(".mx-name-actionButton1"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const button25 = page.getByRole("button", { name: "Trigger On Hover" }); await expect(button25).toBeVisible(); await button25.hover(); @@ -102,7 +98,7 @@ test.describe("Popup-menu-web", () => { test.describe("using custom option", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if custom popupmenu is rendered in the top left position", async ({ @@ -110,7 +106,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton11"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`customPopUpMenuTopLeft.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`customPopUpMenuTopLeft.png`); }); test("compares with a screenshot baseline and checks if custom popupmenu is rendered in the left position", async ({ @@ -118,7 +114,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton17"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`CustomPopUpMenuLeft.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`CustomPopUpMenuLeft.png`); }); test("compares with a screenshot baseline and checks if custom popupmenu is rendered in the top position", async ({ @@ -126,7 +122,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton24"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`customPopUpMenuTop.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`customPopUpMenuTop.png`); }); test("compares with a screenshot baseline and checks if custom popupmenu is rendered in the top right position", async ({ @@ -134,7 +130,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton23"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`customPopUpMenuTopRight.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`customPopUpMenuTopRight.png`); }); test("compares with a screenshot baseline and checks if custom popupmenu is rendered in the right position", async ({ @@ -142,7 +138,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton26"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`customPopUpMenuRight.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`customPopUpMenuRight.png`); }); test("compares with a screenshot baseline and checks if custom popupmenu is rendered in the bottom position", async ({ @@ -150,7 +146,7 @@ test.describe("Popup-menu-web", () => { }) => { await page.click(".mx-name-actionButton29"); const container = await page.locator(".mx-name-container15"); - await expect(container).toHaveScreenshot(`customPopUpMenuBottom.png`, { threshold: 0.1 }); + await expect(container).toHaveScreenshot(`customPopUpMenuBottom.png`); }); test("shows a message when one item is clicked", async ({ page }) => { diff --git a/packages/pluggableWidgets/progress-bar-web/e2e/differentViews.spec.js b/packages/pluggableWidgets/progress-bar-web/e2e/differentViews.spec.js index 276a77ad1f..9676b6da64 100644 --- a/packages/pluggableWidgets/progress-bar-web/e2e/differentViews.spec.js +++ b/packages/pluggableWidgets/progress-bar-web/e2e/differentViews.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("Progress Bar", () => { test("renders in a group box", async ({ page }) => { diff --git a/packages/pluggableWidgets/progress-bar-web/e2e/displayText.spec.js b/packages/pluggableWidgets/progress-bar-web/e2e/displayText.spec.js index 90a4186823..3c27d0bb01 100644 --- a/packages/pluggableWidgets/progress-bar-web/e2e/displayText.spec.js +++ b/packages/pluggableWidgets/progress-bar-web/e2e/displayText.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("Progress Bar", () => { test("should render attribute text", async ({ page }) => { diff --git a/packages/pluggableWidgets/progress-bar-web/e2e/errors.spec.js b/packages/pluggableWidgets/progress-bar-web/e2e/errors.spec.js index 5b6116a3cc..367fbeca43 100644 --- a/packages/pluggableWidgets/progress-bar-web/e2e/errors.spec.js +++ b/packages/pluggableWidgets/progress-bar-web/e2e/errors.spec.js @@ -1,9 +1,4 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("Progress Bar", () => { test("should render progress bar when there's no context", async ({ page }) => { diff --git a/packages/pluggableWidgets/progress-bar-web/e2e/onClick.spec.js b/packages/pluggableWidgets/progress-bar-web/e2e/onClick.spec.js index be553dbae6..0a6541bdc7 100644 --- a/packages/pluggableWidgets/progress-bar-web/e2e/onClick.spec.js +++ b/packages/pluggableWidgets/progress-bar-web/e2e/onClick.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Progress Bar on click", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/eventOnClick"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("should call Microflow", async ({ page }) => { diff --git a/packages/pluggableWidgets/progress-circle-web/e2e/ProgressCircle.spec.js b/packages/pluggableWidgets/progress-circle-web/e2e/ProgressCircle.spec.js index 28dd567a5b..44110f7de1 100644 --- a/packages/pluggableWidgets/progress-circle-web/e2e/ProgressCircle.spec.js +++ b/packages/pluggableWidgets/progress-circle-web/e2e/ProgressCircle.spec.js @@ -1,21 +1,17 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Progress Circle", () => { test("renders with a value", async ({ page }) => { await page.goto("p/Home"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-progressCircleNegative")).toBeVisible(); await expect(page.locator(".mx-name-progressCircleNegative .progressbar-text")).toHaveText("20%"); }); test("updates the progress percentage when the value is changed", async ({ page }) => { await page.goto("p/Playground"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-progressCirclePercentage")).toBeVisible(); await page.locator(".mx-name-textBoxProgress input").fill("67", { force: true }); await page.locator(".mx-name-textBoxMaximumValue").click(); diff --git a/packages/pluggableWidgets/range-slider-web/e2e/dataTypes.spec.js b/packages/pluggableWidgets/range-slider-web/e2e/dataTypes.spec.js index c45f5985e9..aedfc6039c 100644 --- a/packages/pluggableWidgets/range-slider-web/e2e/dataTypes.spec.js +++ b/packages/pluggableWidgets/range-slider-web/e2e/dataTypes.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Range Slider", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("renders slider with interval context", async ({ page }) => { diff --git a/packages/pluggableWidgets/rating-web/e2e/Rating.spec.js b/packages/pluggableWidgets/rating-web/e2e/Rating.spec.js index a6c75b2506..1dd1062952 100644 --- a/packages/pluggableWidgets/rating-web/e2e/Rating.spec.js +++ b/packages/pluggableWidgets/rating-web/e2e/Rating.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Rating", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if all rating elements are rendered as expected", async ({ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js index 782a344759..c05860d869 100644 --- a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js +++ b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js @@ -1,42 +1,36 @@ -import { expect, test } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { expect, test } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("RichText", () => { test("compares with a screenshot baseline and checks if inline basic mode are rendered as expected", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click("text=Generate Data"); await page.goto("/p/basic"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText1").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText1")).toBeVisible(); - await expect(page.locator(".mx-name-richText1")).toHaveScreenshot(`inlineBasicMode.png`, { threshold: 0.4 }); + await expect(page.locator(".mx-name-richText1")).toHaveScreenshot(`inlineBasicMode.png`); }); test("compares with a screenshot baseline and checks if toolbar basic mode are rendered as expected", async ({ page }) => { await page.goto("/p/basic"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-richText4")).toBeVisible(); - await expect(page.locator(".mx-name-richText4")).toHaveScreenshot(`toolbarBasicMode.png`, { threshold: 0.4 }); + await expect(page.locator(".mx-name-richText4")).toHaveScreenshot(`toolbarBasicMode.png`); }); test("compares with a screenshot baseline and checks if bottom toolbar advanced mode are rendered as expected", async ({ page }) => { await page.goto("/p/advanced"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-richText1")).toBeVisible(); - await expect(page.locator(".mx-name-richText1")).toHaveScreenshot(`bottomToolbarAdvancedMode.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText1")).toHaveScreenshot(`bottomToolbarAdvancedMode.png`); await page.click(".mx-name-richText1 .ql-toolbar button.ql-image"); await expect(page.locator(".widget-rich-text .widget-rich-text-modal-body").first()).toHaveScreenshot( @@ -48,12 +42,10 @@ test.describe("RichText", () => { page }) => { await page.goto("/p/advanced"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText4").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText4")).toBeVisible(); - await expect(page.locator(".mx-name-richText4")).toHaveScreenshot(`toolbarAdvancedMode.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText4")).toHaveScreenshot(`toolbarAdvancedMode.png`); await page.click(".mx-name-richText1 .ql-toolbar button.ql-view-code"); await expect(page.locator(".widget-rich-text .widget-rich-text-modal-body").first()).toHaveScreenshot( @@ -65,77 +57,67 @@ test.describe("RichText", () => { page }) => { await page.goto("/p/custom"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-richText1")).toBeVisible(); - await expect(page.locator(".mx-name-richText1")).toHaveScreenshot(`inlineCustomMode.png`, { threshold: 0.4 }); + await expect(page.locator(".mx-name-richText1")).toHaveScreenshot(`inlineCustomMode.png`); }); test("compares with a screenshot baseline and checks if toolbar custom mode are rendered as expected", async ({ page }) => { await page.goto("/p/custom"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-richText2")).toBeVisible(); - await expect(page.locator(".mx-name-richText2")).toHaveScreenshot(`toolbarCustomMode.png`, { threshold: 0.4 }); + await expect(page.locator(".mx-name-richText2")).toHaveScreenshot(`toolbarCustomMode.png`); }); test("compares with a screenshot baseline and checks if inline custom mode with all options enabled are rendered as expected", async ({ page }) => { await page.goto("/p/custom"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText3").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText3")).toBeVisible(); - await expect(page.locator(".mx-name-richText3")).toHaveScreenshot(`customModeAllOptions.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText3")).toHaveScreenshot(`customModeAllOptions.png`); }); test("compares with a screenshot baseline and checks if toolbar custom mode with none option enabled are rendered as expected", async ({ page }) => { await page.goto("/p/custom"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText4").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText4")).toBeVisible(); - await expect(page.locator(".mx-name-richText4")).toHaveScreenshot(`customModeNoneOptions.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText4")).toHaveScreenshot(`customModeNoneOptions.png`); }); test("compares with a screenshot baseline and checks for readonly mode basic styling", async ({ page }) => { await page.goto("/p/read-only"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText3").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText3")).toBeVisible(); - await expect(page.locator(".mx-name-richText3")).toHaveScreenshot(`readOnlyModeBasic.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText3")).toHaveScreenshot(`readOnlyModeBasic.png`); }); test("compares with a screenshot baseline and checks for readonly mode bordered styling", async ({ page }) => { await page.goto("/p/read-only"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText2").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText2")).toBeVisible(); - await expect(page.locator(".mx-name-richText2")).toHaveScreenshot(`readOnlyModeBordered.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText2")).toHaveScreenshot(`readOnlyModeBordered.png`); }); test("compares with a screenshot baseline and checks for readonly mode read panel styling", async ({ page }) => { await page.goto("/p/read-only"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-richText6").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-richText6")).toBeVisible(); - await expect(page.locator(".mx-name-richText6")).toHaveScreenshot(`readOnlyModeReadPanel.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-richText6")).toHaveScreenshot(`readOnlyModeReadPanel.png`); }); test("compares with a screenshot for rich text inside modal popup layout", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.click(".mx-navbar-item [title='Demo']"); diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/bottomToolbarAdvancedMode-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/bottomToolbarAdvancedMode-chromium-darwin.png new file mode 100644 index 0000000000..cdd2b5dc09 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/bottomToolbarAdvancedMode-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/customModeAllOptions-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/customModeAllOptions-chromium-darwin.png new file mode 100644 index 0000000000..1775c49017 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/customModeAllOptions-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/customModeNoneOptions-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/customModeNoneOptions-chromium-darwin.png new file mode 100644 index 0000000000..744473ed17 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/customModeNoneOptions-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/inlineBasicMode-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/inlineBasicMode-chromium-darwin.png new file mode 100644 index 0000000000..62617b4156 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/inlineBasicMode-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/inlineCustomMode-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/inlineCustomMode-chromium-darwin.png new file mode 100644 index 0000000000..3d68b67944 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/inlineCustomMode-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/insertImageDialog-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/insertImageDialog-chromium-darwin.png new file mode 100644 index 0000000000..1856869bba Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/insertImageDialog-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeBasic-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeBasic-chromium-darwin.png new file mode 100644 index 0000000000..ec63d4771f Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeBasic-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeBordered-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeBordered-chromium-darwin.png new file mode 100644 index 0000000000..689d88bd1c Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeBordered-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeReadPanel-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeReadPanel-chromium-darwin.png new file mode 100644 index 0000000000..913ba1c7b2 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/readOnlyModeReadPanel-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/richTextDialogInsidePopup-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/richTextDialogInsidePopup-chromium-darwin.png new file mode 100644 index 0000000000..7b45dbc71a Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/richTextDialogInsidePopup-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/richTextDialogInsidePopupEdit-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/richTextDialogInsidePopupEdit-chromium-darwin.png new file mode 100644 index 0000000000..75466ed897 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/richTextDialogInsidePopupEdit-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarAdvancedMode-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarAdvancedMode-chromium-darwin.png new file mode 100644 index 0000000000..5d10dfd3d1 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarAdvancedMode-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarBasicMode-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarBasicMode-chromium-darwin.png new file mode 100644 index 0000000000..bbdbf3dcb8 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarBasicMode-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarCustomMode-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarCustomMode-chromium-darwin.png new file mode 100644 index 0000000000..6243197929 Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/toolbarCustomMode-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/viewCodeDialog-chromium-darwin.png b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/viewCodeDialog-chromium-darwin.png new file mode 100644 index 0000000000..d886668aae Binary files /dev/null and b/packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js-snapshots/viewCodeDialog-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/skiplink-web/e2e/SkipLink.spec.js b/packages/pluggableWidgets/skiplink-web/e2e/SkipLink.spec.js index 178384ec0b..8b56d756d3 100644 --- a/packages/pluggableWidgets/skiplink-web/e2e/SkipLink.spec.js +++ b/packages/pluggableWidgets/skiplink-web/e2e/SkipLink.spec.js @@ -1,13 +1,9 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("SkipLink:", function () { @@ -25,9 +21,7 @@ test.describe("SkipLink:", function () { await page.keyboard.press("Tab"); await expect(skipLink).toBeFocused(); - // Element should now be within the viewport - const rect = await skipLink.evaluate(el => el.getBoundingClientRect().toJSON()); - expect(rect.top).toBeGreaterThanOrEqual(0); + await expect(skipLink).toHaveCSS("transform", "matrix(1, 0, 0, 1, 0, 0)"); }); test("skip link navigates to main content when activated", async ({ page }) => { diff --git a/packages/pluggableWidgets/slider-web/e2e/Slider.spec.js b/packages/pluggableWidgets/slider-web/e2e/Slider.spec.js index ba943545fc..02376b95e0 100644 --- a/packages/pluggableWidgets/slider-web/e2e/Slider.spec.js +++ b/packages/pluggableWidgets/slider-web/e2e/Slider.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Slider", () => { test("renders with context", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const minimumValue = await page.inputValue(".mx-name-textBoxMinimumValue input"); const minimumValueText = await page @@ -33,7 +29,7 @@ test.describe("Slider", () => { test("renders without context", async ({ page }) => { await page.goto("/p/no-context"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); const sliderClass = await page.locator(".mx-name-sliderNoContext .rc-slider").getAttribute("class"); await expect(sliderClass).toContain("rc-slider-disabled"); @@ -62,7 +58,7 @@ test.describe("Slider", () => { test.skip(process.env.MODERN_CLIENT === true, () => { test("listens to a grid", async ({ page }) => { await page.goto("/p/listen-to-grid"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider .rc-slider-handle")).toHaveCSS("cursor", /not-allowed/); @@ -76,7 +72,7 @@ test.describe("Slider", () => { test("triggers a microflow after slide", async ({ page }) => { await page.goto("/p/after-slide"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page .locator(".mx-name-sliderMicroflow .rc-slider-handle") @@ -86,7 +82,7 @@ test.describe("Slider", () => { test("triggers a nanoflow after slide", async ({ page }) => { await page.goto("/p/after-slide"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page .locator(".mx-name-sliderNanoflow .rc-slider-handle") @@ -98,7 +94,7 @@ test.describe("Slider", () => { test("renders with a range that goes from negative to positive", async ({ page }) => { await page.goto("/p/negative-and-positive-range"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await expect(page.locator(".mx-name-textValue")).toHaveText(/5/); @@ -112,7 +108,7 @@ test.describe("Slider", () => { test("renders multiple markers", async ({ page }) => { await page.goto("/p/multiple-markers"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); const mark0 = await page.locator(".mx-name-slider .rc-slider-mark > span").nth(0); @@ -132,7 +128,7 @@ test.describe("Slider", () => { test("updates decimal values", async ({ page }) => { await page.goto("/p/decimal-values"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await expect(page.locator(".mx-name-textValue")).toHaveText(/5.5/); @@ -146,7 +142,7 @@ test.describe("Slider", () => { test("updates long values", async ({ page }) => { await page.goto("/p/long-values"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await expect(page.locator(".mx-name-textValue")).toHaveText(/60000/); @@ -160,7 +156,7 @@ test.describe("Slider", () => { test("slides with step size", async ({ page }) => { await page.goto("/p/long-values"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await page.locator(".mx-name-slider .rc-slider-handle").click({ position: { x: 58, y: 0 }, force: true }); @@ -174,7 +170,7 @@ test.describe("Slider", () => { test("snaps to intermediate markers", async ({ page }) => { await page.goto("/p/long-values"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await expect(page.locator(".mx-name-slider .rc-slider-mark > span").nth(1)).toHaveText("140000"); @@ -186,7 +182,7 @@ test.describe("Slider", () => { test("slides without using intermediate marker as base", async ({ page }) => { await page.goto("/p/long-values"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await page.locator(".mx-name-slider .rc-slider-dot:nth-child(2)").click({ force: true }); @@ -201,23 +197,21 @@ test.describe("Slider", () => { test.describe("Style", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/different-slider-styles"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if all slider elements are rendered as expected", async ({ page }) => { await expect(page.locator(".mx-name-sliderPrimary")).toBeVisible(); - await expect(page.locator(".mx-name-sliderPrimary")).toHaveScreenshot(`sliderStyles.png`, { - threshold: 0.4 - }); + await expect(page.locator(".mx-name-sliderPrimary")).toHaveScreenshot(`sliderStyles.png`); }); }); test.describe("Tooltip", () => { test("doesn't render when there's no title", async ({ page }) => { await page.goto("/p/no-tooltip-title"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await expect(page.locator(".mx-name-slider .rc-slider-handle .rc-slider-tooltip")).toHaveCount(0); @@ -225,7 +219,7 @@ test.describe("Slider", () => { test("renders a static title", async ({ page }) => { await page.goto("/p/tooltip-with-static-title"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".mx-name-slider")).toBeVisible(); await expect(page.locator(".rc-slider-tooltip-container")).toHaveText("Slider"); @@ -239,7 +233,7 @@ test.describe("Slider", () => { test("renders the slider's value", async ({ page }) => { await page.goto("/p/tooltip-with-slider-value"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await expect(page.locator(".rc-slider-tooltip-container")).toHaveText("10.00"); diff --git a/packages/pluggableWidgets/switch-web/e2e/Switch.spec.js b/packages/pluggableWidgets/switch-web/e2e/Switch.spec.js index 5213788fa9..0f0564b3de 100644 --- a/packages/pluggableWidgets/switch-web/e2e/Switch.spec.js +++ b/packages/pluggableWidgets/switch-web/e2e/Switch.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("Switch", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("changes color when checked", async ({ page }) => { diff --git a/packages/pluggableWidgets/time-series-chart-web/e2e/TimeSeriesChart.spec.js b/packages/pluggableWidgets/time-series-chart-web/e2e/TimeSeriesChart.spec.js index da828f1251..9b479bba96 100644 --- a/packages/pluggableWidgets/time-series-chart-web/e2e/TimeSeriesChart.spec.js +++ b/packages/pluggableWidgets/time-series-chart-web/e2e/TimeSeriesChart.spec.js @@ -1,22 +1,17 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("time-series-chart-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("renders time series chart with multiple series and compares with a screenshot baseline", async ({ page }) => { await expect(page.locator(".mx-name-containerMultipleSeries", { timeout: 10000 })).toBeVisible(); await page.locator(".mx-name-containerMultipleSeries").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-containerMultipleSeries")).toHaveScreenshot( - `timeSeriesChartMultipleSeries.png`, - { threshold: 0.5 } + `timeSeriesChartMultipleSeries.png` ); }); @@ -24,8 +19,7 @@ test.describe("time-series-chart-web", () => { await expect(page.locator(".mx-name-containerWithoutRangeSlider", { timeout: 10000 })).toBeVisible(); await page.locator(".mx-name-containerWithoutRangeSlider").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-containerWithoutRangeSlider")).toHaveScreenshot( - `timeSeriesChartWithoutRangeSlider.png`, - { threshold: 0.5 } + `timeSeriesChartWithoutRangeSlider.png` ); }); @@ -36,8 +30,7 @@ test.describe("time-series-chart-web", () => { await expect(page.locator(".mx-name-containerWithoutFillArea", { timeout: 10000 })).toBeVisible(); await page.locator(".mx-name-containerWithoutFillArea").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-containerWithoutFillArea")).toHaveScreenshot( - `timeSeriesChartWithoutFillArea.png`, - { threshold: 0.5 } + `timeSeriesChartWithoutFillArea.png` ); }); @@ -47,15 +40,14 @@ test.describe("time-series-chart-web", () => { await expect(page.locator(".mx-name-containerCustomFillAreaColor", { timeout: 10000 })).toBeVisible(); await page.locator(".mx-name-containerCustomFillAreaColor").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-containerCustomFillAreaColor")).toHaveScreenshot( - `timeSeriesChartCustomFillAreaColor.png`, - { threshold: 0.5 } + `timeSeriesChartCustomFillAreaColor.png` ); }); }); test.describe("y axis range", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("renders time series chart with non negative values and compares with a screenshot baseline", async ({ @@ -64,8 +56,7 @@ test.describe("time-series-chart-web", () => { await expect(page.locator(".mx-name-containerYRangeNonNegative", { timeout: 10000 })).toBeVisible(); await page.locator(".mx-name-containerYRangeNonNegative").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-containerYRangeNonNegative")).toHaveScreenshot( - `timeSeriesChartYRangeNonNegative.png`, - { threshold: 0.5 } + `timeSeriesChartYRangeNonNegative.png` ); }); @@ -73,10 +64,7 @@ test.describe("time-series-chart-web", () => { await expect(page.locator(".mx-name-containerYRangeAuto")).toBeVisible(); await page.locator(".mx-name-containerYRangeAuto").scrollIntoViewIfNeeded(); await expect(page.locator(".mx-name-containerYRangeAuto")).toHaveScreenshot( - `timeSeriesChartYRangeAuto.png`, - { - threshold: 0.5 - } + `timeSeriesChartYRangeAuto.png` ); }); }); diff --git a/packages/pluggableWidgets/timeline-web/e2e/timeline.spec.js b/packages/pluggableWidgets/timeline-web/e2e/timeline.spec.js index 6626f7a1f5..21f5aa4b6e 100644 --- a/packages/pluggableWidgets/timeline-web/e2e/timeline.spec.js +++ b/packages/pluggableWidgets/timeline-web/e2e/timeline.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("timeline-web", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test.describe("option: basic", () => { @@ -17,9 +13,7 @@ test.describe("timeline-web", () => { }) => { await page.locator(".mx-name-basicTimelinePage").click(); await expect(page.locator(".mx-name-timelineGrids")).toBeVisible(); - await expect(page.locator(".mx-name-timelineGrids")).toHaveScreenshot(`timelineBasic.png`, { - threshold: 0.2 - }); + await expect(page.locator(".mx-name-timelineGrids")).toHaveScreenshot(`timelineBasic.png`); }); test("shows a message when event onclick is called", async ({ page }) => { @@ -35,9 +29,7 @@ test.describe("timeline-web", () => { page }) => { await expect(page.locator(".mx-name-customTimelineLayoutGrid")).toBeVisible(); - await expect(page.locator(".mx-name-customTimelineLayoutGrid")).toHaveScreenshot(`timelineCusto.png`, { - threshold: 0.2 - }); + await expect(page.locator(".mx-name-customTimelineLayoutGrid")).toHaveScreenshot(`timelineCusto.png`); }); test("shows a message when event onclick is called", async ({ page }) => { diff --git a/packages/pluggableWidgets/tooltip-web/e2e/Tooltip.spec.js b/packages/pluggableWidgets/tooltip-web/e2e/Tooltip.spec.js index eff1b19038..f5ecca26bb 100644 --- a/packages/pluggableWidgets/tooltip-web/e2e/Tooltip.spec.js +++ b/packages/pluggableWidgets/tooltip-web/e2e/Tooltip.spec.js @@ -1,14 +1,10 @@ -import { test, expect } from "@playwright/test"; - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; test.describe("render method: text", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/arrow"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("compares with a screenshot baseline and checks if tooltip arrow start is rendered as expected", async ({ @@ -34,14 +30,14 @@ test.describe("render method: text", () => { test("compares with a screenshot baseline and checks if tooltip position is rendered on top", async ({ page }) => { await page.goto("/p/position"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButtonTop").focus(); await expect(page.locator(".mx-scrollcontainer-center")).toHaveScreenshot(`tooltipPositionTop.png`, 0.1); }); test("compares with a screenshot baseline and checks if tooltip position is rendered on left", async ({ page }) => { await page.goto("/p/position"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButtonLeft").focus(); await expect(page.locator(".mx-scrollcontainer-center")).toHaveScreenshot(`tooltipPositionLeft.png`, 0.1); }); @@ -50,7 +46,7 @@ test.describe("render method: text", () => { page }) => { await page.goto("/p/position"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButtonRight").focus(); await expect(page.locator(".mx-scrollcontainer-center")).toHaveScreenshot(`tooltipPositionRight.png`, 0.1); }); @@ -59,7 +55,7 @@ test.describe("render method: text", () => { page }) => { await page.goto("/p/position"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButtonBottom").focus(); await expect(page.locator(".mx-scrollcontainer-center")).toHaveScreenshot(`tooltipPositionBottom.png`, 0.1); }); @@ -68,7 +64,7 @@ test.describe("render method: text", () => { page }) => { await page.goto("/p/position"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButtonFlip").focus(); await expect(page.locator(".mx-scrollcontainer-center")).toHaveScreenshot(`tooltipPositionFlipped.png`, 0.1); }); @@ -76,7 +72,7 @@ test.describe("render method: text", () => { test.describe("render method: custom", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/arrow"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("verifies tooltip shown custom content and compares with a screenshot baseline", async ({ page }) => { @@ -87,7 +83,7 @@ test.describe("render method: text", () => { test("verifies if tooltip is opened on click", async ({ page }) => { await page.goto("/p/click"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-actionButtonClick").click(); await expect(page.locator(".mx-scrollcontainer-center")).toHaveScreenshot(`tooltipClick.png`, 0.1); }); diff --git a/packages/pluggableWidgets/tree-node-web/e2e/TreeNode.spec.js b/packages/pluggableWidgets/tree-node-web/e2e/TreeNode.spec.js index 78601e0128..56c2482313 100644 --- a/packages/pluggableWidgets/tree-node-web/e2e/TreeNode.spec.js +++ b/packages/pluggableWidgets/tree-node-web/e2e/TreeNode.spec.js @@ -1,11 +1,7 @@ -import { test, expect } from "@playwright/test"; +import { test, expect } from "@mendix/run-e2e/fixtures"; +import { waitForMendixApp } from "@mendix/run-e2e/mendix-helpers"; import AxeBuilder from "@axe-core/playwright"; -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); - function getTreeNodeHeaders(page) { return page.locator(".mx-name-treeNode1 .widget-tree-node-branch-header-value"); } @@ -13,7 +9,7 @@ function getTreeNodeHeaders(page) { test.describe("capabilities: expand", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("expands a node", async ({ page }) => { @@ -33,7 +29,7 @@ test.describe("capabilities: expand", () => { test.describe("capabilities: collapse", () => { test.beforeEach(async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); }); test("collapses a node", async ({ page }) => { @@ -59,7 +55,7 @@ test.describe("capabilities: collapse", () => { test.describe("a11y testing:", () => { test("checks accessibility violations", async ({ page }) => { await page.goto("/"); - await page.waitForLoadState("networkidle"); + await waitForMendixApp(page); await page.locator(".mx-name-treeNode1").waitFor(); const accessibilityScanResults = await new AxeBuilder({ page }) diff --git a/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js b/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js index 87adec0e4a..4fc2904feb 100644 --- a/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js +++ b/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js @@ -1,19 +1,8 @@ -import { test, expect } from "@playwright/test"; - -async function waitForMendixReady(page) { - await page.waitForLoadState("domcontentloaded"); - await page.waitForFunction(() => !!window.mx?.session); -} - -test.afterEach("Cleanup session", async ({ page }) => { - // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test. - await page.evaluate(() => window.mx.session.logout()); -}); +import { test, expect } from "@mendix/run-e2e/fixtures"; test.describe("Video Player", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/grid"); - await waitForMendixReady(page); }); test("renders youtube video", async ({ page }) => { @@ -47,7 +36,6 @@ test.describe("Video Player", () => { test.describe("Tab page", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/tabs"); - await waitForMendixReady(page); }); test("renders youtube video", async ({ page }) => { @@ -102,7 +90,6 @@ test.describe("Tab page", () => { test.describe("Error page", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/errors"); - await waitForMendixReady(page); }); test("renders no content div", async ({ page }) => { @@ -116,7 +103,6 @@ test.describe("Error page", () => { test.describe("External video", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/external"); - await waitForMendixReady(page); }); test("renders a poster", async ({ page }) => { @@ -126,7 +112,6 @@ test.describe("External video", () => { test.describe("Video aspect ratio", () => { test.beforeEach(async ({ page }) => { await page.goto("/p/aspectRatio"); - await waitForMendixReady(page); }); test("renders video aspect ratio correctly", async ({ page }) => { diff --git a/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js-snapshots/videoPlayerExternalPoster-chromium-darwin.png b/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js-snapshots/videoPlayerExternalPoster-chromium-darwin.png new file mode 100644 index 0000000000..d5a08d5191 Binary files /dev/null and b/packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js-snapshots/videoPlayerExternalPoster-chromium-darwin.png differ diff --git a/turbo.json b/turbo.json index 98afa28d8e..ba7b42baf9 100644 --- a/turbo.json +++ b/turbo.json @@ -65,11 +65,10 @@ }, "e2e": { "inputs": [ - "assets/**", + "e2e/**", + "playwright.config.*", "src/**", - "cypress/**", - "cypress-visual-screenshots/**", - "cypress.config.*", + "assets/**", "package.json", "!src/*.{editorConfig,editorPreview,icon,tile,xml}*", "!*/**/__tests__/**"