Skip to content

Commit

Permalink
[feat] introduced jest to replace tape/sinon/enzyme for browser tests…
Browse files Browse the repository at this point in the history
…; upgrade typescript to 4.5.5 (#2339)
  • Loading branch information
igorDykhta committed Oct 1, 2023
1 parent 85fa66f commit ec35ea9
Show file tree
Hide file tree
Showing 40 changed files with 2,239 additions and 590 deletions.
5 changes: 3 additions & 2 deletions .eslintrc
Expand Up @@ -5,13 +5,14 @@
"prettier",
"plugin:prettier/recommended",
"prettier/react",
"plugin:react-hooks/recommended"
"plugin:react-hooks/recommended",
"plugin:jest/recommended"
],
"env": {
"es6": true,
"browser": true,
"node": true,
"jest": true
"jest/globals": true
},
"globals": {
"page": true,
Expand Down
1 change: 1 addition & 0 deletions .gitignore
@@ -1,6 +1,7 @@
node_modules/
*/**/node_modules/
coverage/
*-coverage/
.nyc_output/
dist/
build/
Expand Down
1 change: 0 additions & 1 deletion examples/demo-app/package.json
Expand Up @@ -3,7 +3,6 @@
"start": "webpack-dev-server --mode development --progress --hot --open",
"start-prod": "webpack-dev-server -p --progress --hot --open",
"start-local": "webpack-dev-server --mode development --env.es6 --progress --hot --open",
"start-local-e2e": "webpack-dev-server --mode development --env.es6",
"start-local-deck": "webpack-dev-server --mode development --env.es6 --env.deck --progress --hot --open",
"start-local-deck-src": "webpack-dev-server --mode development --env.es6 --env.deck_src --progress --hot --open",
"start-local-loaders-src": "webpack-dev-server --mode development --env.es6 --env.loaders_src --progress --hot --open",
Expand Down
36 changes: 0 additions & 36 deletions jest-puppeteer.config.js

This file was deleted.

38 changes: 9 additions & 29 deletions jest.config.js
@@ -1,31 +1,11 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

module.exports = {
preset: 'jest-puppeteer',
globals: {
URL: 'http://localhost:8080'
},
testMatch: [
'**/test/e2e/**/*.test.js'
],
/** @type {import('jest').Config} */
const config = {
collectCoverageFrom: ['<rootDir>/src/**/*.{js|ts|tsx}', '!<rootDir>/src/**/*.spec.js'],
coverageDirectory: './jest-coverage',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
verbose: true,
setupFilesAfterEnv: ['./jest-extend-image-snapshot']
testMatch: ['<rootDir>/src/**/*.spec.js', '<rootDir>/test/**/*.spec.js']
};

module.exports = config;
9 changes: 7 additions & 2 deletions jest-extend-image-snapshot.js → jest.setup.js
Expand Up @@ -18,6 +18,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import {toMatchImageSnapshot} from 'jest-image-snapshot';
import '@testing-library/jest-dom';
import * as Utils from '@kepler.gl/utils';

expect.extend({toMatchImageSnapshot});
jest.mock('@kepler.gl/utils', () => ({
...jest.requireActual('@kepler.gl/utils'),
hasPortableWidth: jest.fn(),
hasMobileWidth: jest.fn()
}));
17 changes: 13 additions & 4 deletions package.json
Expand Up @@ -49,9 +49,13 @@
"test-browser-drive": "NODE_ENV=test node ./test/browser-drive.js debug",
"test-node-debug": "NODE_ENV=test yarn babel-tape-runner ./test/node.js",
"test-browser-debug": "NODE_ENV=test yarn babel-tape-runner -r ./test/setup-browser-env.js ./test/js-dom.js",
"test-e2e": "NODE_ENV=test HEADLESS=true SLOWMO=true jest",
"test": "yarn lint && yarn test-node && yarn test-browser",
"cover": "nyc --reporter=lcov --reporter html npm test",
"test-jest": "jest --watch",
"test-tape": "yarn test-node && yarn test-browser",
"test": "yarn test-jest && yarn test-tape",
"cover-tape": "nyc --reporter=json --report-dir=tape-coverage --reporter=html yarn test-tape",
"cover-jest": "yarn jest --coverage --reporter=html --watchAll=false",
"cover-copy": "rm -rf .nyc_output && mkdir .nyc_output && cp tape-coverage/coverage-final.json .nyc_output/tape-coverage-final.json && cp jest-coverage/coverage-final.json .nyc_output/jest-coverage-final.json",
"cover": "yarn cover-jest && yarn cover-tape && yarn cover-copy && nyc report --reporter=json --reporter=html --reporter=lcov",
"start": "yarn install-and-start -- examples/demo-app start-local",
"start:deck": "yarn install-and-start -- examples/demo-app start-local-deck",
"start:deck-src": "yarn install-and-start -- examples/demo-app start-local-deck-src",
Expand Down Expand Up @@ -142,12 +146,14 @@
"@probe.gl/env": "^3.5.0",
"@probe.gl/test-utils": "^3.5.0",
"@testing-library/dom": "^9.0.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@testing-library/react-hooks": "^3.4.2",
"@testing-library/user-event": "^14.4.3",
"@types/d3-array": "^2.0.0",
"@types/d3-scale": "^3.2.2",
"@types/geojson": "^7946.0.7",
"@types/jsdom": "^21.1.1",
"@types/redux-actions": "^2.6.2",
"@types/supercluster": "^7.1.0",
"@typescript-eslint/eslint-plugin": "^5.12.0",
Expand All @@ -167,10 +173,13 @@
"eslint-config-uber-jsx": "^3.3.3",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-enzyme-deprecation": "^0.7.7",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"gl": "^4.9.2",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"jsdom": "^16.4.0",
"json-loader": "^0.5.4",
"nyc": "^15.1.0",
Expand All @@ -192,7 +201,7 @@
"tape": "^4.9.2",
"tape-catch": "^1.0.6",
"typedoc-plugin-markdown": "^3.0.11",
"typescript": "4.2.3",
"typescript": "4.5.5",
"uber-licence": "^3.1.1",
"url-loader": "^4.1.1",
"watchify": "^3.6.1",
Expand Down
9 changes: 5 additions & 4 deletions src/components/src/notification-panel/notification-item.tsx
Expand Up @@ -22,6 +22,7 @@ import React, {Component} from 'react';
import styled from 'styled-components';
import {Delete, Info, Warning, Checkmark} from '../common/icons';
import ReactMarkdown from 'react-markdown';
import {dataTestIds} from '@kepler.gl/constants';
import {ActionHandler, removeNotification as removeNotificationActions} from '@kepler.gl/actions';

interface NotificationItemContentBlockProps {
Expand Down Expand Up @@ -114,10 +115,10 @@ const NotificationIcon = styled.div`
`;

const icons = {
info: <Info />,
warning: <Warning />,
error: <Warning />,
success: <Checkmark />
info: <Info data-testid={dataTestIds.infoIcon} />,
warning: <Warning data-testid={dataTestIds.warningIcon} />,
error: <Warning data-testid={dataTestIds.errorIcon} />,
success: <Checkmark data-testid={dataTestIds.successIcon} />
};

const LinkRenderer = props => {
Expand Down
2 changes: 2 additions & 0 deletions src/components/src/side-panel/layer-panel/layer-list.tsx
Expand Up @@ -30,6 +30,7 @@ import {useDroppable} from '@dnd-kit/core';
import {useSortable, SortableContext, verticalListSortingStrategy} from '@dnd-kit/sortable';
import {CSS} from '@dnd-kit/utilities';
import {findById} from '@kepler.gl/utils';
import {dataTestIds} from '@kepler.gl/constants';

export type LayerListProps = {
datasets: Datasets;
Expand Down Expand Up @@ -93,6 +94,7 @@ function LayerListFactory(LayerPanel: ReturnType<typeof LayerPanelFactory>) {
<SortableStyledItem
ref={setNodeRef}
className={classnames('sortable-layer-items', {sorting: isDragging})}
data-testid={dataTestIds.sortableLayerItems}
transform={CSS.Transform.toString(transform)}
transition={transition}
{...attributes}
Expand Down
13 changes: 9 additions & 4 deletions src/components/src/side-panel/layer-panel/layer-panel-header.tsx
Expand Up @@ -42,6 +42,7 @@ import {

import {InlineInput, StyledPanelHeader} from '../../common/styled-components';
import {FormattedMessage} from '@kepler.gl/localization';
import {dataTestIds} from '@kepler.gl/constants';
import {RGBColor} from '@kepler.gl/types';
import {BaseProps} from '../../common/icons';

Expand Down Expand Up @@ -206,6 +207,11 @@ export const DragHandle: React.FC<{
</StyledDragHandle>
);

const noOp = (event: MouseEvent) => {
event.stopPropagation();
event.preventDefault();
};

export const LayerLabelEditor: React.FC<LayerLabelEditorProps> = ({
layerId,
label,
Expand All @@ -216,11 +222,9 @@ export const LayerLabelEditor: React.FC<LayerLabelEditorProps> = ({
<InlineInput
type="text"
className="layer__title__editor"
data-testid={dataTestIds.layerTitleEditor}
value={label}
onClick={(e: MouseEvent) => {
e.stopPropagation();
e.preventDefault();
}}
onClick={noOp}
onChange={onEdit}
onFocus={onFocus}
onBlur={onBlur}
Expand Down Expand Up @@ -302,6 +306,7 @@ export function LayerPanelHeaderActionSectionFactory(
{showRemoveLayer ? (
<PanelHeaderAction
className="layer__remove-layer"
testId="remove-layer-action"
id={layerId}
tooltip={'tooltip.removeLayer'}
onClick={onRemoveLayer}
Expand Down
2 changes: 2 additions & 0 deletions src/components/src/side-panel/layer-panel/layer-panel.tsx
Expand Up @@ -29,6 +29,7 @@ import styled from 'styled-components';

import LayerConfiguratorFactory from './layer-configurator';
import LayerPanelHeaderFactory from './layer-panel-header';
import {dataTestIds} from '@kepler.gl/constants';
import {NestedPartial, LayerVisConfig, ColorUI} from '@kepler.gl/types';
import {Layer, LayerBaseConfig} from '@kepler.gl/layers';
import {toggleModal, VisStateActions, ActionHandler} from '@kepler.gl/actions';
Expand Down Expand Up @@ -151,6 +152,7 @@ function LayerPanelFactory(
<PanelWrapper
active={isConfigActive}
className={`layer-panel ${this.props.className}`}
data-testid={dataTestIds.layerPanel}
style={this.props.style}
onMouseDown={this.props.onMouseDown}
onTouchStart={this.props.onTouchStart}
Expand Down
10 changes: 8 additions & 2 deletions src/components/src/side-panel/panel-header-action.tsx
Expand Up @@ -39,15 +39,19 @@ export interface PanelHeaderActionProps {
onClick?: MouseEventHandler;
tooltipType?: TooltipProps['type'];
IconComponent: PanelHeaderActionIcon;
testId?: string;
}

type HeaderActionWrapperProps = {
flush?: boolean;
active?: boolean;
hoverColor?: string | null;
testId?: string;
};

const HeaderActionWrapper = styled.div<HeaderActionWrapperProps>`
const HeaderActionWrapper = styled.div.attrs((props: HeaderActionWrapperProps) => ({
dataTestId: props.testId
}))<HeaderActionWrapperProps>`
margin-left: ${props => (props.flush ? 0 : 8)}px;
display: flex;
align-items: center;
Expand Down Expand Up @@ -81,7 +85,8 @@ export default function PanelHeaderActionFactory(): React.FC<PanelHeaderActionPr
tooltipType,
disabled,
className,
IconComponent
IconComponent,
testId
}) => {
return (
<HeaderActionWrapper
Expand All @@ -96,6 +101,7 @@ export default function PanelHeaderActionFactory(): React.FC<PanelHeaderActionPr
{IconComponent ? (
<IconComponent
className="panel--header__action__component"
data-testid={testId}
data-tip
data-for={`${tooltip}_${id}`}
height="16px"
Expand Down
12 changes: 12 additions & 0 deletions src/constants/src/default-settings.ts
Expand Up @@ -1126,3 +1126,15 @@ export const MAP_CONTROLS = keyMirror({
* https://github.com/visgl/deck.gl/blob/master/docs/upgrade-guide.md
*/
export const PROJECTED_PIXEL_SIZE_MULTIPLIER = 2 / 3;

export const dataTestIds: Record<string, string> = {
infoIcon: 'info-icon',
warningIcon: 'warning-icon',
errorIcon: 'error-icon',
successIcon: 'success-icon',
checkmarkIcon: 'checkmark-icon',
sortableLayerItems: 'sortable-layer-items',
layerTitleEditor: 'layer__title__editor',
removeLayerAction: 'remove-layer-action',
layerPanel: 'layer-panel'
};
2 changes: 1 addition & 1 deletion src/layers/src/mapbox-utils.ts
Expand Up @@ -51,7 +51,7 @@ export function generateMapboxLayers(
return acc;
}

const layer = layers[layerId];
const layer = layers[layerIndex];

if (!(layer.overlayType === OVERLAY_TYPE_CONST.mapboxgl && layersToRender[layerId])) {
return acc;
Expand Down
3 changes: 2 additions & 1 deletion src/reducers/src/layer-utils.ts
Expand Up @@ -144,7 +144,8 @@ export function calculateLayerData<S extends MinVisStateForLayerData>(
});
layer.isValid = false;

layer.errorMessage = err?.message ? err.message.substring(0, 100) : 'Unknown error';
layer.errorMessage =
err instanceof Error && err.message ? err.message.substring(0, 100) : 'Unknown error';

layerData = {};
}
Expand Down
1 change: 0 additions & 1 deletion src/reducers/src/root.ts
Expand Up @@ -89,7 +89,6 @@ export function provideInitialState(initialState, extraReducers?) {
};

// TODO: Understand why the Lint sees an error here, while the IDE does not.
// @ts-expect-error
return handleActions(handlers, initialCoreState)(state, action);
};
}
Expand Down
1 change: 1 addition & 0 deletions src/utils/src/index.ts
Expand Up @@ -34,6 +34,7 @@ export {errorNotification} from './notifications-utils';

export {createNotification, exportImageError, successNotification} from './notifications-utils';

export {setStyleSheetBaseHref} from './dom-utils';
export {default as domtoimage} from './dom-to-image';
export {getFrequency, getMode, aggregate} from './aggregate-utils';
// eslint-disable-next-line prettier/prettier
Expand Down

0 comments on commit ec35ea9

Please sign in to comment.