mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Links] Fix link settings not persisting (#211041)
Closes https://github.com/elastic/kibana/issues/211022 ## Summary This PR fixes a bug with persisting Link options where, because we weren't providing the "initial" state to the options editor, it was always starting with the default state - therefore, editing something **other** than the options would reset the link options back to the default. I tested this in `8.14` and the bug was present there, too - based on [the file history / git blame](https://github.com/elastic/kibana/blame/main/src/platform/plugins/private/links/public/components/editor/link_editor.tsx#L60), this bug has been around from the very beginning 🙈 **Before:** https://github.com/user-attachments/assets/360af02e-ae0f-470c-91a3-a52fc9b3d8c6 **After:** https://github.com/user-attachments/assets/d1e93bfa-566a-4506-99e3-47f92c922d49 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
96b4f8442e
commit
c6e6a77c54
3 changed files with 109 additions and 4 deletions
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { LinkEditor } from './link_editor';
|
||||
|
||||
jest.mock('./link_destination', () => {
|
||||
// mock this component to prevent handleDestinationPicked from being called on mount
|
||||
return { LinkDestination: () => <>LinkDestinationMock</> };
|
||||
});
|
||||
|
||||
describe('LinksEditor', () => {
|
||||
const nonDefaultOptions = {
|
||||
openInNewTab: true,
|
||||
useCurrentDateRange: false,
|
||||
useCurrentFilters: false,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
link: {
|
||||
id: 'foo',
|
||||
type: 'dashboardLink' as const,
|
||||
destination: '123',
|
||||
title: 'dashboard 01',
|
||||
},
|
||||
parentDashboardId: 'test',
|
||||
onSave: jest.fn(),
|
||||
onClose: jest.fn(),
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
const getOptionAriaChecked = (option: string): string | null => {
|
||||
return screen
|
||||
.getByTestId(`dashboardDrillDownOptions--${option}--checkbox`)
|
||||
.getAttribute('aria-checked');
|
||||
};
|
||||
|
||||
describe('dashboard link options', () => {
|
||||
test('starts with default when options not provided', async () => {
|
||||
render(<LinkEditor {...defaultProps} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('dashboardDrillDownOptions')).not.toBeNull(); // wait for lazy load
|
||||
});
|
||||
|
||||
expect(getOptionAriaChecked('useCurrentFilters')).toBe('true');
|
||||
expect(getOptionAriaChecked('useCurrentDateRange')).toBe('true');
|
||||
expect(getOptionAriaChecked('openInNewTab')).toBe('false');
|
||||
});
|
||||
|
||||
test('properly overrides default values when provided', async () => {
|
||||
render(
|
||||
<LinkEditor
|
||||
{...defaultProps}
|
||||
link={{
|
||||
...defaultProps.link,
|
||||
options: nonDefaultOptions,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('dashboardDrillDownOptions')).not.toBeNull(); // wait for lazy load
|
||||
});
|
||||
|
||||
expect(getOptionAriaChecked('useCurrentFilters')).toBe('false');
|
||||
expect(getOptionAriaChecked('useCurrentDateRange')).toBe('false');
|
||||
expect(getOptionAriaChecked('openInNewTab')).toBe('true');
|
||||
});
|
||||
|
||||
test('options are persisted on edit', async () => {
|
||||
render(
|
||||
<LinkEditor
|
||||
{...defaultProps}
|
||||
link={{
|
||||
...defaultProps.link,
|
||||
options: nonDefaultOptions,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('dashboardDrillDownOptions')).not.toBeNull(); // wait for lazy load
|
||||
});
|
||||
|
||||
await userEvent.click(screen.getByTestId('links--linkEditor--linkLabel--input'));
|
||||
await userEvent.keyboard('test label');
|
||||
await userEvent.click(screen.getByTestId('links--linkEditor--saveBtn'));
|
||||
|
||||
expect(defaultProps.onSave).toBeCalledWith({
|
||||
...defaultProps.link,
|
||||
label: 'test label',
|
||||
options: nonDefaultOptions,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -54,10 +54,10 @@ export const LinkEditor = ({
|
|||
const [selectedLinkType, setSelectedLinkType] = useState<LinkType>(
|
||||
link?.type ?? DASHBOARD_LINK_TYPE
|
||||
);
|
||||
const [defaultLinkLabel, setDefaultLinkLabel] = useState<string | undefined>();
|
||||
const [defaultLinkLabel, setDefaultLinkLabel] = useState<string | undefined>(link?.title);
|
||||
const [currentLinkLabel, setCurrentLinkLabel] = useState<string>(link?.label ?? '');
|
||||
const [linkDescription, setLinkDescription] = useState<string | undefined>();
|
||||
const [linkOptions, setLinkOptions] = useState<LinkOptions | undefined>();
|
||||
const [linkDescription, setLinkDescription] = useState<string | undefined>(link?.description);
|
||||
const [linkOptions, setLinkOptions] = useState<LinkOptions | undefined>(link?.options);
|
||||
const [linkDestination, setLinkDestination] = useState<string | undefined>(link?.destination);
|
||||
|
||||
const linkTypes: EuiRadioGroupOption[] = useMemo(() => {
|
||||
|
|
|
@ -24,7 +24,7 @@ export const DashboardDrilldownOptionsComponent = ({
|
|||
}: DashboardDrilldownOptionsProps) => {
|
||||
return (
|
||||
<>
|
||||
<EuiFormRow>
|
||||
<EuiFormRow data-test-subj="dashboardDrillDownOptions">
|
||||
<div>
|
||||
<EuiSwitch
|
||||
compressed
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue