8000 test(crux-ui): add e2e test for version and deployment deletes and fix test flakyness by m8vago · Pull Request #706 · dyrector-io/dyrectorio · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

test(crux-ui): add e2e test for version and deployment deletes and fix test flakyness #706

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
34d8999
test: add e2e test for version and deployment deletes
m8vago Jun 21, 2023
e31b135
Merge branch 'develop' into test/resource-copy-ids
m8vago Jun 22, 2023
0eb8142
fix: patch type in e2e
m8vago Jun 22, 2023
730016a
Merge branch 'develop' into test/resource-copy-ids
m8vago Jun 22, 2023
b183df3
fix: socket wait
m8vago Jun 22, 2023
4877096
Merge branch 'develop' into test/resource-copy-ids
m8vago Jun 22, 2023
f2e4fd1
Merge branch 'develop' into test/resource-copy-ids
robot9706 Jun 23, 2023
aa52aa6
test(crux-ui): moved waitSocket
robot9706 Jun 23, 2023
1fa05cf
Merge branch 'develop' into test/resource-copy-ids
m8vago Jun 26, 2023
b396d0a
Merge branch 'develop' into test/resource-copy-ids
Jun 29, 2023
92ff2d5
Merge branch 'develop' into test/resource-copy-ids
m8vago Jul 5, 2023
ec2c44f
Merge branch 'develop' into test/resource-copy-ids
m8vago Jul 19, 2023
c49b58d
Merge branch 'develop' into test/resource-copy-ids
m8vago Jul 27, 2023
af670b7
fix(crux-ui): ws patch sent calls
ngyradi Jul 28, 2023
aee5aa7
fix(crux-ui): playwright config
ngyradi Jul 28, 2023
81717d6
Merge branch 'develop' into test/resource-copy-ids
ngyradi Jul 28, 2023
bc35398
fix(crux-ui): container port config
ngyradi Jul 28, 2023
8e76481
fix(crux-ui): changed test order
ngyradi Jul 31, 2023
103b2e1
fix(crux-ui): deploy copy parent delete test
ngyradi Jul 31, 2023
7a0dccf
fix(crux-ui): container config with json
ngyradi Aug 1, 2023
3f2f3a3
fix(crux-ui): missing await
ngyradi Aug 1, 2023
9e413c4
fix(crux-ui): test consistency
ngyradi Aug 1, 2023
2dea76f
Merge branch 'develop' into test/resource-copy-ids
robot9706 Aug 18, 2023
25b4a6c
fix(crux-ui): test merge
robot9706 Aug 18, 2023
3d81f83
Merge branch 'develop' into test/resource-copy-ids
robot9706 Aug 18, 2023
32b743f
fix(crux-ui): fixing some flaky tests
robot9706 Aug 18, 2023
2c6206c
feat(crux-ui): wait for patch request
robot9706 Aug 21, 2023
a20588c
feat(crux-ui): e2e exec and dagent logs
robot9706 Aug 21, 2023
1f0dd71
fix(crux-ui): save stderr and stdout
robot9706 Aug 21, 2023
a5ebca0
fix(crux-ui): save stderr and stdout
robot9706 Aug 21, 2023
cf07293
fix(crux-ui): delete tests
robot9706 Aug 21, 2023
1d8c6b2
feat(crux-ui): adjusted playwright timeouts & copy test
robot9706 Aug 21, 2023
1d5a6a0
fix(crux-ui): deploy timeout
robot9706 Aug 22, 2023
f985db1
test(crux-ui): test ws logging
robot9706 Aug 22, 2023
8b041ac
test(crux-ui): test specific
robot9706 Aug 22, 2023
ac1e9a4
test(crux-ui): revert testing
robot9706 Aug 22, 2023
55464c5
fix(crux-ui): parallel tests
robot9706 Aug 23, 2023
75047c6
fix(crux-ui): wait for after each navigation
robot9706 Aug 23, 2023
8f58568
fix(crux-ui): revert some mistakes
robot9706 Aug 25, 2023
fb56b3f
test(crux-ui): install script logging & page console log
robot9706 Aug 28, 2023
e8aad93
test(crux-ui): webSocket order & page console log
robot9706 Aug 28, 2023
694ef72
test(crux-ui): websocket ref
robot9706 Aug 28, 2023
3ffa2ea
Merge branch 'develop' into test/resource-copy-ids
m8vago Aug 29, 2023
c1731d2
Merge branch 'develop' into test/resource-copy-ids
robot9706 Aug 30, 2023
e504eea
fix(crux-ui): config bundle test update
robot9706 Aug 30, 2023
3188fca
Merge branch 'develop' into test/resource-copy-ids
m8vago Aug 30, 2023
f4af833
fix(crux-ui): e2e test websocket
robot9706 Aug 30, 2023
1ea8cca
fix(crux-ui): remove old e2e patch
robot9706 Aug 30, 2023
5bbc49a
Merge branch 'develop' into test/resource-copy-ids
m8vago Aug 31, 2023
8e336af
fix: save button flakiness
m8vago Aug 31, 2023
1e87e92
fix: ws patchreceived
m8vago Aug 31, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/product_builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -583,9 +583,10 @@ jobs:
if: always()
run: |
mkdir logs
docker logs dyo-e2e_crux-ui > logs/e2e-crux-ui.log
docker logs dyo-e2e_crux > logs/e2e-crux.log
docker logs dyo-e2e_kratos > logs/e2e-kratos.log
docker logs dyo-e2e_crux-ui > logs/e2e-crux-ui.log 2>&1
docker logs dyo-e2e_crux > logs/e2e-crux.log 2>&1
docker logs dyo-e2e_kratos > logs/e2e-kratos.log 2>&1
docker logs dagent > logs/e2e-dagent.log 2>&1
- uses: actions/upload-artifact@v3
if: failure()
with:
Expand Down
39 changes: 37 additions & 2 deletions web/crux-ui/e2e/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Locator, Page } from '@playwright/test'
import path from 'path'
import { v4 as uuid } from 'uuid'
import MailSlurper from './mail-slurper'
import { ChildProcess, ExecException, ExecOptions, exec } from 'child_process'

export const MAILSLURPER_TIMEOUT = 30000 // millis
export const USER_EMAIL = 'john.doe@example.com'
Expand Down Expand Up @@ -170,5 +171,39 @@ export const clearInput = async (input: Locator) => {
await input.press('Backspace')
}

export const waitForURLExcept = (page: Page, options: { startsWith: string; except: string }) =>
page.waitForURL(it => it.toString() !== options.except && it.pathname.startsWith(options.startsWith))
export const waitForURLExcept = async (page: Page, options: { startsWith: string; except: string }) =>
await page.waitForURL(it => it.toString() !== options.except && it.pathname.startsWith(options.startsWith))

export const getExecOptions = (): ExecOptions =>
process.platform === 'win32'
? {
shell: 'C:\\Program Files\\git\\bin\\bash.exe',
}
: null

export const logCmdOutput = (logStdOut: boolean) => (err: Error, stdOut: string, stdErr: string) => {
if (logStdOut) {
console.info(stdOut)
}

if (err) {
console.error(err)
}

if (stdErr) {
console.error(stdErr)
}
}

export const execAsync = (
command: string,
options: ExecOptions,
callback?: (error: ExecException | null, stdout: string, stderr: string) => void,
) => {
return new Promise<ChildProcess>(resolve => {
const childProcess = exec(command, options, (error: ExecException | null, stdout: string, stderr: string) => {
callback?.call(null, error, stdout, stderr)
resolve(childProcess)
})
})
}
8 changes: 4 additions & 4 deletions web/crux-ui/e2e/utils/config-bundle.ts
< F438 /span>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { TEAM_ROUTES } from './common'
import { Page, expect } from '@playwright/test'
import { waitSocket, wsPatchSent } from './websocket'
import { waitSocketRef, wsPatchSent } from './websocket'
import { PatchConfigBundleMessage, WS_TYPE_PATCH_CONFIG_BUNDLE } from '@app/models/config-bundle'

const matchPatchEnvironment = (expected: Record<string, string>) => (message: PatchConfigBundleMessage) =>
const matchPatchEnvironment = (expected: Record<string, string>) => (message: PatchConfigBundleMessage) =>
Object.entries(expected).every(
([key, value]) => message.environment?.find(it => it.key === key && it.value === value),
)
Expand All @@ -16,7 +16,7 @@ export const createConfigBundle = async (page: Page, name: string, data: Record<
await expect(page.locator('h4')).toContainText('New config bundle')
await page.locator('input[name=name] >> visible=true').fill(name)

const sock = waitSocket(page)
const sock = waitSocketRef(page)
await page.locator('text=Save').click()
await page.waitForURL(`${TEAM_ROUTES.configBundles.list()}/**`)
await page.waitForSelector(`h4:text-is("View ${name}")`)
Expand All @@ -28,7 +28,7 @@ export const createConfigBundle = async (page: Page, name: string, data: Record<

await page.locator('button:has-text("Edit")').click()

const wsPatchReceived = wsPatchSent(ws, wsRoute, matchPatchEnvironment(data), WS_TYPE_PATCH_CONFIG_BUNDLE)
const wsPatchReceived = wsPatchSent(ws, wsRoute, WS_TYPE_PATCH_CONFIG_BUNDLE, matchPatchEnvironment(data))

const entries = Object.entries(data)
for (let i = 0; i < entries.length; i++) {
Expand Down
28 changes: 28 additions & 0 deletions web/crux-ui/e2e/utils/container-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { expect, Page } from '@playwright/test'
import { WebSocketRef, wsPatchSent } from './websocket'
import { wsPatchMatchPorts } from './websocket-match'

export const addPortsToContainerConfig = async (
page: Page,
ws: WebSocketRef,
wsRoute: string,
sentWsType: string,
internal: string,
external: string,
) => {
await page.locator('button:has-text("JSON")').click()

const jsonEditor = await page.locator('textarea')
const json = JSON.parse(await jsonEditor.inputValue())
json.ports = [{ internal: Number.parseInt(internal, 10), external: Number.parseInt(external, 10) }]

let wsSent = wsPatchSent(ws, wsRoute, sentWsType, wsPatchMatchPorts(internal, external))
await jsonEditor.fill(JSON.stringify(json))
await wsSent

await page.reload()

await expect(page.locator('input[placeholder="Internal"]')).toHaveValue(internal)
await expect(page.locator('input[placeholder="External"]')).toHaveValue(external)
}
8 changes: 7 additions & 1 deletion web/crux-ui/e2e/utils/global.setup.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import { ROUTE_LOGIN, ROUTE_TEAMS_CREATE } from '@app/routes'
import { test } from '@playwright/test'
import { test } from './test.fixture'
import { BASE_URL, STORAGE_STATE } from '../../playwright.config'
import {
createUser,
Expand Down Expand Up @@ -29,30 +29,36 @@ test('global setup', async ({ page }) => {

logInfo('logging in')
await page.goto(ROUTE_LOGIN)
await page.waitForSelector('h1:text-is("Log in")')
await page.locator('input[name=email]').fill(USER_EMAIL)
await page.locator('input[name=password]').fill(USER_PASSWORD)
await page.locator('button[type=submit]').click()

logInfo('creating team')
await page.waitForURL(ROUTE_TEAMS_CREATE)
await page.waitForSelector('h4:text-is("Create new team")')
await page.locator('input[name=name]').fill(USER_TEAM)
await page.locator('input[name=slug]').fill(USER_TEAM_SLUG)
await page.locator('button[type=submit]').click()

await page.waitForURL(TEAM_ROUTES.dashboard.index())
await page.waitForSelector('h2:text-is("Dashboard")')

logInfo('saving storage state')
await page.context().storageState({ path: STORAGE_STATE as string })

logInfo('changing registry to ghcr')
await page.goto(TEAM_ROUTES.registry.list())
await page.waitForSelector('h2:text-is("Registries")')
await page.click('h3:has-text("Docker Hub Library")')
await page.waitForURL(`${TEAM_ROUTES.registry.list()}/**`)
await page.waitForSelector('h3:text-is("Docker Hub Library")')
await page.click('button:has-text("Edit")')
await page.click('button:has-text("Unchecked")')
await page.locator('input[name=name]').fill(REGISTRY_NAME)
await page.locator('input[name=url]').fill(GHCR_MIRROR)
await page.click('button:has-text("Save")')
await page.waitForSelector(`h3:text-is("${REGISTRY_NAME}")`)

logInfo('installing dagent')
await installDagent(page)
Expand Down
2 changes: 1 addition & 1 deletion web/crux-ui/e2e/utils/global.teardown.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test } from '@playwright/test'
import { test } from './test.fixture'
import { globalTeardown } from './global.teardown'

test('teardown', async () => {
Expand Down
25 changes: 16 additions & 9 deletions web/crux-ui/e2e/utils/global.teardown.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec, ExecOptions } from 'child_process'
import { exec, ExecOptions, execSync } from 'child_process'
/* eslint-disable import/no-extraneous-dependencies */
import { internalError } from '@app/error-responses'
import { UserMeta } from '@app/models'
Expand All @@ -8,10 +8,13 @@ import { BASE_URL } from '../../playwright.config'
import {
cruxUrlFromEnv,
deleteUserByEmail,
execAsync,
getExecOptions,
getUserByEmail,
getUserSessionToken,
kratosFromConfig,
kratosFrontendFromConfig,
logCmdOutput,
USER_EMAIL,
} from './common'

Expand Down Expand Up @@ -84,15 +87,19 @@ export const globalTeardown = async () => {
logInfo('fetch', 'delete user')
await deleteUserByEmail(kratos, USER_EMAIL)

const settings: ExecOptions =
process.platform === 'win32'
? {
shell: 'C:\\Program Files\\git\\git-bash.exe',
}
: null
const settings = getExecOptions()

logInfo('docker', 'remove stack')

exec(`docker rm -f $(docker ps -a -q --filter "name=^pw")`, settings)
exec('docker rm -f dagent', settings)
await execAsync(`docker rm -f $(docker ps -a -q --filter "name=^pw")`, settings)

if (!process.env.CI) {
// When running in CI a pipeline step will gather the dagent logs
const dagentInspect = await execAsync('docker inspect dagent', settings)
if (dagentInspect.exitCode === 0) {
logInfo('Saved dagent logs to ./e2e_results/dagent.log')
await execAsync('docker logs dagent > ./e2e_results/dagent.log 2>&1', settings, logCmdOutput(true))
}
await execAsync('docker rm -f dagent', settings)
}
}
65 changes: 36 additions & 29 deletions web/crux-ui/e2e/utils/node-helper.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { expect, test, Page } from '@playwright/test'
import { exec, ExecOptions } from 'child_process'
import { DAGENT_NODE, screenshotPath, TEAM_ROUTES } from './common'
import { expect, Page } from '@playwright/test'
import { ExecOptions } from 'child_process'
import { DAGENT_NODE, execAsync, getExecOptions, logCmdOutput, screenshotPath, TEAM_ROUTES } from './common'
import { fillDeploymentPrefix } from './projects'
import { Readable } from 'stream'

export const installDagent = async (page: Page) => {
await page.goto(TEAM_ROUTES.node.list())
await page.waitForSelector('h2:text-is("Nodes")')

await page.locator('button:has-text("Add")').click()

Expand All @@ -25,10 +27,17 @@ export const installDagent = async (page: Page) => {
const commandInput = await page.locator('input[readonly]')
const curl = await commandInput.inputValue()

const installOutput: string[] = []
// eslint-disable-next-line @typescript-eslint/no-use-before-define
exec(curl, getInstallScriptExecSettings(), logCmdOutput)

await page.waitForSelector('div.bg-dyo-green')
await execAsync(curl, getInstallScriptExecSettings(), storeCmdOutput(installOutput))

try {
await page.waitForSelector('div.bg-dyo-green')
} catch (err) {
console.log('[E2E] Agent install failed, script output:')
installOutput.forEach(it => console.log(it))
throw err
}

await page.screenshot({ path: screenshotPath('node-dagent-install-successful'), fullPage: true })
}
Expand All @@ -52,8 +61,10 @@ export const deployWithDagent = async (
): Promise<string> => {
if (versionId) {
await page.goto(TEAM_ROUTES.project.versions(projectId).details(versionId))
await page.waitForSelector('h2:text-is("Versions")')
} else {
await page.goto(TEAM_ROUTES.project.details(projectId))
await page.waitForSelector('h2:text-is("Projects")')
}

await page.locator('button:has-text("Add deployment")').click()
Expand Down Expand Up @@ -100,6 +111,7 @@ export const deploy = async (
): Promise<string> => {
if (navigate !== false) {
await page.goto(TEAM_ROUTES.deployment.details(deploymentId))
await page.waitForSelector('h2:text-is("Deployments")')
}

const deploy = page.getByText('Deploy', {
Expand All @@ -108,6 +120,7 @@ export const deploy = async (

await deploy.click()
await page.waitForURL(TEAM_ROUTES.deployment.deploy(deploymentId))
await page.waitForLoadState('networkidle')

if (ignoreResult) {
return deploymentId
Expand All @@ -120,33 +133,27 @@ export const deploy = async (
return deploymentId
}

const logCmdOutput = (err: Error, stdOut: string, stdErr: string, logStdOut?: boolean) => {
if (logStdOut) {
console.info(stdOut)
}
const getInstallScriptExecSettings = (): ExecOptions => ({
...getExecOptions(),
...(process.platform === 'darwin'
? {
env: { ...process.env },
}
: process.platform === 'win32'
? null
: {
env: { ...process.env, ROOTLESS: 'true', PERSISTENCE_FOLDER: `${__dirname}/dagent` },
}),
})

export const storeCmdOutput = (storage: string[]) => (err: Error, stdOut: string, stdErr: string) => {
storage.push(stdOut)

if (err) {
console.error(err)
storage.push(`${err.message} at ${err.stack}`)
}

if (stdErr) {
console.error(stdErr)
}
}

const getInstallScriptExecSettings = (): ExecOptions => {
switch (process.platform) {
case 'darwin':
return {
env: { ...process.env },
}
case 'win32':
return {
shell: 'C:\\Program Files\\git\\git-bash.exe',
}
default:
return {
env: { ...process.env, ROOTLESS: 'true', PERSISTENCE_FOLDER: `${__dirname}/dagent` },
}
storage.push(stdErr)
}
}
1 change: 1 addition & 0 deletions web/crux-ui/e2e/utils/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TEAM_ROUTES } from './common'
// eslint-disable-next-line import/prefer-default-export
export const createNode = async (page: Page, name: string) => {
await page.goto(TEAM_ROUTES.node.list())
await page.waitForSelector('h2:text-is("Nodes")')

await page.locator('button:has-text("Add")').click()
await expect(page.locator('h4:has-text("New node")')).toHaveCount(1)
Expand Down
Loading
0