Browse Source

End to end automated tests run on Github workflows (#384)

* WIP for automated integration test

* See if it runs under a workflow

* Support running test locally as well as a workflow

* Use already downloaded repo to build. Do not re-clone

* Add comments

* Update to support new default config file

* Split out different test suites

* Add test for chat

* Always run test with config-default and ignore local config file

* Remove the build workflow because the end to end test does that now
pull/397/head
Gabe Kangas 5 years ago committed by GitHub
parent
commit
5dff6f32fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      .github/workflows/automated-end-to-end.yaml
  2. 41
      .github/workflows/buildmaster.yaml
  3. 2
      test/automated/.gitignore
  4. 49
      test/automated/admin.test.js
  5. 49
      test/automated/chat.test.js
  6. 21
      test/automated/index.test.js
  7. 5197
      test/automated/package-lock.json
  8. 18
      test/automated/package.json
  9. 43
      test/automated/run.sh
  10. BIN
      test/automated/test.mp4

16
.github/workflows/automated-end-to-end.yaml

@ -0,0 +1,16 @@
name: Automated end to end tests
on:
push:
# branches:
# - master
pull_request:
branches: master
jobs:
Jest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup and run
run: cd test/automated && ./run.sh

41
.github/workflows/buildmaster.yaml

@ -1,41 +0,0 @@
name: Build Owncast
on:
push:
branches:
- master
pull_request:
branches: master
jobs:
build:
strategy:
matrix:
go-version: [~1.13, ^1]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- uses: actions/checkout@v2
- name: Build
run: go build -o owncast *.go
docker-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Copy default config file
run: cp config-default.yaml config.yaml
- name: Build Docker image
run: docker build -t owncast .
- name: Run Docker image
run: docker run -d -p 8080:8080 -p 1935:1935 owncast

2
test/automated/.gitignore vendored

@ -0,0 +1,2 @@
node_modules
ffmpeg

49
test/automated/admin.test.js

@ -0,0 +1,49 @@
var request = require('supertest');
request = request('http://127.0.0.1:8080');
test('stream details are correct', (done) => {
request.get('/api/admin/status').auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body.broadcaster.streamDetails.width).toBe(320);
expect(res.body.broadcaster.streamDetails.height).toBe(180);
expect(res.body.broadcaster.streamDetails.framerate).toBe(24);
expect(res.body.broadcaster.streamDetails.videoBitrate).toBe(1269);
expect(res.body.broadcaster.streamDetails.videoCodec).toBe('H.264');
expect(res.body.broadcaster.streamDetails.audioCodec).toBe('AAC');
expect(res.body.online).toBe(true);
done();
});
});
test('admin configuration is correct', (done) => {
request.get('/api/admin/serverconfig').auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body.instanceDetails.name).toBe('Owncast');
expect(res.body.instanceDetails.title).toBe('Owncast');
expect(res.body.instanceDetails.summary).toBe('This is brief summary of whom you are or what your stream is. You can edit this description in your config file.');
expect(res.body.instanceDetails.logo).toBe('/img/logo.svg');
expect(res.body.instanceDetails.tags).toStrictEqual(['music', 'software', 'streaming']);
expect(res.body.videoSettings.segmentLengthSeconds).toBe(4);
expect(res.body.videoSettings.numberOfPlaylistItems).toBe(5);
expect(res.body.videoSettings.videoQualityVariants[0].framerate).toBe(24);
expect(res.body.videoSettings.videoQualityVariants[0].encoderPreset).toBe('veryfast');
expect(res.body.videoSettings.numberOfPlaylistItems).toBe(5);
expect(res.body.yp.enabled).toBe(false);
expect(res.body.streamKey).toBe('abc123');
done();
});
});
test('correct number of log entries exist', (done) => {
request.get('/api/admin/logs').auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body).toHaveLength(4);
done();
});
});

49
test/automated/chat.test.js

@ -0,0 +1,49 @@
const { test } = require('@jest/globals');
var request = require('supertest');
request = request('http://127.0.0.1:8080');
const WebSocket = require('ws');
var ws;
const id = Math.random().toString(36).substring(7);
const username = 'user' + Math.floor(Math.random() * 100);
const message = Math.floor(Math.random() * 100) + ' test 123';
const messageRaw = message + ' *and some markdown too*';
const messageMarkdown = '<p>' + message + ' <em>and some markdown too</em></p>'
const date = new Date().toISOString();
const testMessage = {
author: username,
body: messageRaw,
id: id,
type: 'CHAT',
visible: true,
timestamp: date,
};
test('can send a chat message', (done) => {
ws = new WebSocket('ws://127.0.0.1:8080/entry', {
origin: 'http://localhost',
});
function onOpen() {
ws.send(JSON.stringify(testMessage), function() {
ws.close();
done();
});
}
ws.on('open', onOpen);
});
test('can fetch chat messages', (done) => {
request.get('/api/chat').expect(200)
.then((res) => {
expect(res.body[0].author).toBe(testMessage.author);
expect(res.body[0].body).toBe(messageMarkdown);
expect(res.body[0].date).toBe(testMessage.date);
expect(res.body[0].type).toBe(testMessage.type);
done();
});
});

21
test/automated/index.test.js

@ -0,0 +1,21 @@
var request = require('supertest');
request = request('http://127.0.0.1:8080');
test('service is online', (done) => {
request.get('/api/status').expect(200)
.then((res) => {
expect(res.body.online).toBe(true);
done();
});
});
test('frontend configuration is correct', (done) => {
request.get('/api/config').expect(200)
.then((res) => {
expect(res.body.title).toBe('Owncast');
expect(res.body.logo).toBe('/img/logo.svg');
expect(res.body.socialHandles[0].platform).toBe('github');
expect(res.body.socialHandles[0].url).toBe('http://github.com/owncast/owncast');
done();
});
});

5197
test/automated/package-lock.json generated

File diff suppressed because it is too large Load Diff

18
test/automated/package.json

@ -0,0 +1,18 @@
{
"name": "owncast-test-automation",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"author": "",
"license": "ISC",
"dependencies": {
"supertest": "^6.0.1",
"websocket": "^1.0.32"
},
"devDependencies": {
"jest": "^26.6.3"
}
}

43
test/automated/run.sh

@ -0,0 +1,43 @@
#!/bin/bash
TEMP_DB=$(mktemp)
# Install the node test framework
npm install --silent > /dev/null
# Download a specific version of ffmpeg
if [ ! -d "ffmpeg" ]; then
mkdir ffmpeg
pushd ffmpeg > /dev/null
curl -sL https://github.com/vot/ffbinaries-prebuilt/releases/download/v4.2.1/ffmpeg-4.2.1-linux-64.zip --output ffmpeg.zip > /dev/null
unzip -o ffmpeg.zip > /dev/null
PATH=$PATH:$(pwd)
popd > /dev/null
fi
pushd ../.. > /dev/null
# Build and run owncast from source
go build -o owncast main.go pkged.go
./owncast -database $TEMP_DB -configFile config-default.yaml &
SERVER_PID=$!
popd > /dev/null
sleep 5
# Start streaming the test file over RTMP to
# the local owncast instance.
ffmpeg -hide_banner -loglevel panic -re -i test.mp4 -vcodec libx264 -profile:v main -sc_threshold 0 -b:v 1300k -acodec copy -f flv rtmp://127.0.0.1/live/abc123 &
FFMPEG_PID=$!
function finish {
rm $TEMP_DB
kill $SERVER_PID $FFMPEG_PID
}
trap finish EXIT
echo "Waiting..."
sleep 15
# Run the tests against the instance.
npm test

BIN
test/automated/test.mp4

Binary file not shown.
Loading…
Cancel
Save