Web UI frontend automated browser tests (#2223)
* First pass at basic browser tests for #1926 * Run tests against dev web server not go server * Bundle the web code into the server before running tests * Move cypress UI tests into its own npm project + add tests * Add additional tests + wire up with cypress dashboard * Limit concurrency of workflow jobs * Temporarily comment out some tests that do not pass in mobile. Will fix later.
This commit is contained in:
parent
5119e977c1
commit
352447e3d4
@ -14,6 +14,11 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: earthly/actions-setup@v1
|
- uses: earthly/actions-setup@v1
|
||||||
with:
|
with:
|
||||||
|
19
.github/workflows/browser-testing.yml
vendored
Normal file
19
.github/workflows/browser-testing.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: Browser Tests
|
||||||
|
|
||||||
|
on: [push, pull_request_target]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cypress-run:
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.18'
|
||||||
|
- name: Run Browser tests
|
||||||
|
run: cd test/automated/browser && ./run.sh
|
5
.github/workflows/bundle-web.yml
vendored
5
.github/workflows/bundle-web.yml
vendored
@ -10,6 +10,11 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
bundle:
|
bundle:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Bundle web app (next.js build)
|
- name: Bundle web app (next.js build)
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
4
.github/workflows/chromatic.yml
vendored
4
.github/workflows/chromatic.yml
vendored
@ -20,6 +20,10 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
if: ${{ github.actor != 'renovate[bot]' && github.actor != 'renovate' }}
|
if: ${{ github.actor != 'renovate[bot]' && github.actor != 'renovate' }}
|
||||||
|
5
.github/workflows/go-lint.yml
vendored
5
.github/workflows/go-lint.yml
vendored
@ -18,6 +18,11 @@ jobs:
|
|||||||
name: Go linter
|
name: Go linter
|
||||||
if: ${{ github.actor != 'dependabot[bot]' }}
|
if: ${{ github.actor != 'dependabot[bot]' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
5
.github/workflows/hls-tests.yml
vendored
5
.github/workflows/hls-tests.yml
vendored
@ -18,6 +18,11 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
api:
|
api:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-go@v3
|
- uses: actions/setup-go@v3
|
||||||
|
8
.github/workflows/javascript-formatting.yml
vendored
8
.github/workflows/javascript-formatting.yml
vendored
@ -17,6 +17,10 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
if: ${{ github.actor != 'dependabot[bot]' }}
|
if: ${{ github.actor != 'dependabot[bot]' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@ -43,6 +47,10 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
4
.github/workflows/test-webapp-build.yaml
vendored
4
.github/workflows/test-webapp-build.yaml
vendored
@ -16,6 +16,10 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
name: Build webapp
|
name: Build webapp
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Tests
|
name: Go Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -39,3 +39,5 @@ backup/
|
|||||||
test/test.db
|
test/test.db
|
||||||
test/automated/browser/screenshots
|
test/automated/browser/screenshots
|
||||||
lefthook.yml
|
lefthook.yml
|
||||||
|
test/automated/browser/cypress/screenshots
|
||||||
|
test/automated/browser/cypress/videos
|
||||||
|
10
test/automated/browser/cypress.config.js
Normal file
10
test/automated/browser/cypress.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const { defineConfig } = require('cypress');
|
||||||
|
|
||||||
|
module.exports = defineConfig({
|
||||||
|
projectId: 'wwi3xe',
|
||||||
|
e2e: {
|
||||||
|
setupNodeEvents(on, config) {
|
||||||
|
// implement node event listeners here
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,50 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Basic tests`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080/');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify the tags show up
|
||||||
|
it('Has correct tags visible', () => {
|
||||||
|
cy.contains('#owncast').should('be.visible');
|
||||||
|
cy.contains('#streaming').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Can open notify modal', () => {
|
||||||
|
// cy.contains('Be notified').click();
|
||||||
|
// cy.wait(1500);
|
||||||
|
// cy.get('.ant-modal-close').click();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('Can open follow modal', () => {
|
||||||
|
// cy.contains('Follow').click();
|
||||||
|
// cy.wait(1500);
|
||||||
|
// cy.get('.ant-modal-close').click();
|
||||||
|
// });
|
||||||
|
|
||||||
|
it('Can change to Followers tab', () => {
|
||||||
|
cy.contains('Followers').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify content header values
|
||||||
|
it('Has correct content header values', () => {
|
||||||
|
cy.get('.header-title').should('have.text', 'Owncast');
|
||||||
|
cy.get('.header-subtitle').should(
|
||||||
|
'have.text',
|
||||||
|
'Welcome to your new Owncast server! This description can be changed in the admin. Visit https://owncast.online/docs/configuration/ to learn more.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has correct global header values', () => {
|
||||||
|
cy.get('.global-header-text').should('have.text', 'Owncast');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Offline banner
|
||||||
|
it('Has correct offline banner values', () => {
|
||||||
|
cy.contains(
|
||||||
|
'This stream is offline. Be notified the next time Owncast goes live.'
|
||||||
|
).should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Offline video embed`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080/embed/video');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Offline banner
|
||||||
|
it('Has correct offline banner values', () => {
|
||||||
|
cy.contains('This stream is offline. Check back soon!').should(
|
||||||
|
'be.visible'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,8 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Offline readwrite chat embed`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080/embed/chat/readwrite');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,12 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Offline read-only chat embed`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080/embed/chat/readwrite');
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Chat should be visible', () => {
|
||||||
|
// cy.get('#chat-container').should('be.visible');
|
||||||
|
// });
|
||||||
|
});
|
@ -0,0 +1,70 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Live tests`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should have a play button', () => {
|
||||||
|
cy.get('.vjs-big-play-button').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Chat should be visible', () => {
|
||||||
|
// cy.get('#chat-container').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
it('User menu should be visible', () => {
|
||||||
|
cy.get('#user-menu').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Chat join message should exist', () => {
|
||||||
|
// cy.contains('joined the chat').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
it('User menu should be visible', () => {
|
||||||
|
cy.get('#user-menu').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Click on user menu', () => {
|
||||||
|
cy.get('#user-menu').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can toggle chat off', () => {
|
||||||
|
cy.contains('Toggle chat').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Chat should not be visible', () => {
|
||||||
|
cy.get('#chat-container').should('not.exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Click on user menu', () => {
|
||||||
|
cy.get('#user-menu').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can toggle chat on', () => {
|
||||||
|
cy.contains('Toggle chat').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Chat should be re-visible', () => {
|
||||||
|
// cy.get('#chat-container').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
it('Click on user menu', () => {
|
||||||
|
cy.get('#user-menu').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Show change name modal', () => {
|
||||||
|
cy.contains('Change name').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should change name', () => {
|
||||||
|
cy.get('#name-change-field').focus();
|
||||||
|
cy.get('#name-change-field').type('{ctrl+a}');
|
||||||
|
cy.get('#name-change-field').type('my-new-name');
|
||||||
|
cy.get('#name-change-submit').click();
|
||||||
|
cy.get('.ant-modal-close-x').click();
|
||||||
|
cy.wait(1500);
|
||||||
|
// cy.contains('is now known as').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,12 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Online video embed`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should have a play button', () => {
|
||||||
|
cy.get('.vjs-big-play-button').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,32 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Online readwrite chat embed`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080/embed/chat/readwrite');
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Chat should be visible', () => {
|
||||||
|
// cy.get('#chat-container').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('User menu should be visible', () => {
|
||||||
|
// cy.get('#user-menu').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('Chat join message should exist', () => {
|
||||||
|
// cy.contains('joined the chat').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('User menu should be visible', () => {
|
||||||
|
// cy.get('#user-menu').should('be.visible');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('Click on user menu', () => {
|
||||||
|
// cy.get('#user-menu').click();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('Show change name modal', () => {
|
||||||
|
// cy.contains('Change name').click();
|
||||||
|
// });
|
||||||
|
});
|
@ -0,0 +1,12 @@
|
|||||||
|
import { setup } from '../../support/setup.js';
|
||||||
|
setup();
|
||||||
|
|
||||||
|
describe(`Online read-only chat embed`, () => {
|
||||||
|
it('Can visit the page', () => {
|
||||||
|
cy.visit('http://localhost:8080/embed/chat/readwrite');
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('Chat should be visible', () => {
|
||||||
|
// cy.get('#chat-container').should('be.visible');
|
||||||
|
// });
|
||||||
|
});
|
5
test/automated/browser/cypress/fixtures/example.json
Normal file
5
test/automated/browser/cypress/fixtures/example.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Using fixtures to represent data",
|
||||||
|
"email": "hello@cypress.io",
|
||||||
|
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||||
|
}
|
25
test/automated/browser/cypress/support/commands.js
Normal file
25
test/automated/browser/cypress/support/commands.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// ***********************************************
|
||||||
|
// This example commands.js shows you how to
|
||||||
|
// create various custom commands and overwrite
|
||||||
|
// existing commands.
|
||||||
|
//
|
||||||
|
// For more comprehensive examples of custom
|
||||||
|
// commands please read more here:
|
||||||
|
// https://on.cypress.io/custom-commands
|
||||||
|
// ***********************************************
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a parent command --
|
||||||
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a child command --
|
||||||
|
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a dual command --
|
||||||
|
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This will overwrite an existing command --
|
||||||
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
20
test/automated/browser/cypress/support/e2e.js
Normal file
20
test/automated/browser/cypress/support/e2e.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// ***********************************************************
|
||||||
|
// This example support/e2e.js is processed and
|
||||||
|
// loaded automatically before your test files.
|
||||||
|
//
|
||||||
|
// This is a great place to put global configuration and
|
||||||
|
// behavior that modifies Cypress.
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off
|
||||||
|
// automatically serving support files with the
|
||||||
|
// 'supportFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/configuration
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// Import commands.js using ES2015 syntax:
|
||||||
|
import './commands'
|
||||||
|
|
||||||
|
// Alternatively you can use CommonJS syntax:
|
||||||
|
// require('./commands')
|
6
test/automated/browser/cypress/support/setup.js
Normal file
6
test/automated/browser/cypress/support/setup.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export function setup() {
|
||||||
|
Cypress.on(
|
||||||
|
'uncaught:exception',
|
||||||
|
(err) => !err.message.includes('ResizeObserver loop limit exceeded')
|
||||||
|
);
|
||||||
|
}
|
3177
test/automated/browser/package-lock.json
generated
Normal file
3177
test/automated/browser/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
test/automated/browser/package.json
Normal file
14
test/automated/browser/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "owncast-browser-tests",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"cypress": "^10.10.0"
|
||||||
|
}
|
||||||
|
}
|
67
test/automated/browser/run.sh
Executable file
67
test/automated/browser/run.sh
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
TEMP_DB=$(mktemp)
|
||||||
|
BUILD_ID=$((RANDOM % 7200 + 600))
|
||||||
|
|
||||||
|
# Change to the root directory of the repository
|
||||||
|
cd "$(git rev-parse --show-toplevel)"
|
||||||
|
|
||||||
|
# Bundle the updated web code into the server codebase.
|
||||||
|
echo "Bundling web code into server..."
|
||||||
|
./build/web/bundleWeb.sh >/dev/null
|
||||||
|
|
||||||
|
# Install the web test framework
|
||||||
|
echo "Installing test dependencies..."
|
||||||
|
pushd test/automated/browser
|
||||||
|
npm install --silent >/dev/null
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Download a specific version of ffmpeg
|
||||||
|
if [ ! -d "ffmpeg" ]; then
|
||||||
|
echo "Downloading ffmpeg..."
|
||||||
|
mkdir -p /tmp/ffmpeg
|
||||||
|
pushd /tmp/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
|
||||||
|
|
||||||
|
# Build and run owncast from source
|
||||||
|
echo "Building owncast..."
|
||||||
|
go build -o owncast main.go
|
||||||
|
echo "Running owncast..."
|
||||||
|
./owncast -database $TEMP_DB &
|
||||||
|
SERVER_PID=$!
|
||||||
|
|
||||||
|
pushd test/automated/browser
|
||||||
|
|
||||||
|
# Run cypress browser tests for desktop
|
||||||
|
npx cypress run --group "desktop-offline" --ci-build-id $BUILD_ID --tag "desktop,offline" --record --key e9c8b547-7a8f-452d-8c53-fd7531491e3b --spec "cypress/e2e/offline/*.cy.js"
|
||||||
|
# Run cypress browser tests for mobile
|
||||||
|
npx cypress run --group "mobile-offline" --ci-build-id $BUILD_ID --tag "mobile,offline" --record --key e9c8b547-7a8f-452d-8c53-fd7531491e3b --spec "cypress/e2e/offline/*.cy.js" --config viewportWidth=375,viewportHeight=667
|
||||||
|
|
||||||
|
# Start streaming the test file over RTMP to
|
||||||
|
# the local owncast instance.
|
||||||
|
echo "Waiting for stream to start..."
|
||||||
|
ffmpeg -hide_banner -loglevel panic -stream_loop -1 -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 &
|
||||||
|
STREAMING_CLIENT=$!
|
||||||
|
|
||||||
|
function finish {
|
||||||
|
echo "Cleaning up..."
|
||||||
|
rm $TEMP_DB
|
||||||
|
kill $SERVER_PID $STREAMING_CLIENT
|
||||||
|
}
|
||||||
|
trap finish EXIT SIGHUP SIGINT SIGTERM SIGQUIT SIGABRT SIGTERM
|
||||||
|
|
||||||
|
sleep 20
|
||||||
|
|
||||||
|
# Run cypress browser tests for desktop
|
||||||
|
npx cypress run --group "desktop-online" --ci-build-id $BUILD_ID --tag "desktop,online" --record --key e9c8b547-7a8f-452d-8c53-fd7531491e3b --spec "cypress/e2e/online/*.cy.js"
|
||||||
|
# Run cypress browser tests for mobile
|
||||||
|
npx cypress run --group "mobile-online" --ci-build-id $BUILD_ID --tag "mobile,online" --record --key e9c8b547-7a8f-452d-8c53-fd7531491e3b --spec "cypress/e2e/online/*.cy.js" --config viewportWidth=375,viewportHeight=667
|
@ -190,7 +190,7 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.chatContainer}>
|
<div id="chat-container" className={styles.chatContainer}>
|
||||||
{MessagesTable}
|
{MessagesTable}
|
||||||
{showInput && <ChatTextField />}
|
{showInput && <ChatTextField />}
|
||||||
</div>
|
</div>
|
||||||
|
@ -250,6 +250,7 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText }) => {
|
|||||||
>
|
>
|
||||||
<Slate editor={editor} value={defaultEditorValue}>
|
<Slate editor={editor} value={defaultEditorValue}>
|
||||||
<Editable
|
<Editable
|
||||||
|
className="chat-text-input"
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
onPaste={onPaste}
|
onPaste={onPaste}
|
||||||
renderElement={renderElement}
|
renderElement={renderElement}
|
||||||
|
@ -29,8 +29,8 @@ export const ContentHeader: FC<ContentHeaderProps> = ({
|
|||||||
<Logo src={logo} />
|
<Logo src={logo} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.titleSection}>
|
<div className={styles.titleSection}>
|
||||||
<div className={cn(styles.title, styles.row)}>{name}</div>
|
<div className={cn(styles.title, styles.row, 'header-title')}>{name}</div>
|
||||||
<div className={cn(styles.subtitle, styles.row)}>
|
<div className={cn(styles.subtitle, styles.row, 'header-subtitle')}>
|
||||||
<Linkify>{title || summary}</Linkify>
|
<Linkify>{title || summary}</Linkify>
|
||||||
</div>
|
</div>
|
||||||
<div className={cn(styles.tagList, styles.row)}>
|
<div className={cn(styles.tagList, styles.row)}>
|
||||||
|
@ -81,7 +81,7 @@ export const UserDropdown: FC<UserDropdownProps> = ({ username: defaultUsername
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.root}`}>
|
<div id="user-menu" className={`${styles.root}`}>
|
||||||
<Dropdown overlay={menu} trigger={['click']}>
|
<Dropdown overlay={menu} trigger={['click']}>
|
||||||
<Button type="primary" icon={<UserOutlined style={{ marginRight: '.5rem' }} />}>
|
<Button type="primary" icon={<UserOutlined style={{ marginRight: '.5rem' }} />}>
|
||||||
<Space>
|
<Space>
|
||||||
|
@ -57,6 +57,7 @@ export const NameChangeModal: FC = () => {
|
|||||||
Your chat display name is what people see when you send chat messages. Other information can
|
Your chat display name is what people see when you send chat messages. Other information can
|
||||||
go here to mention auth, and stuff.
|
go here to mention auth, and stuff.
|
||||||
<Input
|
<Input
|
||||||
|
id="name-change-field"
|
||||||
value={newName}
|
value={newName}
|
||||||
onChange={e => setNewName(e.target.value)}
|
onChange={e => setNewName(e.target.value)}
|
||||||
placeholder="Your chat display name"
|
placeholder="Your chat display name"
|
||||||
@ -64,7 +65,7 @@ export const NameChangeModal: FC = () => {
|
|||||||
showCount
|
showCount
|
||||||
defaultValue={displayName}
|
defaultValue={displayName}
|
||||||
/>
|
/>
|
||||||
<Button disabled={!saveEnabled} onClick={handleNameChange}>
|
<Button id="name-change-submit" disabled={!saveEnabled} onClick={handleNameChange}>
|
||||||
Change name
|
Change name
|
||||||
</Button>
|
</Button>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Layout, Tag, Tooltip } from 'antd';
|
import { Layout, Tag, Tooltip } from 'antd';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import cn from 'classnames';
|
||||||
import { UserDropdown } from '../../common/UserDropdown/UserDropdown';
|
import { UserDropdown } from '../../common/UserDropdown/UserDropdown';
|
||||||
import { OwncastLogo } from '../../common/OwncastLogo/OwncastLogo';
|
import { OwncastLogo } from '../../common/OwncastLogo/OwncastLogo';
|
||||||
import styles from './Header.module.scss';
|
import styles from './Header.module.scss';
|
||||||
@ -17,10 +18,10 @@ export const Header: FC<HeaderComponentProps> = ({
|
|||||||
chatAvailable,
|
chatAvailable,
|
||||||
chatDisabled,
|
chatDisabled,
|
||||||
}) => (
|
}) => (
|
||||||
<AntHeader className={`${styles.header}`}>
|
<AntHeader className={cn([`${styles.header}`], 'global-header')}>
|
||||||
<div className={`${styles.logo}`}>
|
<div className={`${styles.logo}`}>
|
||||||
<OwncastLogo variant="contrast" />
|
<OwncastLogo variant="contrast" />
|
||||||
<span>{name}</span>
|
<span className="global-header-text">{name}</span>
|
||||||
</div>
|
</div>
|
||||||
{chatAvailable && !chatDisabled && <UserDropdown />}
|
{chatAvailable && !chatDisabled && <UserDropdown />}
|
||||||
{!chatAvailable && !chatDisabled && (
|
{!chatAvailable && !chatDisabled && (
|
||||||
|
2398
web/package-lock.json
generated
2398
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -88,6 +88,7 @@
|
|||||||
"chromatic": "6.11.4",
|
"chromatic": "6.11.4",
|
||||||
"css-loader": "6.7.1",
|
"css-loader": "6.7.1",
|
||||||
"eslint": "8.26.0",
|
"eslint": "8.26.0",
|
||||||
|
"cypress": "^10.9.0",
|
||||||
"eslint-config-airbnb": "19.0.4",
|
"eslint-config-airbnb": "19.0.4",
|
||||||
"eslint-config-next": "13.0.1",
|
"eslint-config-next": "13.0.1",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user