fix: validate typed frontend startup in Chromium
This commit is contained in:
@@ -1590,7 +1590,7 @@ async function loadPlugins(group) {
|
|||||||
for (const path of pluginGroups[group]) await loadPlugin(path);
|
for (const path of pluginGroups[group]) await loadPlugin(path);
|
||||||
}
|
}
|
||||||
async function loadEagerPlugins() {
|
async function loadEagerPlugins() {
|
||||||
await Promise.all(["digital-modes", "map-data", "bookmarks", "settings"].map(loadPlugins));
|
await Promise.all(["digital-modes", "bookmarks", "settings"].map(loadPlugins));
|
||||||
}
|
}
|
||||||
async function loadPluginsForTab(tab) {
|
async function loadPluginsForTab(tab) {
|
||||||
await loadPlugins(tab);
|
await loadPlugins(tab);
|
||||||
@@ -1892,7 +1892,7 @@ var centerFreqEl = requiredElement("center-freq");
|
|||||||
var wavelengthEl = requiredElement("wavelength");
|
var wavelengthEl = requiredElement("wavelength");
|
||||||
var sigStrengthEl = requiredElement("sig-strength");
|
var sigStrengthEl = requiredElement("sig-strength");
|
||||||
var modeEl = requiredElement("mode");
|
var modeEl = requiredElement("mode");
|
||||||
var bandLabel = requiredElement("band-label");
|
var bandLabel = document.getElementById("band-label");
|
||||||
var powerBtn = requiredElement("power-btn");
|
var powerBtn = requiredElement("power-btn");
|
||||||
var powerHint = requiredElement("power-hint");
|
var powerHint = requiredElement("power-hint");
|
||||||
var vfoPicker = requiredElement("vfo-picker");
|
var vfoPicker = requiredElement("vfo-picker");
|
||||||
@@ -1912,7 +1912,7 @@ var loadingEl = requiredElement("loading");
|
|||||||
var contentEl = requiredElement("content");
|
var contentEl = requiredElement("content");
|
||||||
var serverSubtitle = requiredElement("server-subtitle");
|
var serverSubtitle = requiredElement("server-subtitle");
|
||||||
var rigSubtitle = requiredElement("rig-subtitle");
|
var rigSubtitle = requiredElement("rig-subtitle");
|
||||||
var ownerSubtitle = requiredElement("owner-subtitle");
|
var ownerSubtitle = document.getElementById("owner-subtitle");
|
||||||
var locationSubtitle = requiredElement("location-subtitle");
|
var locationSubtitle = requiredElement("location-subtitle");
|
||||||
var loadingTitle = requiredElement("loading-title");
|
var loadingTitle = requiredElement("loading-title");
|
||||||
var loadingSub = requiredElement("loading-sub");
|
var loadingSub = requiredElement("loading-sub");
|
||||||
@@ -2241,7 +2241,7 @@ function setTheme(theme) {
|
|||||||
invalidateBookmarkColors();
|
invalidateBookmarkColors();
|
||||||
}
|
}
|
||||||
function invalidateBookmarkColors() {
|
function invalidateBookmarkColors() {
|
||||||
const bookmarks = window.trx.modules.bookmarks;
|
const bookmarks = window.trx?.modules.bookmarks;
|
||||||
if (!bookmarks) return;
|
if (!bookmarks) return;
|
||||||
bookmarks.invalidateColors();
|
bookmarks.invalidateColors();
|
||||||
void getComputedStyle(document.documentElement).getPropertyValue("--bg");
|
void getComputedStyle(document.documentElement).getPropertyValue("--bg");
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ npm run verify-generated
|
|||||||
|
|
||||||
`npm run verify-generated` regenerates Rust wire contracts and browser bundles,
|
`npm run verify-generated` regenerates Rust wire contracts and browser bundles,
|
||||||
then rejects drift from the committed files. The browser smoke test needs a
|
then rejects drift from the committed files. The browser smoke test needs a
|
||||||
local Chromium-family executable; set `CHROMIUM_PATH` when it is not installed
|
local Chromium-family executable; set `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH`
|
||||||
at a conventional system path.
|
when it is not installed at `/usr/bin/chromium`.
|
||||||
|
|
||||||
Cargo consumes committed output under `../assets/web/generated`. It never
|
Cargo consumes committed output under `../assets/web/generated`. It never
|
||||||
invokes Node.js, installs packages, or accesses the network. After changing a
|
invokes Node.js, installs packages, or accesses the network. After changing a
|
||||||
|
|||||||
@@ -673,7 +673,7 @@ const centerFreqEl = requiredElement<HTMLInputElement>("center-freq");
|
|||||||
const wavelengthEl = requiredElement("wavelength");
|
const wavelengthEl = requiredElement("wavelength");
|
||||||
const sigStrengthEl = requiredElement("sig-strength");
|
const sigStrengthEl = requiredElement("sig-strength");
|
||||||
const modeEl = requiredElement<HTMLSelectElement>("mode");
|
const modeEl = requiredElement<HTMLSelectElement>("mode");
|
||||||
const bandLabel = requiredElement("band-label");
|
const bandLabel = document.getElementById("band-label");
|
||||||
const powerBtn = requiredElement<HTMLButtonElement>("power-btn");
|
const powerBtn = requiredElement<HTMLButtonElement>("power-btn");
|
||||||
const powerHint = requiredElement("power-hint");
|
const powerHint = requiredElement("power-hint");
|
||||||
const vfoPicker = requiredElement("vfo-picker");
|
const vfoPicker = requiredElement("vfo-picker");
|
||||||
@@ -693,7 +693,7 @@ const loadingEl = requiredElement("loading");
|
|||||||
const contentEl = requiredElement("content");
|
const contentEl = requiredElement("content");
|
||||||
const serverSubtitle = requiredElement("server-subtitle");
|
const serverSubtitle = requiredElement("server-subtitle");
|
||||||
const rigSubtitle = requiredElement("rig-subtitle");
|
const rigSubtitle = requiredElement("rig-subtitle");
|
||||||
const ownerSubtitle = requiredElement("owner-subtitle");
|
const ownerSubtitle = document.getElementById("owner-subtitle");
|
||||||
const locationSubtitle = requiredElement("location-subtitle");
|
const locationSubtitle = requiredElement("location-subtitle");
|
||||||
const loadingTitle = requiredElement("loading-title");
|
const loadingTitle = requiredElement("loading-title");
|
||||||
const loadingSub = requiredElement("loading-sub");
|
const loadingSub = requiredElement("loading-sub");
|
||||||
@@ -1063,7 +1063,7 @@ function setTheme(theme: string) {
|
|||||||
|
|
||||||
// Recolour bookmark chips after any palette/theme change (setTheme or setStyle).
|
// Recolour bookmark chips after any palette/theme change (setTheme or setStyle).
|
||||||
function invalidateBookmarkColors() {
|
function invalidateBookmarkColors() {
|
||||||
const bookmarks = window.trx.modules.bookmarks;
|
const bookmarks = window.trx?.modules.bookmarks;
|
||||||
if (!bookmarks) return;
|
if (!bookmarks) return;
|
||||||
bookmarks.invalidateColors();
|
bookmarks.invalidateColors();
|
||||||
// Force the browser to recalculate styles so getComputedStyle reads new values.
|
// Force the browser to recalculate styles so getComputedStyle reads new values.
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ async function loadPlugins(group: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadEagerPlugins(): Promise<void> {
|
export async function loadEagerPlugins(): Promise<void> {
|
||||||
await Promise.all(["digital-modes", "map-data", "bookmarks", "settings"].map(loadPlugins));
|
await Promise.all(["digital-modes", "bookmarks", "settings"].map(loadPlugins));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadPluginsForTab(tab: string): Promise<void> {
|
export async function loadPluginsForTab(tab: string): Promise<void> {
|
||||||
|
|||||||
@@ -17,6 +17,49 @@ const jsonRoutes = new Map([
|
|||||||
["/auth/session", { authenticated: true, role: "control", auth_disabled: true }],
|
["/auth/session", { authenticated: true, role: "control", auth_disabled: true }],
|
||||||
["/decoders", []],
|
["/decoders", []],
|
||||||
["/rigs", { rigs: [], active_remote: null }],
|
["/rigs", { rigs: [], active_remote: null }],
|
||||||
|
["/status", {
|
||||||
|
info: {
|
||||||
|
manufacturer: "Smoke",
|
||||||
|
model: "Fixture",
|
||||||
|
revision: "1",
|
||||||
|
access: { Tcp: { addr: "127.0.0.1:0" } },
|
||||||
|
capabilities: {
|
||||||
|
min_freq_step_hz: 1,
|
||||||
|
supported_bands: [],
|
||||||
|
supported_modes: ["FM"],
|
||||||
|
num_vfos: 1,
|
||||||
|
lock: false,
|
||||||
|
lockable: false,
|
||||||
|
attenuator: false,
|
||||||
|
preamp: false,
|
||||||
|
rit: false,
|
||||||
|
rpt: false,
|
||||||
|
split: false,
|
||||||
|
tx: false,
|
||||||
|
tx_limit: false,
|
||||||
|
vfo_switch: false,
|
||||||
|
filter_controls: false,
|
||||||
|
signal_meter: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: { freq: { hz: 100_000_000 }, mode: "FM", tx_en: false, vfo: null, tx: null, rx: null, lock: null },
|
||||||
|
band: null,
|
||||||
|
enabled: true,
|
||||||
|
initialized: true,
|
||||||
|
cw_auto: false,
|
||||||
|
cw_wpm: 20,
|
||||||
|
cw_tone_hz: 700,
|
||||||
|
aprs_decode_enabled: false,
|
||||||
|
hf_aprs_decode_enabled: false,
|
||||||
|
cw_decode_enabled: false,
|
||||||
|
ft8_decode_enabled: false,
|
||||||
|
ft4_decode_enabled: false,
|
||||||
|
ft2_decode_enabled: false,
|
||||||
|
wspr_decode_enabled: false,
|
||||||
|
lrpt_decode_enabled: false,
|
||||||
|
wefax_decode_enabled: false,
|
||||||
|
recorder_enabled: false,
|
||||||
|
}],
|
||||||
["/bandplan.json", {}],
|
["/bandplan.json", {}],
|
||||||
["/api/recorder/status", []],
|
["/api/recorder/status", []],
|
||||||
["/api/recorder/files", []],
|
["/api/recorder/files", []],
|
||||||
@@ -80,10 +123,12 @@ const executablePath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
|
|||||||
const browser = await chromium.launch({ executablePath, headless: true, args: ["--no-sandbox"] });
|
const browser = await chromium.launch({ executablePath, headless: true, args: ["--no-sandbox"] });
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
const runtimeErrors = [];
|
const runtimeErrors = [];
|
||||||
page.on("pageerror", (error) => runtimeErrors.push(error.message));
|
page.on("pageerror", (error) => runtimeErrors.push(error.stack ?? error.message));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await page.goto(`http://127.0.0.1:${address.port}/`, { waitUntil: "networkidle" });
|
await page.goto(`http://127.0.0.1:${address.port}/`, { waitUntil: "domcontentloaded" });
|
||||||
|
await page.waitForTimeout(500);
|
||||||
|
assert.deepEqual(runtimeErrors, []);
|
||||||
await page.locator("#content").waitFor({ state: "visible" });
|
await page.locator("#content").waitFor({ state: "visible" });
|
||||||
assert.equal(await page.locator("#auth-gate").isVisible(), false);
|
assert.equal(await page.locator("#auth-gate").isVisible(), false);
|
||||||
assert.equal(await page.locator("#tab-main").isVisible(), true);
|
assert.equal(await page.locator("#tab-main").isVisible(), true);
|
||||||
|
|||||||
Reference in New Issue
Block a user