-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Continuation of #6644 Now chromium browser is used in workspaces tests instead of firefox and screenshots after each test are properly saved in one folder when run from IDE and from terminal using `yarn test:e2e` command
- Loading branch information
Showing
15 changed files
with
315 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Playwright Tests | ||
on: | ||
push: | ||
branches: [ main, master ] | ||
pull_request: | ||
branches: [ main, master ] | ||
jobs: | ||
test: | ||
timeout-minutes: 60 | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: lts/* | ||
- name: Install dependencies | ||
run: npm install -g yarn && yarn | ||
- name: Install Playwright Browsers | ||
run: yarn playwright install --with-deps | ||
- name: Run Playwright tests | ||
run: yarn test:e2e companies | ||
- uses: actions/upload-artifact@v4 | ||
if: always() | ||
with: | ||
name: playwright-report | ||
path: playwright-report/ | ||
retention-days: 30 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,5 +26,5 @@ dist | |
storybook-static | ||
*.tsbuildinfo | ||
.eslintcache | ||
.cache | ||
.nyc_output | ||
test-results/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,22 @@ | ||
# Note that provide always without trailing forward slash to have expected behaviour | ||
FRONTEND_BASE_URL="http://localhost:3001" | ||
FRONTEND_BASE_URL=http://localhost:3001 | ||
CI_DEFAULT_BASE_URL=https://demo.twenty.com | ||
DEFAULT_LOGIN=[email protected] | ||
NEW_WORKSPACE_LOGIN=[email protected] | ||
DEMO_DEFAULT_LOGIN=[email protected] | ||
DEFAULT_PASSWORD=Applecar2025 | ||
WEBSITE_URL=https://twenty.com | ||
|
||
# === DO NOT USE, WORK IN PROGRESS === | ||
# This URL must have trailing forward slash as all REST API endpoints have object after it | ||
# Documentation for REST API: https://twenty.com/developers/rest-api/core#/ | ||
# REST_API_BASE_URL=http://localhost:3000/rest/ | ||
|
||
# Documentation for GraphQL API: https://twenty.com/developers/graphql/core | ||
# GRAPHQL_BASE_URL=http://localhost:3000/graphql | ||
|
||
# Without this key, all API tests will fail, to generate this key | ||
# Log in to Twenty workspace, go to Settings > Developers, generate new key and paste it here | ||
# In order to use it, header Authorization: Bearer token must be used | ||
# This key works for both REST and GraphQL API | ||
# API_DEV_KEY=fill_with_proper_key |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
node_modules/ | ||
/test-results/ | ||
/playwright-report/ | ||
/blob-report/ | ||
/playwright/.cache/ | ||
test-results/ | ||
playwright-report/ | ||
blob-report/ | ||
playwright/.cache/ | ||
run_results/ | ||
playwright-report/.last-run.json | ||
results/ | ||
run_results/.playwright-artifacts-0/ | ||
run_results/.playwright-artifacts-1/ | ||
.auth/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { | ||
Reporter, | ||
FullConfig, | ||
Suite, | ||
TestCase, | ||
TestResult, | ||
FullResult, | ||
} from '@playwright/test/reporter'; | ||
|
||
class CustomReporter implements Reporter { | ||
constructor(options: { customOption?: string } = {}) { | ||
console.log( | ||
`my-awesome-reporter setup with customOption set to ${options.customOption}`, | ||
); | ||
} | ||
|
||
onBegin(config: FullConfig, suite: Suite) { | ||
console.log(`Starting the run with ${suite.allTests().length} tests`); | ||
} | ||
|
||
onTestBegin(test: TestCase) { | ||
console.log(`Starting test ${test.title}`); | ||
} | ||
|
||
onTestEnd(test: TestCase, result: TestResult) { | ||
console.log(`Finished test ${test.title}: ${result.status}`); | ||
} | ||
|
||
onEnd(result: FullResult) { | ||
console.log(`Finished the run: ${result.status}`); | ||
} | ||
} | ||
export default CustomReporter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { exec } from 'child_process'; | ||
|
||
export async function sh(cmd) { | ||
return new Promise((resolve, reject) => { | ||
exec(cmd, (err, stdout, stderr) => { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve({ stdout, stderr }); | ||
} | ||
}); | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { test as base } from '@playwright/test'; | ||
import path from 'path'; | ||
|
||
const date = new Date(); | ||
|
||
export const test = base.extend<{ screenshotHook: void }>({ | ||
screenshotHook: [ | ||
async ({ page, browserName }, use, workerInfo) => { | ||
// here everything is the same as beforeEach() | ||
// goto is to go to website as login setup saves the cookies of logged-in user, not the state of browser | ||
await page.goto('/'); | ||
await use(); // here is the code of test | ||
// here everything is the same as afterEach() | ||
// automatic fixture of making screenshot after each test | ||
await page.screenshot({ | ||
path: path.resolve( | ||
__dirname, | ||
'..', | ||
'..', | ||
'results', | ||
'screenshots', | ||
`${workerInfo.project.name}`, | ||
browserName, | ||
`${date.toISOString()}.png`, | ||
), | ||
}); | ||
}, | ||
{ auto: true }, // automatic fixture runs with every test | ||
], | ||
}); | ||
|
||
export { expect } from '@playwright/test'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,85 @@ | ||
import { defineConfig, devices } from '@playwright/test'; | ||
|
||
import { config } from 'dotenv'; | ||
import path from 'path'; | ||
|
||
config(); | ||
|
||
/* === Run your local dev server before starting the tests === */ | ||
|
||
/** | ||
* See https://playwright.dev/docs/test-configuration. | ||
* See https://playwright.dev/docs/trace-viewer to Collect trace when retrying the failed test | ||
*/ | ||
export default defineConfig({ | ||
testDir: 'e2e', | ||
/* Run tests in files in parallel */ | ||
fullyParallel: true, | ||
reporter: 'html', | ||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ | ||
testDir: '.', | ||
outputDir: 'run_results/', // directory for screenshots and videos | ||
snapshotPathTemplate: '{testDir}/__screenshots__/{testFilePath}/{arg}{ext}', // just in case, do not delete it | ||
fullyParallel: true, // false only for specific tests, overwritten in specific projects or global setups of projects | ||
forbidOnly: !!process.env.CI, | ||
retries: process.env.CI ? 2 : 0, | ||
workers: process.env.CI ? 1 : undefined, // undefined = amount of projects * amount of tests | ||
timeout: 30 * 1000, // timeout can be changed | ||
use: { | ||
/* Base URL to use in actions like `await page.goto('/')`. */ | ||
baseURL: process.env.FRONTEND_BASE_URL ?? 'http://localhost:3001', | ||
baseURL: process.env.CI | ||
? process.env.CI_DEFAULT_BASE_URL | ||
: (process.env.FRONTEND_BASE_URL ?? 'http://localhost:3001'), | ||
trace: 'retain-on-failure', // trace takes EVERYTHING from page source, records every single step, should be used only when normal debugging won't work | ||
screenshot: 'on', // either 'on' here or in different method in modules, if 'on' all screenshots are overwritten each time the test is run | ||
headless: true, // instead of changing it to false, run 'yarn test:e2e:debug' or 'yarn test:e2e:ui' | ||
testIdAttribute: 'data-testid', // taken from Twenty source | ||
viewport: { width: 1920, height: 1080 }, // most laptops use this resolution | ||
launchOptions: { | ||
slowMo: 500, // time in milliseconds between each step, better to use it than explicitly define timeout in tests | ||
}, | ||
}, | ||
|
||
/* Configure projects for major browsers */ | ||
expect: { | ||
timeout: 5000, | ||
}, | ||
reporter: [['html', { open: 'never' }]], | ||
projects: [ | ||
{ | ||
name: 'Login setup', | ||
testMatch: /login\.setup\.ts/, // finds all tests matching this regex, in this case only 1 test should be found | ||
}, | ||
{ | ||
name: 'chromium', | ||
use: { ...devices['Desktop Chrome'] }, | ||
use: { | ||
...devices['Desktop Chrome'], | ||
storageState: path.resolve(__dirname, '.auth', 'user.json'), // takes saved cookies from directory | ||
}, | ||
dependencies: ['Login setup'], // forces to run login setup before running tests from this project - CASE SENSITIVE | ||
}, | ||
|
||
{ | ||
name: 'firefox', | ||
use: { ...devices['Desktop Firefox'] }, | ||
use: { | ||
...devices['Desktop Firefox'], | ||
storageState: path.resolve(__dirname, '.auth', 'user.json'), | ||
}, | ||
dependencies: ['Login setup'], | ||
}, | ||
|
||
{ | ||
name: 'webkit', | ||
use: { ...devices['Desktop Safari'] }, | ||
}, | ||
//{ | ||
// name: 'webkit', | ||
// use: { ...devices['Desktop Safari'] }, | ||
//}, | ||
|
||
{ | ||
name: 'Google Chrome', | ||
use: { ...devices['Desktop Chrome'], channel: 'chrome' }, | ||
}, | ||
/* Test against mobile viewports. */ | ||
// { | ||
// name: 'Mobile Chrome', | ||
// use: { ...devices['Pixel 5'] }, | ||
// }, | ||
// { | ||
// name: 'Mobile Safari', | ||
// use: { ...devices['iPhone 12'] }, | ||
// }, | ||
|
||
/* Test against branded browsers. */ | ||
//{ | ||
// name: 'Microsoft Edge', | ||
// use: { ...devices['Desktop Edge'], channel: 'msedge' }, | ||
//}, | ||
//{ | ||
// name: 'Google Chrome', | ||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' }, | ||
//}, | ||
], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { test, expect } from '../lib/fixtures/screenshot'; | ||
import { config } from 'dotenv'; | ||
import path = require('path'); | ||
config({ path: path.resolve(__dirname, '..', '.env') }); | ||
|
||
test.describe('Basic check', () => { | ||
test('Checking if table in Companies is visible', async ({ page }) => { | ||
await expect(page.getByTestId('tooltip').nth(0)).toHaveText('Companies'); | ||
await expect(page.getByTestId('tooltip').nth(0)).toBeVisible(); | ||
expect(page.url()).toContain('/companies'); | ||
await expect(page.locator('table')).toBeVisible(); | ||
await expect(page.locator('tbody > tr')).toHaveCount(13); // shouldn't be hardcoded in case of tests on demo | ||
}); | ||
|
||
test('', async ({ page }) => { | ||
await page.getByRole('link', { name: 'Opportunities' }).click(); | ||
await expect(page.locator('table')).toBeVisible(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { test as setup, expect } from '@playwright/test'; | ||
import path from 'path'; | ||
|
||
setup('Login test', async ({ page }) => { | ||
await page.goto('/'); | ||
await page.getByRole('button', { name: 'Continue With Email' }).click(); | ||
await page.getByPlaceholder('Email').fill(process.env.DEFAULT_LOGIN); | ||
await page.getByRole('button', { name: 'Continue', exact: true }).click(); | ||
await page.getByPlaceholder('Password').fill(process.env.DEFAULT_PASSWORD); | ||
await page.getByRole('button', { name: 'Sign in' }).click(); | ||
await expect(page.getByText('Welcome to Twenty')).not.toBeVisible(); | ||
|
||
// End of authentication steps. | ||
|
||
await page.context().storageState({ | ||
path: path.resolve(__dirname, '..', '.auth', 'user.json'), | ||
}); | ||
}); |
Oops, something went wrong.