From 72111c6c0027c09af83be64167c7171a271bc337 Mon Sep 17 00:00:00 2001 From: Artur Kantorczyk <64010779+dzania@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:26:38 +0200 Subject: [PATCH] 279 e2e test enrollment process (#312) * Added proxy service to e2e compose * working enrollment test --------- Co-authored-by: Kamil Chudy --- docker-compose.e2e.yaml | 7 +++ e2e/config.ts | 3 + e2e/tests/enrollment.spec.ts | 86 +++++++++++++++++++++++++++ e2e/utils/controllers/enrollment.ts | 90 +++++++++++++++++++++++++++++ e2e/utils/docker.ts | 2 +- 5 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 e2e/tests/enrollment.spec.ts create mode 100644 e2e/utils/controllers/enrollment.ts diff --git a/docker-compose.e2e.yaml b/docker-compose.e2e.yaml index 4c0ec8256..ff6ff32c7 100644 --- a/docker-compose.e2e.yaml +++ b/docker-compose.e2e.yaml @@ -49,3 +49,10 @@ services: - core cap_add: - NET_ADMIN + + proxy: + image: ghcr.io/defguard/defguard-proxy:latest + ports: + - "8080:8080" + environment: + DEFGUARD_PROXY_UPSTREAM_GRPC_URL: "http://core:50055/" diff --git a/e2e/config.ts b/e2e/config.ts index 3996e3a6d..bb5b1baf8 100644 --- a/e2e/config.ts +++ b/e2e/config.ts @@ -3,16 +3,19 @@ import { mergeObjects } from './utils/utils'; type TestsConfig = { BASE_URL: string; CORE_BASE_URL: string; + ENROLLMENT_URL: string; }; const defaultConfig: TestsConfig = { BASE_URL: 'http://localhost:8000', CORE_BASE_URL: 'http://localhost:8000/api/v1', + ENROLLMENT_URL: 'http://localhost:8080' }; const envConfig: Partial = { BASE_URL: process.env.BASE_URL, CORE_BASE_URL: process.env.CORE_BASE_URL, + ENROLLMENT_URL: process.env.ENROLLMENT_URL }; export const testsConfig: TestsConfig = mergeObjects(envConfig, defaultConfig); diff --git a/e2e/tests/enrollment.spec.ts b/e2e/tests/enrollment.spec.ts new file mode 100644 index 000000000..e6c50b185 --- /dev/null +++ b/e2e/tests/enrollment.spec.ts @@ -0,0 +1,86 @@ +import { BrowserContext, expect, Page, test } from '@playwright/test'; + +import { testsConfig } from '../config'; +import { NetworkForm, User } from '../types'; +import { apiGetUserProfile } from '../utils/api/users'; +import { + createDevice, + createUserEnrollment, + password, + setPassword, + setToken, + validateData, +} from '../utils/controllers/enrollment'; +import { loginBasic } from '../utils/controllers/login'; +import { logout } from '../utils/controllers/logout'; +import { createNetwork } from '../utils/controllers/vpn/createNetwork'; +import { dockerRestart } from '../utils/docker'; +import { getPageClipboard } from '../utils/getPageClipboard'; +import { waitForBase } from '../utils/waitForBase'; +import { waitForPromise } from '../utils/waitForPromise'; + +test.describe.configure({ + mode: 'serial', +}); + +const testNetwork: NetworkForm = { + name: 'test network', + address: '10.10.10.1/24', + endpoint: '127.0.0.1', + port: '5055', +}; + +test.describe('Create user with enrollment enabled', () => { + let token: string; + let page: Page; + let context: BrowserContext; + let user: User; + + // Setup client and user for tests + test.beforeAll(async ({ browser }) => { + context = await browser.newContext(); + page = await context.newPage(); + await waitForBase(page); + user = await createUserEnrollment(context, 'testauth01'); + await createNetwork(context, testNetwork); + logout(page); + const response = (await getPageClipboard(page)).split('\n'); + // Extract token and url + const tokenResponse = response[1].split(' ')[1]; + token = tokenResponse; + }); + + test.afterEach(async () => { + dockerRestart(); + }); + + test.afterAll(() => { + dockerRestart(); + }); + + test('Go to enrollment', async () => { + expect(token).toBeDefined(); + await page.goto(testsConfig.ENROLLMENT_URL); + await waitForPromise(2000); + await setToken(token, page); + // Welcome page + await page.getByTestId('enrollment-next').click(); + // Data validation + await validateData(user, page); + await page.getByTestId('enrollment-next').click(); + // Set password + await setPassword(page); + // VPN + await page.getByTestId('enrollment-next').click(); + await createDevice(page); + // Finish message + await page.getByTestId('enrollment-next').click(); + loginBasic(page, { username: user.username, password }); + await waitForPromise(2000); + const testUserProfile = await apiGetUserProfile(page, user.username); + expect(testUserProfile.devices.length).toBe(1); + const createdDevice = testUserProfile.devices[0]; + expect(createdDevice.networks[0].device_wireguard_ip).toBe('10.10.10.2'); + expect(createdDevice.name).toBe('test'); + }); +}); diff --git a/e2e/utils/controllers/enrollment.ts b/e2e/utils/controllers/enrollment.ts new file mode 100644 index 000000000..936ede4e0 --- /dev/null +++ b/e2e/utils/controllers/enrollment.ts @@ -0,0 +1,90 @@ +import { expect, Page } from '@playwright/test'; +import { BrowserContext } from 'playwright'; + +import { defaultUserAdmin, routes, testUserTemplate } from '../../config'; +import { User } from '../../types'; +import { waitForBase } from '../waitForBase'; +import { waitForPromise } from '../waitForPromise'; +import { loginBasic } from './login'; +import { logout } from './logout'; + +export const password = 'TestEnrollment1234!!'; + +export const createUserEnrollment = async ( + context: BrowserContext, + username: string +): Promise => { + const user: User = { ...testUserTemplate, username }; + const page = await context.newPage(); + await waitForBase(page); + await page.goto(routes.base + routes.auth.login); + await loginBasic(page, defaultUserAdmin); + await page.goto(routes.base + routes.admin.users); + await page.getByTestId('add-user').click(); + const formElement = page.getByTestId('add-user-form'); + await formElement.waitFor({ state: 'visible' }); + await formElement.getByTestId('field-username').type(user.username); + await formElement.getByTestId('field-first_name').type(user.firstName); + await formElement.getByTestId('field-last_name').type(user.lastName); + await formElement.getByTestId('field-email').type(user.mail); + await formElement.getByTestId('field-phone').type(user.phone); + await formElement.getByTestId('field-enable_enrollment').click(); + await formElement.locator('button[type="submit"]').click(); + waitForPromise(2000); + const modalElement = page.locator('#add-user-modal'); + const enrollmentForm = modalElement.getByTestId('start-enrollment-form'); + await enrollmentForm.locator('.toggle-option').nth(1).click(); + await enrollmentForm.locator('button[type="submit"]').click(); + // Copy to clipboard + await modalElement + .locator('.step-content') + .locator('#enrollment-token-step') + .locator('.expandable-card') + .locator('.top') + .locator('.actions') + .locator('button') + .click(); + + await modalElement + .locator('.step-content') + .locator('#enrollment-token-step') + .locator('.controls') + .locator('button') + .click(); + await modalElement.waitFor({ state: 'hidden' }); + await logout(page); + return user; +}; + +export const setToken = async (token: string, page: Page) => { + const formElement = page.getByTestId('enrollment-token-form'); + await formElement.getByTestId('field-token').type(token); + await formElement.locator('button[type="submit"]').click(); +}; + +export const validateData = async (user: User, page: Page) => { + const formElement = page + .locator('#enrollment-data-verification-card') + .getByTestId('enrollment-data-verification') + .locator('.row'); + const firstName = await formElement.locator('p').nth(0).textContent(); + const lastName = await formElement.locator('p').nth(1).textContent(); + const mail = await formElement.locator('p').nth(2).textContent(); + const phone = await formElement.getByTestId('field-phone').inputValue(); + expect(firstName).toBe(user.firstName); + expect(lastName).toBe(user.lastName); + expect(mail).toBe(user.mail); + expect(phone).toBe(user.phone); +}; + +export const setPassword = async (page: Page) => { + const formElement = page.getByTestId('enrollment-password-form'); + await formElement.getByTestId('field-password').type(password); + await formElement.getByTestId('field-repeat').type(password); +}; + +export const createDevice = async (page: Page) => { + const formElement = page.getByTestId('enrollment-device-form'); + await formElement.getByTestId('field-name').type('test'); + await formElement.locator('button[type="submit"]').click(); +}; diff --git a/e2e/utils/docker.ts b/e2e/utils/docker.ts index 5b992d4d9..8b810b251 100644 --- a/e2e/utils/docker.ts +++ b/e2e/utils/docker.ts @@ -7,7 +7,7 @@ const dockerFilePath = path.resolve(defguardPath, 'docker-compose.e2e.yaml'); // Startups defguard stack with docker compose export const dockerUp = () => { - const command = `docker compose -f ${dockerFilePath.toString()} up -d core db gateway`; + const command = `docker compose -f ${dockerFilePath.toString()} up -d core db gateway proxy`; execSync(command); };