Skip to content

Commit

Permalink
add tests for acceleration create
Browse files Browse the repository at this point in the history
Signed-off-by: Shenoy Pratik <[email protected]>
  • Loading branch information
ps48 committed Oct 2, 2023
1 parent 835e6b4 commit 2fbb601
Show file tree
Hide file tree
Showing 18 changed files with 556 additions and 63 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@
},
"devDependencies": {
"@testing-library/user-event": "^13.1.9",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/react-test-renderer": "^16.9.1",
"cypress": "^5.0.0",
"eslint": "^6.8.0",
"husky": "^4.2.5",
"jest-raw-loader": "^1.0.1",
"lint-staged": "^10.2.0",
"mutationobserver-shim": "^0.3.3",
"jest-dom": "^4.0.0",
"ts-jest": "^29.1.0"
},
"resolutions": {
Expand Down
7 changes: 5 additions & 2 deletions public/ace-themes/sql_console.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
* SPDX-License-Identifier: Apache-2.0
*/


import * as ace from 'brace';

ace.define('ace/theme/sql_console', ['require', 'exports', 'module', 'ace/lib/dom'], function (acequire, exports, module) {
ace.define('ace/theme/sql_console', ['require', 'exports', 'module', 'ace/lib/dom'], function (
acequire,
exports,
module
) {
exports.isDark = false;
exports.cssClass = 'ace-sql-console';
exports.cssText = require('../index.scss');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Acceleration callout renders acceleration flyout callout 1`] = `ReactWrapper {}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Create acceleration flyout components renders acceleration flyout component with default options 1`] = `ReactWrapper {}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Acceleration header renders acceleration flyout header 1`] = `ReactWrapper {}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { waitFor } from '@testing-library/dom';
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import { CautionBannerCallout } from '../caution_banner_callout';

describe('Acceleration callout', () => {
configure({ adapter: new Adapter() });

it('renders acceleration flyout callout', async () => {
const wrapper = mount((<CautionBannerCallout />) as React.ReactElement<any>);
wrapper.update();
await waitFor(() => {
expect(wrapper).toMatchSnapshot();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { waitFor } from '@testing-library/dom';
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import { CreateAcceleration } from '../create_acceleration';

describe('Create acceleration flyout components', () => {
configure({ adapter: new Adapter() });

it('renders acceleration flyout component with default options', async () => {
const dataSource = '';
const resetFlyout = jest.fn();
const updateQueries = jest.fn();
const wrapper = mount(
(
<CreateAcceleration
dataSource={dataSource}
resetFlyout={resetFlyout}
updateQueries={updateQueries}
/>
) as React.ReactElement<any>
);
wrapper.update();
await waitFor(() => {
expect(wrapper).toMatchSnapshot();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { waitFor } from '@testing-library/dom';
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import { CreateAccelerationHeader } from '../create_acceleration_header';

describe('Acceleration header', () => {
configure({ adapter: new Adapter() });

it('renders acceleration flyout header', async () => {
const wrapper = mount((<CreateAccelerationHeader />) as React.ReactElement<any>);
wrapper.update();
await waitFor(() => {
expect(wrapper).toMatchSnapshot();
});
});
});
262 changes: 262 additions & 0 deletions public/components/acceleration/create/__tests__/utils.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
ACCELERATION_INDEX_NAME_REGEX,
ACCELERATION_S3_URL_REGEX,
} from '../../../../../common/constants';
import {
coveringIndexDataMock,
materializedViewEmptyDataMock,
materializedViewEmptyTumbleDataMock,
materializedViewStaleDataMock,
materializedViewValidDataMock,
skippingIndexDataMock,
} from '../../../../../test/mocks/accelerationMock';
import {
pluralizeTime,
validateCheckpointLocation,
validateCoveringIndexData,
validateDataSource,
validateDataTable,
validateDatabase,
validateIndexName,
validateMaterializedViewData,
validatePrimaryShardCount,
validateRefreshInterval,
validateReplicaCount,
validateSkippingIndexData,
} from '../utils';

describe('pluralizeTime', () => {
it('should return "s" for a time window greater than 1', () => {
expect(pluralizeTime(2)).toBe('s');
expect(pluralizeTime(10)).toBe('s');
expect(pluralizeTime(100)).toBe('s');
});

it('should return an empty string for a time window of 1/0', () => {
expect(pluralizeTime(1)).toBe('');
expect(pluralizeTime(0)).toBe(''); // form throws validation error, doesn't allow user to proceed
});
});

describe('validateDataSource', () => {
it('should return an array with an error message when the dataSource is empty', () => {
expect(validateDataSource('')).toEqual(['Select a valid data source']);
expect(validateDataSource(' ')).toEqual(['Select a valid data source']);
});

it('should return an empty array when the dataSource is not empty', () => {
expect(validateDataSource('Some_valid_data_source')).toEqual([]);
expect(validateDataSource(' Some_valid_data_source ')).toEqual([]);
});
});

describe('validateDatabase', () => {
it('should return an array with an error message when the database is empty', () => {
expect(validateDatabase('')).toEqual(['Select a valid database']);
expect(validateDatabase(' ')).toEqual(['Select a valid database']);
});

it('should return an empty array when the database is not empty', () => {
expect(validateDatabase('Some_valid_database')).toEqual([]);
expect(validateDatabase(' Some_valid_database ')).toEqual([]);
});
});

describe('validateDataTable', () => {
it('should return an array with an error message when the dataTable is empty', () => {
expect(validateDataTable('')).toEqual(['Select a valid table']);
expect(validateDataTable(' ')).toEqual(['Select a valid table']);
});

it('should return an empty array when the dataTable is not empty', () => {
expect(validateDataTable('Some_valid_table')).toEqual([]);
expect(validateDataTable(' Some_valid_table ')).toEqual([]);
});
});

describe('validatePrimaryShardCount', () => {
it('should return an array with an error message when primaryShardCount is less than 1', () => {
expect(validatePrimaryShardCount(0)).toEqual(['Primary shards count should be greater than 0']);
expect(validatePrimaryShardCount(-1)).toEqual([
'Primary shards count should be greater than 0',
]); // form throws validation error, doesn't allow user to proceed
});

it('should return an empty array when primaryShardCount is greater than or equal to 1', () => {
expect(validatePrimaryShardCount(1)).toEqual([]);
expect(validatePrimaryShardCount(5)).toEqual([]);
expect(validatePrimaryShardCount(100)).toEqual([]);
});
});

describe('validateReplicaCount', () => {
it('should return an array with an error message when replicaCount is less than 1', () => {
expect(validateReplicaCount(0)).toEqual(['Replica count should be greater than 0']);
expect(validateReplicaCount(-1)).toEqual(['Replica count should be greater than 0']); // form throws validation error, doesn't allow user to proceed
});

it('should return an empty array when replicaCount is greater than or equal to 1', () => {
expect(validateReplicaCount(1)).toEqual([]);
expect(validateReplicaCount(5)).toEqual([]);
expect(validateReplicaCount(100)).toEqual([]);
});
});

describe('validateRefreshInterval', () => {
it('should return an array with an error message when refreshType is "interval" and refreshWindow is less than 1', () => {
expect(validateRefreshInterval('interval', 0)).toEqual([
'refresh window should be greater than 0',
]);
expect(validateRefreshInterval('interval', -1)).toEqual([
'refresh window should be greater than 0',
]);
expect(validateRefreshInterval('interval', -10)).toEqual([
'refresh window should be greater than 0',
]);
});

it('should return an empty array when refreshType is not "interval" or when refreshWindow is greater than or equal to 1', () => {
expect(validateRefreshInterval('auto', 0)).toEqual([]);
expect(validateRefreshInterval('auto', 1)).toEqual([]);
expect(validateRefreshInterval('interval', 1)).toEqual([]);
expect(validateRefreshInterval('auto', 5)).toEqual([]);
});
});

describe('validateIndexName', () => {
it('should return an array with an error message when the index name is invalid', () => {
expect(validateIndexName('_invalid')).toEqual(['Enter a valid index name']);
expect(validateIndexName('-invalid')).toEqual(['Enter a valid index name']);
expect(validateIndexName('InVal1d')).toEqual(['Enter a valid index name']);
expect(validateIndexName('invalid_with spaces')).toEqual(['Enter a valid index name']);
});

it('should return an empty array when the index name is valid', () => {
expect(validateIndexName('valid')).toEqual([]);
expect(validateIndexName('valid_name')).toEqual([]);
expect(validateIndexName('another-valid-name')).toEqual([]);
});

it('should use the ACCELERATION_INDEX_NAME_REGEX pattern to validate the index name', () => {
expect(ACCELERATION_INDEX_NAME_REGEX.test('valid_name')).toBe(true);
expect(ACCELERATION_INDEX_NAME_REGEX.test('invalid name')).toBe(false);
expect(ACCELERATION_INDEX_NAME_REGEX.test('-invalid')).toBe(false);
expect(ACCELERATION_INDEX_NAME_REGEX.test('_invalid')).toBe(false);
expect(ACCELERATION_INDEX_NAME_REGEX.test('invalid.')).toBe(false);
expect(ACCELERATION_INDEX_NAME_REGEX.test('invalid<')).toBe(false);
expect(ACCELERATION_INDEX_NAME_REGEX.test('invalid*')).toBe(false);
});
});

describe('validateCheckpointLocation', () => {
it('should return an array with an error message when creating a materialized view without a checkpoint location', () => {
const materializedError = validateCheckpointLocation('materialized', undefined);
expect(materializedError).toEqual([
'Checkpoint location is mandatory for materialized view creation',
]);
});

it('should return an array with an error message when creating a materialized view without a checkpoint location', () => {
const materializedError = validateCheckpointLocation('materialized', '');
expect(materializedError).toEqual([
'Checkpoint location is mandatory for materialized view creation',
]);
});

it('should return an array with an error message when the checkpoint location is not a valid S3 URL', () => {
const invalidCheckpoint = validateCheckpointLocation('skipping', 'not_a_valid_s3_url');
expect(invalidCheckpoint).toEqual(['Enter a valid checkpoint location']);
});

it('should return an empty array when the checkpoint location is a valid S3 URL', () => {
const validCheckpoint = validateCheckpointLocation(
'covering',
's3://valid-s3-bucket/path/to/checkpoint'
);
expect(validCheckpoint).toEqual([]);
});

it('should return an empty array when the checkpoint location is a valid S3A URL', () => {
const validCheckpoint = validateCheckpointLocation(
'skipping',
's3a://valid-s3-bucket/path/to/checkpoint'
);
expect(validCheckpoint).toEqual([]);
});

it('should return an empty array when creating a materialized view with a valid checkpoint location', () => {
const validMaterializedCheckpoint = validateCheckpointLocation(
'materialized',
's3://valid-s3-bucket/path/to/checkpoint'
);
expect(validMaterializedCheckpoint).toEqual([]);
});

it('should use the ACCELERATION_S3_URL_REGEX pattern to validate the checkpoint location', () => {
expect(ACCELERATION_S3_URL_REGEX.test('s3://valid-s3-bucket/path/to/checkpoint')).toBe(true);
expect(ACCELERATION_S3_URL_REGEX.test('s3a://valid-s3-bucket/path/to/checkpoint')).toBe(true);
expect(ACCELERATION_S3_URL_REGEX.test('https://amazon.com')).toBe(false);
expect(ACCELERATION_S3_URL_REGEX.test('http://www.amazon.com')).toBe(false);
});
});

describe('validateSkippingIndexData', () => {
it('should return an array with an error message when accelerationIndexType is "skipping" and no skipping index data is provided', () => {
const error = validateSkippingIndexData('skipping', []);
expect(error).toEqual(['Add fields to the skipping index definition']);
});

it('should return an empty array when accelerationIndexType is not "skipping"', () => {
const noError = validateSkippingIndexData('covering', []);
expect(noError).toEqual([]);
});

it('should return an empty array when accelerationIndexType is "skipping" and skipping index data is provided', () => {
const noError = validateSkippingIndexData('skipping', skippingIndexDataMock);
expect(noError).toEqual([]);
});
});

describe('validateCoveringIndexData', () => {
it('should return an array with an error message when accelerationIndexType is "covering" and no covering index data is provided', () => {
const error = validateCoveringIndexData('covering', []);
expect(error).toEqual(['Add fields to covering index definition']);
});

it('should return an empty array when accelerationIndexType is not "covering"', () => {
const noError = validateCoveringIndexData('skipping', []);
expect(noError).toEqual([]);
});

it('should return an empty array when accelerationIndexType is "covering" and covering index data is provided', () => {
const noError = validateCoveringIndexData('covering', coveringIndexDataMock);
expect(noError).toEqual([]);
});
});

describe('validateMaterializedViewData', () => {
it('should return an array with an error message when accelerationIndexType is "materialized" and no materialized view data is provided', () => {
const error = validateMaterializedViewData('materialized', materializedViewEmptyDataMock);
expect(error).toEqual(['Add columns to materialized view definition']);
});

it('should return an array with an error message when accelerationIndexType is "materialized" and groupByTumbleValue is incomplete', () => {
const error = validateMaterializedViewData('materialized', materializedViewEmptyTumbleDataMock);
expect(error).toEqual(['Add a time field to tumble function in materialized view definition']);
});

it('should return an empty array when accelerationIndexType is not "materialized"', () => {
const noError = validateMaterializedViewData('covering', materializedViewStaleDataMock);
expect(noError).toEqual([]);
});

it('should return an empty array when accelerationIndexType is "materialized" and materialized view data is complete', () => {
const noError = validateMaterializedViewData('materialized', materializedViewValidDataMock);
expect(noError).toEqual([]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const CreateAcceleration = ({
<EuiForm
isInvalid={hasError(accelerationFormData.formErrors)}
error={Object.values(accelerationFormData.formErrors).flat()}
component="form"
component="div"
id="acceleration-form"
>
<AccelerationDataSourceSelector
Expand Down
Loading

0 comments on commit 2fbb601

Please sign in to comment.