From da4e7565893f57b937b4da52cdafe273cb540ee2 Mon Sep 17 00:00:00 2001 From: Mark Bremer Date: Wed, 18 Mar 2026 11:09:02 +0100 Subject: [PATCH 01/10] Add Resource --- web/client/plugins/ResourcesCatalog/components/MenuItem.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx b/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx index 8a950a0778e..0bba57ebaa5 100644 --- a/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx +++ b/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx @@ -115,7 +115,8 @@ const MenuItem = ({ iconType, square, tooltipId, - src + src, + toggleAttributes } = item || {}; const target = itemTarget ?? defaultTarget; @@ -140,6 +141,7 @@ const MenuItem = ({ style={style} bsSize={size} noCaret={noCaret} + {...toggleAttributes} > {src ? From 5a6249387bedad3b84f3f8db59b31e8851ac17fd Mon Sep 17 00:00:00 2001 From: Mark Bremer Date: Wed, 18 Mar 2026 11:21:37 +0100 Subject: [PATCH 02/10] Dropdown Data --- web/client/plugins/ResourcesCatalog/components/MenuItem.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx b/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx index 0bba57ebaa5..9810456dd20 100644 --- a/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx +++ b/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx @@ -35,6 +35,7 @@ const DropdownMenuItems = ({ if (itm.type === 'divider') { return ; } + const menuItemAttributes = itm.menuItemAttributes || {}; const labelNode = itm.labelId ? : itm.label; return ( @@ -44,6 +45,7 @@ const DropdownMenuItems = ({ as={itm?.items ? 'span' : 'a' } target={itm.target ?? target} className={itm.className} + {...menuItemAttributes} > {itm.glyph ? : null} {itm.glyph && labelNode ? ' ' : null} From a0b9817c5eec73eb7f77e26913eded5a09f7c4ec Mon Sep 17 00:00:00 2001 From: Mark Bremer Date: Wed, 18 Mar 2026 13:09:47 +0100 Subject: [PATCH 03/10] Add data attributes for accessibility in ResourceCard components --- .../components/ResourceCard.jsx | 30 ++++++++++++++++--- .../components/ResourceCardActionButtons.jsx | 14 +++++++-- .../components/ResourcesContainer.jsx | 2 ++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/web/client/plugins/ResourcesCatalog/components/ResourceCard.jsx b/web/client/plugins/ResourcesCatalog/components/ResourceCard.jsx index f8f3d2639a9..1d84a803b0c 100644 --- a/web/client/plugins/ResourcesCatalog/components/ResourceCard.jsx +++ b/web/client/plugins/ResourcesCatalog/components/ResourceCard.jsx @@ -34,8 +34,14 @@ const ResourceCardButton = ({ variant, borderTransparent, loading, + cardCyPrefix, + dataCy, ...props }) => { + const resolvedDataCy = dataCy + || (cardCyPrefix && ['heart', 'heart-o'].includes(glyph) ? `${cardCyPrefix}-btn-favorite` : null) + || (cardCyPrefix && glyph === 'details' ? `${cardCyPrefix}-properties` : null); + function handleOnClick(event) { event.stopPropagation(); if (onClick) { @@ -48,6 +54,7 @@ const ResourceCardButton = ({ square={square} borderTransparent={borderTransparent} {...props} + {...resolvedDataCy ? { 'cy-data': resolvedDataCy } : {}} tooltipId={square && labelId ? labelId : null} onClick={handleOnClick} > @@ -74,6 +81,7 @@ const ResourceCardWrapper = ({ layoutCardsStyle, query, target, + cardCyPrefix, ...props }) => { const showViewerLink = !!(!readOnly && viewerUrl); @@ -104,6 +112,7 @@ const ResourceCardWrapper = ({ ) : null} @@ -234,7 +243,8 @@ const ResourceCardGridBody = ({ options, thumbnailUrl, hideThumbnail, - target + target, + cardCyPrefix }) => { const headerEntry = metadata.find(entry => entry.target === 'header'); @@ -254,7 +264,11 @@ const ResourceCardGridBody = ({ > - + {((icon || headerEntry?.icon) && !loading) && ( <>{' '} )} @@ -304,6 +318,7 @@ const ResourceCardGridBody = ({ resource={resource} viewerUrl={viewerUrl} component={ResourceCardButton} + cardCyPrefix={cardCyPrefix} readOnly={readOnly} target={target} /> @@ -318,6 +333,7 @@ const ResourceCardGridBody = ({ resource={resource} viewerUrl={viewerUrl} options={options} + cardCyPrefix={cardCyPrefix} readOnly={readOnly} target={target} className="_absolute _margin-sm _corner-tr" @@ -340,7 +356,8 @@ const ResourceCardListBody = ({ options: optionsProp, buttons, columns, - target + target, + cardCyPrefix }) => { const options = [ ...(buttons || []), @@ -379,6 +396,7 @@ const ResourceCardListBody = ({ resource={resource} viewerUrl={viewerUrl} options={options} + cardCyPrefix={cardCyPrefix} readOnly={readOnly} target={target} /> @@ -411,7 +429,8 @@ const ResourceCard = forwardRef(({ formatHref, onClick, hideThumbnail, - target + target, + cardIndex }, ref) => { const resource = data; @@ -420,6 +439,7 @@ const ResourceCard = forwardRef(({ viewerUrl, thumbnailUrl } = getResourceInfo(resource); + const cardCyPrefix = cardIndex !== undefined ? `dataset-card-${cardIndex}` : undefined; const CardComponent = component || ResourceCardWrapper; const CardBody = cardBody[layoutCardsStyle]; @@ -437,6 +457,7 @@ const ResourceCard = forwardRef(({ columns={columns} metadata={metadata} query={query} + cardCyPrefix={cardCyPrefix} target={target} > {CardBody ? : null} diff --git a/web/client/plugins/ResourcesCatalog/components/ResourceCardActionButtons.jsx b/web/client/plugins/ResourcesCatalog/components/ResourceCardActionButtons.jsx index 28421dacc47..0852e23eb71 100644 --- a/web/client/plugins/ResourcesCatalog/components/ResourceCardActionButtons.jsx +++ b/web/client/plugins/ResourcesCatalog/components/ResourceCardActionButtons.jsx @@ -16,10 +16,18 @@ const ActionMenuItem = ({ iconType, children, labelId, + cardCyPrefix, + dataCy, ...props }) => { + const resolvedDataCy = dataCy + || (cardCyPrefix && glyph === 'duplicate' ? `${cardCyPrefix}-actions-clone` : null) + || (cardCyPrefix && glyph === 'trash' ? `${cardCyPrefix}-actions-delete` : null); return ( - + {glyph ? <>{' '} : null} {labelId ? : null} @@ -32,6 +40,7 @@ function ResourceCardActionButtons({ resource, className, target, + cardCyPrefix, ...props }) { @@ -59,6 +68,7 @@ function ResourceCardActionButtons({ size="xs" noCaret className="_border-transparent" + {...cardCyPrefix ? { 'cy-data': `${cardCyPrefix}-actions` } : {}} > @@ -66,7 +76,7 @@ function ResourceCardActionButtons({ {options.map((option) => { if (option.Component) { const { Component } = option; - return ; + return ; } return null; })} diff --git a/web/client/plugins/ResourcesCatalog/components/ResourcesContainer.jsx b/web/client/plugins/ResourcesCatalog/components/ResourcesContainer.jsx index c889e277445..e53c6d15b5a 100644 --- a/web/client/plugins/ResourcesCatalog/components/ResourcesContainer.jsx +++ b/web/client/plugins/ResourcesCatalog/components/ResourcesContainer.jsx @@ -64,8 +64,10 @@ const ResourcesContainer = (props) => { return (
  • Date: Wed, 18 Mar 2026 13:50:01 +0100 Subject: [PATCH 04/10] Add accessibility data attributes to DetailsHeader and DetailsInfo components --- .../components/DetailsHeader.jsx | 3 ++- .../components/DetailsInfo.jsx | 24 +++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/web/client/plugins/ResourcesCatalog/components/DetailsHeader.jsx b/web/client/plugins/ResourcesCatalog/components/DetailsHeader.jsx index 0d57e33fdbd..ce577a94a48 100644 --- a/web/client/plugins/ResourcesCatalog/components/DetailsHeader.jsx +++ b/web/client/plugins/ResourcesCatalog/components/DetailsHeader.jsx @@ -64,6 +64,7 @@ function DetailsHeader({ onClick={onClose} square borderTransparent + cy-data="dataset-view-sidepanel-close" > @@ -83,7 +84,7 @@ function DetailsHeader({
    - + {!loading ? : }{' '} {title} diff --git a/web/client/plugins/ResourcesCatalog/components/DetailsInfo.jsx b/web/client/plugins/ResourcesCatalog/components/DetailsInfo.jsx index 8c132e60d61..e6199b3c770 100644 --- a/web/client/plugins/ResourcesCatalog/components/DetailsInfo.jsx +++ b/web/client/plugins/ResourcesCatalog/components/DetailsInfo.jsx @@ -285,6 +285,26 @@ const parseTabItems = (items) => { }; const isDefaultTabType = (type) => type === 'tab'; +const tabCyDataMap = { + info: 'dataset-view-sidepanel-tab-info', + location: 'dataset-view-sidepanel-tab-location', + locations: 'dataset-view-sidepanel-tab-location', + assets: 'dataset-view-sidepanel-tab-assets', + data: 'dataset-view-sidepanel-tab-data', + related: 'dataset-view-sidepanel-tab-data', + share: 'dataset-view-sidepanel-tab-share', + settings: 'dataset-view-sidepanel-tab-settings' +}; + +const getTabCyData = (tab = {}) => { + const normalizedId = `${tab?.id || ''}`.toLowerCase(); + if (tabCyDataMap[normalizedId]) { + return tabCyDataMap[normalizedId]; + } + const normalizedLabel = `${tab?.label || ''}`.toLowerCase(); + return tabCyDataMap[normalizedLabel] || null; +}; + function DetailsInfo({ tabs = [], tabComponents: tabComponentsProp, @@ -321,9 +341,9 @@ function DetailsInfo({ selectedTabId={selectedTab ?? filteredTabs?.[0]?.id} onSelect={onSelectTab} tabs={filteredTabs.map(({Component, ...tab} = {}) => ({ - title: , + title: , eventKey: tab?.id, - component: + component:
    }))} /> ); From b92ca6fe09561af5f6c6c0bb6b0765363f5dc9fb Mon Sep 17 00:00:00 2001 From: Mark Bremer Date: Wed, 18 Mar 2026 15:05:06 +0100 Subject: [PATCH 05/10] Add data attributes for accessibility in DropdownMenuItems and MenuItem components --- .../ResourcesCatalog/components/MenuItem.jsx | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx b/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx index 9810456dd20..d3846128de5 100644 --- a/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx +++ b/web/client/plugins/ResourcesCatalog/components/MenuItem.jsx @@ -30,7 +30,16 @@ const DropdownMenuItems = ({ {items .map((itm, idx) => { if (itm.Component) { - return (); + return ( + + ); } if (itm.type === 'divider') { return ; @@ -118,13 +127,21 @@ const MenuItem = ({ square, tooltipId, src, - toggleAttributes + toggleAttributes, + menuItemAttributes, + dataCy } = item || {}; const target = itemTarget ?? defaultTarget; if (Component) { - return ; + return ; } const labelNode = labelId ? : label; @@ -168,7 +185,7 @@ const MenuItem = ({ if (type === 'link') { return (
  • - + {glyph ? : null} {glyph && labelNode ? ' ' : null} {labelNode} @@ -198,6 +215,8 @@ const MenuItem = ({ href={href} target={target} borderTransparent + dataCy={dataCy} + {...(menuItemAttributes || {})} > {glyph ? : null} {glyph && labelNode ? ' ' : null} From 9c3ef7a5e4e5b5e272a54d004151f1f69232f48d Mon Sep 17 00:00:00 2001 From: Mark Bremer Date: Wed, 18 Mar 2026 15:27:48 +0100 Subject: [PATCH 06/10] Add data attributes for accessibility in DownloadDialog, DownloadOptions, and DownloadWPSOptions components --- .../data/download/DownloadDialog.jsx | 20 ++++++++++++++++++- .../data/download/DownloadOptions.jsx | 18 +++++++++-------- .../data/download/DownloadWPSOptions.jsx | 16 +++++++++++++-- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/web/client/components/data/download/DownloadDialog.jsx b/web/client/components/data/download/DownloadDialog.jsx index 8ab40753ea9..9022b1f8ed4 100644 --- a/web/client/components/data/download/DownloadDialog.jsx +++ b/web/client/components/data/download/DownloadDialog.jsx @@ -124,6 +124,17 @@ const DownloadDialog = ({ } }, [enabled, selectedLayer, defaultSelectedService]); // equivalent componentDidUpdate + useEffect(() => { + if (!enabled) { + return; + } + const dialogRoot = document.querySelector('#mapstore-export'); + dialogRoot?.setAttribute('cy-data', 'dataset-export-box'); + + const formatInput = document.querySelector('#mapstore-export .mapstore-downloadoptions:not(.downloadMode) .Select-input input'); + formatInput?.setAttribute('cy-data', 'dataset-export-select-format'); + }, [enabled, downloadOptions, service, showLoader]); + const renderIcon = () => { return loading ?
    : ; }; @@ -153,7 +164,13 @@ const DownloadDialog = ({ - +
    {showLoader @@ -190,6 +207,7 @@ const DownloadDialog = ({
    { + if (!advancedOptionsOpened) { + return; + } + const srsInput = document.querySelector('.mapstore-downloadwpsoptions-advanced .mapstore-downloadwpsoptions-advanced-menuitem .Select-input input'); + srsInput?.setAttribute('cy-data', 'dataset-export-select-reference-system'); + }, [advancedOptionsOpened, selectedSrs, srsList]); + return ( <> {advancedOptionsVisible &&
    -