diff --git a/public/components/notebooks/components/__tests__/__snapshots__/notebook.test.tsx.snap b/public/components/notebooks/components/__tests__/__snapshots__/notebook.test.tsx.snap
index 90933ace6d..b2bc5ba057 100644
--- a/public/components/notebooks/components/__tests__/__snapshots__/notebook.test.tsx.snap
+++ b/public/components/notebooks/components/__tests__/__snapshots__/notebook.test.tsx.snap
@@ -1,6 +1,344 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[` spec renders the component 1`] = `
+exports[` spec Renders the empty component 1`] = `
+
({
describe('
spec', () => {
configure({ adapter: new Adapter() });
+ const props = {
+ loading: false,
+ fetchNotebooks: jest.fn(),
+ addSampleNotebooks: jest.fn(),
+ createNotebook: jest.fn(),
+ renameNotebook: jest.fn(),
+ cloneNotebook: jest.fn(),
+ deleteNotebook: jest.fn(),
+ parentBreadcrumb: { href: 'parent-href', text: 'parent-text' },
+ setBreadcrumbs: jest.fn(),
+ setToast: jest.fn(),
+ };
+
+ const renderNoteTable = (overrides = {}) => {
+ const utils = render(
);
+ // Additional setup or assertions if needed
+ return utils;
+ };
+
+ afterEach(() => {
+ cleanup(); // Cleanup the rendered component after each test
+ });
+
it('renders the empty component', () => {
- const fetchNotebooks = jest.fn();
- const addSampleNotebooks = jest.fn();
- const createNotebook = jest.fn();
- const renameNotebook = jest.fn();
- const cloneNotebook = jest.fn();
- const deleteNotebook = jest.fn();
- const setBreadcrumbs = jest.fn();
- const setToast = jest.fn();
- const utils = render(
-
- );
+ const utils = renderNoteTable({ notebooks: [] });
expect(utils.container.firstChild).toMatchSnapshot();
});
it('renders the component', () => {
- const fetchNotebooks = jest.fn();
- const addSampleNotebooks = jest.fn();
- const createNotebook = jest.fn();
- const renameNotebook = jest.fn();
- const cloneNotebook = jest.fn();
- const deleteNotebook = jest.fn();
- const setBreadcrumbs = jest.fn();
- const setToast = jest.fn();
const notebooks = Array.from({ length: 5 }, (v, k) => ({
path: `path-${k}`,
id: `id-${k}`,
dateCreated: '2023-01-01 12:00:00',
dateModified: '2023-01-02 12:00:00',
}));
- const utils = render(
-
- );
+ const utils = renderNoteTable({ notebooks });
expect(utils.container.firstChild).toMatchSnapshot();
- utils.getByText('Actions').click();
- utils.getByText('Add samples').click();
- utils.getAllByLabelText('Select this row')[0].click();
- utils.getByText('Actions').click();
- utils.getByText('Delete').click();
- utils.getByText('Cancel').click();
- utils.getAllByLabelText('Select this row')[0].click();
- utils.getByText('Actions').click();
- utils.getByText('Rename').click();
+ fireEvent.click(utils.getByText('Actions'));
+ fireEvent.click(utils.getByText('Add samples'));
+ fireEvent.click(utils.getAllByLabelText('Select this row')[0]);
+ fireEvent.click(utils.getByText('Actions'));
+ fireEvent.click(utils.getByText('Delete'));
+ fireEvent.click(utils.getByText('Cancel'));
+ fireEvent.click(utils.getAllByLabelText('Select this row')[0]);
+ fireEvent.click(utils.getByText('Actions'));
+ fireEvent.click(utils.getByText('Rename'));
});
- it('create notebook', async () => {
- const fetchNotebooks = jest.fn();
- const addSampleNotebooks = jest.fn();
- const createNotebook = jest.fn();
- const renameNotebook = jest.fn();
- const cloneNotebook = jest.fn();
- const deleteNotebook = jest.fn();
- const setBreadcrumbs = jest.fn();
- const setToast = jest.fn();
+ it('create notebook modal', async () => {
const notebooks = Array.from({ length: 5 }, (v, k) => ({
path: `path-${k}`,
id: `id-${k}`,
dateCreated: 'date-created',
dateModified: 'date-modified',
}));
- const utils = render(
-
- );
- utils.getByText('Create notebook').click();
+ const utils = renderNoteTable({ notebooks });
+ fireEvent.click(utils.getByText('Create notebook'));
await waitFor(() => {
expect(global.window.location.href).toContain('/create');
});
});
+
+ it('filters notebooks based on search input', () => {
+ const { getByPlaceholderText, getAllByText, queryByText } = renderNoteTable({
+ notebooks: [
+ {
+ path: 'path-1',
+ id: 'id-1',
+ dateCreated: 'date-created',
+ dateModified: 'date-modified',
+ },
+ ],
+ });
+
+ const searchInput = getByPlaceholderText('Search notebook name');
+ fireEvent.change(searchInput, { target: { value: 'path-1' } });
+
+ // Assert that only the matching notebook is displayed
+ expect(getAllByText('path-1')).toHaveLength(1);
+ expect(queryByText('path-0')).toBeNull();
+ expect(queryByText('path-2')).toBeNull();
+ });
+
+ it('displays empty state message and create notebook button', () => {
+ const { getAllByText, getAllByTestId } = renderNoteTable({ notebooks: [] });
+
+ expect(getAllByText('No notebooks')).toHaveLength(1);
+
+ // Create notebook using the modal
+ fireEvent.click(getAllByText('Create notebook')[0]);
+ fireEvent.click(getAllByTestId('custom-input-modal-input')[0]);
+ fireEvent.input(getAllByTestId('custom-input-modal-input')[0], {
+ target: { value: 'test-notebook' },
+ });
+ fireEvent.click(getAllByText('Create')[0]);
+ expect(props.createNotebook).toHaveBeenCalledTimes(1);
+ });
+
+ it('renames a notebook', () => {
+ const notebooks = [
+ {
+ path: 'path-1',
+ id: 'id-1',
+ dateCreated: 'date-created',
+ dateModified: 'date-modified',
+ },
+ ];
+ const { getByText, getByLabelText, getAllByText, getByTestId } = renderNoteTable({ notebooks });
+
+ // Select a notebook
+ fireEvent.click(getByLabelText('Select this row'));
+
+ // Open Actions dropdown and click Rename
+ fireEvent.click(getByText('Actions'));
+ fireEvent.click(getByText('Rename'));
+
+ // Ensure the modal is open (you may need to adjust based on your modal implementation)
+ expect(getAllByText('Rename notebook')).toHaveLength(1);
+
+ // Mock user input and submit
+ fireEvent.input(getByTestId('custom-input-modal-input'), {
+ target: { value: 'test-notebook-newname' },
+ });
+ fireEvent.click(getByTestId('custom-input-modal-confirm-button'));
+
+ // Assert that the renameNotebook function is called
+ expect(props.renameNotebook).toHaveBeenCalledTimes(1);
+ expect(props.renameNotebook).toHaveBeenCalledWith('test-notebook-newname', 'id-1');
+ });
+
+ it('clones a notebook', () => {
+ const notebooks = [
+ {
+ path: 'path-1',
+ id: 'id-1',
+ dateCreated: 'date-created',
+ dateModified: 'date-modified',
+ },
+ ];
+ const { getByText, getByLabelText, getAllByText, getByTestId } = renderNoteTable({ notebooks });
+
+ // Select a notebook
+ fireEvent.click(getByLabelText('Select this row'));
+
+ // Open Actions dropdown and click Duplicate
+ fireEvent.click(getByText('Actions'));
+ fireEvent.click(getByText('Duplicate'));
+
+ // Ensure the modal is open (you may need to adjust based on your modal implementation)
+ expect(getAllByText('Duplicate notebook')).toHaveLength(1);
+
+ // Mock user input and submit
+ fireEvent.input(getByTestId('custom-input-modal-input'), {
+ target: { value: 'new-copy' },
+ });
+ fireEvent.click(getByTestId('custom-input-modal-confirm-button'));
+
+ // Assert that the cloneNotebook function is called
+ expect(props.cloneNotebook).toHaveBeenCalledTimes(1);
+ expect(props.cloneNotebook).toHaveBeenCalledWith('new-copy', 'id-1');
+ });
+
+ it('deletes a notebook', () => {
+ const notebooks = [
+ {
+ path: 'path-1',
+ id: 'id-1',
+ dateCreated: 'date-created',
+ dateModified: 'date-modified',
+ },
+ ];
+ const { getByText, getByLabelText, getAllByText, getByTestId } = renderNoteTable({ notebooks });
+
+ // Select a notebook
+ fireEvent.click(getByLabelText('Select this row'));
+
+ // Open Actions dropdown and click Delete
+ fireEvent.click(getByText('Actions'));
+ fireEvent.click(getByText('Delete'));
+
+ // Ensure the modal is open (you may need to adjust based on your modal implementation)
+ expect(getAllByText('Delete 1 notebook')).toHaveLength(1);
+
+ // Mock user confirmation and submit
+ fireEvent.input(getByTestId('delete-notebook-modal-input'), {
+ target: { value: 'delete' },
+ });
+ fireEvent.click(getByTestId('delete-notebook-modal-delete-button'));
+
+ // Assert that the deleteNotebook function is called
+ expect(props.deleteNotebook).toHaveBeenCalledTimes(1);
+ expect(props.deleteNotebook).toHaveBeenCalledWith(['id-1'], expect.any(String));
+ });
+
+ it('adds sample notebooks', async () => {
+ const { getByText, getAllByText, getByTestId } = renderNoteTable({ notebooks: [] });
+
+ // Open Actions dropdown and click Add samples
+ fireEvent.click(getByText('Actions'));
+ fireEvent.click(getAllByText('Add samples')[0]);
+
+ // Ensure the modal is open (you may need to adjust based on your modal implementation)
+ expect(getAllByText('Add sample notebooks')).toHaveLength(1);
+
+ // Mock user confirmation and submit
+ fireEvent.click(getByTestId('confirmModalConfirmButton'));
+
+ // Assert that the addSampleNotebooks function is called
+ expect(props.addSampleNotebooks).toHaveBeenCalledTimes(1);
+ });
+
+ it('closes the action panel', async () => {
+ const { getByText, queryByTestId } = renderNoteTable({ notebooks: [] });
+ expect(queryByTestId('rename-notebook-btn')).not.toBeInTheDocument();
+
+ // Open Actions dropdown
+ fireEvent.click(getByText('Actions'));
+
+ // Ensure the action panel is open
+ expect(queryByTestId('rename-notebook-btn')).toBeInTheDocument();
+
+ await act(async () => {
+ fireEvent.click(getByText('Actions'));
+ });
+
+ // Ensure the action panel is closed
+ expect(queryByTestId('rename-notebook-btn')).not.toBeInTheDocument();
+ });
+
+ it('closes the delete modal', () => {
+ const notebooks = [
+ {
+ path: 'path-1',
+ id: 'id-1',
+ dateCreated: 'date-created',
+ dateModified: 'date-modified',
+ },
+ ];
+ const { getByText, getByLabelText, queryByText } = renderNoteTable({ notebooks });
+
+ // Select a notebook
+ fireEvent.click(getByLabelText('Select this row'));
+
+ // Open Actions dropdown and click Delete
+ fireEvent.click(getByText('Actions'));
+ fireEvent.click(getByText('Delete'));
+
+ // Ensure the modal is open
+ expect(getByText('Delete 1 notebook')).toBeInTheDocument();
+
+ // Close the delete modal
+ fireEvent.click(getByText('Cancel'));
+
+ // Ensure the delete modal is closed
+ expect(queryByText('Delete 1 notebook')).toBeNull();
+ });
});
diff --git a/public/components/notebooks/components/__tests__/notebook.test.tsx b/public/components/notebooks/components/__tests__/notebook.test.tsx
index f31508852e..eb33888af0 100644
--- a/public/components/notebooks/components/__tests__/notebook.test.tsx
+++ b/public/components/notebooks/components/__tests__/notebook.test.tsx
@@ -3,17 +3,27 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { fireEvent, render, waitFor } from '@testing-library/react';
-import { configure, mount, shallow } from 'enzyme';
+import '@testing-library/jest-dom';
+import { act, fireEvent, render, waitFor } from '@testing-library/react';
+import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
-import PPLService from '../../../../services/requests/ppl';
import React from 'react';
import { HttpResponse } from '../../../../../../../src/core/public';
-import httpClientMock from '../../../../../test/__mocks__/httpClientMock';
-import { sampleNotebook1 } from '../helpers/__tests__/sampleDefaultNotebooks';
-import { Notebook } from '../notebook';
-import { SavedObjectsActions } from '../../../../services/saved_objects/saved_object_client/saved_objects_actions';
+import { getOSDHttp } from '../../../../../common/utils';
+import {
+ addCodeBlockResponse,
+ clearOutputNotebook,
+ codeBlockNotebook,
+ codePlaceholderText,
+ emptyNotebook,
+ notebookPutResponse,
+ runCodeBlockResponse,
+ sampleNotebook1,
+} from '../../../../../test/notebooks_constants';
import { sampleSavedVisualization } from '../../../../../test/panels_constants';
+import PPLService from '../../../../services/requests/ppl';
+import { SavedObjectsActions } from '../../../../services/saved_objects/saved_object_client/saved_objects_actions';
+import { Notebook } from '../notebook';
jest.mock('../../../../../../../src/plugins/embeddable/public', () => ({
ViewMode: {
@@ -36,23 +46,27 @@ global.fetch = jest.fn(() =>
describe('
spec', () => {
configure({ adapter: new Adapter() });
+ const httpClient = getOSDHttp();
+ const pplService = new PPLService(httpClient);
+ const setBreadcrumbs = jest.fn();
+ const renameNotebook = jest.fn();
+ const cloneNotebook = jest.fn();
+ const deleteNotebook = jest.fn();
+ const setToast = jest.fn();
+ const location = jest.fn() as any;
+ location.search = '';
+ const history = jest.fn() as any;
+ history.replace = jest.fn();
+ history.push = jest.fn();
- it('renders the empty component', async () => {
- const pplService = new PPLService(httpClientMock);
- const setBreadcrumbs = jest.fn();
- const renameNotebook = jest.fn();
- const cloneNotebook = jest.fn();
- const deleteNotebook = jest.fn();
- const setToast = jest.fn();
- const location = jest.fn();
- const history = jest.fn() as any;
- history.replace = jest.fn();
+ it('Renders the empty component', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((emptyNotebook as unknown) as HttpResponse));
const utils = render(
spec', () => {
history={history}
/>
);
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
expect(utils.container.firstChild).toMatchSnapshot();
- utils.getByText('Add code block').click();
- utils.getByText('Add visualization').click();
});
- it('renders the component', async () => {
- const pplService = new PPLService(httpClientMock);
- const setBreadcrumbs = jest.fn();
- const renameNotebook = jest.fn();
- const cloneNotebook = jest.fn();
- const deleteNotebook = jest.fn();
- const setToast = jest.fn();
- const location = jest.fn();
- const history = jest.fn() as any;
- history.replace = jest.fn();
+ it('test reporting action button', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((emptyNotebook as unknown) as HttpResponse));
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+ expect(utils.container.firstChild).toMatchSnapshot();
+
+ act(() => {
+ fireEvent.click(utils.getByText('Reporting actions'));
+ });
+
+ expect(utils.queryByTestId('download-notebook-pdf')).toBeInTheDocument();
+
+ act(() => {
+ fireEvent.click(utils.getByText('Reporting actions'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByTestId('download-notebook-pdf')).toBeNull();
+ });
+ });
+
+ it('Adds a code block', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((emptyNotebook as unknown) as HttpResponse));
+ let postFlag = 1;
+ httpClient.post = jest.fn(() => {
+ if (postFlag === 1) {
+ postFlag += 1;
+ return Promise.resolve((addCodeBlockResponse as unknown) as HttpResponse);
+ } else return Promise.resolve((runCodeBlockResponse as unknown) as HttpResponse);
+ });
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ utils.getByText('Add code block').click();
+ });
+
+ await waitFor(() => {
+ expect(utils.getByPlaceholderText(codePlaceholderText)).toBeInTheDocument();
+ });
+ });
+
+ it('toggles show input in code block', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((emptyNotebook as unknown) as HttpResponse));
+ let postFlag = 1;
+ httpClient.post = jest.fn(() => {
+ if (postFlag === 1) {
+ postFlag += 1;
+ return Promise.resolve((addCodeBlockResponse as unknown) as HttpResponse);
+ } else return Promise.resolve((runCodeBlockResponse as unknown) as HttpResponse);
+ });
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ utils.getByText('Add code block').click();
+ });
+
+ await waitFor(() => {
+ expect(utils.getByPlaceholderText(codePlaceholderText)).toBeInTheDocument();
+ });
+
+ act(() => {
+ utils.getByLabelText('Toggle show input').click();
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByPlaceholderText(codePlaceholderText)).toBeNull();
+ });
+ });
+
+ it('runs a code block and checks the output', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((emptyNotebook as unknown) as HttpResponse));
+ let postFlag = 1;
+ httpClient.post = jest.fn(() => {
+ if (postFlag === 1) {
+ postFlag += 1;
+ return Promise.resolve((addCodeBlockResponse as unknown) as HttpResponse);
+ } else return Promise.resolve((runCodeBlockResponse as unknown) as HttpResponse);
+ });
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ utils.getByText('Add code block').click();
+ });
+
+ await waitFor(() => {
+ expect(utils.getByPlaceholderText(codePlaceholderText)).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.input(utils.getByPlaceholderText(codePlaceholderText), {
+ target: { value: '%md \\n hello' },
+ });
+ fireEvent.click(utils.getByText('Run'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByText('Run')).toBeNull();
+ expect(utils.getByText('hello')).toBeInTheDocument();
+ });
+ });
+
+ it('toggles between input/output only views', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((emptyNotebook as unknown) as HttpResponse));
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ utils.getByText('Add code block').click();
+ });
+
+ await waitFor(() => {
+ expect(utils.getByPlaceholderText(codePlaceholderText)).toBeInTheDocument();
+ });
+
+ act(() => {
+ utils.getByLabelText('Toggle show input').click();
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByPlaceholderText(codePlaceholderText)).toBeNull();
+ });
+
+ act(() => {
+ utils.getByLabelText('Toggle show input').click();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByTestId('input_only'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByText('Refresh')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByTestId('output_only'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByText('Refresh')).toBeNull();
+ expect(utils.getByText('hello')).toBeInTheDocument();
+ });
+ });
+
+ it('Renders a notebook and checks paragraph actions', async () => {
+ httpClient.get = jest.fn(() => Promise.resolve((codeBlockNotebook as unknown) as HttpResponse));
+ httpClient.put = jest.fn(() =>
+ Promise.resolve((clearOutputNotebook as unknown) as HttpResponse)
+ );
+ httpClient.delete = jest.fn(() =>
+ Promise.resolve(({ paragraphs: [] } as unknown) as HttpResponse)
+ );
+
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Paragraph actions'));
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Clear all outputs'));
+ });
+
+ await waitFor(() => {
+ expect(
+ utils.queryByText(
+ 'Are you sure you want to clear all outputs? The action cannot be undone.'
+ )
+ ).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByTestId('confirmModalConfirmButton'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByText('hello')).toBeNull();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Paragraph actions'));
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Delete all paragraphs'));
+ });
+
+ await waitFor(() => {
+ expect(
+ utils.queryByText(
+ 'Are you sure you want to delete all paragraphs? The action cannot be undone.'
+ )
+ ).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByTestId('confirmModalConfirmButton'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByText('No paragraphs')).toBeInTheDocument();
+ });
+ });
+
+ it('Checks notebook rename action', async () => {
+ const renameNotebookMock = jest.fn(() =>
+ Promise.resolve((notebookPutResponse as unknown) as HttpResponse)
+ );
+ const cloneNotebookMock = jest.fn(() => Promise.resolve('dummy-string'));
+ httpClient.get = jest.fn(() => Promise.resolve((codeBlockNotebook as unknown) as HttpResponse));
+
+ httpClient.put = jest.fn(() => {
+ return Promise.resolve((notebookPutResponse as unknown) as HttpResponse);
+ });
+
+ httpClient.post = jest.fn(() => {
+ return Promise.resolve((addCodeBlockResponse as unknown) as HttpResponse);
+ });
+
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Notebook actions'));
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Rename notebook'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByTestId('custom-input-modal-input')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.input(utils.getByTestId('custom-input-modal-input'), {
+ target: { value: 'test-notebook-newname' },
+ });
+ fireEvent.click(utils.getByTestId('custom-input-modal-confirm-button'));
+ });
+
+ await waitFor(() => {
+ expect(renameNotebookMock).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it('Checks notebook clone action', async () => {
+ const renameNotebookMock = jest.fn(() =>
+ Promise.resolve((notebookPutResponse as unknown) as HttpResponse)
+ );
+ const cloneNotebookMock = jest.fn(() => Promise.resolve('dummy-string'));
+ httpClient.get = jest.fn(() => Promise.resolve((codeBlockNotebook as unknown) as HttpResponse));
+
+ httpClient.put = jest.fn(() => {
+ return Promise.resolve((notebookPutResponse as unknown) as HttpResponse);
+ });
+
+ httpClient.post = jest.fn(() => {
+ return Promise.resolve((addCodeBlockResponse as unknown) as HttpResponse);
+ });
+
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Notebook actions'));
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Duplicate notebook'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByTestId('custom-input-modal-input')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByTestId('custom-input-modal-confirm-button'));
+ });
+
+ expect(cloneNotebookMock).toHaveBeenCalledTimes(1);
+ });
+
+ it('Checks notebook delete action', async () => {
+ const renameNotebookMock = jest.fn(() =>
+ Promise.resolve((notebookPutResponse as unknown) as HttpResponse)
+ );
+ const cloneNotebookMock = jest.fn(() => Promise.resolve('dummy-string'));
+ httpClient.get = jest.fn(() => Promise.resolve((codeBlockNotebook as unknown) as HttpResponse));
+
+ httpClient.put = jest.fn(() => {
+ return Promise.resolve((notebookPutResponse as unknown) as HttpResponse);
+ });
+
+ httpClient.post = jest.fn(() => {
+ return Promise.resolve((addCodeBlockResponse as unknown) as HttpResponse);
+ });
+
+ const utils = render(
+
+ );
+ await waitFor(() => {
+ expect(utils.getByText('sample-notebook-1')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Notebook actions'));
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByText('Delete notebook'));
+ });
+
+ await waitFor(() => {
+ expect(utils.queryByTestId('delete-notebook-modal-input')).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.input(utils.getByTestId('delete-notebook-modal-input'), {
+ target: { value: 'delete' },
+ });
+ });
+
+ act(() => {
+ fireEvent.click(utils.getByTestId('delete-notebook-modal-delete-button'));
+ });
+
+ expect(deleteNotebook).toHaveBeenCalledTimes(1);
+ });
+ it('Renders the visualization component', async () => {
SavedObjectsActions.getBulk = jest.fn().mockResolvedValue({
observabilityObjectList: [{ savedVisualization: sampleSavedVisualization }],
});
- httpClientMock.get = jest.fn(() =>
+ httpClient.get = jest.fn(() =>
Promise.resolve(({
...sampleNotebook1,
path: sampleNotebook1.name,
@@ -108,7 +596,7 @@ describe('
spec', () => {
pplService={pplService}
openedNoteId={sampleNotebook1.id}
DashboardContainerByValueRenderer={jest.fn()}
- http={httpClientMock}
+ http={httpClient}
parentBreadcrumb={{ href: 'parent-href', text: 'parent-text' }}
setBreadcrumbs={setBreadcrumbs}
renameNotebook={renameNotebook}
diff --git a/public/components/notebooks/components/helpers/__tests__/default_parser.test.tsx b/public/components/notebooks/components/helpers/__tests__/default_parser.test.tsx
index 3c03a3d5b9..2339b95026 100644
--- a/public/components/notebooks/components/helpers/__tests__/default_parser.test.tsx
+++ b/public/components/notebooks/components/helpers/__tests__/default_parser.test.tsx
@@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { defaultParagraphParser } from '../default_parser';
import {
sampleNotebook1,
sampleNotebook2,
@@ -12,18 +11,18 @@ import {
sampleNotebook5,
sampleParsedParagraghs1,
sampleParsedParagraghs2,
-} from './sampleDefaultNotebooks';
+} from '../../../../../../test/notebooks_constants';
+import { defaultParagraphParser } from '../default_parser';
// Perfect schema
describe('Testing default backend parser function with perfect schema', () => {
- test('defaultParagraphParserTest1', (done) => {
+ it('defaultParagraphParserTest1', () => {
const parsedParagraphs1 = defaultParagraphParser(sampleNotebook1.paragraphs);
const parsedParagraphs2 = defaultParagraphParser(sampleNotebook2.paragraphs);
const parsedParagraphs3 = defaultParagraphParser([]);
expect(parsedParagraphs1).toEqual(sampleParsedParagraghs1);
expect(parsedParagraphs2).toEqual(sampleParsedParagraghs2);
expect(parsedParagraphs3).toEqual([]);
- done();
});
it('returns parsed paragraphs', () => {
@@ -82,16 +81,15 @@ describe('Testing default backend parser function with perfect schema', () => {
// Issue in schema
describe('Testing default backend parser function with wrong schema', () => {
- test('defaultParagraphParserTest2', (done) => {
+ it('defaultParagraphParserTest2', () => {
expect(() => {
- const parsedParagraphs1 = defaultParagraphParser(sampleNotebook3.paragraphs);
+ const _parsedParagraphs1 = defaultParagraphParser(sampleNotebook3.paragraphs);
}).toThrow(Error);
expect(() => {
- const parsedParagraphs2 = defaultParagraphParser(sampleNotebook4.paragraphs);
+ const _parsedParagraphs2 = defaultParagraphParser(sampleNotebook4.paragraphs);
}).toThrow(Error);
expect(() => {
- const parsedParagraphs3 = defaultParagraphParser(sampleNotebook5.paragraphs);
+ const _parsedParagraphs3 = defaultParagraphParser(sampleNotebook5.paragraphs);
}).toThrow(Error);
- done();
});
});
diff --git a/public/components/notebooks/components/note_table.tsx b/public/components/notebooks/components/note_table.tsx
index 9c63e00082..a25a1d7a68 100644
--- a/public/components/notebooks/components/note_table.tsx
+++ b/public/components/notebooks/components/note_table.tsx
@@ -36,14 +36,13 @@ import {
CREATE_NOTE_MESSAGE,
NOTEBOOKS_DOCUMENTATION_URL,
} from '../../../../common/constants/notebooks';
-import { UI_DATE_FORMAT } from '../../../../common/constants/shared';
+import { UI_DATE_FORMAT, pageStyles } from '../../../../common/constants/shared';
import {
DeleteNotebookModal,
getCustomModal,
getSampleNotebooksModal,
} from './helpers/modal_containers';
import { NotebookType } from './main';
-import { pageStyles } from '../../../../common/constants/shared';
interface NoteTableProps {
loading: boolean;
@@ -222,6 +221,7 @@ export function NoteTable({
setIsActionsPopoverOpen(false);
renameNote();
}}
+ data-test-subj="rename-notebook-btn"
>
Rename
,
@@ -232,6 +232,7 @@ export function NoteTable({
setIsActionsPopoverOpen(false);
cloneNote();
}}
+ data-test-subj="duplicate-notebook-btn"
>
Duplicate
,
@@ -242,6 +243,7 @@ export function NoteTable({
setIsActionsPopoverOpen(false);
deleteNote();
}}
+ data-test-subj="delete-notebook-btn"
>
Delete
,
@@ -251,6 +253,7 @@ export function NoteTable({
setIsActionsPopoverOpen(false);
addSampleNotebooksModal();
}}
+ data-test-subj="add-samples-btn"
>
Add samples
,
diff --git a/public/components/notebooks/components/notebook.tsx b/public/components/notebooks/components/notebook.tsx
index 4f22f146fc..9db0114126 100644
--- a/public/components/notebooks/components/notebook.tsx
+++ b/public/components/notebooks/components/notebook.tsx
@@ -6,7 +6,7 @@
import {
EuiButton,
EuiButtonGroup,
- EuiButtonGroupOption,
+ EuiButtonGroupOptionProps,
EuiCard,
EuiContextMenu,
EuiContextMenuPanelDescriptor,
@@ -27,7 +27,6 @@ import moment from 'moment';
import queryString from 'query-string';
import React, { Component } from 'react';
import { RouteComponentProps } from 'react-router-dom';
-import PPLService from '../../../services/requests/ppl';
import { ChromeBreadcrumb, CoreStart } from '../../../../../../src/core/public';
import { DashboardStart } from '../../../../../../src/plugins/dashboard/public';
import {
@@ -36,6 +35,7 @@ import {
} from '../../../../common/constants/notebooks';
import { UI_DATE_FORMAT } from '../../../../common/constants/shared';
import { ParaType } from '../../../../common/types/notebooks';
+import PPLService from '../../../services/requests/ppl';
import { GenerateReportLoadingModal } from './helpers/custom_modals/reporting_loading_modal';
import { defaultParagraphParser } from './helpers/default_parser';
import { DeleteNotebookModal, getCustomModal, getDeleteModal } from './helpers/modal_containers';
@@ -193,7 +193,7 @@ export class Notebook extends Component
{
paragraphId: para.uniqueId,
},
})
- .then((res) => {
+ .then((_res) => {
const paragraphs = [...this.state.paragraphs];
paragraphs.splice(index, 1);
const parsedPara = [...this.state.parsedPara];
@@ -205,6 +205,7 @@ export class Notebook extends Component {
'Error deleting paragraph, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
}
};
@@ -246,6 +247,7 @@ export class Notebook extends Component {
'Error deleting paragraph, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
},
'Delete all paragraphs',
@@ -354,6 +356,7 @@ export class Notebook extends Component {
'Error deleting visualization, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -388,6 +391,7 @@ export class Notebook extends Component {
'Error adding paragraph, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -421,13 +425,14 @@ export class Notebook extends Component {
.post(`${NOTEBOOKS_API_PREFIX}/set_paragraphs/`, {
body: JSON.stringify(moveParaObj),
})
- .then((res) => this.setState({ paragraphs, parsedPara }))
- .then((res) => this.scrollToPara(targetIndex))
+ .then((_res) => this.setState({ paragraphs, parsedPara }))
+ .then((_res) => this.scrollToPara(targetIndex))
.catch((err) => {
this.props.setToast(
'Error moving paragraphs, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -460,6 +465,7 @@ export class Notebook extends Component {
'Error clearing paragraphs, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -530,9 +536,9 @@ export class Notebook extends Component {
}
};
- runForAllParagraphs = (reducer: (para: ParaType, index: number) => Promise) => {
+ runForAllParagraphs = (reducer: (para: ParaType, _index: number) => Promise) => {
return this.state.parsedPara
- .map((para: ParaType, index: number) => () => reducer(para, index))
+ .map((para: ParaType, _index: number) => () => reducer(para, _index))
.reduce((chain, func) => chain.then(func), Promise.resolve());
};
@@ -588,6 +594,7 @@ export class Notebook extends Component {
'Error fetching notebooks, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -604,6 +611,7 @@ export class Notebook extends Component {
})
.catch((err) => {
this.props.setToast('Error getting query output', 'danger');
+ console.error(err);
});
};
@@ -655,6 +663,7 @@ export class Notebook extends Component {
})
.catch((error) => {
this.props.setToast('Error checking Reporting Plugin Installation status.', 'danger');
+ console.error(error);
});
}
@@ -689,7 +698,7 @@ export class Notebook extends Component {
);
- const viewOptions: EuiButtonGroupOption[] = [
+ const viewOptions: EuiButtonGroupOptionProps[] = [
{
id: 'view_both',
label: 'View both',
@@ -743,7 +752,7 @@ export class Notebook extends Component