diff --git a/help-docs/chaise/facet-panel.md b/help-docs/chaise/facet-panel.md new file mode 100644 index 000000000..0fdcf9b2d --- /dev/null +++ b/help-docs/chaise/facet-panel.md @@ -0,0 +1,56 @@ +# Filter panel + +Filters are the data constraints or restrictions that are applied during search operations. For example, search for "mouse" data, or data submitted by certain "principal investigators". + +The filter panel (displayed on the left under "Refine search") contains a list of filter controls used to set these constraints. This page provides details on how the filter panel works. Please find the topics discussed in the table of contents below: + +- [Customizing the order of filters](#customizing-the-order-of-filters) + - [How to move filters](#how-to-move-filters) + - [How to save the order](#how-to-save-the-order) + - [How to apply the default order](#how-to-apply-the-default-order) + - [How to apply the saved order](#how-to-apply-the-saved-order) + + +## Customizing the order of filters {id=customizing-the-order-of-filters} + +You can change the order of filters in the filter panel. This section goes over how you could move filters, save the customized order, and, if needed, discard the customized order. + +### How to move filters {id=how-to-move-filters} + +To move the filters, + + 1. Left click on the grab ( :span::/span:{.fa-solid .fa-grip-vertical .help-page-icon} ) icon. + 2. While holding the left click, move your mouse to the desired location. + 3. Release the left click to finish the drag movement. + +Keep in mind that this order is not going to be persistent and will change back after refreshing the page. To save the order, please refer to the [How to save the order](#how-to-save-the-order) section. + +### How to save the order {id=how-to-save-the-order} + +If you would like to save the order in your browser, + + 1. Click on the menu icon (:span::/span:{.fa-solid .fa-bars .help-page-icon}) besides the "Refine search". + + 2. In the opened menu, select the ":span::/span:{.fa-solid .fa-check-to-slot .help-page-icon} Save filter order" option. + +This will ensure your customized order is saved in your browser. If you would like to apply the default order, please refer to the [How to discard the saved order](#how-to-apply-the-default-order) section. + +### How to apply the default order {id=how-to-apply-the-default-order} + +If you've customized the order, or applied the saved state, you may go back to the default order by following these steps: + + 1. Click on the menu icon ( :span::/span:{.fa-solid .fa-bars .help-page-icon} ) besides the "Refine search". + + 2. In the opened menu, select the ":span::/span:{.fa-solid .fa-undo .help-page-icon} Reset to default" option. + +With this, the filter panel will reset to the default order. Some filters move, and some might get opened/closed depending on the current state of the page. If you want to return to your saved order, please follow the steps described [here](#how-to-apply-the-saved-order). + +### How to apply the saved order {id=how-to-apply-the-saved-order} + +If you have saved the filter order before, we will apply this order when you load the page. If you made some modifications to this order, follow these steps to go back to the saved order: + + 1. Click on the menu icon ( :span::/span:{.fa-solid .fa-bars .help-page-icon} ) besides the "Refine search". + + 2. In the opened menu, select the ":span::/span:{.fa-solid .fa-check .help-page-icon} Apply saved state" option. + +With this, the filter panel will reset to the saved order. Some filters move, and some might get opened/closed depending on the current state of the page. diff --git a/src/assets/scss/_buttons.scss b/src/assets/scss/_buttons.scss index 6698b4961..7434d5463 100644 --- a/src/assets/scss/_buttons.scss +++ b/src/assets/scss/_buttons.scss @@ -95,6 +95,18 @@ &.chaise-btn-no-padding { padding: 0; } + + // this is currently designed mostly for + &.chaise-btn-with-indicator:before { + content: ''; + background-color: map-get(variables.$color-map, 'primary'); + position: absolute; + top: -1px; + right: -1px; + width: 8px; + height: 8px; + border-radius: 50%; + } } //TODO @@ -113,8 +125,3 @@ .dropdown-item:active { background-color: unset; } - -// override the default behavior of dropdown toggle btn in bootstrap -.show > button.chaise-btn.btn.dropdown-toggle { - @include helpers.chaise-btn-primary(); -} diff --git a/src/assets/scss/_dropdown.scss b/src/assets/scss/_dropdown.scss index f7843ecfd..a34814c6d 100644 --- a/src/assets/scss/_dropdown.scss +++ b/src/assets/scss/_dropdown.scss @@ -1,5 +1,10 @@ @use 'sass:map'; @use 'variables'; +@use 'helpers'; + +.dropdown.chaise-dropdown-no-icon .dropdown-toggle::after{ + display: none; +} // the .dropdown selector is neede to ensure overriding default bootstrap and chaise styles .chaise-dropdown.dropdown { @@ -111,6 +116,7 @@ // style to override react-bootstrap .dropdown-item { padding: 0; + } // change the default link behaviors to not show the underline @@ -132,6 +138,13 @@ padding: 3px 15px 3px 15px; line-height: 1.4; + &.dropdown-item-w-icon { + padding: 3px 15px 3px 8px; + .dropdown-item-icon { + margin-right: 7px; + } + } + &:focus, &:hover { color: lighten(map-get(variables.$color-map, 'black'), 10%); @@ -166,7 +179,7 @@ right: unset; } - .disable-link { + .disable-link, .disabled { pointer-events: none !important; cursor: default !important; color: map-get(variables.$color-map, 'disabled') !important; @@ -177,3 +190,18 @@ } } } + +// override the default behavior of dropdown toggle btn in bootstrap +.dropdown.show > button.chaise-btn.dropdown-toggle { + &.chaise-btn-primary { + @include helpers.chaise-btn-primary(); + } + + &.chaise-btn-secondary, &.chaise-btn-tertiary { + @include helpers.chaise-btn-secondary(); + + &:focus { + background-color: none; + } + } +} diff --git a/src/assets/scss/_faceting.scss b/src/assets/scss/_faceting.scss index b48cae95d..3b37793cf 100644 --- a/src/assets/scss/_faceting.scss +++ b/src/assets/scss/_faceting.scss @@ -1,6 +1,14 @@ @use 'sass:map'; @use 'variables'; +.side-panel-container { + .side-panel-heading-menu { + position: absolute; + top: -37px; + left: 125px; + } +} + .faceting-columns-container { // disable the animation from the accordion .accordion-collapse.collapsing { diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss index 33030119e..30c3525a7 100644 --- a/src/assets/scss/app.scss +++ b/src/assets/scss/app.scss @@ -596,6 +596,10 @@ html { padding: 0; padding-bottom: 3px; } + + .pull-left { + display: flex; + } } } @@ -1076,6 +1080,10 @@ html { padding-top: 20px; padding-bottom: 20px; } + + .help-page-icon { + margin: 0 5px; + } } /****** switch user accounts help page *******/ diff --git a/src/components/faceting/faceting.tsx b/src/components/faceting/faceting.tsx index d8ba4241e..54edbac83 100644 --- a/src/components/faceting/faceting.tsx +++ b/src/components/faceting/faceting.tsx @@ -1,8 +1,15 @@ import '@isrd-isi-edu/chaise/src/assets/scss/_faceting.scss'; +//react-beatiful-dnd +import { + DragDropContext, Draggable, DraggableProvided, DroppableProvided, DropResult +} from 'react-beautiful-dnd'; + // Components import Accordion from 'react-bootstrap/Accordion'; +import ChaiseDroppable from '@isrd-isi-edu/chaise/src/components/chaise-droppable'; import ChaiseTooltip from '@isrd-isi-edu/chaise/src/components/tooltip'; +import Dropdown from 'react-bootstrap/Dropdown'; import FacetChoicePicker from '@isrd-isi-edu/chaise/src/components/faceting/facet-choice-picker'; import FacetCheckPresence from '@isrd-isi-edu/chaise/src/components/faceting/facet-check-presence'; import FacetHeader from '@isrd-isi-edu/chaise/src/components/faceting/facet-header'; @@ -24,13 +31,14 @@ import { ConfigService } from '@isrd-isi-edu/chaise/src/services/config'; import { LogService } from '@isrd-isi-edu/chaise/src/services/log'; import $log from '@isrd-isi-edu/chaise/src/services/logger'; -//react-beatiful-dnd +// utils +import { HELP_PAGES } from '@isrd-isi-edu/chaise/src/utils/constants'; import { - DragDropContext, Draggable, DraggableProvided, DroppableProvided, DropResult -} from 'react-beautiful-dnd'; -import ChaiseDroppable from '@isrd-isi-edu/chaise/src/components/chaise-droppable'; -import { getFacetOrderStorageKey, getInitialFacetOpenStatus, getInitialFacetOrder } from '@isrd-isi-edu/chaise/src/utils/faceting-utils'; + getFacetOrderStorageKey, getInitialFacetOpenStatus, getInitialFacetOrder, + hasStoredFacetOrder +} from '@isrd-isi-edu/chaise/src/utils/faceting-utils'; import LocalStorage from '@isrd-isi-edu/chaise/src/utils/storage'; +import { getHelpPageURL } from '@isrd-isi-edu/chaise/src/utils/uri-utils'; type FacetingProps = { @@ -46,7 +54,7 @@ type FacetingProps = { registerRecordsetCallbacks: ( getAppliedFilters: () => FacetCheckBoxRow[][], removeAppliedFilters: (index?: number | 'filters' | 'cfacets') => void, - focusOnFacet: (index: number, dontUpdate?: boolean) => void + focusOnFacet: (index: number, dontUpdate?: boolean) => void, ) => void, /** * the recordset's log stack path @@ -126,6 +134,12 @@ const Faceting = ({ * when this is set to true, we should save the changes in the local storage and then change it back to false. */ const [facetListModified, setFacetListModified] = useState(false); + /** + * whether the current order is based on teh stored facet order or not. + */ + const [isStoredFacetOrderApplied, setIsStoredFacetOrderApplied] = useState(() => { + return hasStoredFacetOrder(reference); + }); const setFacetModelByIndex = (index: number, updatedVals: { [key: string]: boolean }) => { setFacetModels((prevFacetModels: FacetModel[]) => { @@ -260,29 +274,12 @@ const Faceting = ({ */ useEffect(() => { registerFacetCallbacks(updateFacetStates, updateFacets); - registerRecordsetCallbacks(getAppliedFiltersFromRS, removeAppliedFiltersFromRS, focusOnFacet); }, [facetModels]); - /** - * store the facet order in the local stroage if any changes happened to the facets - */ useEffect(() => { - if (!facetOrders || !facetOrders.length) return; - if (!facetListModified) return; - /** - * store isOpen state for facets to localStorage - */ - LocalStorage.setStorage(getFacetOrderStorageKey(reference), facetOrders.map((i) => { - return { - name: reference.facetColumns[i].sourceObjectWrapper.name, - open: facetModelsRef.current[i].isOpen - }; - })); - - // now that the state is saved, just set it to false so we don't update this until the next user action - setFacetListModified(false); - - }, [facetListModified, facetModels, facetOrders]) + console.log('calling registered in faceting'); + registerRecordsetCallbacks(getAppliedFiltersFromRS, removeAppliedFiltersFromRS, focusOnFacet); + }, [facetModels, facetOrders, facetListModified, isStoredFacetOrderApplied]); //------------------- flow-control related functions: --------------------// @@ -629,6 +626,7 @@ const Faceting = ({ // make sure we're saving the new state setFacetListModified(true); + setIsStoredFacetOrderApplied(false); }; /** @@ -684,8 +682,63 @@ const Faceting = ({ } setFacetOrders(items); - setFacetListModified(true) + setFacetListModified(true); + setIsStoredFacetOrderApplied(false); + }; + + const storeFacetOrder = () => { + LocalStorage.setStorage(getFacetOrderStorageKey(reference), facetOrders.map((i) => { + return { + name: reference.facetColumns[i].sourceObjectWrapper.name, + open: facetModelsRef.current[i].isOpen + }; + })); + setFacetListModified(false); + setIsStoredFacetOrderApplied(true); + }; + + const applyDefaultOrStoredFacetOrder = (useDefault: boolean) => { + // change their order + setFacetOrders(() => { + return getInitialFacetOrder(reference, useDefault).map((o) => o.facetIndex); + }); + + // open or close facets + setFacetModels((prevFacetModels) => { + const { openStatus: newOpenStatus } = getInitialFacetOpenStatus(reference, useDefault); + return prevFacetModels.map((fm: FacetModel, fmIndex: number) => { + const isOpen = newOpenStatus[`${fmIndex}`]; + + // if open status has not changed, just return it + if (fm.isOpen === isOpen) return fm; + + // if we are closing + if (!isOpen) { + return { ...fm, isOpen, + // hide the spinner: + isLoading: false, + // if we were waiting for data, make sure to fetch it later + initialized: !fm.isLoading + } + } + + // if we're opening and it's not initialized, initiate the request + if (!fm.initialized) { + // send a request + dispatchFacetUpdate(fmIndex, false); + return { ...fm, isOpen, isLoading: true }; + } + + // otherwise just open it + return { ...fm, isOpen }; + }); + }); + + // set the boolean states + setIsStoredFacetOrderApplied(!useDefault); + setFacetListModified(false); } + //------------------- render logic: --------------------// const renderFacetList = () => { @@ -755,6 +808,61 @@ const Faceting = ({ } }; + const renderFacetDropdownMenu = () => { + const storedIsAvailable = hasStoredFacetOrder(reference); + const showChangeIndicator = facetListModified || (storedIsAvailable && !isStoredFacetOrderApplied); + const allowSave = showChangeIndicator; + const allowApplyDefault = facetListModified || isStoredFacetOrderApplied; + const allowApplySaved = storedIsAvailable && showChangeIndicator; + + return ( + + + + + + + + storeFacetOrder()}> + + + Save filter order + + + applyDefaultOrStoredFacetOrder(true)} + > + + + Reset to default + + + applyDefaultOrStoredFacetOrder(false)} + > + + + Apply saved state + + + + + + Help + + + + + ) + } + // bootstrap expects an array of strings const activeKeys: string[] = []; facetModels.forEach((fm, index) => { if (fm.isOpen) activeKeys.push(`${index}`) }); @@ -768,6 +876,7 @@ const Faceting = ({ return (
+ {renderFacetDropdownMenu()}
diff --git a/src/models/recordset.ts b/src/models/recordset.ts index 963a14757..7d7c4e4d3 100644 --- a/src/models/recordset.ts +++ b/src/models/recordset.ts @@ -220,3 +220,13 @@ export type RecordsetProviderUpdateMainEntity = ( export type RecordsetProviderFetchSecondaryRequests = ( updatePageCB: Function, hideSpinner?: boolean ) => void; + + +export type FacetOrderProps = { + isFacetOrderModified: boolean, + hasStoredFacetOrder: boolean, + isStoredFacetOrderApplied: boolean, + storeFacetOrder: () => void, + applyDefaultOrder: () => void, + applyStoredOrder: () => void +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 6b605b851..9d2cb4539 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -198,7 +198,22 @@ export const CUSTOM_EVENTS = { export const HELP_PAGES_FOLDER_LOCATION = 'help-docs'; -export const HELP_PAGES = { +export const HELP_PAGES : { + [name: string]: { + /** + * the title of page (what users see) + */ + title: string, + /** + * what should be used as the query parameter to find the page. + */ + location: string, + /** + * whether this is a built-in component or a markdown help page. + */ + isComponent: boolean + } +} = { MARKDOWN_HELP: { title: 'Markdown Help', location: 'chaise/markdown-help', @@ -213,6 +228,11 @@ export const HELP_PAGES = { title: 'Viewer Annotation', location: 'chaise/viewer-annotation', isComponent: false + }, + FACET_PANEL: { + title: 'Filter panel', + location: 'chaise/facet-panel', + isComponent: false } } diff --git a/src/utils/faceting-utils.ts b/src/utils/faceting-utils.ts index 168605ee0..bba190e17 100644 --- a/src/utils/faceting-utils.ts +++ b/src/utils/faceting-utils.ts @@ -60,6 +60,12 @@ export const getFacetOrderStorageKey = (reference: any): string => { return `facet-order-${reference.table.schema.catalog.id}_${reference.table.schema.name}_${reference.table.name}`; } +export const hasStoredFacetOrder = (reference: any): boolean => { + const facetListKey = getFacetOrderStorageKey(reference); + const facetOrder = LocalStorage.getStorage(facetListKey); + return facetOrder && Array.isArray(facetOrder) && facetOrder.length > 0; +} + /** * Return the order of facets that should be used initially. * @@ -67,16 +73,19 @@ export const getFacetOrderStorageKey = (reference: any): string => { * * @param reference the reference that represents the main recordset page */ -export const getInitialFacetOrder = (reference: any): { facetIndex: number, isOpen: boolean }[] => { +export const getInitialFacetOrder = (reference: any, ignoreStorage?: boolean): { facetIndex: number, isOpen: boolean }[] => { const res: { facetIndex: number, isOpen: boolean }[] = []; const facetColumns = reference.facetColumns; const facetListKey = getFacetOrderStorageKey(reference); - const facetOrder = LocalStorage.getStorage(facetListKey) as { - name: string, - open: boolean - }[] || undefined; + let facetOrder: { name: string, open: boolean }[] | undefined; let atLeastOneIsOpen = false; + if (ignoreStorage) { + facetOrder = []; + } else { + facetOrder = LocalStorage.getStorage(facetListKey); + } + // no valid stored value was found in storage, so return the annotaion value. if (!facetOrder || !Array.isArray(facetOrder) || facetOrder.length === 0) { facetColumns.forEach((fc: any, index: number) => { @@ -157,11 +166,11 @@ export const getInitialFacetOrder = (reference: any): { facetIndex: number, isOp * * @param reference the reference that represents the main recordset page */ -export const getInitialFacetOpenStatus = (reference: any): { +export const getInitialFacetOpenStatus = (reference: any, ignoreStorage?: boolean): { order: { facetIndex: number, isOpen: boolean }[], openStatus: { [facetIndex: string]: boolean } } => { - const storedOrder = getInitialFacetOrder(reference); + const storedOrder = getInitialFacetOrder(reference, ignoreStorage); const booleanRes: { [facetIndex: string]: boolean } = {}; storedOrder.forEach((r) => { booleanRes[r.facetIndex] = r.isOpen; }); diff --git a/test/e2e/locators/recordset.ts b/test/e2e/locators/recordset.ts index abdd0c5c1..4a5bb401e 100644 --- a/test/e2e/locators/recordset.ts +++ b/test/e2e/locators/recordset.ts @@ -290,7 +290,27 @@ export default class RecordsetLocators { static getShowFilterPanelBtn(container: Page | Locator): Locator { return container.locator('.show-filter-panel-btn'); -} + } + + static getSidePanelHeadingMenu(container: Page | Locator): Locator { + return container.locator('.side-panel-heading-menu .dropdown-toggle'); + } + + static getSaveFacetOrderBtn(container: Page | Locator): Locator { + return container.locator('.save-facet-order-btn'); + } + + static getShowDefaultFacetOrderBtn(container: Page | Locator): Locator { + return container.locator('.show-default-facet-order-btn'); + } + + static getApplySavedFacetOrderBtn(container: Page | Locator): Locator { + return container.locator('.apply-saved-facet-order-btn'); + } + + static getSidePanelHeadingMenuHelpBtn(container: Page | Locator): Locator { + return container.locator('.side-panel-heading-menu-help-btn'); + } static getAllFacets(container: Page | Locator): Locator { return container.locator('.panel-group .facet-panel'); diff --git a/test/e2e/specs/delete-prohibited/recordset/reorder-facet.spec.ts b/test/e2e/specs/delete-prohibited/recordset/reorder-facet.spec.ts index dfe5e528d..ba9bb3655 100644 --- a/test/e2e/specs/delete-prohibited/recordset/reorder-facet.spec.ts +++ b/test/e2e/specs/delete-prohibited/recordset/reorder-facet.spec.ts @@ -1,4 +1,4 @@ -import { test, expect, TestInfo, Page } from '@playwright/test'; +import { test, expect, TestInfo, Page, Locator } from '@playwright/test'; // locators import RecordsetLocators from '@isrd-isi-edu/chaise/test/e2e/locators/recordset'; @@ -9,7 +9,7 @@ import { openRecordsetAndResetFacetState, TestIndividualFacetParams, testIndividualFacet, resetFacetState, testDisplayedFacets } from '@isrd-isi-edu/chaise/test/e2e/utils/recordset-utils'; -import { dragAndDropWithScroll } from '@isrd-isi-edu/chaise/test/e2e/utils/page-utils'; +import { clickNewTabLink, dragAndDropWithScroll } from '@isrd-isi-edu/chaise/test/e2e/utils/page-utils'; const testParams = { @@ -36,7 +36,8 @@ const testParams = { 'f3 (term)', 'from_name', 'to_name', 'F1 with Term', 'Check Presence Text', 'F3 Entity', 'F5', 'F5 with filter', 'Outbound1 (using F1)', 'col_w_column_order_false', 'col_w_column_order', 'col_w_long_values', - ] + ], + facetsToOpenAfterReorder: [4, 10] }, savedStateWInvalids: { storage: [ @@ -153,6 +154,10 @@ test.describe('Facet reorder feature', () => { test('changing the order of facets', async ({ page, baseURL }, testInfo) => { const currParams = testParams.initialState; + const menuBtn = RecordsetLocators.getSidePanelHeadingMenu(page); + const saveBtn = RecordsetLocators.getSaveFacetOrderBtn(page); + const applyDefaultBtn = RecordsetLocators.getShowDefaultFacetOrderBtn(page); + const applySavedBtn = RecordsetLocators.getApplySavedFacetOrderBtn(page); // this will close all the facets await openRecordsetAndResetFacetState( @@ -172,14 +177,72 @@ test.describe('Facet reorder feature', () => { }); await test.step('interacting with the reordered facets', async () => { + // test facet selection await testFacetSelection(page, []); + + // open some of the facets + for await (const facetId of testParams.initialState.facetsToOpenAfterReorder) { + const facet = RecordsetLocators.getFacetById(page, facetId); + await RecordsetLocators.getFacetHeaderButtonById(facet, facetId).click(); + } + }); + + await test.step('the Save button should be available and clicking on it should save the order.', async () => { + await testMenuBtnIndicator(menuBtn, true); + await menuBtn.click(); + + await testMenuBtnDisabled(saveBtn, false); + await testMenuBtnDisabled(applyDefaultBtn, false); + await testMenuBtnDisabled(applySavedBtn, true); + await saveBtn.click(); + + await testMenuBtnIndicator(menuBtn, false); + await testDisplayedFacets(page, testParams.initialState.facetNamesAfterReorder, ['timestamp_col', 'F1']); + }); + + await test.step('clicking on "Reset to default" should display the default order.', async () => { + await menuBtn.click(); + await testMenuBtnDisabled(saveBtn, true); + await testMenuBtnDisabled(applyDefaultBtn, false); + await testMenuBtnDisabled(applySavedBtn, true); + await applyDefaultBtn.click(); + + await testMenuBtnIndicator(menuBtn, true); + await testDisplayedFacets(page, testParams.initialState.facetNames, ['to_name']); + }); + + await test.step('clicking on "Apply saved state" should display the saved state.', async () => { + await menuBtn.click(); + await testMenuBtnDisabled(saveBtn, false); + await testMenuBtnDisabled(applyDefaultBtn, true); + await testMenuBtnDisabled(applySavedBtn, false) + await applySavedBtn.click(); + + await testMenuBtnIndicator(menuBtn, false); + await testDisplayedFacets(page, testParams.initialState.facetNamesAfterReorder, ['timestamp_col', 'F1']); }); await test.step('refreshing the page should display the saved order and open state.', async () => { await page.reload(); - // int_col and id will always be open - await testDisplayedFacets(page, testParams.initialState.facetNamesAfterReorder, ['int_col', 'id']); + // id and int have filters so they will be opened anyways + await RecordsetLocators.waitForRecordsetPageReady(page); + await testDisplayedFacets(page, testParams.initialState.facetNamesAfterReorder, ['int_col', 'id', 'timestamp_col', 'F1']); }); + + await test.step('changing the order of facets without clicking on save should not save the order.', async () => { + await moveFacet(page, 0, 2); + await page.reload(); + await RecordsetLocators.waitForRecordsetPageReady(page); + await testDisplayedFacets(page, testParams.initialState.facetNamesAfterReorder, ['int_col', 'id', 'timestamp_col', 'F1']); + }); + + await test.step('"Help" option should navigate to the help page.', async () => { + await menuBtn.click(); + const newPage = await clickNewTabLink(RecordsetLocators.getSidePanelHeadingMenuHelpBtn(page)); + await newPage.waitForURL('**/help/?page=chaise%2Ffacet-panel'); + await newPage.close(); + }); + }); test('opening a page where the saved state has extra or invalid facets', async ({ page, baseURL }, testInfo) => { @@ -200,7 +263,7 @@ test.describe('Facet reorder feature', () => { // open a facet since all of them are closed due to the previous test await RecordsetLocators.getFacetHeaderButtonById(RecordsetLocators.getFacetById(page, 12), 12).click(); await page.reload(); - await testDisplayedFacets(page, currParams.facetNames, ['id', 'int_col', 'f3 (term)']); + await testDisplayedFacets(page, currParams.facetNames, currParams.openFacets.names); }); }); @@ -220,7 +283,7 @@ test.describe('Facet reorder feature', () => { await test.step('refreshing the page should display the saved order and open state.', async () => { await page.reload(); - await testDisplayedFacets(page, currParams.facetNames); + await testDisplayedFacets(page, currParams.facetNames, currParams.openFacets.names); }); }); @@ -276,3 +339,21 @@ const changeStoredOrder = async (page: Page, testInfo: TestInfo, order: any) => await page.reload(); } + +const testMenuBtnDisabled = async (locator: Locator, disabled: boolean) => { + await expect.soft(locator).toBeVisible(); + if (disabled) { + await expect.soft(locator).toHaveClass(/disabled/); + } else { + await expect.soft(locator).not.toHaveClass(/disabled/); + } +} + +const testMenuBtnIndicator = async (locator: Locator, hasIndicator: boolean) => { + await expect.soft(locator).toBeVisible(); + if (hasIndicator) { + await expect.soft(locator).toHaveClass(/chaise-btn-with-indicator/); + } else { + await expect.soft(locator).not.toHaveClass(/chaise-btn-with-indicator/); + } +}