Skip to content

Commit

Permalink
[Table Vis][Test] Add unit tests via testing-library and enzyme
Browse files Browse the repository at this point in the history
Issue Resolved:
opensearch-project#2856

Signed-off-by: Anan Zhuang <ananzh@amazon.com>
  • Loading branch information
ananzh committed Feb 21, 2023
1 parent 7177fe3 commit a38cffa
Show file tree
Hide file tree
Showing 12 changed files with 702 additions and 52 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Vis Builder] Adds field unit tests ([#3211](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3211))
- [BWC Tests] Add BWC tests for 2.6.0 ([#3356](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3356))
- Prevent primitive linting limitations from being applied to unit tests found under `src/setup_node_env` ([#3403](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3403))
- [Table Vis][Test] Add unit tests via testing-library and enzyme ([#3435](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3435))

## [2.x]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render } from '@testing-library/react';
import { coreMock } from '../../../../core/public/mocks';
import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
import { TableVisApp } from './table_vis_app';
import { TableVisConfig } from '../types';
import { TableContext } from '../table_vis_response_handler';

jest.mock('./table_vis_component_group', () => ({
TableVisComponentGroup: () => (
<div data-test-subj="TableVisComponentGroup">TableVisComponentGroup</div>
),
}));

jest.mock('./table_vis_component', () => ({
TableVisComponent: () => <div data-test-subj="TableVisComponent">TableVisComponent</div>,
}));

describe('TableVisApp', () => {
const serviceMock = coreMock.createStart();
const handlersMock = ({
done: jest.fn(),
uiState: 'uiState',
event: 'event',
} as unknown) as IInterpreterRenderHandlers;
const visConfigMock = ({} as unknown) as TableVisConfig;

it('should render TableVisComponent if no split table', () => {
const visDataMock = {
table: {
columns: [],
rows: [],
},
tableGroups: [],
} as TableContext;
const { getByTestId } = render(
<TableVisApp
services={serviceMock}
visData={visDataMock}
visConfig={visConfigMock}
handlers={handlersMock}
/>
);
expect(getByTestId('TableVisComponent')).toBeInTheDocument();
});

it('should render TableVisComponentGroup component if split direction is column', () => {
const visDataMock = {
tableGroups: [],
direction: 'column',
} as TableContext;
const { container, getByTestId } = render(
<TableVisApp
services={serviceMock}
visData={visDataMock}
visConfig={visConfigMock}
handlers={handlersMock}
/>
);

expect(container.outerHTML.includes('visTable visTable__groupInColumns')).toBe(true);
expect(getByTestId('TableVisComponentGroup')).toBeInTheDocument();
});

it('should render TableVisComponentGroup component if split direction is row', () => {
const visDataMock = {
tableGroups: [],
direction: 'row',
} as TableContext;
const { container, getByTestId } = render(
<TableVisApp
services={serviceMock}
visData={visDataMock}
visConfig={visConfigMock}
handlers={handlersMock}
/>
);
expect(container.outerHTML.includes('visTable')).toBe(true);
expect(getByTestId('TableVisComponentGroup')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render } from '@testing-library/react';
import { TableVisComponentGroup } from './table_vis_component_group';
import { TableVisConfig, ColumnSort } from '../types';
import { Table, TableGroup, FormattedTable } from '../table_vis_response_handler';

jest.mock('./table_vis_component', () => ({
TableVisComponent: () => <div data-test-subj="TableVisComponent">TableVisComponent</div>,
}));

const table1 = {
tables: [
{
columns: [],
rows: [],
} as Table,
],
title: '',
name: 'table-1',
key: '1',
row: 10,
column: 3,
} as TableGroup;

const table2 = {
tables: [
{
columns: [],
rows: [],
} as Table,
],
title: '',
name: 'table-2',
key: '2',
row: 10,
column: 3,
} as TableGroup;

const tableUiStateMock = {
sort: { colIndex: undefined, direction: undefined } as ColumnSort,
setSort: jest.fn(),
width: [],
setWidth: jest.fn(),
};

describe('TableVisApp', () => {
it('should not render table component if no table', () => {
const { container, queryAllByText } = render(
<TableVisComponentGroup
tableGroups={[table1, table2]}
visConfig={({} as unknown) as TableVisConfig}
event={jest.fn()}
uiState={tableUiStateMock}
/>
);
expect(queryAllByText('TableVisComponent')).toHaveLength(0);
expect(container.outerHTML.includes('visTable__group')).toBe(true);
});

it('should render table component 2 times', () => {
table1.table = {} as FormattedTable;
table2.table = {} as FormattedTable;
const { container, queryAllByText } = render(
<TableVisComponentGroup
tableGroups={[table1, table2]}
visConfig={({} as unknown) as TableVisConfig}
event={jest.fn()}
uiState={tableUiStateMock}
/>
);
expect(queryAllByText('TableVisComponent')).toHaveLength(2);
expect(container.outerHTML.includes('visTable__group')).toBe(true);
});
});
75 changes: 75 additions & 0 deletions src/plugins/vis_type_table/public/utils/add_percentage_col.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { addPercentageCol } from './add_percentage_col';
import { FormattedColumn } from '../types';
import { Table } from '../table_vis_response_handler';

const mockDeserialize = jest.fn(() => ({}));
jest.mock('../services', () => ({
getFormatService: jest.fn(() => ({
deserialize: mockDeserialize,
})),
}));

const formattedColumns = [
{
id: 'col-0-2',
title: 'name.keyword: Descending',
formatter: {},
filterable: true,
},
{
id: 'col-1-1',
title: 'Count',
formatter: {},
filterable: false,
sumTotal: 5,
formattedTotal: 5,
total: 5,
},
] as FormattedColumn[];

const rows = [
{ 'col-0-2': 'Alice', 'col-1-1': 3 },
{ 'col-0-2': 'Anthony', 'col-1-1': 1 },
{ 'col-0-2': 'Timmy', 'col-1-1': 1 },
] as Table['rows'];

describe('addPercentageCol', () => {
it('should add new percentage column', () => {
const result = addPercentageCol(formattedColumns, 'count', rows, 1);
expect(result).toEqual({
cols: [
{
id: 'col-0-2',
title: 'name.keyword: Descending',
formatter: {},
filterable: true,
},
{
id: 'col-1-1',
title: 'Count',
formatter: {},
filterable: false,
sumTotal: 5,
formattedTotal: 5,
total: 5,
},
{
title: 'count percentages',
id: 'col-1-1-percents',
formatter: {},
filterable: false,
},
],
rows: [
{ 'col-1-1-percents': 0.6, 'col-0-2': 'Alice', 'col-1-1': 3 },
{ 'col-1-1-percents': 0.2, 'col-0-2': 'Anthony', 'col-1-1': 1 },
{ 'col-1-1-percents': 0.2, 'col-0-2': 'Timmy', 'col-1-1': 1 },
],
});
});
});
73 changes: 73 additions & 0 deletions src/plugins/vis_type_table/public/utils/add_percentage_col.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Any modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { i18n } from '@osd/i18n';
import { Table } from '../table_vis_response_handler';
import { getFormatService } from '../services';
import { FormattedColumn } from '../types';

function insert(arr: FormattedColumn[], index: number, col: FormattedColumn) {
const newArray = [...arr];
newArray.splice(index + 1, 0, col);
return newArray;
}
/**
* @param columns - the formatted columns that will be displayed
* @param title - the title of the column to add to
* @param rows - the row data for the columns
* @param insertAtIndex - the index to insert the percentage column at
* @returns cols and rows for the table to render now included percentage column(s)
*/
export function addPercentageCol(
columns: FormattedColumn[],
title: string,
rows: Table['rows'],
insertAtIndex: number
) {
const { id, sumTotal } = columns[insertAtIndex];
const newId = `${id}-percents`;
const formatter = getFormatService().deserialize({ id: 'percent' });
const i18nTitle = i18n.translate('visTypeTable.params.percentageTableColumnName', {
defaultMessage: '{title} percentages',
values: { title },
});
const newCols = insert(columns, insertAtIndex, {
title: i18nTitle,
id: newId,
formatter,
filterable: false,
});
const newRows = rows.map((row) => ({
[newId]: (row[id] as number) / (sumTotal as number),
...row,
}));

return { cols: newCols, rows: newRows };
}
Loading

0 comments on commit a38cffa

Please sign in to comment.