Skip to content

Commit

Permalink
Update integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TheSomeMan committed Apr 23, 2024
1 parent 344e8ea commit 975e9af
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 34 deletions.
10 changes: 10 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"sass-loader": "^13.2.0",
"sinon": "^15.0.2",
"sinon-chai": "^3.7.0",
"string-argv": "^0.3.2",
"style-loader": "^3.3.1",
"webpack": "^5.76.0",
"webpack-cli": "^5.0.1",
Expand Down
3 changes: 3 additions & 0 deletions scripts/http_server_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ def log(msg):
def create_ssl_context(cert_file, key_file, ca_file):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
if cert_file == key_file:
log(f'Loading cert file {cert_file} as both cert and key file.')
context.load_cert_chain(cert_file)
else:
log(f'Loading cert file {cert_file} and key file {key_file}.')
context.load_cert_chain(cert_file, key_file)

if ca_file is not None:
log(f'Loading CA file {ca_file}.')
context.load_verify_locations(ca_file)
context.verify_mode = ssl.CERT_REQUIRED
return context
Expand Down
124 changes: 119 additions & 5 deletions scripts/ruuvi_gw_ui_script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import path from "path";
import fetch from 'node-fetch';
import https from 'https';
import logger from './ruuvi_gw_ui_logger.js';
import {exec} from 'child_process';
import {exec, spawn} from 'child_process';
import parseArgs from 'string-argv';

let array_of_spawned_processes = [];

/** Delay execution for the specified number of milliseconds
*
Expand Down Expand Up @@ -389,6 +392,7 @@ export class UiScriptActionDo extends UiScriptAction {
HTTP_GET: "httpGet",
DOWNLOAD_HISTORY: "downloadHistory",
EXEC: "exec",
SPAWN: "spawn",
};

/**
Expand Down Expand Up @@ -474,6 +478,9 @@ export class UiScriptActionDo extends UiScriptAction {
if (action_type === UiScriptActionDo.UiScriptActionDoType.EXEC) {
return new UiScriptActionDoExec(action_type, args, params);
}
if (action_type === UiScriptActionDo.UiScriptActionDoType.SPAWN) {
return new UiScriptActionDoSpawn(action_type, args, params);
}
throw new Error(`Invalid 'do' action: ${action_type}`);
}

Expand Down Expand Up @@ -527,13 +534,23 @@ export class UiScriptActionDoFillInput extends UiScriptActionDo {

await page.focus(this.selector);
// Select all text in the input element
await page.keyboard.down('Control');
if (process.platform === 'darwin') {
await page.keyboard.down('Meta');
} else {
await page.keyboard.down('Control');
}
await page.keyboard.press('KeyA');
await page.keyboard.up('Control');

if (process.platform === 'darwin') {
await page.keyboard.up('Meta');
} else {
await page.keyboard.up('Control');
}
// Press 'Backspace' to delete all selected text
await page.keyboard.press('Backspace');

// Clears the input field
await page.$eval(this.selector, (el) => el.value = '');

await page.type(this.selector, this.value);

await delay(this.postClickDelay, "Post click delay");
Expand Down Expand Up @@ -1269,6 +1286,100 @@ export class UiScriptActionDoExec extends UiScriptActionDo {
}
}

class ProcessManager {
constructor(cmd_line) {
const cmd_line_arr = parseArgs(cmd_line);
this.cmd = cmd_line_arr[0];
this.cmdArgs = cmd_line_arr.slice(1);
this.processRunning = false;
this.command = null;
}

runCommandInBackground() {
logger.info(`Spawn: '${this.cmd}' with args: ${this.cmdArgs}`);

this.command = spawn(this.cmd, this.cmdArgs, {
detached: false,
// stdio: 'ignore'
});
this.processRunning = true;
logger.info(`Started command in background with pid: ${this.command.pid}`);

this.command.on('error', (error) => {
logger.error(`Spawn failed with error: ${error.message}`);
});

// Listens for the 'exit' event.
this.command.on('exit', (exitCode) => {
logger.info(`Command with PID ${this.command.pid} has finished with exit code: ${exitCode}`);
this.processRunning = false;
this.exitCode = exitCode;
})

this.command.stdout.on('data', (data) => {
logger.info(`[PID:${this.command.pid}] stdout: ${data}`);
});

this.command.stderr.on('data', (data) => {
logger.error(`[PID:${this.command.pid}] stderr: ${data}`);
});

// Now, you can kill the process like this:
// command.kill();

// To kill the process with 'Ctrl+C' signal:
// command.kill('SIGINT');
// Keep in mind that this will only work if the child process is not independent (meaning detached is not set to true and unref method is not called).
}

isProcessRunning() {
return this.processRunning;
}

killProcess() {
if (this.command && this.isProcessRunning()) {
logger.info(`Kill process with PID: ${this.command.pid}`);
this.command.kill();
}
}
}

/**
* @class
* @extends UiScriptActionDo
*/
export class UiScriptActionDoSpawn extends UiScriptActionDo {
/**
* @param {string} action_type
* @param {string[]} args
* @param {Object | undefined} params
*/
constructor(action_type, args, params) {
super(action_type, params);
if (args.length !== 1) {
throw new Error(`UiScriptActionDoSpawn: Expected 1 argument, got ${args.length}, args: ${args}`);
}
this.cmd_line = args[0];
this.process = new ProcessManager(this.cmd_line)
}

/**
* @param {Browser} browser
* @param {Page} page
* @returns {Promise<void>}
*/
async execute(browser, page) {
logger.info(`Execute sequence: Spawn cmd: '${this.cmd_line}'`);
this.process.runCommandInBackground();
array_of_spawned_processes.push(this.process);
await delay(1000);
if (!this.process.isProcessRunning()) {
throw new Error(`The spawned process exited with exit code: ${this.process.exitCode}`);
}
}

}

/**
* @class
*/
Expand Down Expand Up @@ -1629,7 +1740,7 @@ export class UiScript {
if (subst_obj[name] !== undefined) {
return subst_obj[name];
}
throw new Error(`Placeholder not found for ${match}`);
throw new Error(`Placeholder is not found for ${match}`);
});
}
});
Expand Down Expand Up @@ -1657,6 +1768,9 @@ export class UiScript {
for (const page_obj of this.pages) {
await page_obj.execute(browser, page);
}
for (const process of array_of_spawned_processes) {
process.killProcess();
}

await browser.close();
}
Expand Down
8 changes: 5 additions & 3 deletions tests/test_http.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
http_port: 8000
http_server: "http://${secrets:hostname}:${env:http_port}/record"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500

pages:
- page?: "#page-auth"
steps:
- steps:
- do: spawn "python3 scripts/http_server_auth.py --port "${env:http_port}""
- if: isInvisible "#auth-user_login"
then: fail "Remote access is disabled"
- if: isEnabled "#auth-user"
Expand Down
14 changes: 9 additions & 5 deletions tests/test_http_with_auth.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
http_port: 8000
http_server: "http://${secrets:hostname}:${env:http_port}/record"
http_auth_user: "user1"
http_auth_pass: "[email protected]"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500

pages:
- page?: "#page-auth"
steps:
- steps:
- do: spawn "python3 scripts/http_server_auth.py --port "${env:http_port}" -u "${env:http_auth_user}" -p "${env:http_auth_pass}""
- if: isInvisible "#auth-user_login"
then: fail "Remote access is disabled"
- if: isEnabled "#auth-user"
Expand Down Expand Up @@ -76,14 +80,14 @@ pages:

- do: checkCheckbox "#use_http_auth" # Check checkbox 'Use authentication'
- do: fillInput "#http_user" "user1" # Fill the input 'Username'
- do: fillInput "#http_pass" "[email protected]" # Fill the input 'Password'
- do: fillInput "#http_pass" "incorrect_password.137!" # Fill the input 'Password'

- do: clickButton "#page-custom_server-button-check" # Click on button 'Check'
- do: waitUntilLoaded 20000 # Wait until checking is done
- if: isInvisible "#page-custom_server-http_validation_error"
then: fail "HTTP server check failed"

- do: fillInput "#http_pass" "[email protected]" # Fill the input 'Password'
- do: fillInput "#http_pass" "${env:http_auth_pass}" # Fill the input 'Password'

- do: clickButton "#page-custom_server-button-check" # Click on button 'Check'
- do: waitUntilLoaded 20000 # Wait until checking is done
Expand Down
14 changes: 11 additions & 3 deletions tests/test_https_with_server_and_client_cert_checking.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
https_port: 8001
https_server: "https://${secrets:hostname}:${env:https_port}/record"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500

pages:
- page?: "#page-auth"
steps:
- steps:
- do: exec "openssl genrsa -out ${dir:test}/server_key.pem 2048" 5
- do: exec "openssl req -new -key ${dir:test}/server_key.pem -out ${dir:test}/server_csr.pem -subj "/C=FI/ST=Uusimaa/L=Helsinki/O=Ruuvi/OU=/CN=${secrets:hostname}"" 5
- do: exec "openssl x509 -req -in ${dir:test}/server_csr.pem -signkey ${dir:test}/server_key.pem -out ${dir:test}/server_cert.pem -days 365" 5
- do: exec "openssl genrsa -out ${dir:test}/client_key.pem 2048" 5
- do: exec "openssl req -new -key ${dir:test}/client_key.pem -out ${dir:test}/client_csr.pem -subj "/C=FI/ST=Uusimaa/L=Helsinki/O=Ruuvi/OU=/CN=${secrets:gw_hostname}"" 5
- do: exec "openssl x509 -req -in ${dir:test}/client_csr.pem -signkey ${dir:test}/client_key.pem -out ${dir:test}/client_cert.pem -days 365" 5
- do: spawn "python3 scripts/http_server_auth.py --port "${env:https_port}" --ssl_cert "${dir:test}/server_cert.pem" --ssl_key "${dir:test}/server_key.pem" --ca_cert "${dir:test}/client_cert.pem""
- if: isInvisible "#auth-user_login"
then: fail "Remote access is disabled"
- if: isEnabled "#auth-user"
Expand Down
12 changes: 9 additions & 3 deletions tests/test_https_with_server_cert_checking.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
https_port: 8001
https_server: "https://${secrets:hostname}:${env:https_port}/record"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500

pages:
- page?: "#page-auth"
steps:
- steps:
- do: exec "openssl genrsa -out ${dir:test}/server_key.pem 2048" 5
- do: exec "openssl req -new -key ${dir:test}/server_key.pem -out ${dir:test}/server_csr.pem -subj "/C=FI/ST=Uusimaa/L=Helsinki/O=Ruuvi/OU=/CN=${secrets:hostname}"" 5
- do: exec "openssl x509 -req -in ${dir:test}/server_csr.pem -signkey ${dir:test}/server_key.pem -out ${dir:test}/server_cert.pem -days 365" 5
- do: delay 1000
- do: spawn "python3 scripts/http_server_auth.py --port "${env:https_port}" --ssl_cert "${dir:test}/server_cert.pem" --ssl_key "${dir:test}/server_key.pem""
- if: isInvisible "#auth-user_login"
then: fail "Remote access is disabled"
- if: isEnabled "#auth-user"
Expand Down
4 changes: 1 addition & 3 deletions tests/test_mqtt_aws.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500
Expand Down
4 changes: 1 addition & 3 deletions tests/test_mqtt_ssl.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500
Expand Down
4 changes: 1 addition & 3 deletions tests/test_mqtt_tcp.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500
Expand Down
4 changes: 1 addition & 3 deletions tests/test_mqtt_ws.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500
Expand Down
4 changes: 1 addition & 3 deletions tests/test_mqtt_wss.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
env:
url: "${secrets:url}"
url: "http://${secrets:gw_hostname}"
gw_id: "${secrets:gw_id}"
gw_mac: "${secrets:gw_mac}"
http_server: "${secrets:http_server}"
https_server: "${secrets:https_server}"
navigationTimeout: 3000
preClickDelay: 1000
postClickDelay: 1500
Expand Down

0 comments on commit 975e9af

Please sign in to comment.