Skip to content
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

279 e2e test enrollment process #312

Merged
merged 14 commits into from
Aug 22, 2023
7 changes: 7 additions & 0 deletions docker-compose.e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
3 changes: 3 additions & 0 deletions e2e/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TestsConfig> = {
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);
Expand Down
86 changes: 86 additions & 0 deletions e2e/tests/enrollment.spec.ts
Original file line number Diff line number Diff line change
@@ -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');
});
});
90 changes: 90 additions & 0 deletions e2e/utils/controllers/enrollment.ts
Original file line number Diff line number Diff line change
@@ -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<User> => {
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();
};
2 changes: 1 addition & 1 deletion e2e/utils/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down
Loading