mirror of
https://github.com/rommapp/romm.git
synced 2026-10-12 02:21:58 +00:00
Merge pull request #4863 from rommapp/chore/lint-rom-fixture-casts
chore(lint): ban double-cast ROM fixtures in tests
This commit is contained in:
@@ -213,6 +213,26 @@ export default tseslint.config(
|
||||
"romm/no-layout-media-query": "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/**/*.test.ts"],
|
||||
ignores: [
|
||||
"src/views/**",
|
||||
"src/components/**",
|
||||
"src/console/**",
|
||||
"src/layouts/**",
|
||||
],
|
||||
rules: {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector:
|
||||
"TSAsExpression[expression.type='TSAsExpression'][expression.typeAnnotation.type='TSUnknownKeyword'][typeAnnotation.typeName.name=/^(DetailedRom|SimpleRom)$/]",
|
||||
message:
|
||||
"Build ROM fixtures with makeRom or makeDetailedRom from @/utils/rom.fixtures instead of `as unknown as`.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
// Keep last: Prettier owns formatting, so this switches off every
|
||||
// stylistic rule the two tools would otherwise fight over.
|
||||
prettierConfig,
|
||||
|
||||
@@ -6,6 +6,7 @@ import router, { applyRouteTitle, ROUTES } from "@/plugins/router";
|
||||
import storeAuth from "@/stores/auth";
|
||||
import storeRoms, { type DetailedRom } from "@/stores/roms";
|
||||
import type { User } from "@/stores/users";
|
||||
import { makeDetailedRom } from "@/utils/rom.fixtures";
|
||||
|
||||
const { getRom, stubView } = vi.hoisted(() => ({
|
||||
getRom: vi.fn(),
|
||||
@@ -24,11 +25,7 @@ vi.mock("@/v2/layouts/AppLayout.vue", stubView);
|
||||
vi.mock("@/v2/views/GameDetails.vue", stubView);
|
||||
|
||||
function makeRom(overrides: Partial<DetailedRom> = {}): DetailedRom {
|
||||
return {
|
||||
id: 1,
|
||||
name: "Chrono Trigger",
|
||||
...overrides,
|
||||
} as unknown as DetailedRom;
|
||||
return makeDetailedRom({ name: "Chrono Trigger", ...overrides });
|
||||
}
|
||||
|
||||
describe("route titles", () => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
PlatformSupport,
|
||||
PlatformSupportQuery,
|
||||
} from "@/types/rommNative";
|
||||
import { makeRom as baseRom } from "@/utils/rom.fixtures";
|
||||
|
||||
const shellPresent = { value: true };
|
||||
const fetchPlatformSupport = vi.fn(
|
||||
@@ -74,8 +75,7 @@ vi.mock("@/utils", () => ({
|
||||
const { useNativeStore } = await import("@/stores/native");
|
||||
|
||||
function makeRom(overrides: Partial<SimpleRom> = {}): SimpleRom {
|
||||
return {
|
||||
id: 1,
|
||||
return baseRom({
|
||||
name: "Chrono Trigger",
|
||||
fs_name: "Chrono Trigger.sfc",
|
||||
fs_name_no_ext: "Chrono Trigger",
|
||||
@@ -84,9 +84,11 @@ function makeRom(overrides: Partial<SimpleRom> = {}): SimpleRom {
|
||||
platform_slug: "snes",
|
||||
has_file_on_disk: true,
|
||||
// As a single-rom endpoint answers. A gallery card passes `files: []`.
|
||||
files: [{ full_path: "snes/game.sfc", file_size_bytes: 4194304 }],
|
||||
files: [
|
||||
{ full_path: "snes/game.sfc", file_size_bytes: 4194304 },
|
||||
] as SimpleRom["files"],
|
||||
...overrides,
|
||||
} as unknown as SimpleRom;
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { flushPromises, mount } from "@vue/test-utils";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { defineComponent } from "vue";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { makeRom } from "@/utils/rom.fixtures";
|
||||
import AnniversaryWidget from "./AnniversaryWidget.vue";
|
||||
|
||||
const { getRoms } = vi.hoisted(() => ({ getRoms: vi.fn() }));
|
||||
@@ -58,15 +59,15 @@ function releasedOn(year: number, month: number, day: number): number {
|
||||
}
|
||||
|
||||
function rom(id: number, name: string, released: number): SimpleRom {
|
||||
return {
|
||||
return makeRom({
|
||||
id,
|
||||
name,
|
||||
fs_name: `${name}.sfc`,
|
||||
platform_slug: "snes",
|
||||
platform_display_name: "Super Nintendo",
|
||||
is_identified: true,
|
||||
metadatum: { first_release_date: released },
|
||||
} as unknown as SimpleRom;
|
||||
metadatum: { first_release_date: released } as SimpleRom["metadatum"],
|
||||
});
|
||||
}
|
||||
|
||||
/** A page of the shared rom list, as `getRoms` resolves it. */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { mount, type VueWrapper } from "@vue/test-utils";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { makeRom } from "@/utils/rom.fixtures";
|
||||
import PlayerShell from "./PlayerShell.vue";
|
||||
|
||||
const mocks = vi.hoisted(() => ({ setStageActive: vi.fn() }));
|
||||
@@ -21,7 +22,7 @@ vi.mock("@/v2/components/shared/GameCover.vue", () => ({
|
||||
default: { template: "<div class='game-cover' />" },
|
||||
}));
|
||||
|
||||
const heroRom = { id: 1, platform_id: 2 } as unknown as SimpleRom;
|
||||
const heroRom = makeRom({ id: 1, platform_id: 2 });
|
||||
|
||||
function mountShell(
|
||||
props: Partial<{
|
||||
@@ -106,7 +107,7 @@ describe("PlayerShell", () => {
|
||||
|
||||
it("disables the gallery link when the hero carries no platform", () => {
|
||||
const { toPlatform } = backLinks(
|
||||
mountShell({ heroRom: { id: 1 } as unknown as SimpleRom }),
|
||||
mountShell({ heroRom: makeRom({ id: 1 }) }),
|
||||
);
|
||||
|
||||
expect(toPlatform.props("to")).toBeUndefined();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { ref } from "vue";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { makeRom as baseRom } from "@/utils/rom.fixtures";
|
||||
import { useCanPlay } from "./index";
|
||||
|
||||
// Each engine's support check is stubbed so a test can enable one route at a
|
||||
@@ -49,13 +50,12 @@ vi.mock("@/utils", () => ({
|
||||
}));
|
||||
|
||||
function makeRom(overrides: Partial<SimpleRom> = {}): SimpleRom {
|
||||
return {
|
||||
id: 1,
|
||||
return baseRom({
|
||||
name: "Chrono Trigger",
|
||||
platform_slug: "snes",
|
||||
has_file_on_disk: true,
|
||||
...overrides,
|
||||
} as unknown as SimpleRom;
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ActionKey } from "@/__generated__";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { makeRom as baseRom } from "@/utils/rom.fixtures";
|
||||
import { useGameActions } from "./index";
|
||||
|
||||
// Controllable stubs shared with the mocked modules below.
|
||||
@@ -124,14 +125,13 @@ vi.mock("@/v2/composables/useViewTransition", () => ({
|
||||
}));
|
||||
|
||||
function makeRom(status: SimpleRom["rom_user"]["status"] = null): SimpleRom {
|
||||
return {
|
||||
id: 1,
|
||||
return baseRom({
|
||||
name: "Chrono Trigger",
|
||||
fs_name_no_ext: "Chrono Trigger",
|
||||
platform_slug: "snes",
|
||||
has_file_on_disk: true,
|
||||
rom_user: { status },
|
||||
} as unknown as SimpleRom;
|
||||
rom_user: { status } as SimpleRom["rom_user"],
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import playSessionApi from "@/services/api/play-session";
|
||||
import type { SimpleRom } from "@/stores/roms";
|
||||
import { makeRom as baseRom } from "@/utils/rom.fixtures";
|
||||
import { usePlaySession } from "./index";
|
||||
|
||||
vi.mock("@/services/api/play-session", () => ({
|
||||
@@ -21,7 +22,7 @@ vi.mock("@/stores/auth", () => ({
|
||||
const ingest = vi.mocked(playSessionApi.ingestPlaySessionsKeepalive);
|
||||
|
||||
function makeRom(id = 7): SimpleRom {
|
||||
return { id } as unknown as SimpleRom;
|
||||
return baseRom({ id });
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import storeCollections, { type Collection } from "@/stores/collections";
|
||||
import storeGalleryFilter from "@/stores/galleryFilter";
|
||||
import type { Platform } from "@/stores/platforms";
|
||||
import storeRoms, { type DetailedRom, type SimpleRom } from "@/stores/roms";
|
||||
import { makeDetailedRom, makeRom as baseRom } from "@/utils/rom.fixtures";
|
||||
import storeGalleryRoms from "@/v2/stores/galleryRoms";
|
||||
import storeGallerySelection from "@/v2/stores/gallerySelection";
|
||||
import { useRomSync } from "./index";
|
||||
@@ -18,11 +19,7 @@ vi.mock("@/services/api/rom", () => ({
|
||||
}));
|
||||
|
||||
function makeRom(overrides: Partial<SimpleRom> = {}): SimpleRom {
|
||||
return {
|
||||
id: 1,
|
||||
name: "Chrono Trigger",
|
||||
...overrides,
|
||||
} as unknown as SimpleRom;
|
||||
return baseRom({ name: "Chrono Trigger", ...overrides });
|
||||
}
|
||||
|
||||
/** Put the gallery in a platform context with one loaded window so
|
||||
@@ -257,7 +254,7 @@ describe("useRomSync", () => {
|
||||
|
||||
describe("refetchRom", () => {
|
||||
const detailed = (id: number) =>
|
||||
({ id, name: "Chrono Trigger" }) as unknown as DetailedRom;
|
||||
makeDetailedRom({ id, name: "Chrono Trigger" });
|
||||
|
||||
it("applies the fresh rom to the open view and the caches", async () => {
|
||||
const romsStore = storeRoms();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { MusicTrackSchema, TrackMetaSchema } from "@/__generated__";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { makeDetailedRom } from "@/utils/rom.fixtures";
|
||||
import {
|
||||
isAudioFile,
|
||||
nowPlayingCaption,
|
||||
@@ -15,7 +16,7 @@ function romFile(id: number, fileName: string, category = "soundtrack") {
|
||||
}
|
||||
|
||||
function rom(files: unknown[]): DetailedRom {
|
||||
return { id: 7, files } as unknown as DetailedRom;
|
||||
return makeDetailedRom({ id: 7, files: files as DetailedRom["files"] });
|
||||
}
|
||||
|
||||
describe("isAudioFile", () => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { defineComponent } from "vue";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import type { LaunchState, SaveSyncOutcome } from "@/types/rommNative";
|
||||
import { makeDetailedRom } from "@/utils/rom.fixtures";
|
||||
import EmulatorJS from "./EmulatorJS.vue";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
@@ -168,7 +169,7 @@ vi.mock("@/v2/composables/useStageActive", () => ({ useStageActive: vi.fn() }));
|
||||
|
||||
vi.mock("@/v2/composables/useUnloadGuard", () => ({ useUnloadGuard: vi.fn() }));
|
||||
|
||||
const ROM = {
|
||||
const ROM = makeDetailedRom({
|
||||
id: 7,
|
||||
name: "Shadow of the Colossus",
|
||||
platform_id: 4,
|
||||
@@ -176,25 +177,26 @@ const ROM = {
|
||||
has_file_on_disk: true,
|
||||
files: [],
|
||||
user_saves: [],
|
||||
user_states: [],
|
||||
user_screenshots: [],
|
||||
} as unknown as DetailedRom;
|
||||
});
|
||||
|
||||
// Two discs, so the panel renders its disc selector and there is a pick to
|
||||
// carry. Ids rather than names: a pick is a rom file's id.
|
||||
const DISC_SET = {
|
||||
const DISC_SET = makeDetailedRom({
|
||||
...ROM,
|
||||
files: [
|
||||
{ id: 101, file_name: "Game (Disc 1).chd" },
|
||||
{ id: 102, file_name: "Game (Disc 2).chd" },
|
||||
],
|
||||
} as unknown as DetailedRom;
|
||||
] as DetailedRom["files"],
|
||||
});
|
||||
|
||||
// A scraped bezel, which is what puts the panel's bezel switch on screen.
|
||||
const BEZELED_ROM = {
|
||||
const BEZELED_ROM = makeDetailedRom({
|
||||
...ROM,
|
||||
ss_metadata: { bezel_path: "roms/7/bezel/bezel.png" },
|
||||
} as unknown as DetailedRom;
|
||||
ss_metadata: {
|
||||
bezel_path: "roms/7/bezel/bezel.png",
|
||||
} as DetailedRom["ss_metadata"],
|
||||
});
|
||||
|
||||
// One BIOS file for the platform, which is what puts the firmware picker on
|
||||
// screen. Its contents do not matter: the panel lists what the server returns.
|
||||
|
||||
@@ -5,6 +5,7 @@ import { defineComponent, type Slots, type VNodeChild } from "vue";
|
||||
import type { SaveSchema, StateSchema } from "@/__generated__";
|
||||
import type { DetailedRom } from "@/stores/roms";
|
||||
import { saveFixture, stateFixture } from "@/utils/assets.fixtures";
|
||||
import { makeDetailedRom } from "@/utils/rom.fixtures";
|
||||
import AssetPreview from "@/v2/components/Player/AssetPreview.vue";
|
||||
import SaveDataPanel from "@/v2/components/Player/SaveDataPanel.vue";
|
||||
import AssetList from "@/v2/components/shared/AssetList.vue";
|
||||
@@ -214,19 +215,18 @@ const ARCHIVES = [
|
||||
];
|
||||
|
||||
function romWith(saves: SaveSchema[], states: StateSchema[] = []): DetailedRom {
|
||||
return {
|
||||
return makeDetailedRom({
|
||||
id: 3,
|
||||
name: "Archer Maclean's 3D Pool (USA)",
|
||||
platform_slug: "gba",
|
||||
platform_name: "Game Boy Advance",
|
||||
platform_display_name: "Game Boy Advance",
|
||||
fs_name: "Archer Maclean's 3D Pool (USA).gba",
|
||||
files: [],
|
||||
user_saves: saves,
|
||||
all_user_states: states,
|
||||
all_user_states: states.map((state) => ({ ...state, username: "admin" })),
|
||||
user_screenshots: [],
|
||||
metadatum: {},
|
||||
} as unknown as DetailedRom;
|
||||
metadatum: {} as DetailedRom["metadatum"],
|
||||
});
|
||||
}
|
||||
|
||||
// The view listens on document and window, so a mount left standing would
|
||||
|
||||
Reference in New Issue
Block a user