Skip to content

Commit

Permalink
Add playwright create/login test for all db
Browse files Browse the repository at this point in the history
  • Loading branch information
Timshel committed Feb 20, 2024
1 parent 94b077c commit 604d08b
Show file tree
Hide file tree
Showing 12 changed files with 592 additions and 0 deletions.
5 changes: 5 additions & 0 deletions test/scenarios/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
logs
node_modules/
/test-results/
/playwright-report/
/playwright/.cache/
34 changes: 34 additions & 0 deletions test/scenarios/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# OpenID Keycloak scenarios

This allow to run integration testss using [Playwright](https://playwright.dev/).
\
It use it's own [test.env](/test/scenarios/test.env) with different ports to not collide with a running dev instance.

## Install

```bash
npm install
```

## Usage

To run all the tests:

```bash
npx playwright test
```

To access the ui to easily run test individually and debug if needed:

```bash
npx playwright test --ui
```

## Writing scenario

When creating new scenario use the recorder to more easily identify elements (in general try to rely on visible hint to identify elements and not hidden ids).
This does not start the server, you will need to start it manually.

```bash
npx playwright codegen "http://127.0.0.1:8000"
```
83 changes: 83 additions & 0 deletions test/scenarios/global-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { firefox, type FullConfig } from '@playwright/test';
import { exec, execSync } from 'node:child_process';
import fs from 'fs';
import yaml from 'js-yaml';

const utils = require('./global-utils');

utils.loadEnv();
var kcPath = process.env.KC_SETUP_PATH;

function readCurrentVersion(){
try {
const vw_version_file = fs.readFileSync('data/web-vault/vw-version.json', {
encoding: 'utf8',
flag: 'r'
});

return JSON.parse(vw_version_file)["version"];
} catch(err) {
console.log(`Failed to read frontend current version: ${err}`);
}
}

function readDockerVersion(){
try {
const docker_settings = fs.readFileSync('../../docker/DockerSettings.yaml', {
encoding: 'utf8',
flag: 'r'
});

const settings = yaml.load(docker_settings);
return settings["vault_version"];
} catch(err) {
console.log(`Failed to read docker frontend current version: ${err}`);
}
}

function retrieveFrontend(){
const vw_version = readCurrentVersion();
const vv = readDockerVersion()

if( !vv ){
console.log("Empty docker frontend version");
process.exit(1);
}

try {
if( vv != `v${vw_version}`) {
fs.rmSync("./data/web-vault", { recursive: true, force: true });

execSync(`cd data && wget -c https://github.com/dani-garcia/bw_web_builds/releases/download/${vv}/bw_web_${vv}.tar.gz -O - | tar xz`, { stdio: "inherit" });

// Make the SSO button visible
execSync(`bash -c "sed -i 's#a.routerlink=./sso..,##' data/web-vault/app/main.*.css"`, { stdio: "inherit" });

console.log(`Retrieved bw_web_builds-${vv}`);
} else {
console.log(`Using existing bw_web_builds-${vv}`);
}
} catch(err) {
console.log(`Failed to retrieve frontend: ${err}`);
process.exit(1);
}
}

function buildServer(){
if( !fs.existsSync('data/vaultwarden') ){
console.log("Rebuilding server");
execSync(`cd ../.. && cargo build --features sqlite,mysql,postgresql --release`, { stdio: "inherit" });
execSync(`cp ../../target/release/vaultwarden data/vaultwarden`, { stdio: "inherit" });
} else {
console.log("Using existing server");
}
}

async function globalSetup(config: FullConfig) {
execSync("mkdir -p data/logs");

buildServer();
retrieveFrontend();
}

export default globalSetup;
65 changes: 65 additions & 0 deletions test/scenarios/global-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { type Browser } from '@playwright/test';
import dotenv from 'dotenv';
import dotenvExpand from 'dotenv-expand';

const fs = require("fs");
const { spawn } = require('node:child_process');

function loadEnv(){
var myEnv = dotenv.config({ path: 'test.env' });
dotenvExpand.expand(myEnv);
}

async function waitFor(url: String, browser: Browser) {
var ready = false;
var context;

do {
try {
context = await browser.newContext();
const page = await context.newPage();
await page.waitForTimeout(500);
const result = await page.goto(url);
ready = result.status() === 200;
} catch(e) {
if( !e.message.includes("NS_ERROR_CONNECTION_REFUSED") ){
throw e;
}
} finally {
await context.close();
}
} while(!ready);
}

async function startVaultWarden(browser: Browser, env = {}, reset: Boolean = true) {
if( reset ){
fs.rmSync("data/db.sqlite3", { force: true });
fs.rmSync("data/db.sqlite3-shm", { force: true });
fs.rmSync("data/db.sqlite3-wal", { force: true });
}

const vw_log = fs.openSync("data/logs/vaultwarden.log", "a");
var proc = spawn("../../target/release/vaultwarden", {
env: { ...process.env, ...env },
stdio: [process.stdin, vw_log, vw_log]
});

await waitFor("/", browser);

console.log(`VaultWarden running on: ${process.env.DOMAIN}`);

return proc;
}

async function stopVaultWarden(proc) {
console.log(`VaultWarden stopping`);
proc.kill();
}

async function restartVaultWarden(proc, browser: Browser, env) {
stopVaultWarden(proc);
return startVaultWarden(browser, env, false);
}


export { loadEnv, waitFor, startVaultWarden, stopVaultWarden, restartVaultWarden };
155 changes: 155 additions & 0 deletions test/scenarios/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions test/scenarios/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "scenarios",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.41.2",
"@types/node": "^20.11.16",
"abort-controller": "3.0.0",
"dotenv": "^16.4.1",
"dotenv-expand": "^10.0.0",
"js-yaml": "4.1.0"
}
}
Loading

0 comments on commit 604d08b

Please sign in to comment.