feat: reconcile WebAVP desktop parity and releases
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import unittest
|
||||
|
||||
from app import Handler, HOST
|
||||
|
||||
|
||||
class AppServerTests(unittest.TestCase):
|
||||
def test_server_defaults_to_loopback(self):
|
||||
self.assertEqual(HOST, "127.0.0.1")
|
||||
|
||||
def test_certificate_response_interpretation(self):
|
||||
cases = [
|
||||
(b"true", True),
|
||||
(b"false", False),
|
||||
(b'{"verified": false}', False),
|
||||
(b'{"isValid": true}', True),
|
||||
(b'{"unknown": true}', None),
|
||||
(b"", None),
|
||||
(b"not-json", None),
|
||||
]
|
||||
for body, expected in cases:
|
||||
with self.subTest(body=body):
|
||||
self.assertIs(Handler._interpret_verify_body(body), expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
|
||||
const targetUrl = process.env.WEBAVP_SMOKE_WEB_URL || 'http://127.0.0.1:5152/';
|
||||
let failed = false;
|
||||
|
||||
app.commandLine.appendSwitch('disable-gpu');
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
const win = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true, nodeIntegration: false, sandbox: true } });
|
||||
win.webContents.on('console-message', (_event, level, message) => {
|
||||
if (level >= 2) {
|
||||
failed = true;
|
||||
console.error(`[WebAVP] Browser console error: ${message}`);
|
||||
}
|
||||
});
|
||||
try {
|
||||
await win.loadURL(targetUrl);
|
||||
const result = await win.webContents.executeJavaScript(`(async () => {
|
||||
const deadline = Date.now() + 12000;
|
||||
while (!document.getElementById('releaseStatus')?.textContent && Date.now() < deadline) {
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
async function importCameraCount(count) {
|
||||
const input = document.getElementById('fileInput');
|
||||
const transfer = new DataTransfer();
|
||||
for (let index = 1; index <= count; index += 1) {
|
||||
transfer.items.add(new File(['x'], 'Camera' + index + '.mp4', { type: 'video/mp4' }));
|
||||
}
|
||||
Object.defineProperty(input, 'files', { value: transfer.files, configurable: true });
|
||||
input.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
const importDeadline = Date.now() + 5000;
|
||||
while (document.querySelectorAll('.cam-cell').length < count && Date.now() < importDeadline) {
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
}
|
||||
return [...document.querySelectorAll('.cam-cell')]
|
||||
.filter(cell => getComputedStyle(cell).display !== 'none').length;
|
||||
}
|
||||
|
||||
document.querySelector('[data-layout="2x2"]').click();
|
||||
const fixedVisible = await importCameraCount(5);
|
||||
document.getElementById('newSessionBtn').click();
|
||||
document.querySelector('[data-layout="auto"]').click();
|
||||
const autoVisible = await importCameraCount(17);
|
||||
|
||||
return ({
|
||||
title: document.title,
|
||||
hasUtils: !!window.WebAVPUtils,
|
||||
autoGrid16: window.WebAVPUtils?.getAutoGrid(16),
|
||||
releaseText: document.getElementById('releaseAction')?.textContent.trim(),
|
||||
releaseFallback: document.getElementById('releaseAction')?.href,
|
||||
releaseStatus: document.getElementById('releaseStatus')?.textContent,
|
||||
hasFourByFour: !!document.querySelector('[data-layout="4x4"]'),
|
||||
hasDewarp: /dewarp|fisheye/i.test(document.documentElement.textContent),
|
||||
fixedVisible,
|
||||
autoVisible
|
||||
});
|
||||
})()`);
|
||||
const passed = result.title === 'Alta Video Player'
|
||||
&& result.hasUtils
|
||||
&& result.autoGrid16?.cols === 4
|
||||
&& result.autoGrid16?.rows === 4
|
||||
&& result.releaseText === 'Download Desktop App'
|
||||
&& result.releaseFallback.startsWith('https://git.pejicorp.com/peji/WebAVP/releases')
|
||||
&& result.releaseStatus.length > 0
|
||||
&& result.hasFourByFour
|
||||
&& !result.hasDewarp
|
||||
&& result.fixedVisible === 4
|
||||
&& result.autoVisible === 16
|
||||
&& !failed;
|
||||
if (!passed) throw new Error(`Browser assertions failed: ${JSON.stringify(result)}`);
|
||||
console.log(`[WebAVP] Browser smoke passed at ${targetUrl}`);
|
||||
app.exit(0);
|
||||
} catch (err) {
|
||||
console.error(`[WebAVP] Browser smoke failed: ${err.message}`);
|
||||
app.exit(1);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const {
|
||||
compareVersions,
|
||||
evaluateUpdate,
|
||||
getAutoGrid,
|
||||
normalizeRelease,
|
||||
selectReleaseAsset,
|
||||
} = require('../static/webavp-utils.js');
|
||||
|
||||
assert.deepEqual(getAutoGrid(0), { cols: 1, rows: 1 });
|
||||
assert.deepEqual(getAutoGrid(1), { cols: 1, rows: 1 });
|
||||
assert.deepEqual(getAutoGrid(2), { cols: 2, rows: 1 });
|
||||
assert.deepEqual(getAutoGrid(4), { cols: 2, rows: 2 });
|
||||
assert.deepEqual(getAutoGrid(6), { cols: 3, rows: 2 });
|
||||
assert.deepEqual(getAutoGrid(9), { cols: 3, rows: 3 });
|
||||
assert.deepEqual(getAutoGrid(12), { cols: 4, rows: 3 });
|
||||
assert.deepEqual(getAutoGrid(16), { cols: 4, rows: 4 });
|
||||
assert.deepEqual(getAutoGrid(99), { cols: 4, rows: 4 });
|
||||
|
||||
assert.equal(compareVersions('v1.2.0', '1.1.9'), 1);
|
||||
assert.equal(compareVersions('1.2.0', '1.2.0'), 0);
|
||||
assert.equal(compareVersions('1.2.0-beta.1', '1.2.0'), -1);
|
||||
assert.equal(compareVersions('1.2.0+linux.1', '1.2.0+build.9'), 0);
|
||||
assert.equal(compareVersions('2.0', '1.99.99'), 1);
|
||||
assert.throws(() => compareVersions('latest', '1.0.0'), /version/i);
|
||||
|
||||
const rawRelease = {
|
||||
tag_name: 'v1.4.0',
|
||||
html_url: 'https://git.pejicorp.com/peji/WebAVP/releases/tag/v1.4.0',
|
||||
name: 'WebAVP 1.4.0',
|
||||
assets: [
|
||||
{ name: 'Alta Video Player-1.4.0-linux-x64.AppImage', browser_download_url: 'https://git.pejicorp.com/peji/WebAVP/releases/download/v1.4.0/linux.AppImage' },
|
||||
{ name: 'Alta Video Player-1.4.0-linux-x64.deb', browser_download_url: 'https://git.pejicorp.com/peji/WebAVP/releases/download/v1.4.0/linux.deb' },
|
||||
{ name: 'Alta Video Player-1.4.0-mac-arm64.dmg', browser_download_url: 'https://git.pejicorp.com/peji/WebAVP/releases/download/v1.4.0/mac-arm64.dmg' },
|
||||
{ name: 'Alta Video Player-1.4.0-mac-x64.dmg', browser_download_url: 'https://git.pejicorp.com/peji/WebAVP/releases/download/v1.4.0/mac-x64.dmg' },
|
||||
{ name: 'Alta Video Player-1.4.0-win-x64.exe', browser_download_url: 'https://git.pejicorp.com/peji/WebAVP/releases/download/v1.4.0/win.exe' },
|
||||
],
|
||||
};
|
||||
const release = normalizeRelease(rawRelease);
|
||||
assert.equal(release.version, '1.4.0');
|
||||
assert.equal(selectReleaseAsset(release, 'linux', 'x64').name.endsWith('.AppImage'), true);
|
||||
assert.equal(selectReleaseAsset(release, 'linux', 'arm64'), null);
|
||||
assert.equal(selectReleaseAsset(release, 'darwin', 'arm64').name.endsWith('.dmg'), true);
|
||||
assert.equal(selectReleaseAsset(release, 'win32', 'x64').name.endsWith('.exe'), true);
|
||||
assert.equal(selectReleaseAsset(release, 'win32', 'arm64'), null);
|
||||
assert.throws(() => normalizeRelease({ tag_name: 'v1.0.0', assets: [{ name: 'bad.exe', browser_download_url: 'https://evil.example/bad.exe' }] }), /asset/i);
|
||||
|
||||
assert.equal(evaluateUpdate(release, '1.4.0', 'linux', 'x64').status, 'current');
|
||||
assert.equal(evaluateUpdate(release, '1.3.9', 'linux', 'x64').status, 'available');
|
||||
assert.equal(evaluateUpdate(release, '1.3.9', 'linux', 'arm64').status, 'unavailable-platform');
|
||||
|
||||
console.log('[WebAVP] utility regression tests passed');
|
||||
Reference in New Issue
Block a user