cicd: Improve tests (#205)

* cicd: make it easier to grab snapshot builds

* cicd: Better support for running tests against VMs

* Update multipleDropdowns.js
This commit is contained in:
James Read 2023-12-28 22:04:47 +00:00 committed by GitHub
parent e92ab8d741
commit 4ce5b0e645
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 100 additions and 25 deletions

View File

@ -1,2 +1,3 @@
---
require: require:
- mochaSetup.mjs - mochaSetup.mjs

View File

@ -2,4 +2,9 @@ default:
npm install --no-fund npm install --no-fund
./node_modules/.bin/mocha ./node_modules/.bin/mocha
getsnapshot:
rm -rf /opt/OliveTin-snapshot/*
gh run download -D /opt/OliveTin-snapshot/
.PHONY: default .PHONY: default

View File

@ -1 +1,14 @@
# OliveTin-integration-tests # OliveTin-integration-tests
## GitHub Actions (Ubuntu, Local Process)
- `mocha` is run with the default runner that starts and stops OliveTin as a local process (ie, localhost:1337).
## Running different configurations (Local Process, VM, Container)
- Get the snapshot you want to test `make getsnapshot`
- To test against VMs:
-- `export OLIVETIN_TEST_RUNNER=container`
-- `vagrant up f38` (or whatever distro you like defined in `Vagrantfile`)
-- `. envVagrant.sh f38` to set the $IP and $PORT
- `mocha`

View File

@ -5,12 +5,18 @@
Vagrant.configure("2") do |config| Vagrant.configure("2") do |config|
config.vm.box = "generic/centos8" config.vm.box = "generic/centos8"
config.vm.provision "shell", inline: "mkdir /etc/OliveTin && chmod o+w /etc/OliveTin/", privileged: true config.vm.provision "shell", inline: "mkdir /etc/OliveTin && chmod o+w /etc/OliveTin/", privileged: true
config.vm.provision "file", source: "configs/config.general.yaml/.", destination: "/etc/OliveTin/config.yaml" config.vm.provision "file", source: "configs/general/config.yaml/.", destination: "/etc/OliveTin/config.yaml"
config.vm.provider :libvirt do |libvirt| config.vm.provider :libvirt do |libvirt|
libvirt.management_network_device = 'virbr0' libvirt.management_network_device = 'virbr0'
end end
config.vm.define :f38 do |f36|
f36.vm.box = "generic/fedora38"
f36.vm.provision "file", source: "/opt/OliveTin-snapshot/OliveTin_linux_amd64.rpm", destination: "$HOME/"
f36.vm.provision "shell", inline: "rpm -U OliveTin* && systemctl enable --now OliveTin && systemctl disable --now firewalld"
end
config.vm.define :f36 do |f36| config.vm.define :f36 do |f36|
f36.vm.box = "generic/fedora36" f36.vm.box = "generic/fedora36"
f36.vm.provision "file", source: "/opt/OliveTin-snapshot/OliveTin_linux_amd64.rpm", destination: "$HOME/" f36.vm.provision "file", source: "/opt/OliveTin-snapshot/OliveTin_linux_amd64.rpm", destination: "$HOME/"

View File

@ -0,0 +1,8 @@
#!/bin/bash
# Run this like `. envVagrant.sh f38` before `mocha`
# args:
# $1: The Vagrant VM to test against. If blank and only one VM is provisioned, it will use that.
export IP=$(vagrant ssh-config $1 | grep HostName | awk '{print $2}')
export PORT=1337

View File

@ -10,7 +10,7 @@ export async function mochaGlobalSetup () {
global.runner = getRunner() global.runner = getRunner()
console.log("Runner constructor: " + global.runner.constructor.name) console.log('Runner constructor: ' + global.runner.constructor.name)
} }
export async function mochaGlobalTeardown () { export async function mochaGlobalTeardown () {

View File

@ -2,8 +2,6 @@ import process from 'node:process'
import waitOn from 'wait-on' import waitOn from 'wait-on'
import { spawn } from 'node:child_process' import { spawn } from 'node:child_process'
let ot = null
export default function getRunner () { export default function getRunner () {
const type = process.env.OLIVETIN_TEST_RUNNER const type = process.env.OLIVETIN_TEST_RUNNER
@ -11,33 +9,41 @@ export default function getRunner () {
switch (type) { switch (type) {
case 'local': case 'local':
return new OliveTinTestRunnerLocalProcess() return new OliveTinTestRunnerStartLocalProcess()
case 'vm': case 'vm':
return null return new OliveTinTestRunnerVm()
case 'container': case 'container':
return null return new OliveTinTestRunnerEnv()
default: default:
return new OliveTinTestRunnerLocalProcess() return new OliveTinTestRunnerStartLocalProcess()
} }
} }
class OliveTinTestRunnerLocalProcess { class OliveTinTestRunner {
BASE_URL = 'http://nohost:1337/';
baseUrl() {
return this.BASE_URL
}
}
class OliveTinTestRunnerStartLocalProcess extends OliveTinTestRunner {
async start (cfg) { async start (cfg) {
ot = spawn('./../OliveTin', ['-configdir', 'configs/' + cfg + '/']) this.ot = spawn('./../OliveTin', ['-configdir', 'configs/' + cfg + '/'])
const logStdout = process.env.OLIVETIN_TEST_RUNNER_LOG_STDOUT === '1' const logStdout = process.env.OLIVETIN_TEST_RUNNER_LOG_STDOUT === '1'
if (logStdout) { if (logStdout) {
ot.stdout.on('data', (data) => { this.ot.stdout.on('data', (data) => {
console.log(`stdout: ${data}`) console.log(`stdout: ${data}`)
}) })
ot.stderr.on('data', (data) => { this.ot.stderr.on('data', (data) => {
console.error(`stderr: ${data}`) console.error(`stderr: ${data}`)
}) })
} }
ot.on('close', (code) => { this.ot.on('close', (code) => {
if (code != null) { if (code != null) {
console.log(`child process exited with code ${code}`) console.log(`child process exited with code ${code}`)
} }
@ -48,14 +54,51 @@ class OliveTinTestRunnerLocalProcess {
console.log(`server running on port ${this.server.port}`); console.log(`server running on port ${this.server.port}`);
*/ */
await waitOn({ this.BASE_URL = 'http://localhost:1337/'
'resources': ['http://localhost:1337/']
})
return ot await waitOn({
resources: [this.BASE_URL]
})
} }
async stop () { async stop () {
await ot.kill() await this.ot.kill()
}
}
class OliveTinTestRunnerEnv extends OliveTinTestRunner {
constructor () {
super()
const IP = process.env.IP
const PORT = process.env.PORT
this.BASE_URL = 'http://' + IP + ':' + PORT + '/'
console.log('Runner ENV endpoint: ' + this.BASE_URL)
}
async start () {
await waitOn({
resources: [this.BASE_URL]
})
}
async stop () {
}
}
class OliveTinTestRunnerVm extends OliveTinTestRunnerEnv {
constructor() {
super()
}
async start (cfg) {
console.log("vagrant changing config")
spawn('vagrant', ['ssh', '-c', '"ln -sf /etc/OliveTin/ /opt/otConfigs/' + cfg + '/"'])
spawn('vagrant', ['ssh', '-c', '"systemctl restart OliveTin"'])
return null
} }
} }

View File

@ -11,7 +11,7 @@ describe('config: general', function () {
}); });
it('Page title', async function () { it('Page title', async function () {
await webdriver.get('http://localhost:1337') await webdriver.get(runner.baseUrl())
let title = await webdriver.getTitle(); let title = await webdriver.getTitle();
expect(title).to.be.equal("OliveTin") expect(title).to.be.equal("OliveTin")
@ -24,12 +24,12 @@ describe('config: general', function () {
}) })
it('Default buttons are rendered', async function() { it('Default buttons are rendered', async function() {
await webdriver.get('http://localhost:1337') await webdriver.get(runner.baseUrl())
// await webdriver.manage().setTimeouts({ implicit: 2000 }); // await webdriver.manage().setTimeouts({ implicit: 2000 });
let buttons = await webdriver.findElement(By.id('root-group')).findElements(By.tagName('button')) let buttons = await webdriver.findElement(By.id('root-group')).findElements(By.tagName('button'))
expect(buttons).to.have.length(6); expect(buttons).to.have.length(6)
}) })
}) })

View File

@ -12,7 +12,7 @@ describe('config: hiddenFooter', function () {
}); });
it('Check that footer is hidden', async () => { it('Check that footer is hidden', async () => {
await webdriver.get('http://localhost:1337') await webdriver.get(runner.baseUrl())
let footer = await webdriver.findElement(By.tagName('footer')) let footer = await webdriver.findElement(By.tagName('footer'))

View File

@ -11,7 +11,7 @@ describe('config: hiddenNav', function () {
}) })
it('nav is hidden', async () => { it('nav is hidden', async () => {
await webdriver.get('http://localhost:1337') await webdriver.get(runner.baseUrl())
const toggler = await webdriver.findElement(By.id('sidebar-toggle-wrapper')) const toggler = await webdriver.findElement(By.id('sidebar-toggle-wrapper'))

View File

@ -1,6 +1,5 @@
import { expect } from 'chai' import { expect } from 'chai'
import { By, until } from 'selenium-webdriver' import { By, until } from 'selenium-webdriver'
import fs from 'node:fs'
describe('config: multipleDropdowns', function () { describe('config: multipleDropdowns', function () {
before(async function () { before(async function () {
@ -12,7 +11,7 @@ describe('config: multipleDropdowns', function () {
}) })
it('Multiple dropdowns are possible', async function() { it('Multiple dropdowns are possible', async function() {
await webdriver.get('http://localhost:1337') await webdriver.get(runner.baseUrl())
await webdriver.manage().setTimeouts({ implicit: 2000 }); await webdriver.manage().setTimeouts({ implicit: 2000 });
const button = await webdriver.findElement(By.id('actionButton_bdc45101bbd12c1397557790d9f3e059')).findElement(By.tagName('button')); const button = await webdriver.findElement(By.id('actionButton_bdc45101bbd12c1397557790d9f3e059')).findElement(By.tagName('button'));