-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* docs: add examples * chore: cleanup basic playwright config * ci: run tests from `examples` directory during CI build * test: add basic suite to examples directory * docs: refactor readme
- Loading branch information
1 parent
dbc769b
commit df030be
Showing
14 changed files
with
1,075 additions
and
41 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
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,10 @@ | ||
# Examples of using the `playwright-decorators` library | ||
To see all available decorators, refer to the [documentation](../README.md#-documentation) | ||
|
||
## Tests | ||
The tests are located in the [./tests](./tests) directory. | ||
Each test file contains a description that explains the purpose of the test. | ||
|
||
## Custom decorators | ||
Custom decorators are located in the [./tests/decorators](./tests/decorators) directory. | ||
Each decorator includes code comments to help understand its functionality. |
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,118 @@ | ||
const express = require('express'); | ||
const expressSession = require('express-session'); | ||
const { faker } = require('@faker-js/faker'); | ||
const app = express(); | ||
const usersDB = []; | ||
|
||
app.use(expressSession({ | ||
secret: 'secret_key', | ||
resave: false, | ||
saveUninitialized: true | ||
})) | ||
app.use(express.json()) | ||
app.use(express.urlencoded({ extended: false })) | ||
|
||
function isAuthenticated (req, res, next) { | ||
if (req.session.userId) { | ||
return next() | ||
} | ||
|
||
return res.redirect('/sign-in'); | ||
} | ||
|
||
/** | ||
* Create a test user | ||
*/ | ||
app.post('/create-user', (req, res) => { | ||
const user = { | ||
userId: faker.datatype.uuid(), | ||
username: faker.internet.userName(), | ||
email: faker.internet.email(), | ||
avatar: faker.image.avatar(), | ||
password: faker.internet.password(), | ||
features: req.body.features | ||
} | ||
|
||
usersDB.push(user); | ||
res.json(user); | ||
}) | ||
|
||
/** | ||
* Sign in | ||
*/ | ||
app.get('/sign-in', (req, res) => { | ||
res.send(` | ||
<h1>Sign in</h1> | ||
<form action="/sign-in" method="POST"> | ||
<input name="email" data-testid="sign-in-email"/> | ||
<input name="password" data-testid="sign-in-password" type="password"/> | ||
<button type="submit" data-testid="sign-in-submit">sign in</button> | ||
</form> | ||
`) | ||
}) | ||
|
||
/** | ||
* Sign in request | ||
*/ | ||
app.post('/sign-in', (req, res) => { | ||
const { email, password } = req.body; | ||
const user = usersDB.find(user => user.email === email && user.password === password); | ||
|
||
if (!user) { | ||
return res.redirect('/sign-in'); | ||
} | ||
|
||
req.session.regenerate(function (err) { | ||
if (err) next(err) | ||
|
||
req.session.userId = user.userId | ||
res.redirect('/'); | ||
}) | ||
}); | ||
|
||
|
||
/** | ||
* Sign in SSO (in progress) - response is delayed by 1 second | ||
*/ | ||
app.get('/sign-in/sso', (req, res) => { | ||
setTimeout(() => { | ||
res.send(` | ||
<h1 data-testid="page-title">SSO Login</h1> | ||
<h2>Select provider</h2> | ||
<ul> | ||
<li>X</li> | ||
<li>Y</li> | ||
</ul> | ||
`) | ||
}, 1000) | ||
}) | ||
|
||
/** | ||
* Authenticated page | ||
*/ | ||
app.get('/', isAuthenticated, (req, res) => { | ||
const user = usersDB.find(user => user.userId === req.session.userId); | ||
|
||
res.send(` | ||
<h1 data-testid="page-title">Hello ${user.username} 👋</h1> | ||
<a href="/settings">Settings</a> | ||
`) | ||
}) | ||
|
||
/** | ||
* Settings page | ||
*/ | ||
app.get('/settings', isAuthenticated, (req, res) => { | ||
const user = usersDB.find(user => user.userId === req.session.userId); | ||
|
||
res.send(` | ||
<h1>Settings</h1> | ||
<h2>Features</h2> | ||
<ul> | ||
${ user.features.map(feature => `<li data-testid="settings-feature">${feature}</li>`).join('\n') } | ||
</ul> | ||
`) | ||
}) | ||
|
||
app.listen(3000); | ||
console.log("Server listening on port 3000"); |
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,17 @@ | ||
{ | ||
"name": "examples", | ||
"private": true, | ||
"scripts": { | ||
"start": "node app.js", | ||
"test": "playwright test" | ||
}, | ||
"devDependencies": { | ||
"@faker-js/faker": "7.6.0", | ||
"@playwright/test": "^1.36.1", | ||
"body-parser": "1.20.2", | ||
"express": "4.18.2", | ||
"express-session": "1.17.3", | ||
"node-fetch": "2.7.0", | ||
"playwright-decorators": "../" | ||
} | ||
} |
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,30 @@ | ||
import { defineConfig, devices } from '@playwright/test'; | ||
|
||
/** | ||
* See https://playwright.dev/docs/test-configuration. | ||
*/ | ||
export default defineConfig({ | ||
testDir: './tests', | ||
fullyParallel: true, | ||
forbidOnly: !!process.env.CI, | ||
retries: process.env.CI ? 2 : 0, | ||
workers: 1, | ||
reporter: 'html', | ||
timeout: 500, | ||
use: { | ||
trace: 'on-first-retry' | ||
}, | ||
projects: [ | ||
{ | ||
name: 'chromium', | ||
use: { ...devices['Desktop Chrome'] }, | ||
} | ||
], | ||
webServer: { | ||
command: 'npm run start', | ||
url: 'http://127.0.0.1:3000', | ||
reuseExistingServer: !process.env.CI, | ||
stdout: 'ignore', | ||
stderr: 'pipe', | ||
}, | ||
}); |
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,48 @@ | ||
import {expect} from "@playwright/test"; | ||
import { | ||
beforeEach, | ||
suite, | ||
test, | ||
tag, | ||
fixme, slow, annotation | ||
} from "playwright-decorators"; | ||
|
||
@tag(['x-api-consumer']) | ||
@suite() | ||
class SignInSuite { | ||
@beforeEach() | ||
async setPageRoute({ page }) { | ||
// set sign-in page context for each test in the suite | ||
await page.goto('http://localhost:3000/sign-in'); | ||
} | ||
|
||
@test() | ||
async userShouldNotBeAbleToSignInWithInvalidCredentials({ page }) { | ||
// when user fills invalid credentials & submits the form | ||
await page.getByTestId('sign-in-email').fill("[email protected]"); | ||
await page.getByTestId('sign-in-password').fill("example password"); | ||
await page.getByTestId('sign-in-submit').click(); | ||
// then user is redirected to sign-in page | ||
await expect(page).toHaveURL('http://localhost:3000/sign-in') | ||
} | ||
|
||
@fixme("Unstable test") | ||
@annotation({ | ||
type: 'issue', | ||
description: 'jira.com/issue-123' | ||
}) | ||
@test() | ||
async userShouldBeAbleToResetPassword({ page }) { | ||
await page.goto('http://localhost:3000/sign-in/reset'); | ||
// ... | ||
} | ||
|
||
@tag(['team-y']) | ||
@slow("/sign-in/sso page is under the development, and needs more then 500ms to load") | ||
@test() | ||
async userShouldBeAbleToLoginViaSSO({ page }) { | ||
await page.goto('http://localhost:3000/sign-in/sso'); | ||
await expect(page.getByTestId('page-title')).toHaveText('SSO Login'); | ||
// ... | ||
} | ||
} |
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,42 @@ | ||
import { suite, test } from "playwright-decorators"; | ||
import { withUser, withRoute } from './decorators'; | ||
import { expect } from "@playwright/test"; | ||
|
||
/** | ||
* This suite is an example of usage of custom decorators. | ||
* Suite is using `withUser` suite-decorator that provides logged-in user context for each @test in the suite. | ||
* Also, you can find here `withRoute` test-decorator that navigates to specific route before specific @test. | ||
*/ | ||
@withUser({ features: ['feature-a', 'feature-b'] }) // <- usage of custom `withUser` decorator | ||
@suite() | ||
class AuthorizedUserSuite { | ||
@test() | ||
async shouldBeLogged({ page }) { | ||
// When on `/` route | ||
await page.goto('http://localhost:3000/') | ||
|
||
// Then username should be displayed | ||
await expect(page.getByTestId('page-title')).toHaveText(/Hello (?<userName>.*) 👋/) | ||
} | ||
|
||
@withRoute('settings') // <- usage of custom `withRoute` decorator | ||
@test() | ||
async shouldHaveRequestedFeatures({ page }) { | ||
// When on `/settings` route | ||
await expect(page).toHaveURL('http://localhost:3000/settings') | ||
|
||
// Then all requested features should be available (features passed in @withUser decorator) | ||
await expect(page.getByTestId('settings-feature')) | ||
.toHaveText(['feature-a', 'feature-b']); | ||
} | ||
} | ||
|
||
|
||
@suite() // <- no `withUser` decorator, so user in @tests are not logged in | ||
class UnauthorizedUserSuite { | ||
@withRoute('settings') // <- usage of custom `withRoute` decorator | ||
@test() | ||
async shouldBeRedirectedToSignInPage({ page }) { | ||
await expect(page).toHaveURL(/sign-in/) | ||
} | ||
} |
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,2 @@ | ||
export * from './withRoute'; | ||
export * from './withUser'; |
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,21 @@ | ||
import {createTestDecorator} from "playwright-decorators"; | ||
import playwright, {Page} from "@playwright/test"; | ||
|
||
/** | ||
* Navigate to specific route before given @test. | ||
* Please use it with `@test` decorator. | ||
* @param url | ||
*/ | ||
export const withRoute = (url: string) => createTestDecorator('withRoute', ({ test }) => { | ||
let _page: Page; | ||
|
||
// #1 Extract `page` from test context | ||
playwright.beforeEach(({ page }) => { | ||
_page = page; | ||
}) | ||
|
||
// #2 Go to specific route before test | ||
test.beforeTest(async () => { | ||
await _page.goto(`http://localhost:3000/${url}`); | ||
}); | ||
}) |
Oops, something went wrong.