Skip to content

Commit

Permalink
Adds error modal and lint fixes (opensearch-project#13)
Browse files Browse the repository at this point in the history
* adds error modal and fixes lint

Signed-off-by: Shivam Dhar <[email protected]>

Co-authored-by: Shivam Dhar <[email protected]>
  • Loading branch information
Shivamdhar and Shivamdhar authored Jun 24, 2022
1 parent 50317b9 commit 0b3296c
Show file tree
Hide file tree
Showing 15 changed files with 235 additions and 67 deletions.
2 changes: 1 addition & 1 deletion DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ echo 'src/plugins/custom_import_map/*' >> .git/info/sparse-checkout
git config core.sparseCheckout true
git checkout main
```
6. Run `yarn osd bootstrap` inside `OpenSearch-Dashboards/plugins/custom_import_map`.
6. Run `yarn osd bootstrap` inside `OpenSearch-Dashboards/plugins/src/plugins/custom_import_map`.

Ultimately, your directory structure should look like this:

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Dashboards-maps is a frontend plugin that helps you in uploading custom GeoJSON
* [Project Website](https://opensearch.org/)
* [Downloads](https://opensearch.org/downloads.html)
* [Documentation](https://opensearch.org/docs/latest/)
* [Developer Guide](DEVELOPER_GUIDE.md)
* Need help? Try [Forums](https://discuss.opendistrocommunity.dev/)
* [Project Principles](https://opensearch.org/#principles)
* [Contributing to OpenSearch](CONTRIBUTING.md)
Expand Down
24 changes: 12 additions & 12 deletions src/plugins/custom_import_map/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
*/

module.exports = {
presets: [
require('@babel/preset-env'),
require('@babel/preset-react'),
require('@babel/preset-typescript'),
],
plugins: [
require('@babel/plugin-proposal-class-properties'),
require('@babel/plugin-proposal-object-rest-spread'),
['@babel/plugin-transform-modules-commonjs', { allowTopLevelThis: true }],
[require('@babel/plugin-transform-runtime'), { regenerator: true }],
],
};
presets: [
require('@babel/preset-env'),
require('@babel/preset-react'),
require('@babel/preset-typescript'),
],
plugins: [
require('@babel/plugin-proposal-class-properties'),
require('@babel/plugin-proposal-object-rest-spread'),
['@babel/plugin-transform-modules-commonjs', { allowTopLevelThis: true }],
[require('@babel/plugin-transform-runtime'), { regenerator: true }],
],
};
17 changes: 14 additions & 3 deletions src/plugins/custom_import_map/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { fromMBtoBytes } from "./util";
import { MAX_FILE_PAYLOAD_SIZE, MAX_FILE_PAYLOAD_SIZE_IN_MB, PLUGIN_ID, PLUGIN_NAME } from "./constants/shared";
import { fromMBtoBytes } from './util';
import {
MAX_FILE_PAYLOAD_SIZE,
MAX_FILE_PAYLOAD_SIZE_IN_MB,
PLUGIN_ID,
PLUGIN_NAME,
} from './constants/shared';

export { fromMBtoBytes, MAX_FILE_PAYLOAD_SIZE, MAX_FILE_PAYLOAD_SIZE_IN_MB, PLUGIN_ID, PLUGIN_NAME };
export {
fromMBtoBytes,
MAX_FILE_PAYLOAD_SIZE,
MAX_FILE_PAYLOAD_SIZE_IN_MB,
PLUGIN_ID,
PLUGIN_NAME,
};
4 changes: 2 additions & 2 deletions src/plugins/custom_import_map/common/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
*/

export const fromMBtoBytes = (sizeInMB: number) => {
return sizeInMB * 1024 * 1024;
}
return sizeInMB * 1024 * 1024;
};
4 changes: 3 additions & 1 deletion src/plugins/custom_import_map/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"build": "yarn plugin-helpers build",
"plugin-helpers": "node ../../../../scripts/plugin_helpers",
"osd": "node ../../../../scripts/osd",
"lint": "node ../../../../scripts/eslint .",
"lint": "yarn run lint:es && yarn run lint:style",
"lint:es": "node ../../../../scripts/eslint",
"lint:style": "node ../../../../scripts/stylelint",
"test:jest": "TZ=UTC ../../../../node_modules/.bin/jest --config ./test/jest.config.js"
},
"husky": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`display error modal renders the error modal based on the props passed 1`] = `
<div
aria-label="showModalOption"
data-testid="showModalOption"
id="showModalOption"
>
<button
className="euiButton euiButton--primary"
disabled={false}
onClick={[Function]}
style={
Object {
"minWidth": undefined,
}
}
type="button"
>
<span
className="euiButtonContent euiButton__content"
>
<span
className="euiButton__text"
>
testButtonText
</span>
</span>
</button>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import * as React from 'react';
import { ShowErrorModal } from './show_error_modal';
import renderer, { act } from 'react-test-renderer';
import { fireEvent } from '@testing-library/dom';
import { screen, render } from '@testing-library/react';

describe('display error modal', () => {
const props = {
modalTitle: 'testModalTitle',
modalBody: 'testModalBody',
buttonText: 'testButtonText',
};

it('renders the error modal based on the props passed', async () => {
let tree;
await act(async () => {
tree = renderer.create(<ShowErrorModal {...props} />);
});
expect(tree.toJSON().props.id).toBe('showModalOption');
expect(tree.toJSON()).toMatchSnapshot();
});

it('renders the error modal when showModal button is clicked', () => {
render(<ShowErrorModal {...props} />);
const button = screen.getByRole('button');
fireEvent.click(button);
const closeButton = screen.getByTestId('closeModal');
fireEvent.click(closeButton);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState } from 'react';
import {
EuiButton,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiCodeBlock,
} from '@elastic/eui';

export interface ShowErrorModalProps {
modalTitle: string;
modalBody: string;
buttonText: string;
}

const ShowErrorModal = (props: ShowErrorModalProps) => {
const [isModalVisible, setIsModalVisible] = useState(false);

const closeModal = () => setIsModalVisible(false);
const showModal = () => setIsModalVisible(true);

let modal;

if (isModalVisible) {
modal = (
<EuiModal onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>{props.modalTitle}</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>

<EuiModalBody>
<EuiCodeBlock isCopyable>{props.modalBody}</EuiCodeBlock>
</EuiModalBody>

<EuiModalFooter>
<EuiButton
id="closeModal"
aria-label="closeModal"
data-testid="closeModal"
onClick={closeModal}
fill
>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
);
}

return (
<div id="showModalOption" aria-label="showModalOption" data-testid="showModalOption">
<EuiButton onClick={showModal}>{props.buttonText}</EuiButton>
{modal}
</div>
);
};

export { ShowErrorModal };
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ import * as serviceApiCalls from '../services';
jest.mock('../../../../../../src/plugins/opensearch_dashboards_react/public', () => ({
useOpenSearchDashboards: jest.fn().mockReturnValue({
services: {
http: { post: () => {Promise.resolve({});} },
notifications: { toasts: { addSuccess: jest.fn(), addDanger: jest.fn(), addWarning: jest.fn() } },
http: {
post: () => {
Promise.resolve({});
},
},
notifications: {
toasts: { addSuccess: jest.fn(), addDanger: jest.fn(), addWarning: jest.fn() },
},
},
}),
toMountPoint: jest.fn().mockReturnValue({}),
}));


describe('vector_upload_options', () => {
const props = {
};
const props = {};

const getIndexResponseWhenIndexIsNotPresent = {
ok: false,
Expand Down Expand Up @@ -104,7 +108,7 @@ describe('vector_upload_options', () => {
await expect(tree.findAllByText(message)).toBeTruthy();
};

const addUserInputToDOM = async () => {
const addUserInputToDOM = async () => {
const jsonData = {
type: 'FeatureCollection',
name: 'sample',
Expand All @@ -120,7 +124,7 @@ describe('vector_upload_options', () => {
const indexName = screen.getByTestId('customIndex');
fireEvent.change(indexName, { target: { value: 'sample' } });
const uploader = getByTestId('filePicker');

const str = JSON.stringify([jsonData]);
const blob = new Blob([str]);
const file = new File([blob], 'sample.json', { type: 'application/JSON' });
Expand Down Expand Up @@ -152,25 +156,34 @@ describe('vector_upload_options', () => {

it('renders the VectorUploadOptions component with error message when index name has upper case letters', async () => {
try {
await vectorUploadOptionsWithIndexNameRendererUtil('ABC', 'Upper case letters are not allowed');
await vectorUploadOptionsWithIndexNameRendererUtil(
'ABC',
'Upper case letters are not allowed'
);
} catch (err) {}
});

it('renders the VectorUploadOptions component with error message when index name has special characters', async () => {
try {
await vectorUploadOptionsWithIndexNameRendererUtil('a#bc', 'Special characters are not allowed.');
await vectorUploadOptionsWithIndexNameRendererUtil(
'a#bc',
'Special characters are not allowed.'
);
} catch (err) {}
});

it('renders the VectorUploadOptions component with error message when index name has -map as suffix', async () => {
try {
await vectorUploadOptionsWithIndexNameRendererUtil('sample-map', "Map name can't end with -map.");
await vectorUploadOptionsWithIndexNameRendererUtil(
'sample-map',
"Map name can't end with -map."
);
} catch (err) {}
});

it('renders the VectorUploadOptions component when we have successfully indexed all the data', async () => {
addUserInputToDOM();
console.log("test case for successfully indexed file data");
console.log('test case for successfully indexed file data');
const button = screen.getByRole('button', { name: 'import-file-button' });
jest.spyOn(serviceApiCalls, 'getIndex').mockImplementation(() => {
return Promise.resolve(getIndexResponseWhenIndexIsNotPresent);
Expand All @@ -185,7 +198,7 @@ describe('vector_upload_options', () => {

it('renders the VectorUploadOptions component when we have partial failures during indexing', async () => {
addUserInputToDOM();
console.log("test case for partial failures during indexing");
console.log('test case for partial failures during indexing');
const button = screen.getByRole('button', { name: 'import-file-button' });
jest.spyOn(serviceApiCalls, 'getIndex').mockImplementation(() => {
return Promise.resolve(getIndexResponseWhenIndexIsNotPresent);
Expand All @@ -200,7 +213,7 @@ describe('vector_upload_options', () => {

it('renders the VectorUploadOptions component when all the documents fail to index', async () => {
addUserInputToDOM();
console.log("test case for failed documents");
console.log('test case for failed documents');
const button = screen.getByRole('button', { name: 'import-file-button' });
jest.spyOn(serviceApiCalls, 'getIndex').mockImplementation(() => {
return Promise.resolve(getIndexResponseWhenIndexIsNotPresent);
Expand All @@ -215,7 +228,7 @@ describe('vector_upload_options', () => {

it('renders the VectorUploadOptions component when postGeojson call fails', async () => {
addUserInputToDOM();
console.log("test case for call failure to postGeojson");
console.log('test case for call failure to postGeojson');
const button = screen.getByRole('button', { name: 'import-file-button' });
jest.spyOn(serviceApiCalls, 'getIndex').mockImplementation(() => {
return Promise.resolve(getIndexResponseWhenIndexIsNotPresent);
Expand All @@ -230,7 +243,7 @@ describe('vector_upload_options', () => {

it('renders the VectorUploadOptions component when getIndex returns a duplicate index', async () => {
addUserInputToDOM();
console.log("test case for duplicate index check");
console.log('test case for duplicate index check');
const button = screen.getByRole('button', { name: 'import-file-button' });
jest.spyOn(serviceApiCalls, 'getIndex').mockImplementation(() => {
return Promise.resolve(getIndexResponseWhenIndexIsPresent);
Expand Down
Loading

0 comments on commit 0b3296c

Please sign in to comment.