From e58ad50ac2ea5dd177fb51770ff406ba0a69b1fb Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Wed, 1 Jan 2025 16:20:25 -0500 Subject: [PATCH 1/2] feat(hash): surface source URLs on the Supported Game Files page --- app/Platform/Data/GameHashData.php | 3 + lang/en_US.json | 4 +- .../HashesList/HashesList.test.tsx | 89 ++++++++++++++++--- .../HashesList/HashesListItem.tsx | 23 ++++- resources/js/types/generated.d.ts | 3 +- 5 files changed, 105 insertions(+), 17 deletions(-) diff --git a/app/Platform/Data/GameHashData.php b/app/Platform/Data/GameHashData.php index cb71d763bf..969b512865 100644 --- a/app/Platform/Data/GameHashData.php +++ b/app/Platform/Data/GameHashData.php @@ -20,6 +20,8 @@ public function __construct( #[TypeScriptType('App\\Platform\\Data\\GameHashLabelData[]')] public array $labels, public ?string $patchUrl, + /** "Resource Page URL" */ + public ?string $source, ) { } @@ -31,6 +33,7 @@ public static function fromGameHash(GameHash $gameHash): self name: $gameHash->name, labels: GameHashLabelData::fromLabelsString($gameHash->labels), patchUrl: $gameHash->patch_url, + source: $gameHash->source, ); } diff --git a/lang/en_US.json b/lang/en_US.json index a13bafb2cb..24e4dcb110 100644 --- a/lang/en_US.json +++ b/lang/en_US.json @@ -520,5 +520,7 @@ "This page may contain content that is not appropriate for all ages.": "This page may contain content that is not appropriate for all ages.", "Are you sure you want to view this page?": "Are you sure you want to view this page?", "Yes, and don't ask again": "Yes, and don't ask again", - "Yes, I'm an adult": "Yes, I'm an adult" + "Yes, I'm an adult": "Yes, I'm an adult", + "Download from Original Source (Recommended)": "Download from Original Source (Recommended)", + "Mirror": "Mirror" } \ No newline at end of file diff --git a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx index 7f67fd33d5..1c67d7b6c8 100644 --- a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx +++ b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx @@ -68,20 +68,6 @@ describe('Component: HashesList', () => { expect(screen.getByText(hash.md5)).toBeVisible(); }); - it('given the hash has a patch URL, adds a link to it', () => { - // ARRANGE - const hash = createGameHash({ patchUrl: faker.internet.url() }); - - render(, { - pageProps: { hashes: [hash] }, - }); - - // ASSERT - const linkEl = screen.getByRole('link', { name: /download patch file/i }); - expect(linkEl).toBeVisible(); - expect(linkEl).toHaveAttribute('href', hash.patchUrl); - }); - it('given the hash has no patch URL, does not display a download link', () => { // ARRANGE const hash = createGameHash({ patchUrl: null }); @@ -186,4 +172,79 @@ describe('Component: HashesList', () => { expect(renderedMd5s[1]).toContain('77057d9d14b99e465ea9e29783af0ae3'); expect(renderedMd5s[2]).toContain('a78d58b97eddb7c70647d939e20bef4f'); }); + + it('given the hash has both source and patch URLs, displays links to both', () => { + // ARRANGE + const hash = createGameHash({ + source: faker.internet.url(), + patchUrl: faker.internet.url(), + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + const links = screen.getAllByRole('link'); + expect(links[0]).toHaveAttribute('href', hash.source); + expect(links[1]).toHaveAttribute('href', hash.patchUrl); + + expect(screen.getByText(/download from original source/i)).toBeVisible(); + expect(screen.getByText(/mirror/i)).toBeVisible(); + }); + + it('given the hash only has a patch URL, displays a single download link', () => { + // ARRANGE + const hash = createGameHash({ + source: null, + patchUrl: faker.internet.url(), + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + const link = screen.getByRole('link'); + expect(link).toHaveAttribute('href', hash.patchUrl); + expect(screen.getByText(/download patch file/i)).toBeVisible(); + + expect(screen.queryByText(/mirror/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/download from original source/i)).not.toBeInTheDocument(); + }); + + it('given the hash only has a source URL, does not display any links', () => { + // ARRANGE + const hash = createGameHash({ + source: faker.internet.url(), + patchUrl: null, + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + expect(screen.queryByRole('link')).not.toBeInTheDocument(); + }); + + it('given the hash only has a patch URL, displays a single download link', () => { + // ARRANGE + const hash = createGameHash({ + source: null, + patchUrl: faker.internet.url(), + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + const link = screen.getByRole('link'); + expect(link).toHaveAttribute('href', hash.patchUrl); + expect(screen.getByText(/download patch file/i)).toBeVisible(); + + expect(screen.queryByText(/mirror/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/download from original source/i)).not.toBeInTheDocument(); + }); }); diff --git a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx index af9e2bf9c7..0f6f6f186a 100644 --- a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx +++ b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react'; import { useTranslation } from 'react-i18next'; import { buildTrackingClassNames } from '@/common/utils/buildTrackingClassNames'; +import { cn } from '@/common/utils/cn'; interface HashListingProps { hash: App.Platform.Data.GameHash; @@ -27,7 +28,27 @@ export const HashesListItem: FC = ({ hash }) => {

{hash.md5}

- {hash.patchUrl ? ( + {/* Can show RAPatches as the mirror */} + {hash.source && hash.patchUrl ? ( + + ) : null} + + {/* Show RAPatches as the direct download link */} + {!hash.source && hash.patchUrl ? ( ; patchUrl: string | null; + source: string | null; }; export type GameHashLabel = { label: string; From 7731679de178acc0243323aaca015088658149c5 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Wed, 1 Jan 2025 16:24:15 -0500 Subject: [PATCH 2/2] chore: tsc --- resources/js/test/factories/createGameHash.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/js/test/factories/createGameHash.ts b/resources/js/test/factories/createGameHash.ts index dedba16e34..0980d439e0 100644 --- a/resources/js/test/factories/createGameHash.ts +++ b/resources/js/test/factories/createGameHash.ts @@ -15,5 +15,6 @@ export const createGameHash = createFactory((faker) md5: faker.string.alphanumeric(32), name: faker.word.words(3), patchUrl: faker.internet.url(), + source: null, }; });