[Dashboard] Default to saved object description when panel description is not provided (#181177)

Closes https://github.com/elastic/kibana/issues/181172

## Summary

This PR fixes a bug where panels were not showing descriptions from
library items - this is because (1) we weren't providing the
`defaultPanelDescription` as part of the default embeddable API and (2)
the panel header was not defaulting to the `defaultPanelDescription`
when a panel description was not provided.

Because of (1), the panel settings flyout showed a blank description
**despite** having the correct logic for defaulting to the default panel
description - that is why the tests in `customize_panel_editor.test.tsx`
passed but it didn't work in production.

### 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


### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
Hannah Mudge 2024-04-22 08:52:46 -06:00 committed by GitHub
parent fa936db23b
commit a41177f32c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 47 additions and 4 deletions

View file

@ -153,6 +153,7 @@ export const legacyEmbeddableToApi = (
const panelDescription = inputKeyToSubject<string>('description');
const defaultPanelTitle = outputKeyToSubject<string>('defaultTitle');
const defaultPanelDescription = outputKeyToSubject<string>('defaultDescription');
const disabledActionIds = inputKeyToSubject<string[] | undefined>('disabledActions');
function getSavedObjectId(input: { savedObjectId?: string }, output: { savedObjectId?: string }) {
@ -275,6 +276,7 @@ export const legacyEmbeddableToApi = (
setPanelDescription,
panelDescription,
defaultPanelDescription,
canLinkToLibrary: () => canLinkLegacyEmbeddable(embeddable),
linkToLibrary: () => linkLegacyEmbeddable(embeddable),

View file

@ -134,6 +134,7 @@ export abstract class Embeddable<
timeRange$: this.timeRange$,
isEditingEnabled: this.isEditingEnabled,
panelDescription: this.panelDescription,
defaultPanelDescription: this.defaultPanelDescription,
canLinkToLibrary: this.canLinkToLibrary,
disabledActionIds: this.disabledActionIds,
unlinkFromLibrary: this.unlinkFromLibrary,
@ -176,6 +177,7 @@ export abstract class Embeddable<
public isEditingEnabled: LegacyEmbeddableAPI['isEditingEnabled'];
public canLinkToLibrary: LegacyEmbeddableAPI['canLinkToLibrary'];
public panelDescription: LegacyEmbeddableAPI['panelDescription'];
public defaultPanelDescription: LegacyEmbeddableAPI['defaultPanelDescription'];
public disabledActionIds: LegacyEmbeddableAPI['disabledActionIds'];
public unlinkFromLibrary: LegacyEmbeddableAPI['unlinkFromLibrary'];
public setTimeRange: LegacyEmbeddableAPI['setTimeRange'];

View file

@ -157,14 +157,37 @@ describe('Presentation panel', () => {
});
describe('titles', () => {
it('renders the panel title from the api', async () => {
it('renders the panel title from the api and not the default title', async () => {
const api: DefaultPresentationPanelApi = {
uuid: 'test',
panelTitle: new BehaviorSubject<string | undefined>('SUPER TITLE'),
defaultPanelTitle: new BehaviorSubject<string | undefined>('SO Title'),
};
await renderPresentationPanel({ api });
await waitFor(() => {
expect(screen.getByTestId('embeddablePanelTitleInner')).toHaveTextContent('SUPER TITLE');
});
});
it('renders the default title from the api when a panel title is not provided', async () => {
const api: DefaultPresentationPanelApi = {
uuid: 'test',
defaultPanelTitle: new BehaviorSubject<string | undefined>('SO Title'),
};
await renderPresentationPanel({ api });
await waitFor(() => {
expect(screen.getByTestId('embeddablePanelTitleInner')).toHaveTextContent('SO Title');
});
});
it("does not render an info icon when the api doesn't provide a panel description or default description", async () => {
const api: DefaultPresentationPanelApi = {
uuid: 'test',
panelTitle: new BehaviorSubject<string | undefined>('SUPER TITLE'),
};
await renderPresentationPanel({ api });
await waitFor(() => {
expect(screen.getByTestId('embeddablePanelTitleInner')).toHaveTextContent('SUPER TITLE');
expect(screen.queryByTestId('embeddablePanelTitleDescriptionIcon')).toBe(null);
});
});
@ -180,6 +203,18 @@ describe('Presentation panel', () => {
});
});
it('renders an info icon when the api provides a default description', async () => {
const api: DefaultPresentationPanelApi = {
uuid: 'test',
panelTitle: new BehaviorSubject<string | undefined>('SUPER TITLE'),
defaultPanelDescription: new BehaviorSubject<string | undefined>('SO Description'),
};
await renderPresentationPanel({ api });
await waitFor(() => {
expect(screen.getByTestId('embeddablePanelTitleDescriptionIcon')).toBeInTheDocument();
});
});
it('does not render a title when in view mode when the provided title is blank', async () => {
const api: DefaultPresentationPanelApi & PublishesViewMode = {
uuid: 'test',

View file

@ -55,6 +55,7 @@ export const PresentationPanelInternal = <
hidePanelTitle,
panelDescription,
defaultPanelTitle,
defaultPanelDescription,
rawViewMode,
parentHidePanelTitle,
] = useBatchedOptionalPublishingSubjects(
@ -64,6 +65,7 @@ export const PresentationPanelInternal = <
api?.hidePanelTitle,
api?.panelDescription,
api?.defaultPanelTitle,
api?.defaultPanelDescription,
viewModeSubject,
api?.parentApi?.hidePanelTitle
);
@ -124,9 +126,9 @@ export const PresentationPanelInternal = <
showBadges={showBadges}
getActions={getActions}
actionPredicate={actionPredicate}
panelDescription={panelDescription}
showNotifications={showNotifications}
panelTitle={panelTitle ?? defaultPanelTitle}
panelDescription={panelDescription ?? defaultPanelDescription}
/>
)}
{blockingError && api && (

View file

@ -588,7 +588,9 @@ export class DashboardPageObject extends FtrService {
public async getPanelTitles() {
this.log.debug('in getPanelTitles');
const titleObjects = await this.find.allByCssSelector('span.embPanel__titleInner');
const titleObjects = await this.find.allByCssSelector(
'[data-test-subj=embeddablePanelTitleInner] .embPanel__titleText'
);
return await Promise.all(titleObjects.map(async (title) => await title.getVisibleText()));
}