test: migrate apps folder to playwright (#1201)
This commit is contained in:
6
.github/workflows/playwright.yml
vendored
6
.github/workflows/playwright.yml
vendored
@@ -1,9 +1,7 @@
|
|||||||
name: Automatisch UI Test
|
name: Automatisch UI Test
|
||||||
on:
|
on:
|
||||||
push:
|
schedule:
|
||||||
branches: [main]
|
- cron: '0 12 * * *'
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
|
1
packages/e2e-tests/.gitignore
vendored
1
packages/e2e-tests/.gitignore
vendored
@@ -2,3 +2,4 @@ node_modules/
|
|||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
|
/output
|
||||||
|
12
packages/e2e-tests/fixtures/applications-page.js
Normal file
12
packages/e2e-tests/fixtures/applications-page.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const path = require('node:path');
|
||||||
|
const { BasePage } = require('./base-page');
|
||||||
|
|
||||||
|
export class ApplicationsPage extends BasePage {
|
||||||
|
async screenshot(options = {}) {
|
||||||
|
const { path: plainPath, ...restOptions } = options;
|
||||||
|
|
||||||
|
const computedPath = path.join('applications', plainPath);
|
||||||
|
|
||||||
|
return await super.screenshot({ path: computedPath, ...restOptions });
|
||||||
|
}
|
||||||
|
}
|
34
packages/e2e-tests/fixtures/base-page.js
Normal file
34
packages/e2e-tests/fixtures/base-page.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
const path = require('node:path');
|
||||||
|
|
||||||
|
export class BasePage {
|
||||||
|
/**
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
*/
|
||||||
|
constructor(page) {
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickAway() {
|
||||||
|
await this.page.locator('body').click({ position: { x: 0, y: 0 } });
|
||||||
|
}
|
||||||
|
|
||||||
|
async screenshot(options = {}) {
|
||||||
|
const { path: plainPath, ...restOptions } = options;
|
||||||
|
|
||||||
|
const computedPath = path.join('output/screenshots', plainPath);
|
||||||
|
|
||||||
|
return await this.page.screenshot({ path: computedPath, ...restOptions });
|
||||||
|
}
|
||||||
|
|
||||||
|
async login() {
|
||||||
|
await this.page.goto('/login');
|
||||||
|
await this.page
|
||||||
|
.getByTestId('email-text-field')
|
||||||
|
.fill(process.env.LOGIN_EMAIL);
|
||||||
|
await this.page
|
||||||
|
.getByTestId('password-text-field')
|
||||||
|
.fill(process.env.LOGIN_PASSWORD);
|
||||||
|
|
||||||
|
await this.page.getByTestId('login-button').click();
|
||||||
|
}
|
||||||
|
}
|
9
packages/e2e-tests/fixtures/index.js
Normal file
9
packages/e2e-tests/fixtures/index.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const base = require('@playwright/test');
|
||||||
|
const { ApplicationsPage } = require('./applications-page');
|
||||||
|
|
||||||
|
exports.test = base.test.extend({
|
||||||
|
applicationsPage: async ({ page }, use) => {
|
||||||
|
await use(new ApplicationsPage(page));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
exports.expect = base.expect;
|
@@ -5,7 +5,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"open": "cypress open"
|
"open": "cypress open",
|
||||||
|
"playwright": "playwright test"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
{
|
{
|
||||||
@@ -24,5 +25,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.36.2",
|
"@playwright/test": "^1.36.2",
|
||||||
"cypress": "^10.9.0"
|
"cypress": "^10.9.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^16.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ const { defineConfig, devices } = require('@playwright/test');
|
|||||||
* Read environment variables from file.
|
* Read environment variables from file.
|
||||||
* https://github.com/motdotla/dotenv
|
* https://github.com/motdotla/dotenv
|
||||||
*/
|
*/
|
||||||
// require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://playwright.dev/docs/test-configuration
|
* @see https://playwright.dev/docs/test-configuration
|
||||||
@@ -21,14 +21,18 @@ module.exports = defineConfig({
|
|||||||
/* Opt out of parallel tests on CI. */
|
/* Opt out of parallel tests on CI. */
|
||||||
workers: process.env.CI ? 1 : undefined,
|
workers: process.env.CI ? 1 : undefined,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: 'html',
|
reporter: process.env.CI ? 'github' : 'html',
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
use: {
|
use: {
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
// baseURL: 'http://127.0.0.1:3000',
|
baseURL: process.env.CI
|
||||||
|
? 'https://sandbox.automatisch.io'
|
||||||
|
: 'http://localhost:3001',
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
trace: 'on-first-retry',
|
trace: 'on-first-retry',
|
||||||
|
testIdAttribute: 'data-test',
|
||||||
|
viewport: { width: 1280, height: 720 },
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Configure projects for major browsers */
|
/* Configure projects for major browsers */
|
||||||
@@ -38,15 +42,15 @@ module.exports = defineConfig({
|
|||||||
use: { ...devices['Desktop Chrome'] },
|
use: { ...devices['Desktop Chrome'] },
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
// {
|
||||||
name: 'firefox',
|
// name: 'firefox',
|
||||||
use: { ...devices['Desktop Firefox'] },
|
// use: { ...devices['Desktop Firefox'] },
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
// {
|
||||||
name: 'webkit',
|
// name: 'webkit',
|
||||||
use: { ...devices['Desktop Safari'] },
|
// use: { ...devices['Desktop Safari'] },
|
||||||
},
|
// },
|
||||||
|
|
||||||
/* Test against mobile viewports. */
|
/* Test against mobile viewports. */
|
||||||
// {
|
// {
|
||||||
@@ -76,4 +80,3 @@ module.exports = defineConfig({
|
|||||||
// reuseExistingServer: !process.env.CI,
|
// reuseExistingServer: !process.env.CI,
|
||||||
// },
|
// },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
66
packages/e2e-tests/tests/apps/list-apps.spec.js
Normal file
66
packages/e2e-tests/tests/apps/list-apps.spec.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
const { test, expect } = require('../../fixtures/index');
|
||||||
|
|
||||||
|
test.describe('Apps page', () => {
|
||||||
|
test.beforeEach(async ({ page, applicationsPage }) => {
|
||||||
|
await applicationsPage.login();
|
||||||
|
await page.getByTestId('apps-page-drawer-link').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('displays applications', async ({ page, applicationsPage }) => {
|
||||||
|
await page.getByTestId('apps-loader').waitFor({
|
||||||
|
state: 'detached',
|
||||||
|
});
|
||||||
|
await expect(page.getByTestId('app-row')).not.toHaveCount(0);
|
||||||
|
|
||||||
|
await applicationsPage.screenshot({
|
||||||
|
path: 'Applications.png',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('can add connection', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await expect(page.getByTestId('add-connection-button')).toBeVisible();
|
||||||
|
await page.getByTestId('add-connection-button').click();
|
||||||
|
await page
|
||||||
|
.getByTestId('search-for-app-loader')
|
||||||
|
.waitFor({ state: 'detached' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('lists applications', async ({ page, applicationsPage }) => {
|
||||||
|
const appListItemCount = await page.getByTestId('app-list-item').count();
|
||||||
|
expect(appListItemCount).toBeGreaterThan(10);
|
||||||
|
|
||||||
|
await applicationsPage.clickAway();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('searches an application', async ({ page, applicationsPage }) => {
|
||||||
|
await page.getByTestId('search-for-app-text-field').fill('DeepL');
|
||||||
|
await expect(page.getByTestId('app-list-item')).toHaveCount(1);
|
||||||
|
|
||||||
|
await applicationsPage.clickAway();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('goes to app page to create a connection', async ({
|
||||||
|
page,
|
||||||
|
applicationsPage,
|
||||||
|
}) => {
|
||||||
|
await page.getByTestId('app-list-item').first().click();
|
||||||
|
await expect(page).toHaveURL('/app/deepl/connections/add');
|
||||||
|
await expect(page.getByTestId('add-app-connection-dialog')).toBeVisible();
|
||||||
|
|
||||||
|
await applicationsPage.clickAway();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('closes the dialog on backdrop click', async ({
|
||||||
|
page,
|
||||||
|
applicationsPage,
|
||||||
|
}) => {
|
||||||
|
await page.getByTestId('app-list-item').first().click();
|
||||||
|
await expect(page).toHaveURL('/app/deepl/connections/add');
|
||||||
|
await expect(page.getByTestId('add-app-connection-dialog')).toBeVisible();
|
||||||
|
await applicationsPage.clickAway();
|
||||||
|
await expect(page).toHaveURL('/app/deepl/connections');
|
||||||
|
await expect(page.getByTestId('add-app-connection-dialog')).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -1,19 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
const { test, expect } = require('@playwright/test');
|
|
||||||
|
|
||||||
test('has title', async ({ page }) => {
|
|
||||||
await page.goto('https://playwright.dev/');
|
|
||||||
|
|
||||||
// Expect a title "to contain" a substring.
|
|
||||||
await expect(page).toHaveTitle(/Playwright/);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('get started link', async ({ page }) => {
|
|
||||||
await page.goto('https://playwright.dev/');
|
|
||||||
|
|
||||||
// Click the get started link.
|
|
||||||
await page.getByRole('link', { name: 'Get started' }).click();
|
|
||||||
|
|
||||||
// Expects the URL to contain intro.
|
|
||||||
await expect(page).toHaveURL(/.*intro/);
|
|
||||||
});
|
|
@@ -101,7 +101,9 @@ export default function AddNewAppConnection(
|
|||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
}
|
}
|
||||||
label={formatMessage('apps.searchApp')}
|
label={formatMessage('apps.searchApp')}
|
||||||
data-test="search-for-app-text-field"
|
inputProps={{
|
||||||
|
'data-test': 'search-for-app-text-field',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -109,7 +111,10 @@ export default function AddNewAppConnection(
|
|||||||
<DialogContent>
|
<DialogContent>
|
||||||
<List sx={{ pt: 2, width: '100%' }}>
|
<List sx={{ pt: 2, width: '100%' }}>
|
||||||
{loading && (
|
{loading && (
|
||||||
<CircularProgress sx={{ display: 'block', margin: '20px auto' }} />
|
<CircularProgress
|
||||||
|
data-test="search-for-app-loader"
|
||||||
|
sx={{ display: 'block', margin: '20px auto' }}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!loading &&
|
{!loading &&
|
||||||
|
@@ -14,6 +14,7 @@ type TextFieldProps = {
|
|||||||
name: string;
|
name: string;
|
||||||
clickToCopy?: boolean;
|
clickToCopy?: boolean;
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
|
'data-test'?: string;
|
||||||
} & MuiTextFieldProps;
|
} & MuiTextFieldProps;
|
||||||
|
|
||||||
const createCopyAdornment = (
|
const createCopyAdornment = (
|
||||||
@@ -44,6 +45,7 @@ export default function TextField(props: TextFieldProps): React.ReactElement {
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
onBlur,
|
onBlur,
|
||||||
onChange,
|
onChange,
|
||||||
|
'data-test': dataTest,
|
||||||
...textFieldProps
|
...textFieldProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@@ -82,6 +84,9 @@ export default function TextField(props: TextFieldProps): React.ReactElement {
|
|||||||
readOnly,
|
readOnly,
|
||||||
endAdornment: clickToCopy ? createCopyAdornment(inputRef) : null,
|
endAdornment: clickToCopy ? createCopyAdornment(inputRef) : null,
|
||||||
}}
|
}}
|
||||||
|
inputProps={{
|
||||||
|
'data-test': dataTest,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@@ -7971,6 +7971,11 @@ dotenv@^10.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
|
||||||
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
|
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
|
||||||
|
|
||||||
|
dotenv@^16.3.1:
|
||||||
|
version "16.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
|
||||||
|
integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
|
||||||
|
|
||||||
duplexer3@^0.1.4:
|
duplexer3@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
|
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
|
||||||
|
Reference in New Issue
Block a user