From 1cf3e9b6ef362e1657ede4131a7f5ad90ce7d674 Mon Sep 17 00:00:00 2001 From: Peter Feerick <5500713+pfeerick@users.noreply.github.com> Date: Mon, 27 Jul 2026 09:59:34 +1000 Subject: [PATCH 1/2] feat: reorder firmware tabs and rename Cloud to GitHub CloudBuild is now the first and default tab, followed by Local File and GitHub (renamed from Cloud, since it pulls releases from GitHub). Also fixes the Copy URL deep link to always specify source=releases, since it previously relied on releases being the implicit default tab. --- .../firmware-selection.spec.ts | 7 +++- .../firmware-wizard/flash-firmware.spec.ts | 1 + locales/be/flashing.json | 1 - locales/cs/flashing.json | 1 - locales/da/flashing.json | 1 - locales/de/flashing.json | 1 - locales/es/flashing.json | 1 - locales/fr/flashing.json | 1 - locales/it/flashing.json | 1 - locales/ru/flashing.json | 1 - locales/sv/flashing.json | 1 - locales/uk/flashing.json | 1 - locales/zh/flashing.json | 1 - .../components/firmware/CopyUrlButton.tsx | 2 +- .../firmware/__tests__/CopyUrlButton.spec.tsx | 4 +- .../flash/__tests__/FlashingWizard.spec.tsx | 34 +++++++-------- .../flash/steps/FirmwareSelectionStep.tsx | 42 +++++++++---------- 17 files changed, 47 insertions(+), 54 deletions(-) diff --git a/e2e/pages/firmware-wizard/firmware-selection.spec.ts b/e2e/pages/firmware-wizard/firmware-selection.spec.ts index fbf57713..2a805454 100644 --- a/e2e/pages/firmware-wizard/firmware-selection.spec.ts +++ b/e2e/pages/firmware-wizard/firmware-selection.spec.ts @@ -9,6 +9,7 @@ test.beforeEach(async ({ queries }) => { await ( await queries.findByText("Radio firmware", undefined, { timeout: 10000 }) ).click(); + await (await queries.findByRole("tab", { name: "GitHub" })).click(); }); test("Latest firmware is pre selected by default", async ({ @@ -181,9 +182,11 @@ test("Copy URL button copies a link to the selected firmware", async ({ if (isElectron) { expect(copiedUrl).toBe( - "buddy.edgetx.org/#/flash?version=v2.10.6&target=x10" + "buddy.edgetx.org/#/flash?source=releases&version=v2.10.6&target=x10" ); } else { - expect(copiedUrl).toBe("localhost:8081/#/flash?version=v2.10.6&target=x10"); + expect(copiedUrl).toBe( + "localhost:8081/#/flash?source=releases&version=v2.10.6&target=x10" + ); } }); diff --git a/e2e/pages/firmware-wizard/flash-firmware.spec.ts b/e2e/pages/firmware-wizard/flash-firmware.spec.ts index cefbbbd6..adb97a76 100644 --- a/e2e/pages/firmware-wizard/flash-firmware.spec.ts +++ b/e2e/pages/firmware-wizard/flash-firmware.spec.ts @@ -4,6 +4,7 @@ test.beforeEach(async ({ queries }) => { await ( await queries.findByText("Radio firmware", undefined, { timeout: 10000 }) ).click(); + await (await queries.findByRole("tab", { name: "GitHub" })).click(); }); test.describe.parallel("Flashing", () => { diff --git a/locales/be/flashing.json b/locales/be/flashing.json index 755b3f52..93476dab 100644 --- a/locales/be/flashing.json +++ b/locales/be/flashing.json @@ -14,7 +14,6 @@ "Built": "Built", "Cancel": "Адмяніць", "Click here to select firmware file, or drag it here to upload.": "Націсніце тут, каб абраць файл прашыўкі, або перацягнiце яго сюды , каб загрузіць.", - "Cloud": "Воблака", "Cloudbuild download": "Cloudbuild download", "Connect": "Падлучыць", "Connect radio": "Падлучыць радыё", diff --git a/locales/cs/flashing.json b/locales/cs/flashing.json index 0202db9d..794066b1 100644 --- a/locales/cs/flashing.json +++ b/locales/cs/flashing.json @@ -14,7 +14,6 @@ "Built": "Sestaveno", "Cancel": "Zrušit", "Click here to select firmware file, or drag it here to upload.": "Vyberte firmware nebo ho sem přetáhňete", - "Cloud": "Cloud", "Cloudbuild download": "Cloudbuild download", "Connect": "Připojit", "Connect radio": "Připojit rádio", diff --git a/locales/da/flashing.json b/locales/da/flashing.json index 46be193c..026d2c3f 100755 --- a/locales/da/flashing.json +++ b/locales/da/flashing.json @@ -14,7 +14,6 @@ "Built": "Bygget", "Cancel": "Afbryd", "Click here to select firmware file, or drag it here to upload.": "Klik her for at vælge firmware fil, eller træk hertil for at hente fil.", - "Cloud": "Sky/Cloud", "Cloudbuild download": "Hent byg i Cloud", "Connect": "Forbind", "Connect radio": "Forbind radio", diff --git a/locales/de/flashing.json b/locales/de/flashing.json index ba500e8b..bbddb461 100644 --- a/locales/de/flashing.json +++ b/locales/de/flashing.json @@ -14,7 +14,6 @@ "Built": "Gebaut", "Cancel": "Abbrechen", "Click here to select firmware file, or drag it here to upload.": "Klicken Sie hier, um die Firmware-Datei auszuwählen, oder ziehen Sie sie zum Hochladen hierher.", - "Cloud": "Cloud", "Cloudbuild download": "Cloudbuild download", "Connect": "Anschließen", "Connect radio": "Sender anschließen", diff --git a/locales/es/flashing.json b/locales/es/flashing.json index e81c6603..3e16c582 100644 --- a/locales/es/flashing.json +++ b/locales/es/flashing.json @@ -14,7 +14,6 @@ "Built": "Built", "Cancel": "Cancel", "Click here to select firmware file, or drag it here to upload.": "Click here to select firmware file, or drag it here to upload.", - "Cloud": "Cloud", "Cloudbuild download": "Cloudbuild download", "Connect": "Connect", "Connect radio": "Connect radio", diff --git a/locales/fr/flashing.json b/locales/fr/flashing.json index 3b3fd224..1867ec56 100644 --- a/locales/fr/flashing.json +++ b/locales/fr/flashing.json @@ -14,7 +14,6 @@ "Built": "Built", "Cancel": "Cancel", "Click here to select firmware file, or drag it here to upload.": "Click here to select firmware file, or drag it here to upload.", - "Cloud": "Cloud", "Cloudbuild download": "Cloudbuild download", "Connect": "Connect", "Connect radio": "Connect radio", diff --git a/locales/it/flashing.json b/locales/it/flashing.json index 83532afd..9d30623e 100644 --- a/locales/it/flashing.json +++ b/locales/it/flashing.json @@ -14,7 +14,6 @@ "Built": "Compilato", "Cancel": "Cancella", "Click here to select firmware file, or drag it here to upload.": "Clicca qui per selezionare il file del firmware, o trascinalo qui per caricarlo.", - "Cloud": "Cloud", "Cloudbuild download": "Cloudbuild download", "Connect": "Connetti", "Connect radio": "Connetti la radio", diff --git a/locales/ru/flashing.json b/locales/ru/flashing.json index 53a56e89..179782dc 100644 --- a/locales/ru/flashing.json +++ b/locales/ru/flashing.json @@ -14,7 +14,6 @@ "Built": "Built", "Cancel": "Отменить", "Click here to select firmware file, or drag it here to upload.": "Нажмите здесь, чтобы выбрать файл прошивки, или перетащите его сюда, чтобы загрузить.", - "Cloud": "Облако", "Cloudbuild download": "Cloudbuild download", "Connect": "Подключить", "Connect radio": "Подключить радио", diff --git a/locales/sv/flashing.json b/locales/sv/flashing.json index 52a15488..d8eadbcf 100644 --- a/locales/sv/flashing.json +++ b/locales/sv/flashing.json @@ -14,7 +14,6 @@ "Built": "Byggt", "Cancel": "Avbryt", "Click here to select firmware file, or drag it here to upload.": "Klicka här för att välja firmwarefil, eller dra filen hit för att ladda upp den.", - "Cloud": "Moln/Cloud", "Cloudbuild download": "Cloudbuild download", "Connect": "Anslut", "Connect radio": "Anslut radio", diff --git a/locales/uk/flashing.json b/locales/uk/flashing.json index 2adcca97..8abbf585 100644 --- a/locales/uk/flashing.json +++ b/locales/uk/flashing.json @@ -14,7 +14,6 @@ "Built": "Зібрано", "Cancel": "Скасувати", "Click here to select firmware file, or drag it here to upload.": "Клацніть тут для вибору файлу прошивки, або перетягніть його в це поле.", - "Cloud": "Хмара", "Cloudbuild download": "Cloudbuild download", "Connect": "Під'єднання", "Connect radio": "Під'єднання до радіо", diff --git a/locales/zh/flashing.json b/locales/zh/flashing.json index b6eaeb26..91704a03 100644 --- a/locales/zh/flashing.json +++ b/locales/zh/flashing.json @@ -14,7 +14,6 @@ "Built": "编译好了", "Cancel": "取消", "Click here to select firmware file, or drag it here to upload.": "单击此处选择固件文件,或将其拖动到这里来上传。", - "Cloud": "云端", "Cloudbuild download": "云编译下载", "Connect": "连接", "Connect radio": "连接遥控器", diff --git a/src/renderer/components/firmware/CopyUrlButton.tsx b/src/renderer/components/firmware/CopyUrlButton.tsx index 2e47de29..2e83c6e9 100644 --- a/src/renderer/components/firmware/CopyUrlButton.tsx +++ b/src/renderer/components/firmware/CopyUrlButton.tsx @@ -43,7 +43,7 @@ const CopyUrlButton: React.FC = ({ version, target }) => { environment.isElectron ? "buddy.edgetx.org" : window.location.host - }/#${location.pathname}?version=${version}${ + }/#${location.pathname}?source=releases&version=${version}${ target ? `&target=${target}` : "" }` ); diff --git a/src/renderer/components/firmware/__tests__/CopyUrlButton.spec.tsx b/src/renderer/components/firmware/__tests__/CopyUrlButton.spec.tsx index 62d41aad..8e170903 100644 --- a/src/renderer/components/firmware/__tests__/CopyUrlButton.spec.tsx +++ b/src/renderer/components/firmware/__tests__/CopyUrlButton.spec.tsx @@ -23,7 +23,7 @@ describe("CopyUrlButton", () => { fireEvent.click(screen.getByText("Copy URL")); expect(copyMock).toHaveBeenCalledWith( - "localhost:3000/#/current-page?version=v2.7.0&target=nv14" + "localhost:3000/#/current-page?source=releases&version=v2.7.0&target=nv14" ); }); @@ -37,7 +37,7 @@ describe("CopyUrlButton", () => { fireEvent.click(screen.getByText("Copy URL")); expect(copyMock).toHaveBeenCalledWith( - "localhost:3000/#/current-page?version=v2.7.0" + "localhost:3000/#/current-page?source=releases&version=v2.7.0" ); }); diff --git a/src/renderer/pages/flash/__tests__/FlashingWizard.spec.tsx b/src/renderer/pages/flash/__tests__/FlashingWizard.spec.tsx index f604690a..2465521b 100644 --- a/src/renderer/pages/flash/__tests__/FlashingWizard.spec.tsx +++ b/src/renderer/pages/flash/__tests__/FlashingWizard.spec.tsx @@ -41,7 +41,15 @@ describe("pages/FlashingWizard", () => { expect(stepIndicator).toHaveTextContent("Select a firmware"); }); - describe("Cloud firmware", () => { + it("should default to the CloudBuild tab", () => { + renderPage(); + + expect(screen.getByRole("tab", { selected: true })).toHaveTextContent( + "CloudBuild" + ); + }); + + describe("GitHub firmware", () => { const releases = exampleReleasesList.filter( (release) => !release.isPrerelease )!; @@ -50,28 +58,20 @@ describe("pages/FlashingWizard", () => { (release) => release.isPrerelease )!; - it("should be the default selected tab", () => { - renderPage(); - - expect(screen.getByRole("tab", { selected: true })).toHaveTextContent( - "Cloud" - ); - }); - it("should auto select the latest available firmware", async () => { - renderPage(); + renderPage("/?source=releases"); expect( await screen.findByText(latestReleaseVersion.name) ).toBeVisible(); fireEvent.click(screen.getByText("Copy URL")); expect(copyMock).toHaveBeenCalledWith( - `localhost:3000/#/?version=${latestReleaseVersion.id}` + `localhost:3000/#/?source=releases&version=${latestReleaseVersion.id}` ); }); it("should render all releases and targets, and allow release and target to be selected", async () => { - renderPage(); + renderPage("/?source=releases"); const versionDropdown = screen.getByLabelText("Firmware version"); await waitFor(() => expect(versionDropdown).toBeEnabled()); @@ -128,12 +128,12 @@ describe("pages/FlashingWizard", () => { fireEvent.click(screen.getByText("Copy URL")); expect(copyMock).toHaveBeenCalledWith( - `localhost:3000/#/?version=${latestReleaseVersion.id}&target=${target.code}` + `localhost:3000/#/?source=releases&version=${latestReleaseVersion.id}&target=${target.code}` ); }); it("should allow prerelease to be selected if filter is enabled", async () => { - renderPage(); + renderPage("/?source=releases"); const filtersDropdown = screen.getByText("Filters"); @@ -166,7 +166,7 @@ describe("pages/FlashingWizard", () => { fireEvent.click(screen.getByText("Copy URL")); expect(copyMock).toHaveBeenCalledWith( - `localhost:3000/#/?version=${preRelease.id}` + `localhost:3000/#/?source=releases&version=${preRelease.id}` ); }); @@ -174,7 +174,7 @@ describe("pages/FlashingWizard", () => { const target = exampleTargetsList[3]!; renderPage( - `/?version=${latestReleaseVersion.id}&target=${target.code}` + `/?version=${latestReleaseVersion.id}&target=${target.code}&source=releases` ); expect( @@ -197,7 +197,7 @@ describe("pages/FlashingWizard", () => { it("should pre select the pre release version based off the URL", async () => { const release = preReleases[2]!; - renderPage(`/?version=${release.id}`); + renderPage(`/?version=${release.id}&source=releases`); expect( await screen.findByText(release.name, { diff --git a/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx b/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx index f749e759..f0d64b3d 100644 --- a/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx +++ b/src/renderer/pages/flash/steps/FirmwareSelectionStep.tsx @@ -80,7 +80,7 @@ const FirmwareStep: StepComponent = ({ onNext }) => { !!target && (selectedFlags?.every((flag) => flag.name && flag.value) ?? true); - const [activeTab, setActiveTab] = useState(source ?? "releases"); + const [activeTab, setActiveTab] = useState(source ?? "cloudbuild"); useEffect(() => { if (version === "local" && activeTab !== "file") { @@ -127,27 +127,29 @@ const FirmwareStep: StepComponent = ({ onNext }) => { tab={ - {t(`Cloud`)} + CloudBuild } - key="releases" + key="cloudbuild" + style={{ overflowY: "auto" }} > - { - if (activeTab === "releases") { + if (activeTab === "cloudbuild") { updateParams({ - ...params, - source: activeTab, + source: "cloudbuild", + version: params.version, + target: params.target, + selectedFlags: encodeFlags(params.selectedFlags), filters: encodeFilters(params.filters), }); } }} /> - - , { tab={ - CloudBuild + GitHub } - key="cloudbuild" - style={{ overflowY: "auto" }} + key="releases" > - { - if (activeTab === "cloudbuild") { + if (activeTab === "releases") { updateParams({ - source: "cloudbuild", - version: params.version, - target: params.target, - selectedFlags: encodeFlags(params.selectedFlags), + ...params, + source: activeTab, filters: encodeFilters(params.filters), }); } }} /> + + From 0b816159dd797fae1fd24980f229faf96d0b960b Mon Sep 17 00:00:00 2001 From: Peter Feerick <5500713+pfeerick@users.noreply.github.com> Date: Mon, 27 Jul 2026 10:35:36 +1000 Subject: [PATCH 2/2] test(e2e): fix GitHub tab selection in firmware wizard specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The findByRole("tab") query fails with the @testing-library/dom v7 bundle injected by @playwright-testing-library 4.0.1 — it cannot match antd's role=tab elements even with a 10s wait, breaking every firmware-wizard e2e test in CI. Use a Playwright locator click instead, matching the CSS-selector patterns already used in these specs. --- e2e/pages/firmware-wizard/firmware-selection.spec.ts | 4 ++-- e2e/pages/firmware-wizard/flash-firmware.spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/pages/firmware-wizard/firmware-selection.spec.ts b/e2e/pages/firmware-wizard/firmware-selection.spec.ts index 2a805454..43d10022 100644 --- a/e2e/pages/firmware-wizard/firmware-selection.spec.ts +++ b/e2e/pages/firmware-wizard/firmware-selection.spec.ts @@ -5,11 +5,11 @@ import fs from "fs/promises"; import path from "path"; import { test, expect, waitFor } from "../pageTest"; -test.beforeEach(async ({ queries }) => { +test.beforeEach(async ({ queries, page }) => { await ( await queries.findByText("Radio firmware", undefined, { timeout: 10000 }) ).click(); - await (await queries.findByRole("tab", { name: "GitHub" })).click(); + await page.click('.ant-tabs-tab:has-text("GitHub")'); }); test("Latest firmware is pre selected by default", async ({ diff --git a/e2e/pages/firmware-wizard/flash-firmware.spec.ts b/e2e/pages/firmware-wizard/flash-firmware.spec.ts index adb97a76..d37a19ac 100644 --- a/e2e/pages/firmware-wizard/flash-firmware.spec.ts +++ b/e2e/pages/firmware-wizard/flash-firmware.spec.ts @@ -1,10 +1,10 @@ import { test, expect } from "../pageTest"; -test.beforeEach(async ({ queries }) => { +test.beforeEach(async ({ queries, page }) => { await ( await queries.findByText("Radio firmware", undefined, { timeout: 10000 }) ).click(); - await (await queries.findByRole("tab", { name: "GitHub" })).click(); + await page.click('.ant-tabs-tab:has-text("GitHub")'); }); test.describe.parallel("Flashing", () => {