Skip to content

Commit af602e8

Browse files
[NDH-452] Playwright Tests for Documentation (#354)
* created swagger playwright tests * adding regression test to check for faulty param * removing no longer needed timeouts * adding redoc playwright tests * adding regression test to check for faulty param * adding a constants file to reduce maintanence burden
1 parent bb7b4a3 commit af602e8

File tree

7 files changed

+330
-20
lines changed

7 files changed

+330
-20
lines changed

playwright/tests/constants.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const FHIR_RESOURCES = [
2+
"Endpoint",
3+
"Location",
4+
"Organization",
5+
"Practitioner",
6+
"PractitionerRole",
7+
"metadata",
8+
] as const
9+
10+
export type FHIRResource = (typeof FHIR_RESOURCES)[number]
11+
12+
export let ORGANIZATION: { npi: string; id: string; name: string } = {
13+
npi: "UNSET",
14+
id: "UNSET",
15+
name: "UNSET",
16+
}
17+
18+
export let PRACTITIONER: { npi: string; id: string; name: string } = {
19+
npi: "UNSET",
20+
id: "UNSET",
21+
name: "UNSET",
22+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { expect, test } from "@playwright/test"
2+
import { FHIR_RESOURCES } from "../constants"
3+
4+
test.describe("Redoc", () => {
5+
test("loads successfully", async ({ page }) => {
6+
await page.goto("/fhir/docs/redoc/")
7+
8+
await expect(page.locator(".redoc-wrap")).toBeVisible()
9+
await expect(page.locator(".api-info h1")).toBeVisible()
10+
})
11+
12+
test("displays all FHIR resource sections in navigation", async ({ page }) => {
13+
await page.goto("/fhir/docs/redoc/")
14+
await expect(page.locator(".redoc-wrap")).toBeVisible()
15+
16+
for (const resource of FHIR_RESOURCES) {
17+
const navItem = page.locator(`li[data-item-id="tag/${resource}"]`)
18+
await expect(navItem).toBeVisible()
19+
}
20+
})
21+
22+
// regression test: "search" parameter should not appear in any endpoint
23+
test("does not display invalid 'search' parameter", async ({ page }) => {
24+
await page.goto("/fhir/docs/redoc/")
25+
await expect(page.locator(".redoc-wrap")).toBeVisible()
26+
27+
// check Organization endpoint
28+
const orgSection = page.locator("#tag\\/Organization\\/operation\\/Organization_list")
29+
await expect(orgSection.getByText("query Parameters")).toBeVisible()
30+
await expect(orgSection.locator("td").filter({ hasText: /^search$/ })).not.toBeVisible()
31+
32+
// check Practitioner endpoint
33+
const practitionerSection = page.locator("#tag\\/Practitioner\\/operation\\/Practitioner_list")
34+
await expect(practitionerSection.getByText("query Parameters")).toBeVisible()
35+
await expect(practitionerSection.locator("td").filter({ hasText: /^search$/ })).not.toBeVisible()
36+
37+
})
38+
39+
test("can navigate to Organization section", async ({ page }) => {
40+
await page.goto("/fhir/docs/redoc/")
41+
await expect(page.locator(".redoc-wrap")).toBeVisible()
42+
43+
const navItem = page.locator('li[data-item-id="tag/Organization"] > label')
44+
await navItem.click()
45+
46+
await expect(page.locator("#tag\\/Organization h2")).toBeVisible()
47+
})
48+
49+
test("can navigate to Practitioner section", async ({ page }) => {
50+
await page.goto("/fhir/docs/redoc/")
51+
await expect(page.locator(".redoc-wrap")).toBeVisible()
52+
53+
const navItem = page.locator('li[data-item-id="tag/Practitioner"] > label')
54+
await navItem.click()
55+
56+
await expect(page.locator("#tag\\/Practitioner h2")).toBeVisible()
57+
})
58+
59+
test("can navigate to Location section", async ({ page }) => {
60+
await page.goto("/fhir/docs/redoc/")
61+
await expect(page.locator(".redoc-wrap")).toBeVisible()
62+
63+
const navItem = page.locator('li[data-item-id="tag/Location"] > label')
64+
await navItem.click()
65+
66+
await expect(page.locator("#tag\\/Location h2")).toBeVisible()
67+
})
68+
69+
test("can navigate to Endpoint section", async ({ page }) => {
70+
await page.goto("/fhir/docs/redoc/")
71+
await expect(page.locator(".redoc-wrap")).toBeVisible()
72+
73+
const navItem = page.locator('li[data-item-id="tag/Endpoint"] > label')
74+
await navItem.click()
75+
76+
await expect(page.locator("#tag\\/Endpoint h2")).toBeVisible()
77+
})
78+
79+
test("can navigate to PractitionerRole section", async ({ page }) => {
80+
await page.goto("/fhir/docs/redoc/")
81+
await expect(page.locator(".redoc-wrap")).toBeVisible()
82+
83+
const navItem = page.locator('li[data-item-id="tag/PractitionerRole"] > label')
84+
await navItem.click()
85+
86+
await expect(page.locator("#tag\\/PractitionerRole h2")).toBeVisible()
87+
})
88+
89+
test("can navigate to metadata section", async ({ page }) => {
90+
await page.goto("/fhir/docs/redoc/")
91+
await expect(page.locator(".redoc-wrap")).toBeVisible()
92+
93+
const navItem = page.locator('li[data-item-id="tag/metadata"] > label')
94+
await navItem.click()
95+
96+
await expect(page.locator("#tag\\/metadata h2")).toBeVisible()
97+
})
98+
99+
})
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
import { expect, test } from "@playwright/test"
2+
import { FHIR_RESOURCES } from "../constants"
3+
4+
test.describe("Swagger", () => {
5+
test("loads successfully", async ({ page }) => {
6+
await page.goto("/fhir/docs/")
7+
8+
await expect(page.locator("#swagger-ui")).toBeVisible()
9+
await expect(page.locator(".info .title")).toContainText("NPD FHIR API")
10+
})
11+
12+
test("displays all FHIR resource tags", async ({ page }) => {
13+
await page.goto("/fhir/docs/")
14+
await expect(page.locator("#swagger-ui")).toBeVisible()
15+
16+
for (const resource of FHIR_RESOURCES) {
17+
const tag = page.locator(`h3.opblock-tag[data-tag="${resource}"]`)
18+
await expect(tag).toBeVisible()
19+
}
20+
})
21+
22+
test("regression test: 'search' parameter should not appear in any endpoint", async ({ page }) => {
23+
await page.goto("/fhir/docs/")
24+
await expect(page.locator("#swagger-ui")).toBeVisible()
25+
26+
// check Organization endpoint
27+
const orgOperation = page.locator("#operations-Organization-Organization_list")
28+
await orgOperation.locator(".opblock-summary-control").click()
29+
await expect(orgOperation.locator(".opblock-body")).toBeVisible()
30+
31+
await expect(orgOperation.locator("tr[data-param-name]").first()).toBeAttached()
32+
await expect(orgOperation.locator("tr[data-param-name='search']")).not.toBeAttached()
33+
34+
// check Practitioner endpoint
35+
const practitionerOperation = page.locator("#operations-Practitioner-Practitioner_list")
36+
await practitionerOperation.locator(".opblock-summary-control").click()
37+
await expect(practitionerOperation.locator(".opblock-body")).toBeVisible()
38+
39+
await expect(practitionerOperation.locator("tr[data-param-name]").first()).toBeAttached()
40+
await expect(practitionerOperation.locator("tr[data-param-name='search']")).not.toBeAttached()
41+
})
42+
})
43+
44+
test.describe("Swagger - Organization", () => {
45+
test("GET /fhir/Organization/", async ({ page }) => {
46+
await page.goto("/fhir/docs/")
47+
await expect(page.locator("#swagger-ui")).toBeVisible()
48+
49+
const operation = page.locator("#operations-Organization-Organization_list")
50+
await operation.locator(".opblock-summary-control").click()
51+
await operation.locator(".try-out__btn").click()
52+
await operation.locator(".execute").click()
53+
54+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
55+
await expect(liveResponse).toContainText("200")
56+
})
57+
58+
test("GET /fhir/Organization/{id}/", async ({ page }) => {
59+
// First get a valid organization ID
60+
const orgResponse = await page.request.get("/fhir/Organization/?identifier=1234567893")
61+
const orgData = await orgResponse.json()
62+
const orgId = orgData.results.entry[0].resource.id
63+
64+
await page.goto("/fhir/docs/")
65+
await expect(page.locator("#swagger-ui")).toBeVisible()
66+
67+
const operation = page.locator("#operations-Organization-Organization_retrieve")
68+
await operation.locator(".opblock-summary-control").click()
69+
await operation.locator(".try-out__btn").click()
70+
71+
await operation.locator("tr[data-param-name='id'] input").fill(orgId)
72+
await operation.locator(".execute").click()
73+
74+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
75+
await expect(liveResponse).toContainText("200")
76+
})
77+
})
78+
79+
test.describe("Swagger - Practitioner", () => {
80+
test("GET /fhir/Practitioner/", async ({ page }) => {
81+
await page.goto("/fhir/docs/")
82+
await expect(page.locator("#swagger-ui")).toBeVisible()
83+
84+
const operation = page.locator("#operations-Practitioner-Practitioner_list")
85+
await operation.locator(".opblock-summary-control").click()
86+
await operation.locator(".try-out__btn").click()
87+
await operation.locator(".execute").click()
88+
89+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
90+
await expect(liveResponse).toContainText("200")
91+
})
92+
93+
test("GET /fhir/Practitioner/{id}/", async ({ page }) => {
94+
// First get a valid practitioner ID
95+
const response = await page.request.get("/fhir/Practitioner/?identifier=1234567894")
96+
const data = await response.json()
97+
const practitionerId = data.results.entry[0].resource.id
98+
99+
await page.goto("/fhir/docs/")
100+
await expect(page.locator("#swagger-ui")).toBeVisible()
101+
102+
const operation = page.locator("#operations-Practitioner-Practitioner_retrieve")
103+
await operation.locator(".opblock-summary-control").click()
104+
await operation.locator(".try-out__btn").click()
105+
106+
await operation.locator("tr[data-param-name='id'] input").fill(practitionerId)
107+
await operation.locator(".execute").click()
108+
109+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
110+
await expect(liveResponse).toContainText("200")
111+
})
112+
})
113+
114+
test.describe("Swagger - Location", () => {
115+
test("GET /fhir/Location/", async ({ page }) => {
116+
await page.goto("/fhir/docs/")
117+
await expect(page.locator("#swagger-ui")).toBeVisible()
118+
119+
const operation = page.locator("#operations-Location-Location_list")
120+
await operation.locator(".opblock-summary-control").click()
121+
await operation.locator(".try-out__btn").click()
122+
await operation.locator(".execute").click()
123+
124+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
125+
await expect(liveResponse).toContainText("200")
126+
})
127+
128+
// test("GET /fhir/Location/{id}/", async ({ page }) => {
129+
// we dont have any locations currently in test database
130+
// })
131+
})
132+
133+
test.describe("Swagger - Endpoint", () => {
134+
test("GET /fhir/Endpoint/", async ({ page }) => {
135+
await page.goto("/fhir/docs/")
136+
await expect(page.locator("#swagger-ui")).toBeVisible()
137+
138+
const operation = page.locator("#operations-Endpoint-Endpoint_list")
139+
await operation.locator(".opblock-summary-control").click()
140+
await operation.locator(".try-out__btn").click()
141+
await operation.locator(".execute").click()
142+
143+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
144+
await expect(liveResponse).toContainText("200")
145+
})
146+
147+
test("GET /fhir/Endpoint/{id}/", async ({ page }) => {
148+
// First get a valid endpoint ID
149+
const response = await page.request.get("/fhir/Endpoint/")
150+
const data = await response.json()
151+
152+
const endpointId = data.results.entry[0].resource.id
153+
154+
await page.goto("/fhir/docs/")
155+
await expect(page.locator("#swagger-ui")).toBeVisible()
156+
157+
const operation = page.locator("#operations-Endpoint-Endpoint_retrieve")
158+
await operation.locator(".opblock-summary-control").click()
159+
await operation.locator(".try-out__btn").click()
160+
161+
await operation.locator("tr[data-param-name='id'] input").fill(endpointId)
162+
await operation.locator(".execute").click()
163+
164+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
165+
await expect(liveResponse).toContainText("200")
166+
})
167+
})
168+
169+
test.describe("Swagger - PractitionerRole", () => {
170+
test("GET /fhir/PractitionerRole/", async ({ page }) => {
171+
await page.goto("/fhir/docs/")
172+
await expect(page.locator("#swagger-ui")).toBeVisible()
173+
174+
const operation = page.locator("#operations-PractitionerRole-PractitionerRole_list")
175+
await operation.locator(".opblock-summary-control").click()
176+
await operation.locator(".try-out__btn").click()
177+
await operation.locator(".execute").click()
178+
179+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
180+
await expect(liveResponse).toContainText("200")
181+
})
182+
183+
// test("GET /fhir/PractitionerRole/{id}/", async ({ page }) => {
184+
// // we dont have any PractitionerRoles currently in test database
185+
// })
186+
})
187+
188+
test.describe("Swagger - metadata", () => {
189+
test("GET /fhir/metadata/", async ({ page }) => {
190+
await page.goto("/fhir/docs/")
191+
await expect(page.locator("#swagger-ui")).toBeVisible()
192+
193+
const operation = page.locator("#operations-metadata-metadata_retrieve")
194+
await operation.locator(".opblock-summary-control").click()
195+
await operation.locator(".try-out__btn").click()
196+
await operation.locator(".execute").click()
197+
198+
const liveResponse = operation.locator(".live-responses-table tbody .response-col_status")
199+
await expect(liveResponse).toContainText("200")
200+
})
201+
})

playwright/tests/organizations/organizations.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { expect, test } from "@playwright/test"
2+
import { ORGANIZATION } from "../constants"
23

3-
let organization: { npi: string; id: string; name: string } = {
4-
npi: "UNSET",
5-
id: "UNSET",
6-
name: "UNSET",
7-
}
4+
let organization = ORGANIZATION
85

96
// load a known organization record from the API before running tests
107
test.beforeAll(async ({ request }) => {

playwright/tests/practitioners/practitioners.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { expect, test } from "@playwright/test"
2+
import { PRACTITIONER } from "../constants"
23

3-
let practitioner: { npi: string; id: string; name: string } = {
4-
npi: "UNSET",
5-
id: "UNSET",
6-
name: "UNSET",
7-
}
4+
let practitioner = PRACTITIONER
85

96
// load a known practitioner record from the API before running tests
107
test.beforeAll(async ({ request }) => {

playwright/tests/user-journeys/organization-journey.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { expect, test } from "@playwright/test"
2+
import { ORGANIZATION } from "../constants"
23

3-
let organization: { npi: string; id: string; name: string } = {
4-
npi: "UNSET",
5-
id: "UNSET",
6-
name: "UNSET",
7-
}
4+
let organization = ORGANIZATION
85

96
// load a known practitioner record from the API before running tests
107
test.beforeAll(async ({ request }) => {

playwright/tests/user-journeys/practitioner-journey.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { expect, test } from "@playwright/test"
2+
import { PRACTITIONER } from "../constants"
23

3-
let practitioner: { npi: string; id: string; name: string } = {
4-
npi: "UNSET",
5-
id: "UNSET",
6-
name: "UNSET",
7-
}
4+
let practitioner = PRACTITIONER
85

96
// load a known practitioner record from the API before running tests
107
test.beforeAll(async ({ request }) => {

0 commit comments

Comments
 (0)