Skip to content

Commit 50c56dd

Browse files
frano-mFran McDade
andauthored
chore: update findable-ui to latest v38.0.0 (#4528) (#4532)
* chore: update findable-ui to latest v38.0.0 (#4528) * chore: update findable-ui to v38.1.0 (#4528) --------- Co-authored-by: Fran McDade <franmcdade@Frans-MacBook-Pro.local>
1 parent 3a803fd commit 50c56dd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+254
-294
lines changed

app/components/Index/common/indexTransformer.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { AzulSummaryResponse } from "@databiosphere/findable-ui/lib/apis/azul/common/entities";
2-
import { Summary } from "@databiosphere/findable-ui/lib/components/Index/components/Hero/components/Summaries/summaries";
32
import { formatCountSize } from "@databiosphere/findable-ui/lib/utils/formatCountSize";
43
import {
54
BIND_SUMMARY_RESPONSE,
@@ -20,23 +19,19 @@ export function getPluralizedMetadataLabel(
2019
}
2120

2221
/**
23-
* Maps index summaries from summary API response.
22+
* Maps entity list summaries from summary API response.
2423
* @param summaries - Summary list.
2524
* @param summaryResponse - Response model return from summary API.
26-
* @returns summary counts.
25+
* @returns summary key-value pairs (count, label).
2726
*/
28-
export function getSummaries(
27+
export function mapSummary(
2928
summaries: Array<keyof typeof SUMMARY>,
3029
summaryResponse: AzulSummaryResponse
31-
): Summary[] {
30+
): [string, string][] {
3231
return summaries.map((summary) => {
3332
const summaryBinderFn = BIND_SUMMARY_RESPONSE[summary];
34-
const count = summaryBinderFn(summaryResponse);
35-
const formattedCount = formatCountSize(count);
33+
const count = formatCountSize(summaryBinderFn(summaryResponse));
3634
const label = SUMMARY_LABEL[summary];
37-
return {
38-
count: formattedCount,
39-
label,
40-
};
35+
return [count, label];
4136
});
4237
}

app/components/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export { ManifestDownloadEntity } from "@databiosphere/findable-ui/lib/component
5454
export { ManifestDownloadForm } from "@databiosphere/findable-ui/lib/components/Export/components/ManifestDownload/components/ManifestDownloadForm/manifestDownloadForm";
5555
export { ManifestDownload } from "@databiosphere/findable-ui/lib/components/Export/components/ManifestDownload/manifestDownload";
5656
export { AzulFileDownload } from "@databiosphere/findable-ui/lib/components/Index/components/AzulFileDownload/azulFileDownload";
57-
export { Summaries } from "@databiosphere/findable-ui/lib/components/Index/components/Hero/components/Summaries/summaries";
5857
export {
5958
BackPageContentMainColumn,
6059
BackPageContentSideColumn,
Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,94 @@
1-
import test from "@playwright/test";
2-
import {
3-
testBulkDownloadIndexExportWorkflow,
4-
testIndexExportSummary,
5-
} from "../testFunctions";
1+
import test, { ElementHandle, Response, Page } from "@playwright/test";
2+
import { expect } from "@playwright/test";
3+
import { testBulkDownloadIndexExportWorkflow } from "../testFunctions";
64
import { ANVIL_TABS } from "./anvil-tabs";
5+
import { MUI_CLASSES, TEST_IDS } from "../features/common/constants";
76

8-
test("Smoke test File Manifest Request index export workflow on the Files tab", async ({
9-
page,
10-
}) => {
11-
test.setTimeout(120000);
12-
const testResult = await testBulkDownloadIndexExportWorkflow(
7+
test.describe("AnVIL Data Explorer Export", () => {
8+
test("Smoke test File Manifest Request index export workflow on the Files tab", async ({
139
page,
14-
ANVIL_TABS.FILES
15-
);
16-
if (!testResult) {
17-
test.fail();
18-
}
19-
});
10+
}) => {
11+
test.setTimeout(120000);
12+
const testResult = await testBulkDownloadIndexExportWorkflow(
13+
page,
14+
ANVIL_TABS.FILES
15+
);
16+
if (!testResult) {
17+
test.fail();
18+
}
19+
});
20+
21+
test("Verifies that the Selected Data Summary on the export page displays the same label and count as the summary on the BioSamples tab", async ({
22+
page,
23+
}) => {
24+
await page.goto("/biosamples");
25+
await page.waitForURL(/\/biosamples/);
26+
await Promise.all([waitForTestId(page, TEST_IDS.ENTITY_SUMMARY)]);
27+
28+
// Export button should be visible.
29+
const button = page.getByTestId(TEST_IDS.EXPORT_BUTTON);
30+
await expect(button).toBeVisible();
31+
32+
// Summary should be visible.
33+
const summaryLocator = page.getByTestId(TEST_IDS.ENTITY_SUMMARY);
34+
await expect(summaryLocator).toBeVisible();
35+
36+
// Get each summary span's inner text.
37+
const innerTexts = await summaryLocator
38+
.locator(MUI_CLASSES.TYPOGRAPHY) // Retrieves the count and label and omits the dot separator.
39+
.allTextContents();
2040

21-
test("Check that figures in the Selected Data Summary tab on the index export page matches figures on the index page on the BioSamples tab", async ({
22-
page,
23-
}) => {
24-
const testResult = await testIndexExportSummary(page, ANVIL_TABS.BIOSAMPLES);
25-
if (!testResult) {
26-
test.fail();
27-
}
41+
// Pair each summary item's label and count by iterating through the text contents
42+
// two at a time, and store them as [label, count] tuples in the summary array.
43+
const summary: [string, string][] = [];
44+
for (let i = 0; i < innerTexts.length; i += 2) {
45+
summary.push([innerTexts[i + 1], innerTexts[i]]);
46+
}
47+
48+
// Click the export button and wait for the summary API to be called.
49+
await Promise.all([
50+
button.click(),
51+
page.waitForURL(/\/export/),
52+
page.waitForResponse(urlOrPredicate),
53+
waitForTestId(page, TEST_IDS.EXPORT_SUMMARY),
54+
]);
55+
56+
// Export summary should be visible.
57+
const exportSummaryLocator = page.getByTestId(TEST_IDS.EXPORT_SUMMARY);
58+
await expect(exportSummaryLocator).toBeVisible();
59+
60+
// Test that each summary item is present in the export summary
61+
// with corresponding count.
62+
for (const [label, count] of summary) {
63+
const summaryItem = exportSummaryLocator
64+
.locator("> div")
65+
.filter({ hasText: label });
66+
await expect(summaryItem).toBeVisible();
67+
await expect(summaryItem).toContainText(count, { timeout: 5000 });
68+
}
69+
});
2870
});
71+
72+
/**
73+
* Checks if the response is the index summary API.
74+
* @param r - Response.
75+
* @returns boolean.
76+
*/
77+
function urlOrPredicate(r: Response): boolean {
78+
return r.url().includes("/index/summary") && r.status() === 200;
79+
}
80+
81+
/**
82+
* Waits for a locator to be visible.
83+
* @param page - Page.
84+
* @param testId - Test ID.
85+
* @returns Promise<void>.
86+
*/
87+
function waitForTestId(
88+
page: Page,
89+
testId: string
90+
): Promise<ElementHandle<HTMLElement | SVGElement>> {
91+
return page.waitForSelector(`[data-testid="${testId}"]`, {
92+
state: "visible",
93+
});
94+
}

e2e/features/common/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ export const MUI_CLASSES = {
1818
TABLE_ROW: ".MuiTableRow-root",
1919
TABLE_SORT_LABEL: ".MuiTableSortLabel-root",
2020
TABLE_SORT_LABEL_ICON: ".MuiTableSortLabel-icon",
21+
TYPOGRAPHY: ".MuiTypography-root",
2122
};
2223

2324
export const TEST_IDS = {
2425
CLEAR_ALL_FILTERS: "clear-all-filters",
2526
ENTITIES_VIEW: "entities-view",
27+
ENTITY_SUMMARY: "entity-summary",
2628
EXPORT_BUTTON: "export-button",
29+
EXPORT_SUMMARY: "export-summary",
2730
FILTERS: "filters",
2831
FILTER_CONTROLS: "filter-controls",
2932
FILTER_COUNT: "filter-count",

e2e/testFunctions.ts

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -940,61 +940,6 @@ export async function testBulkDownloadIndexExportWorkflow(
940940
return true;
941941
}
942942

943-
/**
944-
* Check that the summary box on the "Choose Export Method" page has numbers that match those on the index page
945-
* @param page - a Playwright page object
946-
* @param tab - the tab to test on
947-
* @returns - true if the test passes, false if it should fail but does not fail an assertion
948-
*/
949-
export async function testIndexExportSummary(
950-
page: Page,
951-
tab: TabDescription
952-
): Promise<boolean> {
953-
if (tab?.indexExportPage === undefined) {
954-
console.log(
955-
"testIndexExportSummmary Error: indexExportPage not specified for given tab, so test cannot run"
956-
);
957-
return false;
958-
}
959-
await page.goto(tab.url);
960-
const headers: { header: string; value: string }[] = [];
961-
const indexExportButtonLocator = page.getByRole("link", {
962-
name: tab.indexExportPage.indexExportButtonText,
963-
});
964-
await expect(indexExportButtonLocator).toBeVisible();
965-
for (const detail of tab.indexExportPage.detailsToCheck) {
966-
// This Regexp gets a decimal number, some whitespace, then the name of the detail, matching how the detail box appears to Playwright.
967-
const detailBoxRegexp = RegExp(`^(\\d+\\.\\d+k)\\s*${detail}$`);
968-
// This gets the detail's value. The .trim() is necessary since innertext adds extraneous whitespace on Webkit
969-
const headerValueArray = (await page.getByText(detailBoxRegexp).innerText())
970-
.trim()
971-
.match(detailBoxRegexp);
972-
// Check that the regex matches the expected format
973-
if (headerValueArray === null || headerValueArray.length !== 2) {
974-
console.log(
975-
"testIndexExportSummmary Error: The detail box text does not match the expected format"
976-
);
977-
return false;
978-
}
979-
// Save the header value and detail for later comparison
980-
headers.push({
981-
header: detail,
982-
value: headerValueArray[1],
983-
});
984-
}
985-
await indexExportButtonLocator.click();
986-
for (const headerValue of headers) {
987-
// Expect the correct value to be below the correct header in the dataset values table
988-
await expect(
989-
page
990-
.locator(`:below(:text('${headerValue.header}'))`)
991-
.getByText(headerValue.value)
992-
.first()
993-
).toBeVisible();
994-
}
995-
return true;
996-
}
997-
998943
const PAGE_COUNT_REGEX = /Page \d+ of \d+/;
999944
const MAX_PAGINATIONS = 200;
1000945

next.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const ESM_PACKAGES = [
77
"@databiosphere/findable-ui",
88
"@observablehq/plot",
99
"@tanstack/react-table",
10+
"@tanstack/react-virtual",
1011
];
1112

1213
const withMDX = nextMDX({

package-lock.json

Lines changed: 25 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"check-system-status:anvil-cmg": "esrun e2e/anvil/anvil-check-system-status.ts"
3333
},
3434
"dependencies": {
35-
"@databiosphere/findable-ui": "^37.1.0",
35+
"@databiosphere/findable-ui": "^38.1.0",
3636
"@emotion/react": "^11.13.3",
3737
"@emotion/styled": "^11.13.0",
3838
"@mdx-js/loader": "^3.0.1",
@@ -42,6 +42,7 @@
4242
"@next/mdx": "^14.2.28",
4343
"@observablehq/plot": "^0.6.17",
4444
"@tanstack/react-table": "^8.19.2",
45+
"@tanstack/react-virtual": "^3.13.12",
4546
"@types/fhir": "^0.0.35",
4647
"copy-to-clipboard": "3.3.1",
4748
"csv-parse": "^5.0.4",

site-config/anvil-catalog/dev/config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ export function makeConfig(
8686
studiesEntityConfig,
8787
workspaceEntityConfig,
8888
],
89-
explorerTitle: APP_TITLE,
9089
export: exportConfig, // TODO(cc) export config should be optional, we should add notFound to export pages.
9190
gitHubUrl,
9291
layout: {

0 commit comments

Comments
 (0)