Skip to content

Commit

Permalink
chore: replace testing-library with playwright
Browse files Browse the repository at this point in the history
- add playwright configuration
- add authentication/authorization mocking with msal for component testing
- add `ms-playwright.playwright` to vscode extension recommendations
- remove jest and testing-libraries references
- update test cases

BREAKING CHANGE: use playwright instead of jest and testing-library for testing
  • Loading branch information
SimonGolms committed Aug 25, 2022
1 parent 45dbf28 commit 973d42b
Show file tree
Hide file tree
Showing 20 changed files with 535 additions and 82 deletions.
10 changes: 3 additions & 7 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module.exports = {
'plugin:react/recommended',
'plugin:import/recommended',
'plugin:import/typescript',
// 'plugin:jest/recommended',
'plugin:jsx-a11y/recommended',
'plugin:sonarjs/recommended',
'plugin:typescript-sort-keys/recommended',
Expand All @@ -16,7 +15,6 @@ module.exports = {
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
// 'jest',
'jsx-a11y',
'react-hooks',
'react',
Expand All @@ -35,13 +33,11 @@ module.exports = {
'error',
{
ignoreExports: [
'playwright/index.ts',
'src/index.tsx',
'src/setupTests.ts',
'src/**/*.d.ts',
'src/**/*.test.ts',
'src/**/*.test.tsx',
'*.ts', // mostly configuration files
'*.js', // mostly configuration files
'src/**/*.{spec,test}.{ts,tsx}',
'*.{js,ts}', // mostly configuration files
],
missingExports: true,
src: ['.'],
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

# testing
/coverage
/playwright-report/
/playwright/.cache/
/test-results/

# production
/build
Expand Down
3 changes: 2 additions & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run test -- --onlyChanged --watchAll=false
# Due to device performance, the tests are run only on one project and with increased timeout, while the tests stop immediately at the first failure.
npm run test -- --project="Desktop Chromium" --timeout=30000 -x
5 changes: 3 additions & 2 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"mikestead.dotenv",
"ms-azuretools.vscode-docker",
"ms-kubernetes-tools.vscode-kubernetes-tools",
"ms-playwright.playwright",
"streetsidesoftware.code-spell-checker",
"stylelint.vscode-stylelint",
"visualstudioexptteam.vscodeintellicode",
"yzhang.markdown-all-in-one",
"stylelint.vscode-stylelint"
"yzhang.markdown-all-in-one"
]
}
156 changes: 93 additions & 63 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ odsComponentPipeline(
resourceRequestCpu: '10m',
resourceRequestMemory: '1Gi',
workingDir: '/tmp'
),
containerTemplate(
alwaysPullImage: true,
envVars: [
envVar(key: 'HOME', value: '/tmp')
],
image: "mcr.microsoft.com/playwright:v1.25.1-focal",
name: 'playwright',
// Before you increase the resources, make sure that the quotas provide the appropriate resources.
// resourceLimitCpu: '1',
// resourceLimitMemory: '4Gi',
// resourceRequestCpu: '10m',
// resourceRequestMemory: '1Gi',
ttyEnabled: true,
workingDir: '/tmp'
)
],
) { context ->
Expand All @@ -46,6 +61,7 @@ odsComponentPipeline(
odsComponentStageScanWithSonar(context, [
analyzePullRequests: false,
])
stageTest(context)
stageBuild(context)
stageDeploy(context)
odsComponentStageBuildOpenShiftImage(context, [
Expand Down Expand Up @@ -128,11 +144,13 @@ def stageDebug(def context) {
}

def stageInstallDependency(def context) {
stage('Install Dependencies') {
sh(
label: 'Install exact version of Dependencies',
script: 'npm ci',
)
container('playwright') {
stage('Install Dependencies') {
sh(
label: 'Install exact version of Dependencies',
script: 'npm ci',
)
}
}
}

Expand All @@ -154,31 +172,33 @@ def stageVersioningWithReleaseManager(def context) {
}

def stageVersioningWithSemanticRelease(def context) {
stage('Versioning (Semantic Release)') {
def bitbucketService = ServiceRegistry.instance.get(BitbucketService)
container('playwright') {
stage('Versioning (Semantic Release)') {
def bitbucketService = ServiceRegistry.instance.get(BitbucketService)

withCredentials([
usernameColonPassword(
credentialsId: bitbucketService.getPasswordCredentialsId(),
variable: 'GIT_CREDENTIALS'
)
]) {
withEnv([
"BRANCH_NAME=${context.gitBranch}"
]) {
sh(
label: 'Identify semantic-release version',
script: 'npm run release:version',
)
sh(
label: 'Test version file',
script: "test -e .VERSION || (echo ${context.shortGitCommit} > .VERSION)",
withCredentials([
usernameColonPassword(
credentialsId: bitbucketService.getPasswordCredentialsId(),
variable: 'GIT_CREDENTIALS'
)
APP_VERSION = sh(
label: 'Provide version as env variable',
script: 'cat .VERSION',
returnStdout: true
).trim()
]) {
withEnv([
"BRANCH_NAME=${context.gitBranch}",
]) {
sh(
label: 'Identify semantic-release version',
script: 'npm run release:version',
)
sh(
label: 'Test version file',
script: "test -e .VERSION || (echo ${context.shortGitCommit} > .VERSION)",
)
APP_VERSION = sh(
label: 'Provide version as env variable',
script: 'cat .VERSION',
returnStdout: true
).trim()
}
}
}
}
Expand Down Expand Up @@ -213,10 +233,12 @@ def stageWorkaroundFindOpenShiftImageOrElse(def context, Map config = [:], Closu

def stageAnalyzeCode(def context) {
stage('Analyze Code') {
sh(
label: 'Check ESLint Rules',
script: 'npm run lint',
)
container('playwright') {
sh(
label: 'Check ESLint Rules',
script: 'npm run lint',
)
}
sh(
label: 'Check Helm Chart',
script: 'helm lint chart --strict',
Expand All @@ -225,27 +247,33 @@ def stageAnalyzeCode(def context) {
}

def stageTest(def context) {
stage('Test Component') {
/**
* Run tests in the same thread to improve the speed
* See: https://jestjs.io/docs/troubleshooting#tests-are-extremely-slow-on-docker-andor-continuous-integration-ci-server
*/
sh(
label: 'Test React Components',
script: 'npm run test -- --runInBand',
)
container('playwright') {
stage('Test Components') {
withEnv([
'VITE_AZURE_ACTIVE_DIRECTORY_CLIENT_ID=11111111-2222-3333-4444-555555555555',
// IMPORTANT: A valid Azure AD Tenant ID for testing purposes is required.
'VITE_AZURE_ACTIVE_DIRECTORY_TENANT_ID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
]) {
sh(
label: 'Test React Components',
script: 'npm run test',
)
}
}
}
}

def stageBuild(def context) {
stage('Build') {
withEnv([
"VITE_VERSION=${APP_VERSION}",
]) {
sh(
label: 'Build App as a static web application for production',
script: 'npm run build',
)
container('playwright') {
stage('Build') {
withEnv([
"VITE_VERSION=${APP_VERSION}",
]) {
sh(
label: 'Build App as a static web application for production',
script: 'npm run build',
)
}
}
}
}
Expand Down Expand Up @@ -394,22 +422,24 @@ def stageReleaseWithReleaseManager (def context) {
}

def stageReleaseWithSemanticRelease(def context) {
stage('Release (Semenatic Release)') {
def bitbucketService = ServiceRegistry.instance.get(BitbucketService)
container('playwright') {
stage('Release (Semenatic Release)') {
def bitbucketService = ServiceRegistry.instance.get(BitbucketService)

withCredentials([
usernameColonPassword(
credentialsId: bitbucketService.getPasswordCredentialsId(),
variable: 'GIT_CREDENTIALS'
)
]) {
withEnv([
"BRANCH_NAME=${context.gitBranch}",
]) {
sh(
label: 'Run Semantic Release',
script: 'npm run release',
withCredentials([
usernameColonPassword(
credentialsId: bitbucketService.getPasswordCredentialsId(),
variable: 'GIT_CREDENTIALS'
)
]) {
withEnv([
"BRANCH_NAME=${context.gitBranch}",
]) {
sh(
label: 'Run Semantic Release',
script: 'npm run release',
)
}
}
}
}
Expand Down
80 changes: 80 additions & 0 deletions playwright-ct.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { PlaywrightTestConfig } from '@playwright/experimental-ct-react';
import { devices } from '@playwright/experimental-ct-react';

/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,

/* Run tests in files in parallel */
fullyParallel: true,

/* Configure projects for major browsers */
projects: [
{
name: 'Desktop Chromium',
use: {
browserName: 'chromium',
viewport: { height: 720, width: 1280 },
},
},
{
name: 'Desktop Safari',
use: {
browserName: 'webkit',
viewport: { height: 720, width: 1280 },
},
},
{
name: 'Desktop Firefox',
use: {
browserName: 'firefox',
viewport: { height: 720, width: 1280 },
},
},
{
name: 'Mobile Chrome',
use: devices['Pixel 5'],
},
{
name: 'Mobile Safari',
use: devices['iPhone 13 Pro'],
},
],

/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: process.env.CI ? [['junit', { outputFile: 'build/test-results/test/component-test-results.xml' }]] : 'list',

/* Retry on CI only */
retries: process.env.CI ? 2 : 0,

/* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
snapshotDir: './__snapshots__',

testDir: './src',

/* Maximum time one test can run for (in milliseconds). */
timeout: 20_000,

/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Port to use for Playwright component endpoint. */
ctPort: 3100,

ctViteConfig: {
server: {
open: false,
},
},

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
};

export default config;
12 changes: 12 additions & 0 deletions playwright/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Testing Page</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/playwright/index.ts"></script>
</body>
</html>
25 changes: 25 additions & 0 deletions playwright/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { setupIonicReact } from '@ionic/react';
import { setupMsalMock } from '../src/utils/test/setupMsalMock';

/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';

/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';

/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';

/* Styles */
import '../src/theme/index.css';

setupIonicReact();

setupMsalMock();

0 comments on commit 973d42b

Please sign in to comment.