4
0
Эх сурвалжийг харах

cicd: Improve tests (#205)

* cicd: make it easier to grab snapshot builds

* cicd: Better support for running tests against VMs

* Update multipleDropdowns.js
James Read 2 жил өмнө
parent
commit
4ce5b0e645

+ 1 - 0
integration-tests/.mocharc.yml

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

+ 5 - 0
integration-tests/Makefile

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

+ 13 - 0
integration-tests/README.md

@@ -1 +1,14 @@
 # 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`

+ 7 - 1
integration-tests/Vagrantfile

@@ -5,12 +5,18 @@
 Vagrant.configure("2") do |config|
   config.vm.box = "generic/centos8"
   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|
     libvirt.management_network_device = 'virbr0'
   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|
     f36.vm.box = "generic/fedora36"
     f36.vm.provision "file", source: "/opt/OliveTin-snapshot/OliveTin_linux_amd64.rpm", destination: "$HOME/"

+ 8 - 0
integration-tests/envVagrant.sh

@@ -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

+ 1 - 1
integration-tests/mochaSetup.mjs

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

+ 57 - 14
integration-tests/runner.mjs

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

+ 3 - 3
integration-tests/test/general.mjs

@@ -11,7 +11,7 @@ describe('config: general', function () {
   });
 
   it('Page title', async function () {
-    await webdriver.get('http://localhost:1337')
+    await webdriver.get(runner.baseUrl())
 
     let title = await webdriver.getTitle();
     expect(title).to.be.equal("OliveTin")
@@ -24,12 +24,12 @@ describe('config: general', 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 });
 
     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)
   })
 })

+ 1 - 1
integration-tests/test/hiddenFooter.mjs

@@ -12,7 +12,7 @@ describe('config: hiddenFooter', function () {
   });
 
   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'))
 

+ 1 - 1
integration-tests/test/hiddenNav.mjs

@@ -11,7 +11,7 @@ describe('config: hiddenNav', function () {
   })
 
   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'))
 

+ 1 - 2
integration-tests/test/multipleDropdowns.js

@@ -1,6 +1,5 @@
 import { expect } from 'chai'
 import { By, until } from 'selenium-webdriver'
-import fs from 'node:fs'
 
 describe('config: multipleDropdowns', function () {
   before(async function () {
@@ -12,7 +11,7 @@ describe('config: multipleDropdowns', 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 });
 
     const button = await webdriver.findElement(By.id('actionButton_bdc45101bbd12c1397557790d9f3e059')).findElement(By.tagName('button'));