Skip to content

Commit

Permalink
Merge pull request #1680 from weather-gov/mgwalker/1530-afd-comboboxes
Browse files Browse the repository at this point in the history
Switch AFD WFO dropdown to a combo box
  • Loading branch information
greg-does-weather committed Sep 3, 2024
2 parents 08c89fb + 11fff6c commit f512c5a
Show file tree
Hide file tree
Showing 10 changed files with 800 additions and 560 deletions.
94 changes: 64 additions & 30 deletions tests/playwright/e2e/afd-page.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,36 @@ const path = require("path");

const { describe, beforeEach } = test;

const PRODUCT_PATH = path.resolve(__dirname, "..", "..", "api", "data", "testing", "products");
const PRODUCT_PATH = path.resolve(
__dirname,
"..",
"..",
"api",
"data",
"testing",
"products",
);
const OKX_REFERENCES = JSON.parse(
fs.readFileSync(path.join(PRODUCT_PATH, "types", "AFD", "locations", "OKX.json")).toString()
fs
.readFileSync(
path.join(PRODUCT_PATH, "types", "AFD", "locations", "OKX.json"),
)
.toString(),
);
const OVERALL_REFERENCES = JSON.parse(
fs.readFileSync(path.join(PRODUCT_PATH, "types", "AFD.json")).toString()
fs.readFileSync(path.join(PRODUCT_PATH, "types", "AFD.json")).toString(),
);
const firstId = OKX_REFERENCES["@graph"][0].id;

describe("AFD Page Tests", () => {
describe("Partial HTML routes", () => {
test("Can retrieve <option> elements html partial for version listing", async ({page}) => {
test("Can retrieve <option> elements html partial for version listing", async ({
page,
}) => {
await page.goto("http://localhost:8081/play/testing");
await page.goto("http://localhost:8080/wx/afd/locations/OKX");

const options = await page.locator('option:first-child');
const options = await page.locator("option:first-child");
await expect(options).toHaveCount(1);

// Make sure the first option has the same value/id
Expand All @@ -30,7 +44,7 @@ describe("AFD Page Tests", () => {
await expect(val).toEqual(firstId);
});

test("Can retreive html partial for AFD content", async({page}) => {
test("Can retreive html partial for AFD content", async ({ page }) => {
await page.goto("http://localhost:8081/play/testing");
// See tests/api/data/products/
// This is our OKX first AFD testing example data
Expand All @@ -45,11 +59,13 @@ describe("AFD Page Tests", () => {
});

describe("Querystrings and Redirects", () => {
beforeEach(async ({page}) => {
beforeEach(async ({ page }) => {
await page.goto("http://localhost:8081/play/testing");
});

test("Hitting /afd without any querystrings will redirect to the most recent anywhere", async ({page}) => {

test("Hitting /afd without any querystrings will redirect to the most recent anywhere", async ({
page,
}) => {
const expectedId = OVERALL_REFERENCES["@graph"][0].id;
await page.goto(`http://localhost:8080/afd`);
await page.waitForURL(`http://localhost:8080/afd/TAE/${expectedId}`);
Expand All @@ -60,7 +76,9 @@ describe("AFD Page Tests", () => {
await expect(actualId).toEqual(expectedId);
});

test("Hitting /afd with a WFO code querystring will give the most recent for that location", async ({page}) => {
test("Hitting /afd with a WFO code querystring will give the most recent for that location", async ({
page,
}) => {
const expectedId = OKX_REFERENCES["@graph"][0].id;
await page.goto("http://localhost:8080/afd?wfo=OKX");
await page.waitForURL(`http://localhost:8080/afd/OKX/${expectedId}`);
Expand All @@ -71,7 +89,9 @@ describe("AFD Page Tests", () => {
await expect(actualId).toEqual(expectedId);
});

test("Hitting /afd with a WFO code and and id as querystrings will give the right afd and selection in dropdown", async ({page}) => {
test("Hitting /afd with a WFO code and and id as querystrings will give the right afd and selection in dropdown", async ({
page,
}) => {
const expectedId = OKX_REFERENCES["@graph"][1].id;
await page.goto(`http://localhost:8080/afd?wfo=OKX&id=${expectedId}`);
await page.waitForURL(`http://localhost:8080/afd/OKX/${expectedId}`);
Expand All @@ -80,7 +100,7 @@ describe("AFD Page Tests", () => {
await expect(article).toHaveCount(1);
const actualId = await article.getAttribute("data-afd-id");
const select = await page.locator("form > select#version-selector");
const selectedId = await select.evaluate(el => el.value);
const selectedId = await select.evaluate((el) => el.value);

await expect(actualId).toEqual(expectedId);
await expect(selectedId).toEqual(expectedId);
Expand All @@ -94,60 +114,74 @@ describe("AFD Page Tests", () => {
* how these tests run.
*/
describe("Changing selections tests", () => {
beforeEach(async ({page}) => {
beforeEach(async ({ page }) => {
await page.goto("http://localhost:8081/play/testing");
await page.goto("http://localhost:8080/afd/OKX");
});

describe("WFO selector correctly populates based on path", () => {
test("with uppercase WFO code", async ({ page }) => {
const selected = page.locator("wx-afd-selector #wfo-selector");
const selected = page.locator(`wx-combo-box input[name="wfo"]`);
await expect(selected).toHaveValue("OKX");
});

test("with lowercase WFO code", async ({ page }) => {
await page.goto("http://localhost:8080/afd/okx");
const selected = page.locator("wx-afd-selector #wfo-selector");
const selected = page.locator(`wx-combo-box input[name="wfo"]`);
await expect(selected).toHaveValue("OKX");
});
});

test("Selecting third version and clicking button will load that version", async ({page}) => {
test("Selecting third version and clicking button will load that version", async ({
page,
}) => {
const thirdId = OKX_REFERENCES["@graph"][2].id;
const versionSelect = await page.locator('select#version-selector');
const versionSelect = await page.locator("select#version-selector");
await versionSelect.selectOption(thirdId);

const button = await page.locator(`form#afd-selection-form > button[type="submit"]`);
const button = await page.locator(
`form#afd-selection-form > button[type="submit"]`,
);
await button.click();

await page.waitForURL(`http://localhost:8080/afd/OKX/${thirdId}`);

const article = await page.locator("article");
const actualId = await article.getAttribute("data-afd-id");
const updatedSelect = await page.locator('select#version-selector');
const selectedValue = await updatedSelect.evaluate(el => el.value);
const wfoSelect = await page.locator('select#wfo-selector');
const wfoValue = await wfoSelect.evaluate(el => el.value);
const updatedSelect = await page.locator("select#version-selector");
const selectedValue = await updatedSelect.evaluate((el) => el.value);
const wfoSelect = await page.locator(`wx-combo-box input[name="wfo"]`);
const wfoValue = await wfoSelect.evaluate((el) => el.value);

await expect(actualId).toEqual(thirdId);
await expect(wfoValue).toEqual("OKX");
await expect(selectedValue).toEqual(thirdId);
});

test("Selecting an alternate WFO will update the version selector and document", async ({page}) => {
test("Selecting an alternate WFO will update the version selector and document", async ({
page,
}) => {
const targetId = OVERALL_REFERENCES["@graph"][0].id;
const wfoSelect = await page.locator("select#wfo-selector");
await wfoSelect.selectOption("TAE");

const button = await page.locator(`form#afd-selection-form > button[type="submit"]`);

// Playwright won't click things that aren't visible, so drop into the
// browser context and do it there. The browser don't care.
await page.evaluate(() => {
document.querySelector(`wx-combo-box ul li[data-value="TAE"]`).click();
});

const button = await page.locator(
`form#afd-selection-form > button[type="submit"]`,
);
await button.click();

const article = await page.locator("article");
const articleId = await article.getAttribute("data-afd-id");
const updatedSelect = await page.locator("select#wfo-selector");
const selectedWFO = await updatedSelect.evaluate(el => el.value);
const updatedSelect = await page.locator(
`wx-combo-box input[name="wfo"]`,
);
const selectedWFO = await updatedSelect.evaluate((el) => el.value);
const versionSelect = await page.locator("select#version-selector");
const selectedVersion = await versionSelect.evaluate(el => el.value);
const selectedVersion = await versionSelect.evaluate((el) => el.value);

await expect(articleId).toEqual(targetId);
await expect(selectedWFO).toEqual("TAE");
Expand Down
151 changes: 151 additions & 0 deletions tests/playwright/e2e/combo-box-location.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* eslint-disable no-await-in-loop, no-plusplus */
const { test, expect } = require("@playwright/test");
const arcQueryData = require("../mock-data/arc.query.json");
const arcQueryItemsData = require("../mock-data/arc.query.items.json");

const { describe, beforeEach } = test;

describe("wx-combo-box-location tests", () => {
beforeEach(async ({ page }) => {
// Stub the ArcGIS API requests
// so that they use saved data
await page.route(
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/suggest*",
async (route) => {
await route.fulfill({ json: arcQueryData });
},
);
await page.route(
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find*",
async (route) => {
const url = new URL(route.request().url());
const key = url.searchParams.get("magicKey");
const mockData = arcQueryItemsData[key];
if (mockData) {
await route.fulfill({ json: mockData });
} else {
await route.abort();
}
},
);

await page.goto("http://localhost:8080");
});

test("Can find the combo-box element", async ({ page }) => {
const combobox = page.locator("wx-combo-box-location");

await expect(combobox).toHaveCount(1);
await expect(combobox).toBeVisible();
});

describe("When typing into the input", () => {
beforeEach(async ({ page }) => {
const comboInput = page.locator("wx-combo-box-location > input");
await comboInput.fill("Arlin");
});

test("it displays a visible dropdown list", async ({ page }) => {
const list = page.locator("wx-combo-box-location ul");

await expect(list).toBeVisible();
});

test("the first item in the dropdown list is aria-selected", async ({
page,
}) => {
const ariaSelectedItem = page.locator(
'wx-combo-box-location ul li:first-child[aria-selected="true"]',
);

await expect(ariaSelectedItem).toHaveCount(1);
});

test("typing the down key pseudo-focuses the second element", async ({
page,
}) => {
const correctSelection = page.locator(
'wx-combo-box-location ul > li[aria-selected="true"]:nth-child(2)',
);
await page.keyboard.press("ArrowDown");

await expect(correctSelection).toHaveCount(1);
await expect(correctSelection).toBeVisible();
});

test("typing down twice pseudo-focuses the third element", async ({
page,
}) => {
const correctSelection = page.locator(
'wx-combo-box-location ul > li[aria-selected="true"]:nth-child(3)',
);
await page.keyboard.press("ArrowDown");
await page.keyboard.press("ArrowDown");

await expect(correctSelection).toHaveCount(1);
await expect(correctSelection).toBeVisible();
});

test("pressing the up arrow collapses the search list", async ({
page,
}) => {
const resultList = page.locator("wx-combo-box-location ul");
await page.keyboard.press("ArrowUp");

await expect(resultList).not.toBeVisible();
});

test("pressing Enter selects an item, closing the list from view", async ({
page,
}) => {
// Ensure that the page doesn't navigate so we can test the presence of
// the loader
await page.route(
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find*",
async (route) => {
await route.abort();
},
{ times: 1 },
);
await page.keyboard.press("ArrowDown");
await page.keyboard.press("ArrowDown");
await page.keyboard.press("Enter");
const list = page.locator("wx-combo-box-location ul");

await expect(list).not.toBeVisible();
});

test("clicking selects the second item and navigates to the location page", async ({
page,
}) => {
const thirdItem = page.locator(
"wx-combo-box-location ul > li:nth-child(3)",
);
await thirdItem.click();
await page.waitForNavigation();

await expect(page.url()).toMatch(/.*\/point\/.*/);
});

test("clicking the second item displays the loading element", async ({
page,
}) => {
// Ensure that the page doesn't navigate so we can test the presence of
// the loader
await page.route(
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find*",
async (route) => {
await route.abort();
},
{ times: 1 },
);
const thirdItem = page.locator(
"wx-combo-box-location ul > li:nth-child(3)",
);
const loader = page.locator("wx-loader");
await thirdItem.click();

await expect(loader).toBeVisible();
});
});
});
Loading

0 comments on commit f512c5a

Please sign in to comment.