Skip to content

Commit

Permalink
feat(#1304624): Add e2e tests and add the service that lauches them i…
Browse files Browse the repository at this point in the history
…n docker compose
  • Loading branch information
matthias-goupil committed Jan 15, 2025
1 parent 623394d commit 42dda75
Show file tree
Hide file tree
Showing 17 changed files with 623 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- master
- '[1-9].[0-9]+.x'
- 'feature-[a-z]+'
- 'feat-1304624-tests-e2e-playwright'
pull_request:
branches:
- master
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ jobs:
- name: Jest
run: ${{env.docker_compose_cmd}} exec -T pwa yarn test:ci

- name: e2e
run: ${{env.docker_compose_cmd}} exec -T e2e yarn test:ci

- name: Frontend Coverage Report
uses: 5monkeys/cobertura-action@v12
if: ${{ github.event_name == 'pull_request' }}
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ phpunit: ## Run php unit tests, pass the parameter "p=" to launch tests on a spe
jest: ## Run jest unit tests
@$(DOCKER_COMP) exec pwa yarn test

e2e: ## Run e2e tests
@$(DOCKER_COMP) exec e2e yarn test

jest_update: ## Run jest unit tests
@$(DOCKER_COMP) exec pwa yarn test:update

Expand Down
12 changes: 11 additions & 1 deletion compose.ci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include:
- compose.e2e.yml
services:

certbot:
Expand All @@ -13,17 +15,25 @@ services:
environment:
- APP_ENV=dev
- XDEBUG_MODE=off
- TRUSTED_HOSTS=${TRUSTED_HOSTS:-^${SERVER_NAME:-|gally.localhost}|localhost|${E2E_SERVER_NAME:-gally.e2e}|php$$}

pwa:
build:
target: gally_pwa_ci
volumes:
- ./front/example-app/coverage:/usr/src/front/example-app/coverage:rw,cached,z
- ./front/pwa/coverage:/usr/src/front/pwa/coverage:rw,cached,z

environment:
- NEXT_PUBLIC_ENTRYPOINT=
- NEXT_PUBLIC_API_URL=
- REACT_APP_API_URL=
example:
build:
context: ./docker/front
target: gally_example_ci
additional_contexts:
front_src: ./front

e2e:
environment:
- CI=true
15 changes: 15 additions & 0 deletions compose.e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# E2E environment override
services:
e2e:
build:
context: .
dockerfile: ./docker/front/Dockerfile.e2e
environment:
- SERVER_BASE_URL=https://${E2E_SERVER_NAME:-gally.e2e}
- API_SERVER_BASE_URL=https://${E2E_SERVER_NAME:-gally.e2e}/${API_ROUTE_PREFIX:-api}
depends_on:
- proxy
extra_hosts:
- ${E2E_SERVER_NAME:-gally.e2e}:host-gateway
volumes:
- ./front/e2e/:/usr/src/app:rw,cached,z
6 changes: 6 additions & 0 deletions compose.override.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Development environment override
include:
- compose.e2e.yml
services:

certbot:
Expand All @@ -21,6 +23,7 @@ services:
- ./docker/php/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro,z
environment:
- APP_ENV=${APP_ENV:-dev}
- TRUSTED_HOSTS=${TRUSTED_HOSTS:-^${SERVER_NAME:-|gally.localhost}|localhost|${E2E_SERVER_NAME:-gally.e2e}|php$$}
# See https://xdebug.org/docs/all_settings#mode
- XDEBUG_MODE=${XDEBUG_MODE:-off}
- PHP_IDE_CONFIG=serverName=gally
Expand All @@ -41,6 +44,9 @@ services:
environment:
# On Linux, you may want to comment the following line for improved performance
- WATCHPACK_POLLING="true"
- NEXT_PUBLIC_ENTRYPOINT=
- NEXT_PUBLIC_API_URL=
- REACT_APP_API_URL=

example:
user: ${UUID?You must set UUID env var}:${GUID?You must set GUID env var}
Expand Down
14 changes: 14 additions & 0 deletions docker/front/Dockerfile.e2e
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM mcr.microsoft.com/playwright:v1.39.0

WORKDIR /usr/src/app

COPY ./front/e2e/ .

RUN yarn install

RUN npx playwright install chromium
RUN npx playwright install-deps chromium

# CMD ["yarn", "test"]
# CMD ["tail", "-f", "/dev/null"]
CMD ["sleep", "infinity"]
5 changes: 5 additions & 0 deletions front/e2e/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
18 changes: 18 additions & 0 deletions front/e2e/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "e2e",
"private": "false",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"@playwright/test": "^1.47.2",
"@types/node": "^22.6.1"
},
"scripts": {
"test": "yarn playwright test",
"test:ci": "yarn playwright test",
"test:standard": "yarn playwright test --grep @standard",
"test:premium": "yarn playwright test --grep @premium"
},
"dependencies": {}
}
51 changes: 51 additions & 0 deletions front/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { defineConfig, devices } from '@playwright/test'
// import dotenv from 'dotenv'
// import path from 'path'

// Read from ".env" file.
// dotenv.config({ path: path.resolve(__dirname, '.env') })

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// dotenv.config({ path: path.resolve(__dirname, '.env') });

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: false,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL: process.env.SERVER_BASE_URL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
headless: true, // Exécuter tous les tests en mode headless
ignoreHTTPSErrors: true, // Ignorer les erreurs HTTPS
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
})
151 changes: 151 additions & 0 deletions front/e2e/tests/advanced/boost.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { ICatalog, IHydraResponse } from '@elastic-suite/gally-admin-shared'
import { test, expect } from '@playwright/test'
import { randomUUID } from 'crypto'
import { login } from '../helper'

test.describe('Boost Page', () => {
test('Check redirection to boost grid page and presence of "Create a new boost" button', async ({
page,
}) => {
await login(page)

await page.getByTestId('sidebarMenu').locator('a:has-text("Boost")').click()

await expect(page).toHaveURL('/fr/admin/merchandize/boost/grid')

const createBoostButton = await page.getByTestId('createButtonResourceGrid')
await expect(createBoostButton).toBeVisible()
})

test('Create Boost', async ({ page }) => {
await page.route('**/*', (route) => {
const headers = {
...route.request().headers(),
'Cache-Control': 'no-cache',
}
route.continue({ headers })
})

await login(page)

await page.getByTestId('sidebarMenu').locator('a:has-text("Boost")').click()

const catalogs: IHydraResponse<ICatalog> = await (
await page.waitForResponse(
(response) =>
response.url() === `${process.env.API_SERVER_BASE_URL}/catalogs` &&
response.ok()
)
).json()

await expect(page).toHaveURL('/fr/admin/merchandize/boost/grid')
await (
await page.getByTestId('tablePagination').all()
)[0]

const createBoostButton = await page.getByTestId('createButtonResourceGrid')
await createBoostButton.click()

const switchIsActive = await page.getByTestId('isActive')

await expect(await switchIsActive.locator('input')).toBeChecked()
await switchIsActive.click()
await expect(await switchIsActive.locator('input')).not.toBeChecked()
await switchIsActive.click()
await expect(await switchIsActive.locator('input')).toBeChecked()

const modelInput = await page.getByTestId('modelInputText')
await expect(await modelInput.getAttribute('placeholder')).toBe(
'Sélectionnez un modèle'
)

await expect(modelInput).toBeEmpty()
await modelInput.click()
await page.getByText('Constante').click()
await expect(await modelInput.inputValue()).toBe('Constante')

const modelConfig = await page.getByTestId('modelConfig')
await expect(modelConfig).toBeVisible()
await expect(await modelConfig.locator('input').inputValue()).toBe('0')

await expect(
await page.getByText('Veuillez remplir les champs requis')
).toBeVisible()

const boostName = randomUUID()
const nameInput = await page.getByTestId('name')
await nameInput.fill(boostName)

await expect(await nameInput.inputValue()).toBe(boostName)
const localizedCatalogsInput = await page.getByTestId(
'localizedCatalogsInputText'
)

await expect(await localizedCatalogsInput).toBeEmpty()
await localizedCatalogsInput.click()
const catalogGroupTitles = await page
.getByTestId('localizedCatalogsGroupTitle')
.allInnerTexts()
await expect(catalogGroupTitles).toEqual(
catalogs['hydra:member'].map((catalog) => catalog.name)
)

const catalogsCheckbox = await page
.getByTestId('localizedCatalogsCheckbox')
.all()
await catalogsCheckbox[0].click()
await catalogsCheckbox[1].click()

expect(
await page.getByTestId('localizedCatalogsCheckbox').allInnerTexts()
).toEqual(
catalogs['hydra:member']
.map((catalog) =>
catalog.localizedCatalogs.map(
(localizedCatalog) => localizedCatalog.name
)
)
.flat()
)
let catalogsTags = await page
.getByTestId('localizedCatalogsTag')
.allInnerTexts()

expect(catalogsTags).toEqual([
await catalogsCheckbox[0].innerText(),
await catalogsCheckbox[1].innerText(),
])
await catalogsCheckbox[0].click()
catalogsTags = await page
.getByTestId('localizedCatalogsTag')
.allInnerTexts()
expect(catalogsTags).toEqual([await catalogsCheckbox[1].innerText()])
await catalogsCheckbox[0].click()

const requestTypesDropdownInputText = await page.getByTestId(
'requestTypesDropdownInputText'
)
await requestTypesDropdownInputText.click()

const requestTypeCheckboxList = await page.getByTestId(
'requestTypesDropdownCheckbox'
)

for (const tag of await requestTypeCheckboxList.all()) await tag.click()

await expect(
await page.getByTestId('requestTypesDropdownTag').allInnerTexts()
).toEqual(await requestTypeCheckboxList.allInnerTexts())

const submitButton = await page.getByTestId('submitButtonResourceForm')
await submitButton.click()

await expect(page).toHaveURL(
`${process.env.SERVER_BASE_URL}/fr/admin/merchandize/boost/grid`
)

const newBoostName = await page.getByText(boostName)

await expect(newBoostName).toBeVisible()
})
})
43 changes: 43 additions & 0 deletions front/e2e/tests/basics/header.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { test, expect } from '@playwright/test'
import { login } from '../helper'

test('Header', async ({ page }) => {
await login(page)

const appBar = await page.getByTestId('appBar')
const breadcrumbs = await appBar.getByTestId('breadcrumbs')
const tooltip = await appBar.getByTestId('helpToolTip')
const tooltipOver = await tooltip.getByTestId('helpOver')
const userMenu = await appBar.getByTestId('userMenu')

// Global Tests
await expect(breadcrumbs).toBeVisible()
await expect(tooltip).toBeVisible()
await expect(tooltipOver).not.toBeVisible()
await expect(userMenu).toBeVisible()

// ToolTip tests
await tooltip.hover()
await expect(tooltipOver).toBeVisible()

// UserMenu tests
const username = await userMenu.getByTestId('username')
const email = await userMenu.getByTestId('userEmail')
const logOutButton = await userMenu.getByTestId('logOutButton')

await expect(username).toBeVisible()
await expect(await username.innerText()).toBe('[email protected]')
await expect(email).not.toBeVisible()
await expect(logOutButton).not.toBeVisible()

await userMenu.click()

await expect(email).toBeVisible()
await expect(logOutButton).toBeVisible()
await expect(await email.innerText()).toBe('[email protected]')

await logOutButton.click()

await expect(page).toHaveURL(`${process.env.SERVER_BASE_URL}/fr/login`)
await login(page)
})
Loading

0 comments on commit 42dda75

Please sign in to comment.