diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 66c057811d..8dace3329d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,23 +68,49 @@ jobs: steps: - uses: actions/checkout@v4 - name: Build test image - id: docker-build-test + id: docker-build-playwright uses: docker/build-push-action@v6 with: - target: server + target: playwright push: false load: true - - name: Run Perl tests + - name: Start playwright server + id: start-container run: > - docker run -d -i -p 8000:80 - ${{ steps.docker-build-test.outputs.imageid }} + CONTAINER_ID=$(docker run -d -i -p 8000:80 + -v $(pwd):/app + ${{ steps.docker-build-playwright.outputs.imageid }}) + && echo "container_id=$CONTAINER_ID" >> $GITHUB_OUTPUT + || (echo "Failed to start container" && exit 1) - uses: actions/setup-node@v4 with: node-version: 22 - name: Install Playwright Browsers run: ./bin/install-playwright + - name: Install Codecovbash + uses: perl-actions/install-with-cpm@v1 + with: + install: | + Devel::Cover + Devel::Cover::Report::Codecovbash + sudo: true + - name: Check docker status + id: playwright-tests + run: | + npx playwright test || { + echo "Playwright tests failed" + docker logs ${{ steps.start-container.outputs.container_id }} + exit 1 + } - name: Run Playwright tests run: npx playwright test + - name: Generate Codecov report + run: cover -report codecovbash + - uses: codecov/codecov-action@v5 + with: + fail_ci_if_error: true + file: ./cover_db/codecov.json + token: ${{ secrets.CODECOV_TOKEN }} test: runs-on: ubuntu-24.04 name: Dockerless diff --git a/Dockerfile b/Dockerfile index de1ab83000..d19218545f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -123,3 +123,18 @@ CMD [ "prove", "-l", "-r", "-j", "2", "t" ] FROM server AS production USER metacpan + +################### Playwright Server +FROM server AS playwright +USER root + +RUN echo "Starting Playwright stage setup" +RUN --mount=type=cache,target=/root/.perl-cpm,sharing=private \ +< { - await page.goto('/'); - await expect(page).toHaveTitle(/Search the CPAN - metacpan.org/, { timeout: 10 }); +test("home page", async ({ page }) => { + await page.goto("/"); + await expect(page).toHaveTitle(/Search the CPAN - metacpan.org/, { + timeout: 10, + }); +}); + +test("suggest is correct", async ({ page }) => { + await page.goto("/"); + const searchInput = page.getByPlaceholder("Search the CPAN"); + await expect(searchInput).toBeVisible(); + searchInput.fill("HTML:Restrict"); + await searchInput.press("Enter"); + + await expect(page.getByRole('alert')).toContainText('Did you mean: HTML::Restrict'); +}); + +test("suggest accounts for prefix and makes suggestion", async ({ page }) => { + await page.goto("/"); + const searchInput = page.getByPlaceholder("Search the CPAN"); + await expect(searchInput).toBeVisible(); + searchInput.fill("distribution:HTML:Restrict"); + await searchInput.press("Enter"); + + await expect(page.getByRole('alert')).toContainText('Did you mean: distribution:HTML::Restrict'); +}); + +test("suggest accounts for prefix but cannot make suggestion", async ({ page }) => { + await page.goto("/"); + const searchInput = page.getByPlaceholder("Search the CPAN"); + await expect(searchInput).toBeVisible(); + searchInput.fill("distribution:HTMLRestrict"); + await searchInput.press("Enter"); + + await expect(page.getByRole('alert')).toBeHidden(); +}); + +test("suggest ignores misspelled prefix and makes suggestion", async ({ page }) => { + await page.goto("/"); + const searchInput = page.getByPlaceholder("Search the CPAN"); + await expect(searchInput).toBeVisible(); + searchInput.fill("disstribution:HTML:Restrict"); + await searchInput.press("Enter"); + + await expect(page.getByRole('alert')).toContainText('Did you mean: disstribution::HTML::Restrict'); }); diff --git a/lib/MetaCPAN/Web/Controller/Search.pm b/lib/MetaCPAN/Web/Controller/Search.pm index 9754e43066..37b10bb07f 100644 --- a/lib/MetaCPAN/Web/Controller/Search.pm +++ b/lib/MetaCPAN/Web/Controller/Search.pm @@ -84,10 +84,14 @@ sub index : Path : Args(0) { if ( !$results->{total} && !$authors->{total} ) { my $suggest = $query; + my $prefix = q{}; + if ( $suggest =~ s{^(author|distribution|module|version):}{} ) { + $prefix = $1 . ':'; + } $suggest =~ s/\s*:+\s*/::/g; - if ( $suggest ne $query ) { + if ( $prefix . $suggest ne $query ) { $c->stash( { - suggest => $suggest, + suggest => $prefix . $suggest, } ); } $c->stash( { diff --git a/root/home.tx b/root/home.tx index b3f71c2a7e..edfbf12cc5 100644 --- a/root/home.tx +++ b/root/home.tx @@ -33,7 +33,7 @@ MetaCPAN

A search engine for CPAN

-
+
diff --git a/root/no_result.tx b/root/no_result.tx index 884129f751..1bb1c8f090 100644 --- a/root/no_result.tx +++ b/root/no_result.tx @@ -5,8 +5,8 @@

No search results for [% $search_query %]

%% if $suggest { -
- Did you mean : + %% }