diff --git a/package.json b/package.json
index c686236202..50f879245e 100644
--- a/package.json
+++ b/package.json
@@ -122,8 +122,8 @@
},
"dependencies": {
"@date-fns/tz": "1.4.1",
- "@digdir/designsystemet-css": "1.11.1",
- "@digdir/designsystemet-react": "1.11.1",
+ "@digdir/designsystemet-css": "1.18.0",
+ "@digdir/designsystemet-react": "1.18.0",
"@navikt/aksel-icons": "8.10.5",
"@tanstack/react-query": "5.100.10",
"@terraformer/wkt": "2.2.1",
diff --git a/src/components/atoms/AltinnAttachments.tsx b/src/components/atoms/AltinnAttachments.tsx
index 9ecafebf2d..cd28d1785c 100644
--- a/src/components/atoms/AltinnAttachments.tsx
+++ b/src/components/atoms/AltinnAttachments.tsx
@@ -5,7 +5,6 @@ import { Link, List } from '@digdir/designsystemet-react';
import cn from 'classnames';
import classes from 'src/components/atoms/AltinnAttachment.module.css';
-import { MainAttachmentHeader } from 'src/components/atoms/AttachmentHeader';
import { Lang } from 'src/features/language/Lang';
import { useCurrentLanguage } from 'src/features/language/LanguageProvider';
import { useLanguage } from 'src/features/language/useLanguage';
@@ -39,7 +38,7 @@ export function AltinnAttachments({
id={id}
data-testid='attachment-list'
>
-
+ {title}
{
expect(console.error).not.toHaveBeenCalled();
- const showDetailsButton = screen.getByRole('button', { name: 'Vis detaljer om feilen' });
- await user.click(showDetailsButton);
+ const detailsGroup = screen.getByRole('group');
+ expect(detailsGroup).toHaveTextContent('Vis detaljer om feilen');
+ const summary = detailsGroup.querySelector('summary');
+ if (!summary) {
+ throw new Error('Expected a inside the details group');
+ }
+ await user.click(summary);
expect(screen.getByText('Error test message')).toBeInTheDocument();
const writeTextMock = jest.spyOn(navigator.clipboard, 'writeText').mockResolvedValue();
diff --git a/src/layout/Accordion/Accordion.test.tsx b/src/layout/Accordion/Accordion.test.tsx
index 49aac58edd..6df8a15d34 100644
--- a/src/layout/Accordion/Accordion.test.tsx
+++ b/src/layout/Accordion/Accordion.test.tsx
@@ -9,23 +9,23 @@ describe('Accordion', () => {
it('should display text from textResourceBindings', async () => {
await render({ title: 'Accordion title' });
- expect(await screen.findByRole('button', { name: /accordion title/i })).toBeInTheDocument();
+ expect(await screen.findByRole('group')).toHaveTextContent(/accordion title/i);
});
it('should display text from textResourceBindings if an ID to a text resource is used as title', async () => {
await render({ title: 'accordion.title' });
- expect(await screen.findByRole('button', { name: /this is a title/i })).toBeInTheDocument();
+ expect(await screen.findByRole('group')).toHaveTextContent(/this is a title/i);
});
it('should open accordion by default if openByDefault is set to true', async () => {
await render({ openByDefault: true, title: 'accordion.title' });
- expect(await screen.findByRole('button', { name: /this is a title/i })).toHaveAttribute('aria-expanded', 'true');
+ expect(await screen.findByRole('group')).toHaveAttribute('open');
});
it('accordion should be closed by default if openByDefault is set to false', async () => {
await render({ openByDefault: false, title: 'accordion.title' });
- expect(await screen.findByRole('button', { name: /this is a title/i })).toHaveAttribute('aria-expanded', 'false');
+ expect(await screen.findByRole('group')).not.toHaveAttribute('open');
});
});
diff --git a/src/layout/AttachmentList/AttachmentListComponent.tsx b/src/layout/AttachmentList/AttachmentListComponent.tsx
index 9c290c649e..6b8a170048 100644
--- a/src/layout/AttachmentList/AttachmentListComponent.tsx
+++ b/src/layout/AttachmentList/AttachmentListComponent.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import { AltinnAttachments } from 'src/components/atoms/AltinnAttachments';
+import { MainAttachmentHeader } from 'src/components/atoms/AttachmentHeader';
import { AttachmentGroupings } from 'src/components/organisms/AttachmentGroupings';
import { useApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
import { useInstanceDataElements } from 'src/features/instance/InstanceContext';
@@ -82,7 +83,7 @@ export function AttachmentListComponent({ baseComponentId }: PropsFromGenericCom
) : (
: undefined}
showLinks={showLinks}
showDescription={showDescription}
/>
diff --git a/src/layout/Dropdown/DropdownComponent.test.tsx b/src/layout/Dropdown/DropdownComponent.test.tsx
index 16641f53fe..0d2cf14b51 100644
--- a/src/layout/Dropdown/DropdownComponent.test.tsx
+++ b/src/layout/Dropdown/DropdownComponent.test.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { jest } from '@jest/globals';
-import { act, screen, waitFor } from '@testing-library/react';
+import { act, fireEvent, screen, waitFor } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import type { AxiosResponse } from 'axios';
@@ -104,6 +104,43 @@ describe('DropdownComponent', () => {
);
});
+ it('should commit the new value after confirming alertOnChange', async () => {
+ const { formDataMethods } = await render({
+ component: {
+ alertOnChange: true,
+ },
+ options: countries,
+ queries: {
+ fetchFormData: async () => ({
+ ...getFormDataMockForRepGroup(),
+ myDropdown: 'norway',
+ }),
+ },
+ });
+
+ expect(await screen.findByRole('combobox')).toHaveValue('Norway');
+
+ await userEvent.click(screen.getByRole('combobox'));
+ await userEvent.click(screen.getByRole('option', { name: /sweden/i }));
+
+ // Mimic the alert popover stealing focus, which blurs the combobox and reverts the input display
+ // back to the previously-committed value before the change is confirmed.
+ fireEvent.blur(screen.getByRole('combobox'));
+
+ // Alert should appear; confirm the change
+ const confirmButton = await screen.findByRole('button', { name: /bekreft|confirm/i });
+ await userEvent.click(confirmButton);
+
+ await waitFor(() =>
+ expect(formDataMethods.setLeafValue).toHaveBeenCalledWith({
+ reference: { field: 'myDropdown', dataType: defaultDataTypeMock },
+ newValue: 'sweden',
+ }),
+ );
+
+ expect(screen.getByRole('combobox')).toHaveValue('Sweden');
+ });
+
it('should show as readonly when readOnly is true', async () => {
await render({
component: {
diff --git a/src/layout/Dropdown/DropdownComponent.tsx b/src/layout/Dropdown/DropdownComponent.tsx
index ed80f7f1c9..9aca3d0cf5 100644
--- a/src/layout/Dropdown/DropdownComponent.tsx
+++ b/src/layout/Dropdown/DropdownComponent.tsx
@@ -104,6 +104,10 @@ export function DropdownComponent({ baseComponentId, overrideDisplay }: PropsFro
)}
optionFilter(args, selectedLabels)}
data-size='sm'
diff --git a/src/setupTests.ts b/src/setupTests.ts
index 16ce7e38e8..f251638131 100644
--- a/src/setupTests.ts
+++ b/src/setupTests.ts
@@ -60,6 +60,11 @@ Element.prototype.getClientRects = () => ({
[Symbol.iterator]: jest.fn(),
});
+// jsdom doesn't implement elementFromPoint, which Designsystemet's Popover uses
+// in its `isTopLayer` check when handling Escape keydown. Returning the open
+// popover element makes the check pass so ESC actually closes the popover in tests.
+document.elementFromPoint = () => document.querySelector('[popover]');
+
// Forcing a low timeout for useDelayedSaveState()
global.delayedSaveState = 50;
diff --git a/test/e2e/integration/frontend-test/components.ts b/test/e2e/integration/frontend-test/components.ts
index e2aec466ce..8140e2d8ad 100644
--- a/test/e2e/integration/frontend-test/components.ts
+++ b/test/e2e/integration/frontend-test/components.ts
@@ -479,22 +479,17 @@ describe('UI Components', () => {
cy.gotoHiddenPage('label-data-bindings');
cy.get('#form-content-colorsCheckboxes').click();
+ // After selecting an option, the DS combobox renders a removable chip (a ) whose
+ // accessible name is "