Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions backend/npdfhir/management/commands/seedsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def to_json(self, **record) -> str:
def generate_sample_organizations(self, qty: int = 25):
fake = Faker()
for i in range(qty):
name = fake.company()
name = f"TEST {fake.company()}"
org = create_organization(
name=name,
# not bothering with checksum here
Expand All @@ -34,19 +34,21 @@ def generate_sample_organizations(self, qty: int = 25):
other_issuer=fake.company(),
)
self.stdout.write(f"created Organization: {org.id} {name}")

def generate_sample_practitioners(self, qty: int = 25):
fake = Faker()
for i in range(qty):
first_name = fake.first_name()
first_name = f"TEST {fake.first_name()}"
last_name = fake.last_name()
practitioner = create_practitioner(
first_name=first_name,
last_name=last_name,
npi_value=self.generate_npi(),
gender=random.choice(["M", "F"]),
)
self.stdout.write(f"created Practitioner: {practitioner.individual.id} {first_name} {last_name}")
self.stdout.write(
f"created Practitioner: {practitioner.individual.id} {first_name} {last_name}"
)

def handle(self, *args, **options):
if options.get("seed", None):
Expand Down
56 changes: 39 additions & 17 deletions frontend/src/pages/Organization/OrganizationSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Alert, Button, Pagination, Dropdown, type DropdownChangeObject } from "@cmsgov/design-system"
import {
Alert,
Button,
Pagination,
Dropdown,
type DropdownChangeObject,
} from "@cmsgov/design-system"
import classNames from "classnames"
import React, { type ChangeEvent, type FormEvent, useState } from "react"
import { useTranslation } from "react-i18next"
Expand All @@ -11,7 +17,10 @@ import { useSearchDispatch, useSearchState } from "../../state/Search/useSearch"
import layout from "../Layout.module.css"
import search from "../Search.module.css"
import { ListedOrganization } from "./ListedOrganization"
import { ORGANIZATION_SORT_OPTIONS, type OrganizationSortKey } from "../../state/requests/organizations"
import {
ORGANIZATION_SORT_OPTIONS,
type OrganizationSortKey,
} from "../../state/requests/organizations"
import { useOrganizationsAPI } from "../../state/requests/organizations"
import type { FHIROrganization } from "../../@types/fhir"
import { FaHospital } from "react-icons/fa"
Expand All @@ -27,7 +36,7 @@ const OrganizationSearchForm: React.FC = () => {
error: searchError,
data,
pagination,
sort
sort,
} = useSearchState<FHIROrganization>()

const [query, setQueryValue] = useState<string>(initialQuery || "")
Expand All @@ -54,7 +63,7 @@ const OrganizationSearchForm: React.FC = () => {
([value, option]) => ({
value: value as OrganizationSortKey,
label: t(option.labelKey),
})
}),
)

return (
Expand Down Expand Up @@ -85,9 +94,13 @@ const OrganizationSearchForm: React.FC = () => {
<Button
type="submit"
variation="solid"
disabled={query.length < 1 || isLoading && !isBackgroundLoading}
disabled={
query.length < 1 || (isLoading && !isBackgroundLoading)
}
>
{isLoading && !isBackgroundLoading ? "Searching..." : "Search"}
{isLoading && !isBackgroundLoading
? "Searching..."
: "Search organizations"}
</Button>
</div>
</div>
Expand All @@ -109,13 +122,25 @@ const OrganizationSearchForm: React.FC = () => {
<>
{pagination && (
<>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', gap: '8px' }}>
<PaginationCaption pagination={pagination} />
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
{t("organizations.sort.by")}
<Dropdown
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<div style={{ display: "flex", gap: "8px" }}>
<PaginationCaption pagination={pagination} />
</div>
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
{t("organizations.sort.by")}
<Dropdown
label=""
name="sort-dropdown-field"
labelClassName="ds-u-display--none"
Expand Down Expand Up @@ -168,10 +193,7 @@ const OrganizationSearchForm: React.FC = () => {

export const OrganizationSearch = () => {
return (
<SearchProvider
useSearchAPI={useOrganizationsAPI}
defaultSort="name-asc"
>
<SearchProvider useSearchAPI={useOrganizationsAPI} defaultSort="name-asc">
<OrganizationSearchForm />
</SearchProvider>
)
Expand Down
42 changes: 42 additions & 0 deletions playwright/tests/organizations/organizations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,48 @@ test.describe("Organization search", () => {
await page.getByRole("button", { name: "Search" }).click()
await expect(page.getByRole("link", { name: "AAA Test Org" })).toBeVisible()
})

test("search for a Organization and confirm pagination works", async ({ page }) => {
await page.goto("/organizations/search")
await expect(page).toHaveURL("/organizations/search")
await expect(page.getByText("Search organizations")).toBeVisible()

await page
.getByRole("textbox", { name: "Name or NPI" })
.click()
await page
.getByRole("textbox", { name: "Name or NPI" })
.fill("TEST")
await page.getByRole("button", { name: "Search" }).click()
await expect(page.getByRole("link", { name: /AAA Test Org/i })).toBeVisible()
await expect(page.getByRole("caption")).toContainText(
"Showing 1 - 10 of 26",
)

await expect(
page.locator("[data-testid='searchresults']").getByRole("listitem"),
).toHaveCount(10)

await page.getByLabel("Next Page").first().click()

await expect(page).toHaveURL(/page=2/)
await expect(page.getByRole("caption")).toContainText(
"Showing 11 - 20 of 26",
)
await expect(
page.locator("[data-testid='searchresults']").getByRole("listitem"),
).toHaveCount(10)

await page.getByLabel("Next Page").first().click()

await expect(page).toHaveURL(/page=3/)
await expect(page.locator("span[role='caption']")).toContainText(
"Showing 21 - 26 of 26",
)
await expect(
page.locator("[data-testid='searchresults']").getByRole("listitem"),
).toHaveCount(6)
})
})

test.describe("Organization show", () => {
Expand Down
42 changes: 42 additions & 0 deletions playwright/tests/practitioners/practitioners.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,48 @@ test.describe("Practitioner search", () => {
await expect(page.getByTestId("practitioner-name")).toContainText(practitioner.name)
await expect(page.getByTestId("practitioner-npi")).toContainText(`NPI: ${practitioner.npi}`)
})

test("search for a Practitioner and confirm pagination works", async ({ page }) => {
await page.goto("/practitioners/search")
await expect(page).toHaveURL("/practitioners/search")
await expect(page.getByText("Search practitioners")).toBeVisible()

await page
.getByRole("textbox", { name: "Name or NPI" })
.click()
await page
.getByRole("textbox", { name: "Name or NPI" })
.fill("TEST")
await page.getByRole("button", { name: "Search" }).click()
await expect(page.getByRole("link", { name: /AAA Test Practitioner/i })).toBeVisible()
await expect(page.getByRole("caption")).toContainText(
"Showing 1 - 10 of 26",
)

await expect(
page.locator("[data-testid='searchresults']").getByRole("listitem"),
).toHaveCount(10)

await page.getByLabel("Next Page").first().click()

await expect(page).toHaveURL(/page=2/)
await expect(page.getByRole("caption")).toContainText(
"Showing 11 - 20 of 26",
)
await expect(
page.locator("[data-testid='searchresults']").getByRole("listitem"),
).toHaveCount(10)

await page.getByLabel("Next Page").first().click()

await expect(page).toHaveURL(/page=3/)
await expect(page.locator("span[role='caption']")).toContainText(
"Showing 21 - 26 of 26",
)
await expect(
page.locator("[data-testid='searchresults']").getByRole("listitem"),
).toHaveCount(6)
})
})

test.describe("Practitioner show", () => {
Expand Down
29 changes: 22 additions & 7 deletions playwright/tests/user-journeys/organization-journey.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,31 @@ test.describe("Organization Journey", () => {
await expect(banner.getByText(`NPI: ${organization.npi}`)).toBeVisible()
})

test("landing -> organization detail", async ({ page }) => {
test("landing -> last page -> organization detail", async ({ page }) => {
await page.goto("/")

await page.getByRole("link", { name: /search/i }).first().click()
await page.getByRole("link", { name: /organization/i }).click()

await page.getByRole("textbox", { name: "Name or NPI" }).fill("AAA Test Org")
await page.getByRole("textbox", { name: "Name or NPI" }).fill("TEST")
await page.getByRole("button", { name: "Search" }).click()

const sortButton = page.locator(".ds-c-dropdown__button")
await expect(sortButton).toContainText("Name (A-Z)")
await sortButton.click()
await expect(page.locator("[role='listbox']")).toBeVisible()
await page.getByRole("option", { name: "Name (Z-A)" }).click()
await expect(sortButton).toContainText("Name (Z-A)")

await page.getByLabel("Next Page").first().click()
await expect(page).toHaveURL(/page=2/)

await page.getByLabel("Next Page").first().click()
await expect(page).toHaveURL(/page=3/)

await expect(page.getByRole("link", { name: "AAA Test Org" })).toBeVisible()
await page.getByRole("link", { name: "AAA Test Org" }).click()

await expect(page).toHaveURL(`/organizations/${organization.id}`)
await expect(page.locator("div[role='heading']")).toContainText(organization.name)
})
Expand Down Expand Up @@ -113,7 +126,9 @@ test.describe("Organization Journey", () => {
await expect(page).toHaveURL(/sort=name-desc/)
await expect(sortButton).toContainText("Name (Z-A)")

await page.getByRole("link", { name: "AAA Test Org" }).click()
await expect(page).toHaveURL(`/organizations/${organization.id}`)
await page.getByRole("link", { name: /TEST/ }).first().click()

const banner = page.locator("section.banner")
await expect(banner.getByText(/TEST/)).toBeVisible()
})
})
25 changes: 19 additions & 6 deletions playwright/tests/user-journeys/practitioner-journey.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,31 @@ test.describe("Practitioner Journey", () => {
await expect(page.getByTestId("practitioner-npi")).toContainText(`NPI: ${practitioner.npi}`)
})

test("landing -> practitioner detail", async ({ page }) => {
test("landing -> last page -> practitioner detail", async ({ page }) => {
await page.goto("/")

await page.getByRole("link", { name: /search/i }).first().click()
await page.getByRole("link", { name: /practitioner/i }).click()

await page.getByRole("textbox", { name: "Name or NPI" }).fill("AAA Test Practitioner")
await page.getByRole("textbox", { name: "Name or NPI" }).fill("TEST")
await page.getByRole("button", { name: "Search" }).click()


const sortButton = page.locator(".ds-c-dropdown__button")
await expect(sortButton).toContainText("First Name (A-Z)")
await sortButton.click()
await expect(page.locator("[role='listbox']")).toBeVisible()
await page.getByRole("option", { name: "First Name (Z-A)" }).click()
await expect(sortButton).toContainText("First Name (Z-A)")

await page.getByLabel("Next Page").first().click()
await expect(page).toHaveURL(/page=2/)

await page.getByLabel("Next Page").first().click()
await expect(page).toHaveURL(/page=3/)

await expect(page.getByRole("link", { name: /AAA Test Practitioner/i })).toBeVisible()
await page.getByRole("link", { name: /AAA Test Practitioner/i }).click()

await expect(page).toHaveURL(`/practitioners/${practitioner.id}`)
await expect(page.getByTestId("practitioner-name")).toContainText(practitioner.name)
})
Expand Down