mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-31 18:48:08 +00:00
[QTI-188] Update the UI tests to be able to run against a cluster deployed to AWS. Add build hooks (package.json/Makefile) to execute ui tests with a real backend. (#14396)
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
"start2": "ember server --proxy=http://localhost:8202 --port=4202",
|
"start2": "ember server --proxy=http://localhost:8202 --port=4202",
|
||||||
"start:mirage": "start () { MIRAGE_DEV_HANDLER=$1 yarn run start; }; start",
|
"start:mirage": "start () { MIRAGE_DEV_HANDLER=$1 yarn run start; }; start",
|
||||||
"test": "npm-run-all lint:js:quiet lint:hbs:quiet && node scripts/start-vault.js",
|
"test": "npm-run-all lint:js:quiet lint:hbs:quiet && node scripts/start-vault.js",
|
||||||
|
"test:enos": "npm-run-all lint:js:quiet lint:hbs:quiet && node scripts/enos-test-ember.js",
|
||||||
"test:oss": "yarn run test -f='!enterprise'",
|
"test:oss": "yarn run test -f='!enterprise'",
|
||||||
"test:browserstack": "export CI=true; node scripts/start-vault.js --browserstack",
|
"test:browserstack": "export CI=true; node scripts/start-vault.js --browserstack",
|
||||||
"test:quick": "node scripts/start-vault.js",
|
"test:quick": "node scripts/start-vault.js",
|
||||||
|
|||||||
60
ui/scripts/enos-test-ember.js
Executable file
60
ui/scripts/enos-test-ember.js
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
const testHelper = require('./test-helper');
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
try {
|
||||||
|
let unsealKeys = process.env.VAULT_UNSEAL_KEYS;
|
||||||
|
if (!unsealKeys) {
|
||||||
|
console.error(
|
||||||
|
'Cannot run ember tests without unseal keys, please make sure to export the keys, in an env ' +
|
||||||
|
'var named: VAULT_UNSEAL_KEYS'
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
unsealKeys = JSON.parse(unsealKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootToken = process.env.VAULT_TOKEN;
|
||||||
|
if (!rootToken) {
|
||||||
|
console.error(
|
||||||
|
'Cannot run ember tests without root token, please make sure to export the root token, in an env ' +
|
||||||
|
'var named: VAULT_TOKEN'
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
testHelper.writeKeysFile(unsealKeys, rootToken);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vaultAddr = process.env.VAULT_ADDR;
|
||||||
|
if (!vaultAddr) {
|
||||||
|
console.error(
|
||||||
|
'Cannot run ember tests without the Vault Address, please make sure to export the vault address, in an env ' +
|
||||||
|
'var named: VAULT_ADDR'
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('VAULT_ADDR=' + vaultAddr);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const testArgs = ['test', '-c', 'testem.enos.js'];
|
||||||
|
|
||||||
|
if (process.env.TEST_FILTERS) {
|
||||||
|
const filters = JSON.parse(process.env.TEST_FILTERS).map((filter) => '-f=' + filter);
|
||||||
|
testArgs.push(...filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
await testHelper.run('ember', testArgs, false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
process.exit(1);
|
||||||
|
} finally {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -3,24 +3,8 @@
|
|||||||
/* eslint-disable no-process-exit */
|
/* eslint-disable no-process-exit */
|
||||||
/* eslint-disable node/no-extraneous-require */
|
/* eslint-disable node/no-extraneous-require */
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var readline = require('readline');
|
var readline = require('readline');
|
||||||
var execa = require('execa');
|
const testHelper = require('./test-helper');
|
||||||
var chalk = require('chalk');
|
|
||||||
|
|
||||||
function run(command, args = [], shareStd = true) {
|
|
||||||
console.log(chalk.dim('$ ' + command + ' ' + args.join(' ')));
|
|
||||||
// cleanup means that execa will handle stopping the vault subprocess
|
|
||||||
// inherit all of the stdin/out/err so that testem still works as if you were running it directly
|
|
||||||
if (shareStd) {
|
|
||||||
return execa(command, args, { cleanup: true, stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' });
|
|
||||||
}
|
|
||||||
let p = execa(command, args, { cleanup: true });
|
|
||||||
p.stdout.pipe(process.stdout);
|
|
||||||
p.stderr.pipe(process.stderr);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
var output = '';
|
var output = '';
|
||||||
var unseal, root, written, initError;
|
var unseal, root, written, initError;
|
||||||
@@ -37,7 +21,7 @@ async function processLines(input, eachLine = () => {}) {
|
|||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
try {
|
try {
|
||||||
let vault = run(
|
let vault = testHelper.run(
|
||||||
'vault',
|
'vault',
|
||||||
[
|
[
|
||||||
'server',
|
'server',
|
||||||
@@ -57,7 +41,7 @@ async function processLines(input, eachLine = () => {}) {
|
|||||||
output = output + line;
|
output = output + line;
|
||||||
var unsealMatch = output.match(/Unseal Key: (.+)$/m);
|
var unsealMatch = output.match(/Unseal Key: (.+)$/m);
|
||||||
if (unsealMatch && !unseal) {
|
if (unsealMatch && !unseal) {
|
||||||
unseal = unsealMatch[1];
|
unseal = [unsealMatch[1]];
|
||||||
}
|
}
|
||||||
var rootMatch = output.match(/Root Token: (.+)$/m);
|
var rootMatch = output.match(/Root Token: (.+)$/m);
|
||||||
if (rootMatch && !root) {
|
if (rootMatch && !root) {
|
||||||
@@ -68,13 +52,7 @@ async function processLines(input, eachLine = () => {}) {
|
|||||||
initError = errorMatch[1];
|
initError = errorMatch[1];
|
||||||
}
|
}
|
||||||
if (root && unseal && !written) {
|
if (root && unseal && !written) {
|
||||||
fs.writeFile(
|
testHelper.writeKeysFile(unseal, root);
|
||||||
path.join(process.cwd(), 'tests/helpers/vault-keys.js'),
|
|
||||||
`export default ${JSON.stringify({ unseal, root }, null, 2)}`,
|
|
||||||
(err) => {
|
|
||||||
if (err) throw err;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
written = true;
|
written = true;
|
||||||
console.log('VAULT SERVER READY');
|
console.log('VAULT SERVER READY');
|
||||||
} else if (initError) {
|
} else if (initError) {
|
||||||
@@ -87,20 +65,20 @@ async function processLines(input, eachLine = () => {}) {
|
|||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
if (process.argv[2] === '--browserstack') {
|
if (process.argv[2] === '--browserstack') {
|
||||||
await run('ember', ['browserstack:connect']);
|
await testHelper.run('ember', ['browserstack:connect']);
|
||||||
try {
|
try {
|
||||||
await run('ember', ['test', '-f=secrets/secret/create', '-c', 'testem.browserstack.js']);
|
await testHelper.run('ember', ['test', '-f=secrets/secret/create', '-c', 'testem.browserstack.js']);
|
||||||
|
|
||||||
console.log('success');
|
console.log('success');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} finally {
|
} finally {
|
||||||
if (process.env.CI === 'true') {
|
if (process.env.CI === 'true') {
|
||||||
await run('ember', ['browserstack:results']);
|
await testHelper.run('ember', ['browserstack:results']);
|
||||||
}
|
}
|
||||||
await run('ember', ['browserstack:disconnect']);
|
await testHelper.run('ember', ['browserstack:disconnect']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await run('ember', ['test', ...process.argv.slice(2)]);
|
await testHelper.run('ember', ['test', ...process.argv.slice(2)]);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|||||||
54
ui/scripts/test-helper.js
Normal file
54
ui/scripts/test-helper.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const execa = require('execa');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a vault keys file that can be imported in other scripts, that includes the unseal keys and the root token.
|
||||||
|
* @param unsealKeys an array of unseal keys, must contain at least one key
|
||||||
|
* @param rootToken the root token
|
||||||
|
* @param filePath optional file path, if not provided the default path of <cwd>/tests/helpers/vault-keys.js
|
||||||
|
* will be used.
|
||||||
|
*/
|
||||||
|
function writeKeysFile(unsealKeys, rootToken, filePath) {
|
||||||
|
if (filePath === undefined) {
|
||||||
|
filePath = path.join(process.cwd(), 'tests/helpers/vault-keys.js');
|
||||||
|
}
|
||||||
|
let keys = {};
|
||||||
|
keys.unsealKeys = unsealKeys;
|
||||||
|
keys.rootToken = rootToken;
|
||||||
|
|
||||||
|
fs.writeFile(filePath, `export default ${JSON.stringify(keys, null, 2)}`, (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the provided command and pipes the processes stdout and stderr to the terminal. Upon completion with
|
||||||
|
* success or error the child process will be cleaned up.
|
||||||
|
* @param command some command to run
|
||||||
|
* @param args some arguments for the command to run
|
||||||
|
* @param shareStd if true the sub process created by the command will share the stdout and stderr of the parent
|
||||||
|
* process
|
||||||
|
* @returns {*} The child_process for the executed command which is also a Promise.
|
||||||
|
*/
|
||||||
|
function run(command, args = [], shareStd = true) {
|
||||||
|
console.log(chalk.dim('$ ' + command + ' ' + args.join(' ')));
|
||||||
|
// cleanup means that execa will handle stopping the subprocess
|
||||||
|
// inherit all of the stdin/out/err so that testem still works as if you were running it directly
|
||||||
|
if (shareStd) {
|
||||||
|
return execa(command, args, { cleanup: true, stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' });
|
||||||
|
}
|
||||||
|
let p = execa(command, args, { cleanup: true });
|
||||||
|
p.stdout.pipe(process.stdout);
|
||||||
|
p.stderr.pipe(process.stderr);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
writeKeysFile: writeKeysFile,
|
||||||
|
run: run,
|
||||||
|
};
|
||||||
40
ui/testem.enos.js
Normal file
40
ui/testem.enos.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const vault_addr = process.env.VAULT_ADDR;
|
||||||
|
console.log('VAULT_ADDR=' + vault_addr);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
test_page: 'tests/index.html?hidepassed',
|
||||||
|
tap_quiet_logs: true,
|
||||||
|
tap_failed_tests_only: true,
|
||||||
|
disable_watching: true,
|
||||||
|
launch_in_ci: ['Chrome'],
|
||||||
|
browser_start_timeout: 120,
|
||||||
|
browser_args: {
|
||||||
|
Chrome: {
|
||||||
|
ci: [
|
||||||
|
// --no-sandbox is needed when running Chrome inside a container
|
||||||
|
process.env.CI ? '--no-sandbox' : null,
|
||||||
|
'--headless',
|
||||||
|
'--disable-dev-shm-usage',
|
||||||
|
'--disable-software-rasterizer',
|
||||||
|
'--mute-audio',
|
||||||
|
'--remote-debugging-port=0',
|
||||||
|
'--window-size=1440,900',
|
||||||
|
].filter(Boolean),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
proxies: {
|
||||||
|
'/v1': {
|
||||||
|
target: vault_addr,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.CI) {
|
||||||
|
module.exports.reporter = 'xunit';
|
||||||
|
module.exports.report_file = 'test-results/qunit/results.xml';
|
||||||
|
module.exports.xunit_intermediate_output = true;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { click, fillIn, currentURL, currentRouteName, visit, settled } from '@ember/test-helpers';
|
import { click, currentRouteName, currentURL, fillIn, settled, visit } from '@ember/test-helpers';
|
||||||
import { module, test } from 'qunit';
|
import { module, test } from 'qunit';
|
||||||
import { setupApplicationTest } from 'ember-qunit';
|
import { setupApplicationTest } from 'ember-qunit';
|
||||||
import VAULT_KEYS from 'vault/tests/helpers/vault-keys';
|
import VAULT_KEYS from 'vault/tests/helpers/vault-keys';
|
||||||
@@ -6,7 +6,7 @@ import authPage from 'vault/tests/pages/auth';
|
|||||||
import logout from 'vault/tests/pages/logout';
|
import logout from 'vault/tests/pages/logout';
|
||||||
import { pollCluster } from 'vault/tests/helpers/poll-cluster';
|
import { pollCluster } from 'vault/tests/helpers/poll-cluster';
|
||||||
|
|
||||||
const { unseal } = VAULT_KEYS;
|
const { unsealKeys } = VAULT_KEYS;
|
||||||
|
|
||||||
module('Acceptance | unseal', function (hooks) {
|
module('Acceptance | unseal', function (hooks) {
|
||||||
setupApplicationTest(hooks);
|
setupApplicationTest(hooks);
|
||||||
@@ -34,12 +34,15 @@ module('Acceptance | unseal', function (hooks) {
|
|||||||
assert.equal(currentURL(), '/vault/unseal', 'vault is on the unseal page');
|
assert.equal(currentURL(), '/vault/unseal', 'vault is on the unseal page');
|
||||||
|
|
||||||
// unseal
|
// unseal
|
||||||
await fillIn('[data-test-shamir-input]', unseal);
|
for (const key of unsealKeys) {
|
||||||
|
await fillIn('[data-test-shamir-input]', key);
|
||||||
|
|
||||||
await click('button[type="submit"]');
|
await click('button[type="submit"]');
|
||||||
|
|
||||||
|
await pollCluster(this.owner);
|
||||||
|
await settled();
|
||||||
|
}
|
||||||
|
|
||||||
await pollCluster(this.owner);
|
|
||||||
await settled();
|
|
||||||
assert.dom('[data-test-cluster-status]').doesNotExist('ui does not show sealed warning');
|
assert.dom('[data-test-cluster-status]').doesNotExist('ui does not show sealed warning');
|
||||||
assert.equal(currentRouteName(), 'vault.cluster.auth', 'vault is ready to authenticate');
|
assert.equal(currentRouteName(), 'vault.cluster.auth', 'vault is ready to authenticate');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { create, visitable, fillable, clickable } from 'ember-cli-page-object';
|
import { create, visitable, fillable, clickable } from 'ember-cli-page-object';
|
||||||
import { settled } from '@ember/test-helpers';
|
import { settled } from '@ember/test-helpers';
|
||||||
|
import VAULT_KEYS from 'vault/tests/helpers/vault-keys';
|
||||||
|
|
||||||
|
const { rootToken } = VAULT_KEYS;
|
||||||
|
|
||||||
export default create({
|
export default create({
|
||||||
visit: visitable('/vault/auth'),
|
visit: visitable('/vault/auth'),
|
||||||
@@ -19,7 +22,7 @@ export default create({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.tokenInput('root').submit();
|
await this.tokenInput(rootToken).submit();
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user