Skip to content

Commit

Permalink
[Issue #2029] Prepare for Nava fork to HHS
Browse files Browse the repository at this point in the history
  • Loading branch information
acouch committed Sep 18, 2024
1 parent 444fa7a commit ab6465a
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 41 deletions.
2 changes: 2 additions & 0 deletions .grype.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ ignore:
- vulnerability: CVE-2023-39418
- vulnerability: CVE-2023-5868
- vulnerability: CVE-2023-5870
# Affects SSR in pages router which we don't use https://github.com/advisories/GHSA-gp8f-8m3g-qvj9
- vulnerability: GHSA-gp8f-8m3g-qvj9
4 changes: 2 additions & 2 deletions analytics/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ ifeq "$(PY_RUN_APPROACH)" "local"
POETRY := poetry run
GITHUB := gh
else
POETRY := docker-compose run $(DOCKER_EXEC_ARGS) --rm $(APP_NAME) poetry run
GITHUB := docker-compose run $(DOCKER_EXEC_ARGS) --rm $(APP_NAME) gh
POETRY := docker compose run $(DOCKER_EXEC_ARGS) --rm $(APP_NAME) poetry run
GITHUB := docker compose run $(DOCKER_EXEC_ARGS) --rm $(APP_NAME) gh
endif

# Docker user configuration
Expand Down
14 changes: 7 additions & 7 deletions analytics/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ npm-debug.log*

# pa11y
screenshots-output/*
pa11y_output.txt
pa11y_output.txt
33 changes: 33 additions & 0 deletions frontend/src/app/[locale]/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import BetaAlert from "src/components/BetaAlert";
import { GridContainer } from "@trussworks/react-uswds";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { getTranslations, unstable_setRequestLocale } from "next-intl/server";
import { Metadata } from "next";

export async function generateMetadata() {
const t = await getTranslations({ locale: "en" });
const meta: Metadata = {
title: t("ErrorPages.page_not_found.title"),
description: t("Index.meta_description"),
};
return meta;
}

export default function NotFound() {
unstable_setRequestLocale("en");
const t = useTranslations("ErrorPages.page_not_found");

return (
<>
<BetaAlert />
<GridContainer className="padding-y-1 tablet:padding-y-3 desktop-lg:padding-y-15">
<h1 className="nj-h1">{t("title")}</h1>
<p className="margin-bottom-2">{t("message_content_1")}</p>
<Link className="usa-button" href="/" key="returnToHome">
{t("visit_homepage_button")}
</Link>
</GridContainer>
</>
);
}
32 changes: 1 addition & 31 deletions frontend/tests/e2e/search/search-loading.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { Page, expect, test } from "@playwright/test";
import {
expectURLContainsQueryParam,
fillSearchInputAndSubmit,
} from "./searchSpecUtil";
import { fillSearchInputAndSubmit } from "./searchSpecUtil";

import { BrowserContextOptions } from "playwright-core";

Expand All @@ -18,33 +15,6 @@ test.describe("Search page tests", () => {
await page.goto("/search?_ff=showSearchV0:true");
});

test("should return 0 results when searching for obscure term", async ({
page,
browserName,
}: PageProps) => {
// TODO (Issue #2005): fix test for webkit
test.skip(
browserName === "webkit",
"Skipping test for WebKit due to a query param issue.",
);

const searchTerm = "0resultearch";

await fillSearchInputAndSubmit(searchTerm, page);
await new Promise((resolve) => setTimeout(resolve, 3250));
expectURLContainsQueryParam(page, "query", searchTerm);

// eslint-disable-next-line testing-library/prefer-screen-queries
const resultsHeading = page.getByRole("heading", {
name: /0 Opportunities/i,
});
await expect(resultsHeading).toBeVisible();

await expect(page.locator("div.usa-prose h2")).toHaveText(
"Your search did not return any results.",
);
});

test("should show and hide loading state", async ({
page,
browserName,
Expand Down
47 changes: 47 additions & 0 deletions frontend/tests/e2e/search/search-no-results.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Page, expect, test } from "@playwright/test";
import {
expectURLContainsQueryParam,
fillSearchInputAndSubmit,
} from "./searchSpecUtil";

import { BrowserContextOptions } from "playwright-core";

interface PageProps {
page: Page;
browserName?: string;
contextOptions?: BrowserContextOptions;
}

test.describe("Search page tests", () => {
test.beforeEach(async ({ page }: PageProps) => {
// Navigate to the search page with the feature flag set
await page.goto("/search?_ff=showSearchV0:true");
});

test("should return 0 results when searching for obscure term", async ({
page,
browserName,
}: PageProps) => {
// TODO (Issue #2005): fix test for webkit
test.skip(
browserName === "webkit",
"Skipping test for WebKit due to a query param issue.",
);

const searchTerm = "0resultearch";

await fillSearchInputAndSubmit(searchTerm, page);
await new Promise((resolve) => setTimeout(resolve, 3250));
expectURLContainsQueryParam(page, "query", searchTerm);

// eslint-disable-next-line testing-library/prefer-screen-queries
const resultsHeading = page.getByRole("heading", {
name: /0 Opportunities/i,
});
await expect(resultsHeading).toBeVisible();

await expect(page.locator("div.usa-prose h2")).toHaveText(
"Your search did not return any results.",
);
});
});
132 changes: 132 additions & 0 deletions frontend/tests/e2e/search/searchUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// =========================
// Test Helper Functions
// =========================

import { Locator, Page, expect } from "@playwright/test";

export function getSearchInput(page: Page) {
return page.locator("#query");
}

export async function fillSearchInputAndSubmit(term: string, page: Page) {
const searchInput = getSearchInput(page);
await searchInput.fill(term);
await page.click(".usa-search >> button[type='submit']");
expectURLContainsQueryParam(page, "query", term);
}

export function expectURLContainsQueryParam(
page: Page,
queryParamName: string,
queryParamValue: string,
) {
const currentURL = page.url();
expect(currentURL).toContain(`${queryParamName}=${queryParamValue}`);
}

export async function waitForURLContainsQueryParam(
page: Page,
queryParamName: string,
queryParamValue: string,
timeout = 30000, // query params get set after a debounce period
) {
const endTime = Date.now() + timeout;

while (Date.now() < endTime) {
const url = new URL(page.url());
const params = new URLSearchParams(url.search);
const actualValue = params.get(queryParamName);

if (actualValue === queryParamValue) {
return;
}

await page.waitForTimeout(500);
}

throw new Error(
`URL did not contain query parameter ${queryParamName}=${queryParamValue} within ${timeout}ms`,
);
}

export async function clickSearchNavLink(page: Page) {
await page.click("nav >> text=Search");
}

export function getMobileMenuButton(page: Page) {
return page.locator("button >> text=MENU");
}

export async function hasMobileMenu(page: Page) {
const menuButton = getMobileMenuButton(page);
return await menuButton.isVisible();
}

export async function clickMobileNavMenu(menuButton: Locator) {
await menuButton.click();
}

export async function expectCheckboxIDIsChecked(
page: Page,
idWithHash: string,
) {
const checkbox: Locator = page.locator(idWithHash);
await expect(checkbox).toBeChecked();
}

export async function toggleCheckboxes(
page: Page,
checkboxObject: Record<string, string>,
queryParamName: string,
) {
let runningQueryParams = "";
for (const [checkboxID, queryParamValue] of Object.entries(checkboxObject)) {
await toggleCheckbox(page, checkboxID);
runningQueryParams += runningQueryParams
? `,${queryParamValue}`
: queryParamValue;
await waitForURLContainsQueryParam(
page,
queryParamName,
runningQueryParams,
);
}
}

export async function toggleCheckbox(page: Page, idWithoutHash: string) {
const checkBox = page.locator(`label[for=${idWithoutHash}]`);
await checkBox.isEnabled();
await checkBox.click();
}

export async function refreshPageWithCurrentURL(page: Page) {
const currentURL = page.url();
await page.goto(currentURL); // go to new url in same tab
return page;
}

export async function selectSortBy(page: Page, sortByValue: string) {
await page.locator("#search-sort-by-select").selectOption(sortByValue);
}

export async function expectSortBy(page: Page, value: string) {
const selectedValue = await page
.locator('select[name="search-sort-by"]')
.inputValue();
expect(selectedValue).toBe(value);
}

export async function waitForSearchResultsLoaded(page: Page) {
// Wait for number of opportunities to show
const resultsHeading = page.locator('h2:has-text("Opportunities")');
await resultsHeading.waitFor({ state: "visible", timeout: 60000 });
}

export async function clickAccordionWithTitle(
page: Page,
accordionTitle: string,
) {
await page
.locator(`button.usa-accordion__button:has-text("${accordionTitle}")`)
.click();
}

0 comments on commit ab6465a

Please sign in to comment.