Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c56d82a81 | ||
|
|
0fc2115973 |
@@ -5601,6 +5601,39 @@ var _activeTab = "main";
|
||||
function tabFromPath2(pathname = window.location.pathname) {
|
||||
return tabFromPath(pathname);
|
||||
}
|
||||
var pendingMapTarget = null;
|
||||
function applyMapTarget(target) {
|
||||
const map = window.trx.modules.map;
|
||||
if (!map) return false;
|
||||
if (target.kind === "position") {
|
||||
map.focusMapPosition?.(target.lat, target.lon);
|
||||
} else {
|
||||
map.focusMapLocator?.(target.grid, target.preferredType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function requestMapTarget(target) {
|
||||
pendingMapTarget = target;
|
||||
navigateToTab("map");
|
||||
if (window.trx.modules.map) {
|
||||
requestAnimationFrame(() => {
|
||||
drainPendingMapTarget();
|
||||
});
|
||||
}
|
||||
}
|
||||
function drainPendingMapTarget() {
|
||||
const target = pendingMapTarget;
|
||||
if (!target) return;
|
||||
if (applyMapTarget(target)) pendingMapTarget = null;
|
||||
}
|
||||
window.navigateToAprsMap = (lat, lon) => {
|
||||
if (!isFiniteNumber(lat) || !isFiniteNumber(lon)) return;
|
||||
requestMapTarget({ kind: "position", lat, lon });
|
||||
};
|
||||
window.navigateToMapLocator = (grid, preferredType = null) => {
|
||||
if (!grid) return;
|
||||
requestMapTarget({ kind: "locator", grid, preferredType });
|
||||
};
|
||||
var _mapInitTimer = null;
|
||||
function _initMapWhenReady() {
|
||||
const loadingEl2 = document.getElementById("map-loading");
|
||||
@@ -5617,6 +5650,7 @@ function _initMapWhenReady() {
|
||||
requestAnimationFrame(() => {
|
||||
map.sizeAprsMapToViewport();
|
||||
map.aprsMap?.invalidateSize();
|
||||
drainPendingMapTarget();
|
||||
});
|
||||
});
|
||||
return;
|
||||
@@ -6324,15 +6358,15 @@ function renderSdrSquelch() {
|
||||
}
|
||||
if (sdrSquelchDbEl) sdrSquelchDbEl.disabled = !sdrSquelchSupported;
|
||||
if (sdrSquelchToggleBtn) {
|
||||
sdrSquelchToggleBtn.textContent = sdrSquelchEnabled ? "On" : "Off";
|
||||
sdrSquelchToggleBtn.setAttribute("aria-pressed", String(sdrSquelchEnabled));
|
||||
sdrSquelchToggleBtn.title = sdrSquelchEnabled ? "Turn the squelch off" : "Turn the squelch on";
|
||||
}
|
||||
const state = !sdrSquelchEnabled ? "off" : sdrSquelchIsPassing() ? "open" : "closed";
|
||||
if (sdrSquelchStateEl) {
|
||||
sdrSquelchStateEl.dataset.state = state;
|
||||
sdrSquelchStateEl.setAttribute(
|
||||
sdrSquelchStateEl.parentElement?.setAttribute(
|
||||
"aria-label",
|
||||
state === "off" ? "Squelch off" : state === "open" ? "Squelch open" : "Squelch closed"
|
||||
state === "off" ? "Squelch off" : state === "open" ? "Squelch on, open" : "Squelch on, closed"
|
||||
);
|
||||
}
|
||||
if (squelchLabelEl) squelchLabelEl.textContent = String(sdrSquelchThresholdDb);
|
||||
|
||||
@@ -1669,16 +1669,7 @@ var mapWindow = window;
|
||||
popupAnchor: [0, -12]
|
||||
});
|
||||
}
|
||||
mapWindow.navigateToAprsMap = function(lat, lon) {
|
||||
T._activeTab = "map";
|
||||
document.querySelectorAll(".tab-bar .tab").forEach((t) => {
|
||||
t.classList.remove("active");
|
||||
});
|
||||
const mapTabBtn = document.querySelector(".tab-bar .tab[data-tab='map']");
|
||||
if (mapTabBtn) mapTabBtn.classList.add("active");
|
||||
document.querySelectorAll(".tab-panel").forEach((p) => p.style.display = "none");
|
||||
const mapPanel = mapEl("tab-map");
|
||||
if (mapPanel) mapPanel.style.display = "";
|
||||
function focusMapPosition(lat, lon) {
|
||||
initAprsMap();
|
||||
sizeAprsMapToViewport();
|
||||
if (aprsMap) {
|
||||
@@ -1690,19 +1681,10 @@ var mapWindow = window;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
mapWindow.navigateToMapLocator = function(grid, preferredType = null) {
|
||||
}
|
||||
function focusMapLocator(grid, preferredType = null) {
|
||||
const normalizedGrid = String(grid || "").trim().toUpperCase();
|
||||
if (!/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(normalizedGrid)) return false;
|
||||
T._activeTab = "map";
|
||||
document.querySelectorAll(".tab-bar .tab").forEach((t) => {
|
||||
t.classList.remove("active");
|
||||
});
|
||||
const mapTabBtn = document.querySelector(".tab-bar .tab[data-tab='map']");
|
||||
if (mapTabBtn) mapTabBtn.classList.add("active");
|
||||
document.querySelectorAll(".tab-panel").forEach((p) => p.style.display = "none");
|
||||
const mapPanel = mapEl("tab-map");
|
||||
if (mapPanel) mapPanel.style.display = "";
|
||||
initAprsMap();
|
||||
sizeAprsMapToViewport();
|
||||
if (!aprsMap) return false;
|
||||
@@ -1747,7 +1729,7 @@ var mapWindow = window;
|
||||
requestAnimationFrame(focusMarker);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
}
|
||||
function buildReceiverPopupHtml(rigIds) {
|
||||
const call = T.serverCallsign || T.ownerCallsign || "Receiver";
|
||||
let meta = "";
|
||||
@@ -2332,7 +2314,7 @@ var mapWindow = window;
|
||||
selectedMapQsoKey = selectedMapQsoKey === entry.pathKey ? null : entry.pathKey ?? null;
|
||||
syncDecodeContactPathVisibility();
|
||||
if (selectedMapQsoKey && entry.sourceGrid) {
|
||||
mapWindow.navigateToMapLocator?.(entry.sourceGrid, entry.sourceType);
|
||||
focusMapLocator(entry.sourceGrid, entry.sourceType);
|
||||
}
|
||||
});
|
||||
const head = document.createElement("div");
|
||||
@@ -2438,7 +2420,7 @@ var mapWindow = window;
|
||||
card.className = "map-qso-card";
|
||||
if (entry.grid) {
|
||||
card.addEventListener("click", () => {
|
||||
mapWindow.navigateToMapLocator?.(entry.grid ?? "", entry.sourceType);
|
||||
focusMapLocator(entry.grid ?? "", entry.sourceType);
|
||||
});
|
||||
}
|
||||
const head = document.createElement("div");
|
||||
@@ -2544,7 +2526,7 @@ var mapWindow = window;
|
||||
card.className = "map-qso-card";
|
||||
if (entry.grid) {
|
||||
card.addEventListener("click", () => {
|
||||
mapWindow.navigateToMapLocator?.(entry.grid ?? "", entry.sourceType);
|
||||
focusMapLocator(entry.grid ?? "", entry.sourceType);
|
||||
});
|
||||
}
|
||||
const head = document.createElement("div");
|
||||
@@ -3049,6 +3031,8 @@ var mapWindow = window;
|
||||
}
|
||||
modules.map = {
|
||||
initAprsMap,
|
||||
focusMapPosition,
|
||||
focusMapLocator,
|
||||
sizeAprsMapToViewport,
|
||||
syncAprsReceiverMarker,
|
||||
updateMapRigFilter,
|
||||
|
||||
@@ -416,11 +416,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<label class="vol-label">RX<input type="range" id="rx-vol" min="0" max="100" value="80" class="vol-slider" /><small class="vol-pct" id="rx-vol-pct">80%</small></label>
|
||||
<label class="vol-label">TX<input type="range" id="tx-vol" min="0" max="100" value="80" class="vol-slider" /><small class="vol-pct" id="tx-vol-pct">80%</small></label>
|
||||
<span class="sql-control" id="sdr-squelch-wrap" style="display:none;">
|
||||
<span class="sql-title">SQL</span>
|
||||
<span class="sql-state" id="sdr-squelch-state" data-state="off" role="img" aria-label="Squelch state"></span>
|
||||
<button id="sdr-squelch-toggle" type="button" class="sql-toggle" aria-pressed="false" title="Turn the squelch on or off"><span class="sql-state" id="sdr-squelch-state" data-state="off" aria-hidden="true"></span>SQL</button>
|
||||
<label class="sql-db"><input type="number" id="sdr-squelch-db" min="-120" max="-30" step="1" value="-95" inputmode="numeric" aria-label="Squelch threshold in dB" /><span class="sql-db-unit">dB</span></label>
|
||||
<button id="sdr-squelch-auto" type="button" class="sql-auto-btn" title="Set the threshold just above the noise floor">Auto</button>
|
||||
<button id="sdr-squelch-toggle" type="button" class="sql-auto-btn" aria-pressed="false" title="Enable or disable the squelch">Off</button>
|
||||
</span>
|
||||
<div id="audio-level">
|
||||
<div id="audio-level-fill"></div>
|
||||
|
||||
@@ -1856,9 +1856,32 @@ small { color: var(--text-muted); }
|
||||
font-size: 0.82rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.sql-title {
|
||||
/* The name is the switch: one target instead of a label and a button that
|
||||
said the same thing twice, with the dot carrying the state. */
|
||||
.sql-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
height: 1.5rem;
|
||||
min-height: 0;
|
||||
padding: 0 0.4rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.82rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.sql-toggle:hover {
|
||||
border-color: color-mix(in srgb, var(--border-light) 60%, transparent);
|
||||
color: var(--text);
|
||||
}
|
||||
.sql-toggle[aria-pressed="true"] {
|
||||
border-color: color-mix(in srgb, var(--accent-green) 50%, var(--border-light));
|
||||
background: color-mix(in srgb, var(--accent-green) 10%, transparent);
|
||||
color: var(--accent-text);
|
||||
}
|
||||
.sql-state {
|
||||
width: 0.5rem;
|
||||
|
||||
@@ -172,6 +172,8 @@ interface TrxModules {
|
||||
map?: {
|
||||
aprsMap?: { invalidateSize(): void } | null;
|
||||
initAprsMap(): void;
|
||||
focusMapPosition?(lat: number, lon: number): void;
|
||||
focusMapLocator?(grid: string, preferredType?: string | null): boolean;
|
||||
sizeAprsMapToViewport(): void;
|
||||
pruneMapHistory(): void;
|
||||
updateMapBaseLayerForTheme(theme: string): void;
|
||||
@@ -359,6 +361,10 @@ declare global {
|
||||
trx: { state: TrxState; core: Readonly<Record<string, unknown>>; modules: TrxModules };
|
||||
trxUi: TrxUi;
|
||||
trxPluginRuntime: TrxPluginRuntime;
|
||||
// Owned here, not by the lazy map module: decode rows link to the map long
|
||||
// before it has been loaded.
|
||||
navigateToAprsMap(lat: number, lon: number): void;
|
||||
navigateToMapLocator(grid: string, preferredType?: string | null): void;
|
||||
lastSpectrumData: SpectrumFrame | null;
|
||||
lastFreqHz: number | null;
|
||||
currentBandwidthHz: number;
|
||||
@@ -4611,6 +4617,54 @@ function tabFromPath(pathname = window.location.pathname) {
|
||||
return tabFromPathname(pathname);
|
||||
}
|
||||
|
||||
// Map links fire from decode rows — an AIS position, an APRS frame, an FT8
|
||||
// grid — that exist long before the Map tab has ever been opened, and the map
|
||||
// module is lazy. It used to install these two globals itself, so until
|
||||
// something had opened the tab the AIS links threw ("not a function") and the
|
||||
// APRS ones silently did nothing. The app owns them instead: it is the only
|
||||
// place that can materialise the panel, load the module and update history,
|
||||
// and the target waits here until the module is up.
|
||||
type PendingMapTarget =
|
||||
| { kind: "position"; lat: number; lon: number }
|
||||
| { kind: "locator"; grid: string; preferredType: string | null };
|
||||
let pendingMapTarget: PendingMapTarget | null = null;
|
||||
|
||||
function applyMapTarget(target: PendingMapTarget): boolean {
|
||||
const map = window.trx.modules.map;
|
||||
if (!map) return false;
|
||||
if (target.kind === "position") {
|
||||
map.focusMapPosition?.(target.lat, target.lon);
|
||||
} else {
|
||||
map.focusMapLocator?.(target.grid, target.preferredType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function requestMapTarget(target: PendingMapTarget) {
|
||||
pendingMapTarget = target;
|
||||
navigateToTab("map");
|
||||
// Already loaded: the tab switch has shown the panel, so focus can happen
|
||||
// now. Otherwise _initMapWhenReady drains it once the module arrives.
|
||||
if (window.trx.modules.map) {
|
||||
requestAnimationFrame(() => { drainPendingMapTarget(); });
|
||||
}
|
||||
}
|
||||
|
||||
function drainPendingMapTarget() {
|
||||
const target = pendingMapTarget;
|
||||
if (!target) return;
|
||||
if (applyMapTarget(target)) pendingMapTarget = null;
|
||||
}
|
||||
|
||||
window.navigateToAprsMap = (lat: number, lon: number) => {
|
||||
if (!isFiniteNumber(lat) || !isFiniteNumber(lon)) return;
|
||||
requestMapTarget({ kind: "position", lat, lon });
|
||||
};
|
||||
window.navigateToMapLocator = (grid: string, preferredType: string | null = null) => {
|
||||
if (!grid) return;
|
||||
requestMapTarget({ kind: "locator", grid, preferredType });
|
||||
};
|
||||
|
||||
// Initialise the Leaflet map, waiting for both Leaflet (L) and map-core.js
|
||||
// (window.trx.modules.map) if they haven't loaded yet.
|
||||
let _mapInitTimer: ReturnType<typeof setInterval> | null = null;
|
||||
@@ -4630,6 +4684,7 @@ function _initMapWhenReady() {
|
||||
requestAnimationFrame(() => {
|
||||
map.sizeAprsMapToViewport();
|
||||
map.aprsMap?.invalidateSize();
|
||||
drainPendingMapTarget();
|
||||
});
|
||||
});
|
||||
return;
|
||||
@@ -5288,15 +5343,15 @@ function renderSdrSquelch() {
|
||||
}
|
||||
if (sdrSquelchDbEl) sdrSquelchDbEl.disabled = !sdrSquelchSupported;
|
||||
if (sdrSquelchToggleBtn) {
|
||||
sdrSquelchToggleBtn.textContent = sdrSquelchEnabled ? "On" : "Off";
|
||||
sdrSquelchToggleBtn.setAttribute("aria-pressed", String(sdrSquelchEnabled));
|
||||
sdrSquelchToggleBtn.title = sdrSquelchEnabled ? "Turn the squelch off" : "Turn the squelch on";
|
||||
}
|
||||
const state = !sdrSquelchEnabled ? "off" : (sdrSquelchIsPassing() ? "open" : "closed");
|
||||
if (sdrSquelchStateEl) {
|
||||
sdrSquelchStateEl.dataset.state = state;
|
||||
sdrSquelchStateEl.setAttribute(
|
||||
sdrSquelchStateEl.parentElement?.setAttribute(
|
||||
"aria-label",
|
||||
state === "off" ? "Squelch off" : (state === "open" ? "Squelch open" : "Squelch closed"),
|
||||
state === "off" ? "Squelch off" : (state === "open" ? "Squelch on, open" : "Squelch on, closed"),
|
||||
);
|
||||
}
|
||||
if (squelchLabelEl) squelchLabelEl.textContent = String(sdrSquelchThresholdDb);
|
||||
|
||||
@@ -2016,15 +2016,7 @@ const mapWindow = window as unknown as MapWindow;
|
||||
});
|
||||
}
|
||||
|
||||
mapWindow.navigateToAprsMap = function(lat, lon) {
|
||||
// Activate the map tab
|
||||
T._activeTab = "map";
|
||||
document.querySelectorAll(".tab-bar .tab").forEach((t) => { t.classList.remove("active"); });
|
||||
const mapTabBtn = document.querySelector(".tab-bar .tab[data-tab='map']");
|
||||
if (mapTabBtn) mapTabBtn.classList.add("active");
|
||||
document.querySelectorAll<HTMLElement>(".tab-panel").forEach((p) => (p.style.display = "none"));
|
||||
const mapPanel = mapEl("tab-map");
|
||||
if (mapPanel) mapPanel.style.display = "";
|
||||
function focusMapPosition(lat: number, lon: number) {
|
||||
initAprsMap();
|
||||
sizeAprsMapToViewport();
|
||||
if (aprsMap) {
|
||||
@@ -2036,20 +2028,12 @@ const mapWindow = window as unknown as MapWindow;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mapWindow.navigateToMapLocator = function(grid, preferredType = null) {
|
||||
function focusMapLocator(grid: string, preferredType: string | null = null) {
|
||||
const normalizedGrid = String(grid || "").trim().toUpperCase();
|
||||
if (!/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(normalizedGrid)) return false;
|
||||
|
||||
T._activeTab = "map";
|
||||
document.querySelectorAll(".tab-bar .tab").forEach((t) => { t.classList.remove("active"); });
|
||||
const mapTabBtn = document.querySelector(".tab-bar .tab[data-tab='map']");
|
||||
if (mapTabBtn) mapTabBtn.classList.add("active");
|
||||
document.querySelectorAll<HTMLElement>(".tab-panel").forEach((p) => (p.style.display = "none"));
|
||||
const mapPanel = mapEl("tab-map");
|
||||
if (mapPanel) mapPanel.style.display = "";
|
||||
|
||||
initAprsMap();
|
||||
sizeAprsMapToViewport();
|
||||
if (!aprsMap) return false;
|
||||
@@ -2099,7 +2083,7 @@ const mapWindow = window as unknown as MapWindow;
|
||||
requestAnimationFrame(focusMarker);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2810,7 +2794,7 @@ const mapWindow = window as unknown as MapWindow;
|
||||
selectedMapQsoKey = selectedMapQsoKey === entry.pathKey ? null : entry.pathKey ?? null;
|
||||
syncDecodeContactPathVisibility();
|
||||
if (selectedMapQsoKey && entry.sourceGrid) {
|
||||
mapWindow.navigateToMapLocator?.(entry.sourceGrid, entry.sourceType);
|
||||
focusMapLocator(entry.sourceGrid, entry.sourceType);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2937,7 +2921,7 @@ const mapWindow = window as unknown as MapWindow;
|
||||
card.className = "map-qso-card";
|
||||
if (entry.grid) {
|
||||
card.addEventListener("click", () => {
|
||||
mapWindow.navigateToMapLocator?.(entry.grid ?? "", entry.sourceType);
|
||||
focusMapLocator(entry.grid ?? "", entry.sourceType);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3063,7 +3047,7 @@ const mapWindow = window as unknown as MapWindow;
|
||||
card.className = "map-qso-card";
|
||||
if (entry.grid) {
|
||||
card.addEventListener("click", () => {
|
||||
mapWindow.navigateToMapLocator?.(entry.grid ?? "", entry.sourceType);
|
||||
focusMapLocator(entry.grid ?? "", entry.sourceType);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3627,6 +3611,8 @@ const mapWindow = window as unknown as MapWindow;
|
||||
// Register module API for core to call
|
||||
modules.map = {
|
||||
initAprsMap,
|
||||
focusMapPosition,
|
||||
focusMapLocator,
|
||||
sizeAprsMapToViewport,
|
||||
syncAprsReceiverMarker,
|
||||
updateMapRigFilter,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { chromium } from "playwright-core";
|
||||
import { startBrowser, startWebFixture } from "./web-fixture.mjs";
|
||||
|
||||
// page.evaluate callbacks run in the browser, not in this Node process.
|
||||
/* global document, getComputedStyle */
|
||||
/* global document, getComputedStyle, window, location */
|
||||
|
||||
const fixture = await startWebFixture();
|
||||
const { selectedRigs } = fixture;
|
||||
@@ -23,6 +23,33 @@ try {
|
||||
await page.locator("summary", { hasText: "Audio controls" }).click();
|
||||
assert.equal(await page.locator("#rx-audio-btn").count(), 1);
|
||||
|
||||
// Map links from decode rows, before anything has opened the Map tab. The
|
||||
// lazy map module used to install these globals itself, so an AIS pin threw
|
||||
// "not a function" and an APRS link silently did nothing until the tab had
|
||||
// been visited once.
|
||||
const mapLinkReady = await page.evaluate(() => ({
|
||||
position: typeof window.navigateToAprsMap,
|
||||
locator: typeof window.navigateToMapLocator,
|
||||
mapModuleLoaded: !!window.trx.modules.map,
|
||||
}));
|
||||
assert.equal(mapLinkReady.position, "function", "navigateToAprsMap is missing before the map loads");
|
||||
assert.equal(mapLinkReady.locator, "function", "navigateToMapLocator is missing before the map loads");
|
||||
assert.equal(mapLinkReady.mapModuleLoaded, false, "the map module was already loaded, so this proves nothing");
|
||||
|
||||
await page.evaluate(() => { window.navigateToAprsMap(52.2, 21.0); });
|
||||
await page.locator("#aprs-map .leaflet-pane").first().waitFor({ state: "attached" });
|
||||
await page.waitForTimeout(500);
|
||||
const followed = await page.evaluate(() => ({
|
||||
path: location.pathname,
|
||||
active: [...document.querySelectorAll(".tab-bar .tab.active")].map((tab) => tab.dataset.tab || tab.id),
|
||||
mapHeight: Math.round(document.getElementById("aprs-map").getBoundingClientRect().height),
|
||||
}));
|
||||
assert.equal(followed.path, "/map", `the map link left the page on ${followed.path}`);
|
||||
assert.ok(followed.active.includes("map"), `the strip marks ${JSON.stringify(followed.active)}`);
|
||||
assert.ok(followed.mapHeight > 100, `the map came up ${followed.mapHeight}px tall`);
|
||||
await page.locator('.tab[data-tab="main"]').click();
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Section order in the tray. "Advanced radio controls" is built at runtime,
|
||||
// so it lands wherever ui-core puts it rather than where the markup says —
|
||||
// appending, as it once did, always left it last.
|
||||
|
||||
@@ -144,12 +144,12 @@ try {
|
||||
shown: getComputedStyle(line).display !== "none",
|
||||
db: Number(document.getElementById("sdr-squelch-db").value),
|
||||
label: Number(document.getElementById("spectrum-squelch-label").textContent),
|
||||
toggle: document.getElementById("sdr-squelch-toggle").textContent,
|
||||
toggle: document.getElementById("sdr-squelch-toggle").getAttribute("aria-pressed"),
|
||||
top: Math.round(line.getBoundingClientRect().top),
|
||||
};
|
||||
});
|
||||
assert.equal(squelchOn.shown, true, "the threshold line did not appear with the squelch on");
|
||||
assert.equal(squelchOn.toggle, "On", "the toggle did not follow the squelch state");
|
||||
assert.equal(squelchOn.toggle, "true", "the SQL switch did not follow the squelch state");
|
||||
assert.equal(squelchOn.label, squelchOn.db, "the line and the readout disagree on the threshold");
|
||||
|
||||
// Dragging the line down lowers the threshold and tells the server.
|
||||
|
||||
Reference in New Issue
Block a user