From f2c9d120fabbc05e75c51804b21c3c893b73e241 Mon Sep 17 00:00:00 2001 From: session <252201310+session567@users.noreply.github.com> Date: Sun, 1 Mar 2026 00:32:06 +0100 Subject: [PATCH 1/5] Add query param support to pages to distinguish youth matches from senior matches - Add getCurrentSearchParams() utility to read URL search params - Extend Page class to support queryParams option for matching URLs with specific query params - Refactor pages object to use nested structure (e.g., pages.matches.senior.own, pages.matches.youth.own) - Add teamPages() helper for creating own/other team page pairs - Improve getCurrentPage() to disambiguate pages using specificity scoring - Add mockIsPage() test helper for cleaner module tests - Update all modules to use new page structure --- eslint.config.ts | 2 +- src/entrypoints/content/common/test/utils.ts | 8 + .../content/common/types/module.ts | 8 +- .../content/common/utils/location.ts | 7 + .../content/common/utils/pages.test.ts | 215 +++++++++++++----- src/entrypoints/content/common/utils/pages.ts | 142 +++++++++--- src/entrypoints/content/index.ts | 8 +- .../content/modules/htms-points/index.test.ts | 19 +- .../content/modules/htms-points/index.ts | 8 +- .../content/modules/links/constants.ts | 10 +- .../content/modules/links/index.test.ts | 14 +- .../content/modules/salary/index.ts | 2 +- .../content/modules/skill-bonus/index.test.ts | 17 +- .../content/modules/skill-bonus/index.ts | 6 +- .../content/modules/week-number/index.test.ts | 15 +- .../content/modules/week-number/index.ts | 10 +- 16 files changed, 343 insertions(+), 148 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index 454d621..e3fb0d8 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -7,7 +7,7 @@ import eslintPluginTsdoc from 'eslint-plugin-tsdoc' import tseslint from 'typescript-eslint' export default defineConfig( - globalIgnores(['.output/**', '.wxt/**', 'coverage/**', 'node_modules/**', 'public/**']), + globalIgnores(['.wxt/**', 'coverage/**', 'dist/**', 'node_modules/**', 'public/**']), eslint.configs.recommended, tseslint.configs.strictTypeChecked, tseslint.configs.stylisticTypeChecked, diff --git a/src/entrypoints/content/common/test/utils.ts b/src/entrypoints/content/common/test/utils.ts index f8ae6d9..609f774 100644 --- a/src/entrypoints/content/common/test/utils.ts +++ b/src/entrypoints/content/common/test/utils.ts @@ -1,3 +1,7 @@ +import { vi } from 'vitest' + +import { isPage, Page } from '@/entrypoints/content/common/utils/pages' + /** * Helper for creating a DOM element with the HTML content for testing. * @@ -10,3 +14,7 @@ export const createElement = (html: string): HTMLDivElement => { return div } + +export const mockIsPage = (page: Page) => { + vi.mocked(isPage).mockImplementation((...pages: Page[]) => pages.includes(page)) +} diff --git a/src/entrypoints/content/common/types/module.ts b/src/entrypoints/content/common/types/module.ts index dc3dc7c..9e0346a 100644 --- a/src/entrypoints/content/common/types/module.ts +++ b/src/entrypoints/content/common/types/module.ts @@ -1,5 +1,8 @@ import { Page } from '@/entrypoints/content/common/utils/pages' +type PageOrPageArray = Page | Page[] +type PageList = PageOrPageArray[] + /** * Base type for every module. * @@ -10,10 +13,7 @@ export type Module = { // The module's name name: string // Pages where the module should run (see @common/utils/pages.ts for a list of pages) - pages: Page[] - // Pages where the module should not run - // This is only evaluated when `pages: [pages.all]`, otherwise it is ignored - excludePages?: Page[] + pages: PageList // Function containing the module's logic run: () => void } diff --git a/src/entrypoints/content/common/utils/location.ts b/src/entrypoints/content/common/utils/location.ts index 19d527d..bfc9cab 100644 --- a/src/entrypoints/content/common/utils/location.ts +++ b/src/entrypoints/content/common/utils/location.ts @@ -4,3 +4,10 @@ * @returns The pathname (e.g., '/Club/Players/') */ export const getCurrentPathname = (): string => window.location.pathname + +/** + * Get the current page's search params from the browser location. + * + * @returns The URLSearchParams (e.g., '?YouthTeamId=123') + */ +export const getCurrentSearchParams = (): URLSearchParams => new URLSearchParams(window.location.search) diff --git a/src/entrypoints/content/common/utils/pages.test.ts b/src/entrypoints/content/common/utils/pages.test.ts index f5b6e15..6257ba1 100644 --- a/src/entrypoints/content/common/utils/pages.test.ts +++ b/src/entrypoints/content/common/utils/pages.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from 'vitest' -import { getCurrentPathname } from '@/entrypoints/content/common/utils/location' +import { getCurrentPathname, getCurrentSearchParams } from '@/entrypoints/content/common/utils/location' import { getCurrentPage, isPage, Page, pages } from '@/entrypoints/content/common/utils/pages' import { isOwnTeamPage } from '@/entrypoints/content/common/utils/team/utils' @@ -8,74 +8,173 @@ vi.mock(import('@/entrypoints/content/common/utils/location')) vi.mock(import('@/entrypoints/content/common/utils/team/utils')) describe(isPage, () => { - it.each([ - { - desc: 'different path', - currentPathname: '/Foo', - page: new Page('/Bar'), - ownTeamPage: false, - expected: false, - }, - { - desc: 'no teamContext, own team page', - currentPathname: '/Foo', - page: new Page('/Foo'), - ownTeamPage: true, - expected: true, - }, - { - desc: 'no teamContext, not own team page', - currentPathname: '/Foo', - page: new Page('/Foo'), - ownTeamPage: false, - expected: true, - }, - { - desc: 'OWN_TEAM, own team page', - currentPathname: '/Foo', - page: new Page('/Foo', 'OWN_TEAM'), - ownTeamPage: true, - expected: true, - }, - { - desc: 'OWN_TEAM, other team page', - currentPathname: '/Foo', - page: new Page('/Foo', 'OWN_TEAM'), - ownTeamPage: false, - expected: false, - }, - { - desc: 'OTHER_TEAM, own team page', - currentPathname: '/Foo', - page: new Page('/Foo', 'OTHER_TEAM'), - ownTeamPage: true, - expected: false, - }, - { - desc: 'OTHER_TEAM, other team page', - currentPathname: '/Foo', - page: new Page('/Foo', 'OTHER_TEAM'), - ownTeamPage: false, - expected: true, - }, - ])('$desc', ({ currentPathname, page, ownTeamPage, expected }) => { - vi.mocked(getCurrentPathname).mockReturnValue(currentPathname) - vi.mocked(isOwnTeamPage).mockReturnValue(ownTeamPage) - - expect(isPage(page)).toBe(expected) + describe('pathname matching', () => { + it.each([ + { + desc: 'returns false when pathnames differ', + currentPathname: '/Foo', + page: new Page('/Bar'), + expected: false, + }, + { + desc: 'returns true when pathnames match and there are no options', + currentPathname: '/Foo', + page: new Page('/Foo'), + expected: true, + }, + ])('$desc', ({ currentPathname, page, expected }) => { + vi.mocked(getCurrentPathname).mockReturnValue(currentPathname) + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) + + expect(isPage(page)).toBe(expected) + }) + }) + + describe('teamContext', () => { + it.each([ + { + desc: 'no teamContext, matches own team page', + page: new Page('/Foo'), + ownTeamPage: true, + expected: true, + }, + { + desc: 'no teamContext, matches other team page', + page: new Page('/Foo'), + ownTeamPage: false, + expected: true, + }, + { + desc: 'OWN_TEAM, matches own team page', + page: new Page('/Foo', { teamContext: 'OWN_TEAM' }), + ownTeamPage: true, + expected: true, + }, + { + desc: 'OWN_TEAM, does not match own team page', + page: new Page('/Foo', { teamContext: 'OWN_TEAM' }), + ownTeamPage: false, + expected: false, + }, + { + desc: 'OTHER_TEAM, does not match own team page', + page: new Page('/Foo', { teamContext: 'OTHER_TEAM' }), + ownTeamPage: true, + expected: false, + }, + { + desc: 'OTHER_TEAM, matches other team page', + page: new Page('/Foo', { teamContext: 'OTHER_TEAM' }), + ownTeamPage: false, + expected: true, + }, + ])('$desc', ({ page, ownTeamPage, expected }) => { + vi.mocked(getCurrentPathname).mockReturnValue('/Foo') + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) + vi.mocked(isOwnTeamPage).mockReturnValue(ownTeamPage) + + expect(isPage(page)).toBe(expected) + }) + }) + + describe('queryParams', () => { + it.each([ + { + desc: 'matches when required param is present (no value constraint)', + page: new Page('/Foo', { queryParams: [{ name: 'BarId' }] }), + search: '?BarId=123', + expected: true, + }, + { + desc: 'does not match when required param is absent', + page: new Page('/Foo', { queryParams: [{ name: 'BarId' }] }), + search: '', + expected: false, + }, + { + desc: 'matches when param has the required value', + page: new Page('/Foo', { queryParams: [{ name: 'BarId', value: '123' }] }), + search: '?BarId=123', + expected: true, + }, + { + desc: 'does not match when param has a different value', + page: new Page('/Foo', { queryParams: [{ name: 'BarId', value: '123' }] }), + search: '?BarId=456', + expected: false, + }, + { + desc: 'does not match when param with required value is absent', + page: new Page('/Foo', { queryParams: [{ name: 'BarId', value: '123' }] }), + search: '', + expected: false, + }, + { + desc: 'matches when all required params are present', + page: new Page('/Foo', { queryParams: [{ name: 'foo' }, { name: 'bar' }] }), + search: '?foo=1&bar=2', + expected: true, + }, + { + desc: 'does not match when only some required params are present', + page: new Page('/Foo', { queryParams: [{ name: 'foo' }, { name: 'bar' }] }), + search: '?foo=1', + expected: false, + }, + ])('$desc', ({ page, search, expected }) => { + vi.mocked(getCurrentPathname).mockReturnValue('/Foo') + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams(search)) + vi.mocked(isOwnTeamPage).mockReturnValue(false) + + expect(isPage(page)).toBe(expected) + }) }) }) describe(getCurrentPage, () => { - it('returns the current page', () => { + it('returns the correct page for a simple pathname', () => { vi.mocked(getCurrentPathname).mockReturnValue(pages.club.pathname) + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) vi.mocked(isOwnTeamPage).mockReturnValue(false) expect(getCurrentPage()).toBe(pages.club) }) - it('throws an error when no page matches', () => { + it('distinguishes own team player list from other team player list', () => { + vi.mocked(getCurrentPathname).mockReturnValue(pages.player.senior.list.own.pathname) + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) + vi.mocked(isOwnTeamPage).mockReturnValue(true) + + expect(getCurrentPage()).toBe(pages.player.senior.list.own) + }) + + it('distinguishes other team player list from own team player list', () => { + vi.mocked(getCurrentPathname).mockReturnValue(pages.player.senior.list.other.pathname) + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) + vi.mocked(isOwnTeamPage).mockReturnValue(false) + + expect(getCurrentPage()).toBe(pages.player.senior.list.other) + }) + + it('distinguishes youth matches from senior matches by query param', () => { + vi.mocked(getCurrentPathname).mockReturnValue(pages.matches.youth.own.pathname) + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams('?YouthTeamId=123')) + vi.mocked(isOwnTeamPage).mockReturnValue(true) + + expect(getCurrentPage()).toBe(pages.matches.youth.own) + }) + + it('returns senior matches when YouthTeamId param is absent', () => { + vi.mocked(getCurrentPathname).mockReturnValue(pages.matches.senior.own.pathname) + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) + vi.mocked(isOwnTeamPage).mockReturnValue(true) + + expect(getCurrentPage()).toBe(pages.matches.senior.own) + }) + + it('throws error when no page matches', () => { vi.mocked(getCurrentPathname).mockReturnValue('/Unsupported/Path/') + vi.mocked(getCurrentSearchParams).mockReturnValue(new URLSearchParams()) vi.mocked(isOwnTeamPage).mockReturnValue(false) expect(() => getCurrentPage()).toThrowError('The current page is not supported') diff --git a/src/entrypoints/content/common/utils/pages.ts b/src/entrypoints/content/common/utils/pages.ts index b85aa68..7f2eb14 100644 --- a/src/entrypoints/content/common/utils/pages.ts +++ b/src/entrypoints/content/common/utils/pages.ts @@ -1,8 +1,20 @@ -import { getCurrentPathname } from '@/entrypoints/content/common/utils/location' +import { getCurrentPathname, getCurrentSearchParams } from '@/entrypoints/content/common/utils/location' import { isOwnTeamPage } from '@/entrypoints/content/common/utils/team/utils' type TeamContext = 'OWN_TEAM' | 'OTHER_TEAM' +type QueryParam = { + name: string + value?: string +} + +type PageOptions = { + teamContext?: TeamContext + queryParams?: QueryParam[] +} + +type PageTree = Page | Page[] | { [key: string]: PageTree } + /** * Represents a specific page on Hattrick. * @@ -16,22 +28,31 @@ export class Page { /** * @param pathname - The URL pathname of the Hattrick page (e.g., '/Club/Players/') - * @param teamContext - If this page exists for both my team and other teams, specify which one it refers to + * @param options - Optional settings to distinguish pages with the same pathname */ constructor( public readonly pathname: string, - public readonly teamContext?: TeamContext, + public readonly options?: PageOptions, ) {} - toString(): string { - return `Page(pathname=${this.pathname}, teamContext=${this.teamContext})` + toString() { + return this.options ? `Page("${this.pathname}", ${JSON.stringify(this.options)})` : `Page("${this.pathname}")` } } +/** + * Create a pair of {@link Page} instances for a pathname available for both own and other teams. + */ +const teamPages = (pathname: string, options?: Omit) => { + const own = new Page(pathname, { ...options, teamContext: 'OWN_TEAM' }) + const other = new Page(pathname, { ...options, teamContext: 'OTHER_TEAM' }) + return { own, other, both: [own, other] } +} + /** * Dictionary of all supported Hattrick pages. * - * Modules reference these pages to determine where they should run. + * IMPORTANT: For any given pathname, either all {@link Page} instances must have `teamContext`, or none should. */ export const pages = { // Special case @@ -41,43 +62,106 @@ export const pages = { appDenominations: new Page('/Help/Rules/AppDenominations.aspx'), forum: new Page('/Forum/'), series: new Page('/World/Series/'), - transfers: new Page('/World/Transfers/'), - transfersSearchResult: new Page('/World/Transfers/TransfersSearchResult.aspx'), + transfers: { + search: new Page('/World/Transfers/'), + searchResults: new Page('/World/Transfers/TransfersSearchResult.aspx'), + }, // Pages accessible only to the user's own team club: new Page('/Club/'), - matches: new Page('/Club/Matches/'), + matches: { + senior: teamPages('/Club/Matches/'), + youth: teamPages('/Club/Matches/', { queryParams: [{ name: 'YouthTeamId' }] }), + }, specialists: new Page('/Club/Specialists/'), - stadium: new Page('/Club/Stadium/'), // Pages accessible to both the user's own team and other teams - playerDetailOtherTeam: new Page('/Club/Players/Player.aspx', 'OTHER_TEAM'), - playerDetailOwnTeam: new Page('/Club/Players/Player.aspx', 'OWN_TEAM'), - playerListOtherTeam: new Page('/Club/Players/', 'OTHER_TEAM'), - playerListOwnTeam: new Page('/Club/Players/', 'OWN_TEAM'), - // Pages that don't need to distinguish between the user's own team and other teams yet - youthPlayer: new Page('/Club/Players/YouthPlayer.aspx'), - youthPlayers: new Page('/Club/Players/YouthPlayers.aspx'), -} as const satisfies Record + player: { + senior: { + detail: teamPages('/Club/Players/Player.aspx'), + list: teamPages('/Club/Players/'), + }, + youth: { + detail: new Page('/Club/Players/YouthPlayer.aspx'), + list: new Page('/Club/Players/YouthPlayers.aspx'), + }, + }, + stadium: new Page('/Club/Stadium/'), +} as const satisfies Record /** - * Checks if the given page matches the current browser location. + * Checks if any of the given pages match the current browser location. */ -export const isPage = (page: Page): boolean => { - if (page.pathname !== getCurrentPathname()) return false - if (page.teamContext === undefined) return true - if (page.teamContext === 'OWN_TEAM') return isOwnTeamPage() - return !isOwnTeamPage() // OTHER_TEAM +export const isPage = (...pages: Page[]): boolean => { + return pages.some((page) => { + if (page.pathname !== getCurrentPathname()) return false + + const { options } = page + if (!options) return true + + const { teamContext, queryParams } = options + + if (teamContext) { + const ownTeam = isOwnTeamPage() + if (teamContext === 'OWN_TEAM' && !ownTeam) return false + if (teamContext === 'OTHER_TEAM' && ownTeam) return false + } + + if (queryParams) { + const searchParams = getCurrentSearchParams() + + for (const { name, value } of queryParams) { + if (value === undefined ? !searchParams.has(name) : !searchParams.has(name, value)) return false + } + } + + return true + }) +} + +/** + * Recursively flattens a {@link PageTree} into a flat array of {@link Page} instances. + */ +const flattenPages = (tree: PageTree): Page[] => { + if (tree instanceof Page) return [tree] + if (Array.isArray(tree)) return tree.flatMap(flattenPages) + return Object.values(tree).flatMap(flattenPages) } /** * Returns the current page based on the browser's location. - * - * @throws {@link Error} If the current page is not in {@link pages} */ export const getCurrentPage = (): Page => { - const page = Object.values(pages).find((page) => isPage(page)) - if (page === undefined) throw new Error('The current page is not supported') + const allPages = [...new Set(flattenPages(pages))] + const matchingPages = allPages.filter((page) => isPage(page)) + + if (matchingPages.length === 0) throw new Error('The current page is not supported') + if (matchingPages.length === 1) return matchingPages[0] + + // Multiple pages can match the same URL when one page is a more specific variant of another. For example, + // `pages.matches.senior` and `pages.matches.youth` share the same pathname, but `pages.matches.youth` requires an + // additional query param 'YouthTeamId'. Both pass `isPage()`, so we score the pages to pick the most specific match; + // more query params = higher score. + let topPages: Page[] = [] + let topScore = -Infinity + + for (const page of matchingPages) { + const score = page.options?.queryParams?.length ?? 0 + + if (score > topScore) { + topScore = score + topPages = [page] + } else if (score === topScore) { + topPages.push(page) + } + } + + if (topPages.length > 1) { + throw new Error( + `Multiple pages matched with the same specificity score (${topScore}): ${topPages}. ` + + 'Add more specific options to disambiguate.', + ) + } - return page + return topPages[0] } diff --git a/src/entrypoints/content/index.ts b/src/entrypoints/content/index.ts index 911e2ad..6b95873 100644 --- a/src/entrypoints/content/index.ts +++ b/src/entrypoints/content/index.ts @@ -36,10 +36,10 @@ export default defineContentScript({ logger.debug(`Current pathname: ${getCurrentPathname()}`) modules.forEach((module) => { - const isAll = module.pages.includes(pages.all) - const matchesPage = isAll || module.pages.some((page) => isPage(page)) - const isExcluded = isAll && module.excludePages?.some((page) => isPage(page)) - if (!matchesPage || isExcluded) return + const modulePages = module.pages.flat() + const isAll = modulePages.includes(pages.all) + const matchesPage = isAll || isPage(...modulePages) + if (!matchesPage) return logger.debug(`Running module: ${module.name}`) diff --git a/src/entrypoints/content/modules/htms-points/index.test.ts b/src/entrypoints/content/modules/htms-points/index.test.ts index 45f215c..d95ac01 100644 --- a/src/entrypoints/content/modules/htms-points/index.test.ts +++ b/src/entrypoints/content/modules/htms-points/index.test.ts @@ -1,30 +1,27 @@ import { describe, expect, it, vi } from 'vitest' +import { mockIsPage } from '@/entrypoints/content/common/test/utils' import { isPage, pages } from '@/entrypoints/content/common/utils/pages' import htmsPoints from '@/entrypoints/content/modules/htms-points/index' import { calcHTMSPoints } from '@/entrypoints/content/modules/htms-points/utils' -vi.mock(import('@/entrypoints/content/common/utils/pages'), async () => { - const originalModule = await vi.importActual('@/entrypoints/content/common/utils/pages') - +vi.mock(import('@/entrypoints/content/common/utils/pages'), async (importOriginal) => { return { - ...originalModule, + ...(await importOriginal()), isPage: vi.fn(), } }) -vi.mock(import('@/entrypoints/content/modules/htms-points/utils'), async () => { - const originalModule = await vi.importActual('@/entrypoints/content/modules/htms-points/utils') - +vi.mock(import('@/entrypoints/content/modules/htms-points/utils'), async (importOriginal) => { return { - ...originalModule, + ...(await importOriginal()), calcHTMSPoints: vi.fn(), } }) describe('htms-points module', () => { it('adds HTMS points to the player detail page', () => { - vi.mocked(isPage).mockImplementation((page) => page === pages.playerDetailOwnTeam) + mockIsPage(pages.player.senior.detail.own) vi.mocked(calcHTMSPoints).mockReturnValue({ ability: 1234, potential: 5678 }) document.body.innerHTML = ` @@ -86,7 +83,7 @@ describe('htms-points module', () => { }) it('adds HTMS points to the player list page', () => { - vi.mocked(isPage).mockImplementation((page) => page === pages.playerListOwnTeam) + vi.mocked(isPage).mockImplementation((page) => page === pages.player.senior.list.own) vi.mocked(calcHTMSPoints) .mockReturnValueOnce({ ability: 1234, potential: 5678 }) .mockReturnValueOnce({ ability: 2345, potential: 6789 }) @@ -204,7 +201,7 @@ describe('htms-points module', () => { }) it('adds HTMS points to the transfers search result page', () => { - vi.mocked(isPage).mockImplementation((page) => page === pages.transfersSearchResult) + vi.mocked(isPage).mockImplementation((page) => page === pages.transfers.searchResults) vi.mocked(calcHTMSPoints) .mockReturnValueOnce({ ability: 1234, potential: 5678 }) .mockReturnValueOnce({ ability: 2345, potential: 6789 }) diff --git a/src/entrypoints/content/modules/htms-points/index.ts b/src/entrypoints/content/modules/htms-points/index.ts index b8961df..4ab5715 100644 --- a/src/entrypoints/content/modules/htms-points/index.ts +++ b/src/entrypoints/content/modules/htms-points/index.ts @@ -77,17 +77,17 @@ const processPlayers = (playerSelector: string, ageSelector: string): void => { */ const htmsPoints: Module = { name: 'HTMS Points', - pages: [pages.playerDetailOwnTeam, pages.playerDetailOtherTeam, pages.playerListOwnTeam, pages.transfersSearchResult], + pages: [pages.player.senior.detail.both, pages.player.senior.list.own, pages.transfers.searchResults], run: () => { - if (isPage(pages.playerDetailOwnTeam) || isPage(pages.playerDetailOtherTeam)) { + if (isPage(...pages.player.senior.detail.both)) { const playerElement = querySelector('#mainBody .playerInfo') const ageElement = querySelector('#mainBody > .byline') if (playerElement && ageElement) processPlayer(playerElement, ageElement) - } else if (isPage(pages.playerListOwnTeam)) { + } else if (isPage(pages.player.senior.list.own)) { const playerSelector = '#mainBody > .playerList > .teamphoto-player .playerInfo' const ageSelector = '.transferPlayerInformation table tbody tr:first-child td:nth-child(2)' processPlayers(playerSelector, ageSelector) - } else if (isPage(pages.transfersSearchResult)) { + } else if (isPage(pages.transfers.searchResults)) { const playerSelector = '#mainBody .playerListDetails' const ageSelector = '.transferPlayerInformation table tbody tr:nth-child(2) td:nth-child(2)' processPlayers(playerSelector, ageSelector) diff --git a/src/entrypoints/content/modules/links/constants.ts b/src/entrypoints/content/modules/links/constants.ts index a346405..1011117 100644 --- a/src/entrypoints/content/modules/links/constants.ts +++ b/src/entrypoints/content/modules/links/constants.ts @@ -59,14 +59,14 @@ export const SCOUTRICK: Link = { export const linkMap = new Map([ [pages.club, { links: [HATTID_TEAM], getReplacements: getOwnTeamData }], - [pages.matches, { links: [DHTH] }], - [pages.playerDetailOwnTeam, { links: [HATTRICK_PORTAL_TRACKER, HATTRICK_CYCLE_PLANNER] }], - [pages.playerListOwnTeam, { links: [HATTRICK_PORTAL_TRACKER, HATTRICK_CYCLE_PLANNER] }], + [pages.matches.senior.own, { links: [DHTH] }], + [pages.player.senior.detail.own, { links: [HATTRICK_PORTAL_TRACKER, HATTRICK_CYCLE_PLANNER] }], + [pages.player.senior.list.own, { links: [HATTRICK_PORTAL_TRACKER, HATTRICK_CYCLE_PLANNER] }], [ pages.series, { links: [HATTID_LEAGUE, NICKARANA_LEAGUE_SIMULATOR], getReplacements: () => ({ seriesId: getPageSeriesId() }) }, ], [pages.stadium, { links: [ENTERPRISE_CONSTRUCTION_ONLINE] }], - [pages.youthPlayer, { links: [HATTRICK_YOUTHCLUB, SCOUTRICK] }], - [pages.youthPlayers, { links: [HATTRICK_YOUTHCLUB, SCOUTRICK] }], + [pages.player.youth.detail, { links: [HATTRICK_YOUTHCLUB, SCOUTRICK] }], + [pages.player.youth.list, { links: [HATTRICK_YOUTHCLUB, SCOUTRICK] }], ]) diff --git a/src/entrypoints/content/modules/links/index.test.ts b/src/entrypoints/content/modules/links/index.test.ts index 8dd40e7..ef9e912 100644 --- a/src/entrypoints/content/modules/links/index.test.ts +++ b/src/entrypoints/content/modules/links/index.test.ts @@ -4,20 +4,16 @@ import { getCurrentPage, pages } from '@/entrypoints/content/common/utils/pages' import { getOwnTeamData } from '@/entrypoints/content/common/utils/team/utils' import links from '@/entrypoints/content/modules/links/index' -vi.mock(import('@/entrypoints/content/common/utils/pages'), async () => { - const originalModule = await vi.importActual('@/entrypoints/content/common/utils/pages') - +vi.mock(import('@/entrypoints/content/common/utils/pages'), async (importOriginal) => { return { - ...originalModule, + ...(await importOriginal()), getCurrentPage: vi.fn(), } }) -vi.mock(import('@/entrypoints/content/common/utils/team/utils'), async () => { - const originalModule = await vi.importActual('@/entrypoints/content/common/utils/team/utils') - +vi.mock(import('@/entrypoints/content/common/utils/team/utils'), async (importOriginal) => { return { - ...originalModule, + ...(await importOriginal()), getOwnTeamData: vi.fn(), } }) @@ -39,7 +35,7 @@ describe('links module', () => { }) it('inserts box at the beginning of sidebar', () => { - vi.mocked(getCurrentPage).mockReturnValue(pages.matches) + vi.mocked(getCurrentPage).mockReturnValue(pages.matches.senior.own) document.body.innerHTML = `