Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions playwright/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ $ export CONSOLE_ADMIN_EMAIL=<admin_dso_email>
$ export CONSOLE_TEST_USERNAME=<user_dso_username>
$ export CONSOLE_TEST_PASSWORD=<user_dso_password>
$ export CONSOLE_TEST_EMAIL=<user_dso_email>
$ export CONSOLE_SECOND_TEST_USERNAME=<another_user_dso_username>
$ export CONSOLE_SECOND_TEST_PASSWORD=<another_user_dso_password>
$ export CONSOLE_SECOND_TEST_EMAIL=<another_user_dso_email>
$ export CONSOLE_GLOBAL_TIMEOUT='900000'
$ export CONSOLE_EXPECT_TIMEOUT='900000'
$ export CONSOLE_DESTINATION_CLUSTER=<cluster_name_where_argo_deploys_apps>
Expand Down
10 changes: 10 additions & 0 deletions playwright/config/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ export const tcolinUser: Credentials = {
email: 'thibault.colin@test.com',
}

// User for integration test
export const secondTestUser: Credentials = {
id: 'test',
username: process.env.CONSOLE_SECOND_TEST_USERNAME.trim(),
password: process.env.CONSOLE_SECOND_TEST_PASSWORD.trim(),
firstName: 'test',
lastName: 'test',
email: process.env.CONSOLE_SECOND_TEST_EMAIL.trim(),
}

export async function signInCloudPiNative({
page,
credentials,
Expand Down
123 changes: 114 additions & 9 deletions playwright/integration-tests/user-flow.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test'
import { adminUser, testUser, clientURL, signInCloudPiNative } from '../config/console'
import { adminUser, secondTestUser, testUser, clientURL, signInCloudPiNative } from '../config/console'

import {
addProject,
Expand All @@ -8,13 +8,13 @@ import {
} from '../e2e-tests/utils'

const projectsToDelete: string[] = []
const projectName = 'socleprojecttest'
const repositoryName = 'socle-project-test'
const destinationCluster = process.env.CONSOLE_DESTINATION_CLUSTER || 'cpin-app-hp'
projectsToDelete.push(projectName)

test.describe('Integration tests user flow', { tag: '@integ' }, () => {
test.describe('Integration tests user flow: project creation', { tag: '@integ' }, () => {
test.describe.configure({ mode: 'serial' })
const projectName = 'socleprojecttest'
const repositoryName = 'socle-project-test'
const destinationCluster = process.env.CONSOLE_DESTINATION_CLUSTER || 'cpin-app-hp'
projectsToDelete.push(projectName)

test('Preliminary checks', { tag: '@replayable' }, async ({ page }) => {
await page.goto(clientURL)
Expand Down Expand Up @@ -68,6 +68,10 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
await page.getByTestId('updateRepoBtn').click()
await expect(page.getByRole('heading', { name: 'Opération en cours...' })).toBeVisible()
})
})

test.describe('Integration tests user flow: first checks', { tag: '@integ' }, () => {
test.describe.configure({ mode: 'parallel' })

test('Check Vault kv', { tag: '@replayable' }, async ({ page }) => {
await page.goto(clientURL)
Expand All @@ -90,6 +94,37 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
await expect(page1.getByRole('link', { name: 'forge-dso' })).not.toBeVisible()
})

test('Project permissions', async ({ page }) => {
await page.goto(clientURL)
await signInCloudPiNative({ page, credentials: testUser })
await page.getByTestId('menuMyProjects').click()
await page.getByRole('link', { name: projectName }).click()
// Add user to project
await page.getByTestId('test-tab-team').click()
await page.getByTestId('addUserSuggestionInput').locator('input').fill(secondTestUser.email)
await page.getByTestId('addUserBtn').click()
await expect(page.getByRole('heading', { name: 'Reprovisionnement nécessaire' })).toBeVisible()
// Create read-only role
await page.getByTestId('test-tab-roles').click()
await page.getByTestId('addRoleBtn').click()
await page.getByTestId('roleNameInput').fill('readOnly')
await page.getByText('Afficher les secrets Permet d').click()
await page.getByText('Voir les environnements').click()
await page.getByText('Voir les dépôts Permet de').click()
await page.getByTestId('saveBtn').click()
await expect(page.getByText('Rôle mis à jour')).toBeVisible()
await expect(page.getByRole('heading', { name: 'Reprovisionnement nécessaire' })).toBeVisible()
// Add user to read-only role
await page.getByTestId('test-members').click()
await page.getByLabel('Rôles', { exact: true }).getByText(secondTestUser.email).click()
await expect(page.getByText('Rôle mis à jour')).toBeVisible()
await expect(page.getByRole('heading', { name: 'Reprovisionnement nécessaire' })).toBeVisible()
// Replay project hooks
await page.getByTestId('replayHooksBtn').click()
await expect(page.getByRole('heading', { name: 'Opération en cours...' })).toBeVisible()
await expect(page.getByText('Le projet a été reprovisionn')).toBeVisible()
})

test('Pipelines run', { tag: '@replayable' }, async ({ page }) => {
await page.goto(clientURL)
await signInCloudPiNative({ page, credentials: testUser })
Expand Down Expand Up @@ -119,6 +154,10 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
page1.getByRole('link', { name: 'Status: Passed test-sonar' }),
).toBeVisible()
})
})

test.describe('Integration tests user flow: after pipelines checks', { tag: '@integ' }, () => {
test.describe.configure({ mode: 'parallel' })

test('Prepare ArgoCD deployment', async ({ page }) => {
await page.goto(clientURL)
Expand Down Expand Up @@ -177,6 +216,10 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
// Check trivy scan result, hopefully will stay at C
await expect(page1.getByRole('button', { name: 'C', exact: true })).toBeVisible()
})
})

test.describe('Integration tests user flow: deployment and metrics', { tag: '@integ' }, () => {
test.describe.configure({ mode: 'serial' })

test('ArgoCD deployment', { tag: '@replayable' }, async ({ page }) => {
await page.goto(clientURL)
Expand All @@ -200,10 +243,67 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
await expect(page2.locator('html')).toContainText('Application is running')
})

test('Cleanup user test data', async ({ page }) => {
test('Check Grafana', { tag: '@replayable' }, async ({ page }) => {
await page.goto(clientURL)
await signInCloudPiNative({ page, credentials: testUser })
await page.getByTestId('menuMyProjects').click()
await page.getByRole('link', { name: projectName }).click()
await page.getByTestId('test-tab-services').click()
const page1Promise = page.waitForEvent('popup')
await page.getByRole('link', { name: 'Grafana' }).click()
const page1 = await page1Promise
await page1.getByRole('link', { name: 'Sign in with grafana-projects' }).click()
await expect(page1.getByRole('link', { name: 'Grafana', exact: true })).toBeVisible()
await page1.getByTestId('data-testid Toggle menu').click()
await page1.getByRole('button', { name: 'Expand section Dashboards' }).click()
await page1.getByRole('link', { name: 'Dashboards', exact: true }).click()
await page1.getByRole('link', { name: 'dso-grafana' }).click()
// Check if we can see some metrics
await page1.getByRole('link', { name: 'Kubernetes / Views /' }).click()
await expect(page1.getByText('0.100')).toBeVisible() // Cpu request
await expect(page1.getByText('0.500')).toBeVisible() // Cpu limit
await expect(page1.getByText('256')).toBeVisible() // Memory request
await expect(page1.getByText('512')).toBeVisible() // Memory limit
// Check if we can see some logs
await page1.getByTestId('data-testid dso-grafana breadcrumb').click()
await page1.getByRole('link', { name: 'Loki Kubernetes Logs' }).click()
await expect(page1.getByTestId('data-testid Panel status error').first()).not.toBeVisible()
await expect(page1.locator('.rc-drawer-mask')).not.toBeVisible()
await page1.getByTestId('data-testid TimePicker Open Button').click()
await page1.getByText('Last 1 hour').click()
await page1.locator('.css-13x53bc-Icon-topVerticalAlign').first().click()
await expect(page1.getByRole('cell', { name: 'app_kubernetes_io_name' }).nth(1)).toBeVisible()
await expect(page1.getByText('demo-java-helm').nth(1)).toBeVisible()
})
})

test.describe('Integration tests user flow: Cleanup', { tag: '@integ' }, () => {
test.describe.configure({ mode: 'serial' })

test('Remove permissions and user', async ({ page }) => {
await page.goto(clientURL)
await signInCloudPiNative({ page, credentials: testUser })
await page.getByTestId('menuMyProjects').click()
await page.getByRole('link', { name: projectName }).click()
// Remove role membership
await page.getByTestId('test-tab-roles').click()
await page.getByRole('button', { name: 'readOnly' }).click()
await page.getByTestId('test-members').click()
await page.getByLabel('Rôles', { exact: true }).getByText(secondTestUser.email).click()
await expect(page.getByText('Rôle mis à jour')).toBeVisible()
await expect(page.getByRole('heading', { name: 'Reprovisionnement nécessaire' })).toBeVisible()
// Remove role
await page.getByTestId('test-general').click()
await page.getByTestId('deleteBtn').click()
await page.getByText('Rôle supprimé').click()
// Remove project membership
await page.getByTestId('test-tab-team').click()
await page.getByTitle(`Retirer ${secondTestUser.email} du`).click()
})

test('Remove stage', async ({ page }) => {
await page.goto(clientURL)
await signInCloudPiNative({ page, credentials: testUser })
// ArgoCD deployment will be deleted when stage is deleted
await page.getByTestId('menuMyProjects').click()
await page.getByRole('link', { name: projectName }).click()
await page.getByRole('cell', { name: 'integ' }).click()
Expand All @@ -214,6 +314,7 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
await expect(
page.getByRole('cell', { name: 'Aucun environnement existant' }),
).toBeVisible()
// ArgoCD deployment will be deleted when stage is deleted
await page.getByTestId('test-tab-services').click()
const page1Promise = page.waitForEvent('popup')
await page.getByRole('link', { name: 'ArgoCD DSO' }).click()
Expand All @@ -222,7 +323,11 @@ test.describe('Integration tests user flow', { tag: '@integ' }, () => {
await expect(
page1.locator('span').filter({ hasText: `${projectName}-integ-socle-` }),
).not.toBeVisible()
// Remove repository from project
})

test('Remove repository from project', async ({ page }) => {
await page.goto(clientURL)
await signInCloudPiNative({ page, credentials: testUser })
await page.getByTestId('test-tab-resources').click()
await page.getByRole('cell', { name: repositoryName }).click()
await page.getByTestId('showDeleteRepoBtn').click()
Expand Down
4 changes: 1 addition & 3 deletions playwright/playwright.config.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ dotenv.config({
*/
export default defineConfig({
testDir: './integration-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 ? 3 : 1,
workers: 1,
workers: 3,
/* 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. */
Expand Down