({
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/helpers/__tests__/sampleZeppelinNotebooks.tsx b/public/components/notebooks/components/helpers/__tests__/sampleZeppelinNotebooks.tsx
deleted file mode 100644
index db07da1c51..0000000000
--- a/public/components/notebooks/components/helpers/__tests__/sampleZeppelinNotebooks.tsx
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright OpenSearch Contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-// Sample notebook with all input and output
-export const sampleNotebook1 = {
- paragraphs: [
- {
- text:
- "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* You may use the top left buttons to play around with notebooks and Paragraphs",
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:15:04.590',
- config: {},
- settings: { params: {}, forms: {} },
- results: {
- code: 'SUCCESS',
- msg: [
- {
- type: 'HTML',
- data:
- '
\n
Hi Everyone
\n
\n- Here’s a demo on OpenSearch Dashboards Notebooks
\n- You may use the top left buttons to play around with notebooks and Paragraphs
\n
\n\n
',
- },
- ],
- },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958104590_901298942',
- id: 'paragraph_1596519508360_932236116',
- dateCreated: '2020-08-20 21:15:04.590',
- status: 'READY',
- },
- {
- title: 'VISUALIZATION',
- text:
- '%sh #vizobject:{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:25:28.588',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958728587_1310320520',
- id: 'paragraph_1597958728587_1310320520',
- dateCreated: '2020-08-20 21:25:28.587',
- status: 'READY',
- },
- ],
- name: 'Embed Vizualization',
- id: '2FJH8PW8K',
- defaultInterpreterGroup: 'spark',
- version: '0.9.0-preview2',
- noteParams: {},
- noteForms: {},
- angularObjects: {},
- config: { isZeppelinNotebookCronEnable: false },
- info: {},
-};
-
-// Parsed Output of sample notebook1
-export const sampleParsedParagraghs1 = [
- {
- uniqueId: 'paragraph_1596519508360_932236116',
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: false,
- vizObjectInput: '',
- id: 1,
- inp:
- "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* You may use the top left buttons to play around with notebooks and Paragraphs",
- lang: 'text/x-',
- editorLanguage: '',
- typeOut: ['HTML'],
- out: [
- '
\n
Hi Everyone
\n
\n- Here’s a demo on OpenSearch Dashboards Notebooks
\n- You may use the top left buttons to play around with notebooks and Paragraphs
\n
\n\n
',
- ],
- },
- {
- uniqueId: 'paragraph_1597958728587_1310320520',
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: true,
- vizObjectInput:
- '{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- id: 2,
- inp:
- '%sh #vizobject:{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- lang: 'text/x-',
- editorLanguage: '',
- typeOut: [],
- out: [],
- },
-];
-
-// Sample notebook with all input and cleared outputs
-export const sampleNotebook2 = {
- paragraphs: [
- {
- text:
- "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* You may use the top left buttons to play around with notebooks and Paragraphs",
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:15:04.590',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958104590_901298942',
- id: 'paragraph_1596519508360_932236116',
- dateCreated: '2020-08-20 21:15:04.590',
- status: 'READY',
- },
- {
- title: 'Paragraph inserted',
- text: '%md\n\n## Greetings!\n* Yay! you may import and export me ',
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:15:04.590',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958104590_1715920734',
- id: 'paragraph_1596742076640_674206137',
- dateCreated: '2020-08-20 21:15:04.590',
- status: 'READY',
- },
- {
- title: 'Paragraph inserted',
- text:
- "%md\n\n### Let's use Visualization API with dashboard container to embed Visualizations in notebooks\n2. **Unpin** the container to *edit the size* or *delete it*\n3. **Refresh** the container after *date is changed*",
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:15:04.590',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958104590_931410594',
- id: 'paragraph_1596524302932_2112910756',
- dateCreated: '2020-08-20 21:15:04.590',
- status: 'READY',
- },
- {
- title: 'VISUALIZATION',
- text:
- '%sh #vizobject:{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:25:28.588',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958728587_1310320520',
- id: 'paragraph_1597958728587_1310320520',
- dateCreated: '2020-08-20 21:25:28.587',
- status: 'READY',
- },
- ],
- name: 'Embed Vizualization',
- id: '2FJH8PW8K',
- defaultInterpreterGroup: 'spark',
- version: '0.9.0-preview2',
- noteParams: {},
- noteForms: {},
- angularObjects: {},
- config: { isZeppelinNotebookCronEnable: false },
- info: {},
-};
-
-// Parsed Output of sample notebook2
-export const sampleParsedParagraghs2 = [
- {
- uniqueId: 'paragraph_1596519508360_932236116',
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: false,
- vizObjectInput: '',
- id: 1,
- inp:
- "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* You may use the top left buttons to play around with notebooks and Paragraphs",
- lang: 'text/x-',
- editorLanguage: '',
- typeOut: [],
- out: [],
- },
- {
- uniqueId: 'paragraph_1596742076640_674206137',
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: false,
- vizObjectInput: '',
- id: 2,
- inp: '%md\n\n## Greetings!\n* Yay! you may import and export me ',
- lang: 'text/x-md',
- editorLanguage: 'md',
- typeOut: [],
- out: [],
- },
- {
- uniqueId: 'paragraph_1596524302932_2112910756',
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: false,
- vizObjectInput: '',
- id: 3,
- inp:
- "%md\n\n### Let's use Visualization API with dashboard container to embed Visualizations in notebooks\n2. **Unpin** the container to *edit the size* or *delete it*\n3. **Refresh** the container after *date is changed*",
- lang: 'text/x-md',
- editorLanguage: 'md',
- typeOut: [],
- out: [],
- },
- {
- uniqueId: 'paragraph_1597958728587_1310320520',
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: true,
- vizObjectInput:
- '{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- id: 4,
- inp:
- '%sh #vizobject:{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- lang: 'text/x-',
- editorLanguage: '',
- typeOut: [],
- out: [],
- },
-];
-
-// Sample notebook with no paragraph Id
-export const sampleNotebook3 = {
- paragraphs: [
- {
- text:
- "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* You may use the top left buttons to play around with notebooks and Paragraphs",
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:15:04.590',
- config: {},
- settings: { params: {}, forms: {} },
- results: {
- code: 'SUCCESS',
- msg: [
- {
- type: 'HTML',
- data:
- '
\n
Hi Everyone
\n
\n- Here’s a demo on OpenSearch Dashboards Notebooks
\n- You may use the top left buttons to play around with notebooks and Paragraphs
\n
\n\n
',
- },
- ],
- },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958104590_901298942',
- dateCreated: '2020-08-20 21:15:04.590',
- status: 'READY',
- },
- ],
- name: 'Embed Vizualization',
- id: '2FJH8PW8K',
- defaultInterpreterGroup: 'spark',
- version: '0.9.0-preview2',
- noteParams: {},
- noteForms: {},
- angularObjects: {},
- config: { isZeppelinNotebookCronEnable: false },
- info: {},
-};
-
-// Sample notebook with no VISUALIZAITON title
-export const sampleNotebook4 = {
- paragraphs: [
- {
- text:
- '%sh #vizobject:{"viewMode":"view","panels":{"1":{"gridData":{"x":15,"y":0,"w":20,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"06cf9c40-9ee8-11e7-8711-e7a007dcef99"}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"iab4eaba1-e32b-11ea-aac8-99f209533253","timeRange":{"to":"2020-08-20T21:25:28.538Z","from":"2020-07-21T21:25:28.538Z"},"title":"embed_viz_iab4eaba1-e32b-11ea-aac8-99f209533253","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}',
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:25:28.588',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958728587_1310320520',
- id: 'paragraph_1597958728587_1310320520',
- dateCreated: '2020-08-20 21:25:28.587',
- status: 'READY',
- },
- ],
- name: 'Embed Vizualization',
- id: '2FJH8PW8K',
- defaultInterpreterGroup: 'spark',
- version: '0.9.0-preview2',
- noteParams: {},
- noteForms: {},
- angularObjects: {},
- config: { isZeppelinNotebookCronEnable: false },
- info: {},
-};
-
-// Sample notebook with no input and output
-export const sampleNotebook5 = {
- paragraphs: [
- {
- user: 'anonymous',
- dateUpdated: '2020-08-20 21:25:28.588',
- config: {},
- settings: { params: {}, forms: {} },
- apps: [],
- runtimeInfos: {},
- progressUpdateIntervalMs: 500,
- jobName: 'paragraph_1597958728587_1310320520',
- id: 'paragraph_1597958728587_1310320520',
- dateCreated: '2020-08-20 21:25:28.587',
- status: 'READY',
- },
- ],
- name: 'Embed Vizualization',
- id: '2FJH8PW8K',
- defaultInterpreterGroup: 'spark',
- version: '0.9.0-preview2',
- noteParams: {},
- noteForms: {},
- angularObjects: {},
- config: { isZeppelinNotebookCronEnable: false },
- info: {},
-};
diff --git a/public/components/notebooks/components/helpers/__tests__/zeppelin_parser.test.tsx b/public/components/notebooks/components/helpers/__tests__/zeppelin_parser.test.tsx
deleted file mode 100644
index e6c5b351e1..0000000000
--- a/public/components/notebooks/components/helpers/__tests__/zeppelin_parser.test.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright OpenSearch Contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import { zeppelinParagraphParser } from '../zeppelin_parser';
-import {
- sampleNotebook1,
- sampleNotebook2,
- sampleNotebook3,
- sampleNotebook4,
- sampleNotebook5,
- sampleParsedParagraghs1,
- sampleParsedParagraghs2,
-} from './sampleZeppelinNotebooks';
-
-// Perfect schema
-describe('Testing Zeppelin backend parser function with perfect schema', () => {
- test('zeppelinParagraphParserTest1', (done) => {
- const parsedParagraphs1 = zeppelinParagraphParser(sampleNotebook1.paragraphs);
- const parsedParagraphs2 = zeppelinParagraphParser(sampleNotebook2.paragraphs);
- const parsedParagraphs3 = zeppelinParagraphParser([]);
- expect(parsedParagraphs1).toEqual(sampleParsedParagraghs1);
- expect(parsedParagraphs2).toEqual(sampleParsedParagraghs2);
- expect(parsedParagraphs3).toEqual([]);
- done();
- });
-});
-
-// Issue in schema
-describe('Testing default backend parser function with wrong schema', () => {
- test('zeppelinParagraphParserTest2', (done) => {
- expect(() => {
- const parsedParagraphs1 = zeppelinParagraphParser(sampleNotebook3.paragraphs);
- }).toThrow(Error);
- expect(() => {
- const parsedParagraphs2 = zeppelinParagraphParser(sampleNotebook4.paragraphs);
- }).toThrow(Error);
- expect(() => {
- const parsedParagraphs3 = zeppelinParagraphParser(sampleNotebook5.paragraphs);
- }).toThrow(Error);
- done();
- });
-});
diff --git a/public/components/notebooks/components/helpers/zeppelin_parser.tsx b/public/components/notebooks/components/helpers/zeppelin_parser.tsx
deleted file mode 100644
index f2293c3a72..0000000000
--- a/public/components/notebooks/components/helpers/zeppelin_parser.tsx
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright OpenSearch Contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/* This file contains parsing functions
- * These functions have to be changed based on backend configuration
- * If backend changes the incoming paragraph structures may change, so parsing adapts to it
- */
-
-import { ParaType } from '../../../common';
-
-const visualizationPrefix = '%sh #vizobject:';
-const observabilityVisualizationPrefix = '%sh #observabilityviz:';
-
-const langSupport = {
- '%sh': 'shell',
- '%md': 'md',
- '%python': 'python',
- '%opensearchsql': 'sql',
- '%elasticsearch': 'json',
-};
-
-// Get the coding language from a Zeppelin paragraph input
-// Param: textHeader-> header on a Zeppelin paragraph example "%md"
-const parseCodeLanguage = (textHeader: string) => {
- const codeLanguage = langSupport[textHeader];
- return codeLanguage || '';
-};
-
-// Get the type of output message from a Zeppelin paragraph
-// Param: Zeppelin Paragraph
-const parseMessage = (paraObject: any) => {
- try {
- let mtype = [];
- let mdata = [];
- paraObject.results.msg.map((msg: { type: string; data: string }) => {
- mtype.push(msg.type);
- mdata.push(msg.data);
- });
- return {
- outputType: mtype,
- outputData: mdata,
- };
- } catch (error) {
- return {
- outputType: [],
- outputData: [],
- };
- }
-};
-
-// Get the type of output message from a Zeppelin paragraph
-// Param: Zeppelin Paragraph
-const parseText = (paraObject: any) => {
- if ('text' in paraObject) {
- return paraObject.text;
- } else {
- throw new Error('Input text parse issue');
- }
-};
-
-// Get the visualization from a Zeppelin Paragraph input
-// All Visualizations in Zeppelin are stored as shell comment -> "%sh #vizobject:"
-// TODO: This is a workaround need to look for better solutions
-// Param: Zeppelin Paragraph
-const parseVisualization = (paraObject: any) => {
- let vizContent = '';
- if (
- paraObject.hasOwnProperty('text') &&
- paraObject.text.substring(0, 15) === visualizationPrefix
- ) {
- if (paraObject.title !== 'VISUALIZATION') {
- throw new Error('Visualization parse issue');
- }
- vizContent = paraObject.text.substring(15);
- return {
- isViz: true,
- VizObject: vizContent,
- };
- }
-
- if (
- paraObject.hasOwnProperty('text') &&
- paraObject.text.substring(0, 22) === observabilityVisualizationPrefix
- ) {
- if (paraObject.title !== 'OBSERVABILITY_VISUALIZATION') {
- throw new Error('Visualization parse issue');
- }
- vizContent = paraObject.text.substring(22);
- return {
- isViz: true,
- VizObject: vizContent,
- };
- }
-
- return {
- isViz: false,
- VizObject: vizContent,
- };
-};
-
-// This parser is used to get paragraph id
-// Param: Zeppelin Paragraph
-const parseId = (paraObject: any) => {
- if ('id' in paraObject) {
- return paraObject.id;
- } else {
- throw new Error('Id not found in paragraph');
- }
-};
-
-// This parser helps to convert Zeppelin paragraphs to a common ParaType format
-// This parsing makes any backend notebook compatible with notebooks plugin
-export const zeppelinParagraphParser = (zeppelinBackendParagraphs: any) => {
- let parsedPara: Array
= [];
- try {
- zeppelinBackendParagraphs.map((paraObject: ParaType, index: number) => {
- const paragraphId = parseId(paraObject);
- const vizParams = parseVisualization(paraObject);
- const inputParam = parseText(paraObject);
- const codeLanguage = parseCodeLanguage(inputParam.split('\n')[0].split('.')[0]);
- const message = parseMessage(paraObject);
-
- let tempPara = {
- uniqueId: paragraphId,
- isRunning: false,
- inQueue: false,
- ishovered: false,
- isSelected: false,
- isInputHidden: false,
- isOutputHidden: false,
- showAddPara: false,
- isVizualisation: vizParams.isViz,
- vizObjectInput: vizParams.VizObject,
- id: index + 1,
- inp: inputParam,
- lang: 'text/x-' + codeLanguage,
- editorLanguage: codeLanguage,
- typeOut: message.outputType,
- out: message.outputData,
- };
- parsedPara.push(tempPara);
- });
- return parsedPara;
- } catch (error) {
- throw new Error('Parsing Paragraph Issue ' + error);
- }
-};
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 d86d8486fe..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,16 +27,15 @@ 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 {
CREATE_NOTE_MESSAGE,
NOTEBOOKS_API_PREFIX,
- NOTEBOOKS_SELECTED_BACKEND,
} 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';
@@ -45,7 +44,6 @@ import {
contextMenuViewReports,
generateInContextReport,
} from './helpers/reporting_context_menu_helper';
-import { zeppelinParagraphParser } from './helpers/zeppelin_parser';
import { Paragraphs } from './paragraph_components/paragraphs';
const panelStyles: CSS.Properties = {
float: 'left',
@@ -140,12 +138,7 @@ export class Notebook extends Component {
try {
let parsedPara;
// @ts-ignore
- if (NOTEBOOKS_SELECTED_BACKEND === 'ZEPPELIN') {
- parsedPara = zeppelinParagraphParser(paragraphs);
- this.setState({ vizPrefix: '%sh #vizobject:' });
- } else {
- parsedPara = defaultParagraphParser(paragraphs);
- }
+ parsedPara = defaultParagraphParser(paragraphs);
parsedPara.forEach((para: ParaType) => {
para.isInputExpanded = this.state.selectedViewId === 'input_only';
para.paraRef = React.createRef();
@@ -200,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];
@@ -212,6 +205,7 @@ export class Notebook extends Component {
'Error deleting paragraph, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
}
};
@@ -253,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',
@@ -361,6 +356,7 @@ export class Notebook extends Component {
'Error deleting visualization, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -395,6 +391,7 @@ export class Notebook extends Component {
'Error adding paragraph, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -428,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);
});
};
@@ -467,6 +465,7 @@ export class Notebook extends Component {
'Error clearing paragraphs, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -537,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());
};
@@ -595,6 +594,7 @@ export class Notebook extends Component {
'Error fetching notebooks, please make sure you have the correct permission.',
'danger'
);
+ console.error(err);
});
};
@@ -611,6 +611,7 @@ export class Notebook extends Component {
})
.catch((err) => {
this.props.setToast('Error getting query output', 'danger');
+ console.error(err);
});
};
@@ -662,6 +663,7 @@ export class Notebook extends Component {
})
.catch((error) => {
this.props.setToast('Error checking Reporting Plugin Installation status.', 'danger');
+ console.error(error);
});
}
@@ -696,7 +698,7 @@ export class Notebook extends Component {
);
- const viewOptions: EuiButtonGroupOption[] = [
+ const viewOptions: EuiButtonGroupOptionProps[] = [
{
id: 'view_both',
label: 'View both',
@@ -750,7 +752,7 @@ export class Notebook extends Component