Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/common/static/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ import { authentication } from "@modular-rest/client";

export const VERSION = require("../../../package.json").version;

/**
* Installed-extension version for display. Prefers manifest `version_name`
* (carries the full semver incl. prerelease channel, e.g. "1.15.1-dev.1") and
* falls back to the numeric manifest `version` on stable builds. Outside an
* extension context (unit tests / non-chrome), falls back to the package.json
* VERSION constant β€” the Vitest chrome shim doesn't implement getManifest.
*/
export function getExtensionVersion(): string {
try {
const manifest = chrome.runtime.getManifest();
return manifest.version_name || manifest.version;
} catch {
return VERSION;
}
}

export const SUBTURTLE_DASHBOARD_URL = process.env.SUBTURTLE_DASHBOARD_URL;

export function getSubturtleDashboardUrlWithToken(redirectPath?: string) {
Expand Down
13 changes: 12 additions & 1 deletion src/popup/views/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,13 @@
</span>
</router-link>
</div>

<!-- Extension version -->
<div
class="text-center text-xs text-gray-400 dark:text-gray-500 select-text"
>
v{{ appVersion }}
</div>
</div>
</div>
</transition>
Expand All @@ -293,7 +300,10 @@ import { computed, onMounted, ref, watch } from "vue";
import { getAsset } from "../helper/assets";
import { isLogin, logout } from "../../plugins/modular-rest";
import { useRouter } from "vue-router";
import { getSubturtleDashboardUrlWithToken } from "../../common/static/global";
import {
getSubturtleDashboardUrlWithToken,
getExtensionVersion,
} from "../../common/static/global";
import { useSettingsStore } from "../../common/store/settings";
import TranslateCard from "../components/TranslateCard.vue";

Expand All @@ -304,6 +314,7 @@ defineOptions({ name: "HomeView" });
const router = useRouter();
const isLoading = ref(false);
const showLogoutConfirm = ref(false);
const appVersion = getExtensionVersion();

const settings = useSettingsStore();
const currentHost = ref<string>("");
Expand Down
34 changes: 34 additions & 0 deletions tests/global-version.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, it, expect, afterEach } from "vitest";
import { getExtensionVersion, VERSION } from "../src/common/static/global";

// getExtensionVersion drives the "vX.Y.Z" line shown in the popup Home footer.
// It must prefer the manifest's version_name (full semver incl. prerelease
// channel) over the numeric version, and degrade gracefully when there's no
// real extension runtime (the Vitest chrome shim has no getManifest).
describe("getExtensionVersion", () => {
const runtime = (globalThis as any).chrome.runtime;

afterEach(() => {
// The shim is shared across files β€” don't leak a getManifest into it.
delete runtime.getManifest;
});

it("prefers version_name when present (prerelease build)", () => {
runtime.getManifest = () => ({
version: "1.15.1.2",
version_name: "1.15.1-dev.2",
});
expect(getExtensionVersion()).toBe("1.15.1-dev.2");
});

it("falls back to numeric version on a stable build", () => {
runtime.getManifest = () => ({ version: "1.15.1" });
expect(getExtensionVersion()).toBe("1.15.1");
});

it("falls back to the package.json VERSION outside an extension context", () => {
// No getManifest on the shim β†’ call throws β†’ catch returns VERSION.
expect(runtime.getManifest).toBeUndefined();
expect(getExtensionVersion()).toBe(VERSION);
});
});
Loading