;
+ * }
+ */
+ json(): Promise
;
+}
+
+/**
+ *
+ * Most of the parameters are optional but in fact they are not optional.
+ * They are optional for dev experience because injected by a babel plugin
+ */
+
+function getPackageVersion(name?: string, version?: string): string | undefined {
+ if (name) {
+ const sessionVersion = sessionStorage.getItem(name);
+ if (sessionVersion) {
+ return sessionVersion;
+ }
+
+ const metas = document.querySelectorAll(`meta[name="${name}"]`);
+ if (metas.length > 1) {
+ console.warn(`Package ${name} is installed multiple times`);
+ }
+ if (metas.length > 0) {
+ return metas[0].getAttribute('value') || version;
+ }
+ }
+ return version;
+}
+
+function getURL(path: string, name?: string, version?: string) {
+ const overriddenVersion = getPackageVersion(name, version);
+ if (!overriddenVersion) {
+ throw new Error(`Version not found for ${name}`);
+ }
+ return window.Talend.getCDNUrl({ name, version: overriddenVersion, path });
+}
+
+const TIMEOUT = 10000;
+
+function addScript({ src, integrity, ...attr }: Script) {
+ const found = !!document.querySelector(`script[src="${src}"]`);
+ if (found) {
+ return;
+ }
+ const script = document.createElement('script');
+ script.setAttribute('src', src);
+ script.setAttribute('type', 'text/javascript');
+ script.setAttribute('crossorigin', 'anonymous');
+ if (integrity) {
+ script.setAttribute('integrity', integrity);
+ }
+ script.async = false;
+ Object.assign(script, attr);
+ document.body.appendChild(script);
+}
+
+function toDefaultModule(value: any) {
+ return Object.create(null, {
+ default: {
+ value,
+ enumerable: true,
+ },
+ __esModule: {
+ value: true,
+ },
+ [Symbol.toStringTag]: {
+ value: 'Module',
+ },
+ });
+}
+
+function getUMD(name: string, version?: string, varName?: string, path?: string) {
+ const cache = { resolved: false };
+ function loaded() {
+ if (!varName) {
+ return false;
+ }
+ return !!(window as any)[varName];
+ }
+ if (loaded() && varName) {
+ return Promise.resolve((window as any)[varName]);
+ }
+ const src = getURL(path || '/undefined', name, version);
+ console.log('getUMD', src, varName);
+
+ return new Promise((resolve, reject) => {
+ function onload() {
+ if (!varName) {
+ cache.resolved = true;
+ resolve(undefined);
+ } else {
+ console.log(`${varName} onload ok`);
+ }
+ }
+ function onerror(e: Error) {
+ console.error(e);
+ reject(e);
+ }
+ addScript({ src, onload, onerror });
+ if (varName) {
+ const intervalId = setInterval(() => {
+ if (loaded()) {
+ cache.resolved = true;
+ clearInterval(intervalId);
+ resolve((window as any)[varName]);
+ }
+ }, 200);
+ setTimeout(() => {
+ if (!cache.resolved) {
+ clearInterval(intervalId);
+ reject(new Error(`UMD from ${src}, ${varName} not found in ${TIMEOUT}`));
+ }
+ }, TIMEOUT);
+ }
+ });
+}
+
+async function getJSON(path: string, name?: string, version?: string) {
+ const url = getURL(path, name, version);
+ const response: TypedResponse = await fetch(url);
+ if (response.ok) {
+ return response.json();
+ }
+ console.error(`Response not ok: ${response.status} ${response.statusText} from ${url}`);
+
+ return undefined;
+}
+
+function addStyle({ href, integrity, ...attr }: StyleAsset) {
+ const found = !!document.querySelector(`link[href="${href}"]`);
+ if (found) {
+ return;
+ }
+ const style = document.createElement('link');
+ style.setAttribute('rel', 'stylesheet');
+ style.setAttribute('media', 'print');
+ style.setAttribute('onload', 'this.media="all"');
+ if (integrity) {
+ style.setAttribute('integrity', integrity);
+ style.setAttribute('crossorigin', 'anonymous');
+ }
+ style.setAttribute('href', href);
+ Object.assign(style, attr);
+ const title = document.getElementsByTagName('TITLE')[0];
+ document.head.insertBefore(style, title);
+}
+
+if (!window.Talend) {
+ window.Talend = {};
+}
+if (!window.Talend.getCDNUrl) {
+ // eslint-disable-next-line no-console
+ console.log('assets.api add window.Talend.getCDNUrl');
+ window.Talend.getCDNUrl = (info: Asset) => {
+ const CDN_URL = window.Talend.CDN_URL;
+ if (CDN_URL) {
+ if (CDN_URL.startsWith('/')) {
+ const baseTag = document.querySelector('base');
+ if (baseTag) {
+ const root = baseTag.getAttribute('href') || '';
+ return `${root}${CDN_URL}/${info.name}/${info.version}${info.path}`;
+ }
+ }
+ return `${CDN_URL}/${info.name}/${info.version}${info.path}`;
+ }
+ return `https://unpkg.com/${info.name}@${info.version}${info.path}`;
+ };
+}
+
+export default {
+ getURL,
+ getUMD,
+ getJSON,
+ addScript,
+ addStyle,
+ toDefaultModule,
+};
diff --git a/packages/assets-api/talend-scripts.json b/packages/assets-api/talend-scripts.json
new file mode 100644
index 0000000000..4d78bcf08f
--- /dev/null
+++ b/packages/assets-api/talend-scripts.json
@@ -0,0 +1,3 @@
+{
+ "preset": "@talend/scripts-preset-react-lib"
+}
diff --git a/packages/assets-api/tsconfig.json b/packages/assets-api/tsconfig.json
new file mode 100644
index 0000000000..1c67d95f42
--- /dev/null
+++ b/packages/assets-api/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "@talend/scripts-config-typescript/tsconfig.json",
+ "include": ["src/**/*"],
+ "compilerOptions": {
+ "declaration": true
+ }
+}
diff --git a/packages/components/src/FilterBar/FilterBar.test.js b/packages/components/src/FilterBar/FilterBar.test.js
index 9053c3fa54..f3ea952658 100644
--- a/packages/components/src/FilterBar/FilterBar.test.js
+++ b/packages/components/src/FilterBar/FilterBar.test.js
@@ -250,7 +250,7 @@ describe('Filter', () => {
setTimeout(() => {
expect(onFilter).toBeCalledWith(expect.anything(), 'couc');
done();
- }, debounceTimeout);
+ }, debounceTimeout + 100);
});
it('should clear filter on clear button click', () => {
diff --git a/packages/datagrid/.babelrc.json b/packages/datagrid/.babelrc.json
deleted file mode 100644
index 1d6655372a..0000000000
--- a/packages/datagrid/.babelrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": "@talend/scripts-config-babel/.babelrc.json"
-}
diff --git a/packages/datagrid/package.json b/packages/datagrid/package.json
index 4427de4f26..155cee6d50 100644
--- a/packages/datagrid/package.json
+++ b/packages/datagrid/package.json
@@ -12,8 +12,7 @@
"build:lib": "talend-scripts build:ts:lib",
"build-storybook": "talend-scripts build-storybook",
"start": "talend-scripts start-storybook -p 6010",
- "test": "talend-scripts test --silent",
- "test:noisy": "talend-scripts test",
+ "test": "talend-scripts test",
"test:watch": "talend-scripts test --watch",
"test:cov": "talend-scripts test --coverage",
"test:demo": "talend-scripts build-storybook --quiet",
@@ -37,6 +36,7 @@
"url": "https://github.com/Talend/ui.git"
},
"dependencies": {
+ "@talend/assets-api": "^1.0.0",
"@talend/icons": "^6.40.0",
"@talend/react-cmf": "^7.0.2",
"@talend/react-components": "^6.45.1",
@@ -53,6 +53,8 @@
"@talend/react-cmf": "^7.0.2",
"@talend/scripts-core": "^11.6.0",
"@talend/scripts-preset-react-lib": "^11.0.2",
+ "@testing-library/react": "^12.1.5",
+ "@testing-library/jest-dom": "^5.16.4",
"enzyme": "^3.11.0",
"i18next": "^20.6.1",
"immutable": "^3.8.2",
diff --git a/packages/datagrid/src/components/DataGrid/DataGrid.component.js b/packages/datagrid/src/components/DataGrid/DataGrid.component.js
index 14ced7fc85..7b053b4365 100644
--- a/packages/datagrid/src/components/DataGrid/DataGrid.component.js
+++ b/packages/datagrid/src/components/DataGrid/DataGrid.component.js
@@ -1,11 +1,10 @@
+/* eslint-disable react/sort-comp */
import React from 'react';
import classNames from 'classnames';
import keycode from 'keycode';
-import { AgGridReact } from 'ag-grid-react';
-import Inject from '@talend/react-components/lib/Inject';
+import assetsApi from '@talend/assets-api';
+import { Inject } from '@talend/react-components';
import { Icon } from '@talend/design-system';
-import 'ag-grid-community/dist/styles/ag-grid.css';
-
import DefaultHeaderRenderer, { HEADER_RENDERER_COMPONENT } from '../DefaultHeaderRenderer';
import DefaultCellRenderer, { CELL_RENDERER_COMPONENT } from '../DefaultCellRenderer';
import DefaultPinHeaderRenderer, {
@@ -17,6 +16,13 @@ import { NAMESPACE_INDEX } from '../../constants';
import serializer from '../DatasetSerializer';
import theme from './DataGrid.scss';
+const AgGridReact = React.lazy(() =>
+ assetsApi
+ .getUMD('ag-grid-community')
+ .then(() => assetsApi.getUMD('ag-grid-react'))
+ .then(mod => assetsApi.toDefaultModule(mod.AgGridReact)),
+);
+
export const AG_GRID = {
CUSTOM_HEADER_KEY: 'headerComponent',
CUSTOM_CELL_KEY: 'cellRenderer',
@@ -94,6 +100,11 @@ export default class DataGrid extends React.Component {
this.currentColId = null;
}
+ componentDidMount() {
+ const href = assetsApi.getURL('/dist/styles/ag-grid.css', 'ag-grid-community');
+ assetsApi.addStyle({ href });
+ }
+
/**
* componentDidUpdate - call forceRedrawRows after props changes to redraw or
* not the grid
@@ -292,7 +303,6 @@ export default class DataGrid extends React.Component {
DefaultPinHeaderRenderer,
),
};
-
return agGridOptions;
}
@@ -336,7 +346,11 @@ export default class DataGrid extends React.Component {
);
} else {
- content = ;
+ content = (
+ }>
+
+
+ );
}
return (
diff --git a/packages/datagrid/src/components/DataGrid/DataGrid.test.js b/packages/datagrid/src/components/DataGrid/DataGrid.test.js
index 821f1a11b9..316c8b83cb 100644
--- a/packages/datagrid/src/components/DataGrid/DataGrid.test.js
+++ b/packages/datagrid/src/components/DataGrid/DataGrid.test.js
@@ -1,17 +1,10 @@
import React from 'react';
-import keycode from 'keycode';
-import { shallow } from 'enzyme';
-import { JSDOM } from 'jsdom';
-
-import { NAMESPACE_DATA, NAMESPACE_INDEX } from '../../constants';
-
-import DataGrid, { injectHeaderRenderer, AG_GRID } from './DataGrid.component';
-
-function PinHeaderRenderer() {}
-
-function getComponent() {
- return PinHeaderRenderer;
-}
+import ReactDOM from 'react-dom';
+import { Grid as agGrid } from 'ag-grid-community';
+import { AgGridReact, AgGridColumn } from 'ag-grid-react';
+import { render, waitFor, screen } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import DataGrid from './DataGrid.component';
const sample = {
schema: {
@@ -157,697 +150,25 @@ const sample = {
},
};
-jest.mock('react-dom', () => ({
- findDOMNode(mockRef) {
- return mockRef;
- },
-}));
+jest.mock('ally.js');
describe('#DataGrid', () => {
- it('should render DataGrid', () => {
- const wrapper = shallow();
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-
- it('should not call forceRedrawRows when the DataGrid is loading', () => {
- const forceRedrawRows = jest.fn(() => true);
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().componentDidUpdate({});
- expect(forceRedrawRows).not.toHaveBeenCalled();
- });
-
- it('should not call forceRedrawRows when the DataGrid is not ready', () => {
- const forceRedrawRows = jest.fn(() => true);
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().componentDidUpdate({});
- expect(forceRedrawRows).not.toHaveBeenCalled();
- });
-
- it('should call redrawRows when forceRedrawRows return true', () => {
- const forceRedrawRows = jest.fn(() => true);
- const redrawRows = jest.fn();
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().onGridReady({
- api: {
- redrawRows,
- },
- });
- wrapper.instance().componentDidUpdate({});
-
- expect(forceRedrawRows).toHaveBeenCalled();
- expect(redrawRows).toHaveBeenCalled();
- });
-
- it('should not call redrawRows when forceRedrawRows return false', () => {
- const forceRedrawRows = jest.fn(() => false);
- const redrawRows = jest.fn();
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().onGridReady({
- api: {
- redrawRows,
- },
- });
- wrapper.instance().componentDidUpdate({});
-
- expect(forceRedrawRows).toHaveBeenCalled();
- expect(redrawRows).not.toHaveBeenCalled();
- });
-
- it('should render DataGrid with columnsDefs and rowData', () => {
- const wrapper = shallow();
-
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-
- it('should render DataGrid with custom serializer', () => {
- const getPinnedColumnDefsFn = jest.fn();
- const getColumnDefsFn = jest.fn();
- const getRowDataFn = jest.fn();
- const getCellValueFn = jest.fn();
-
- const props = {
- columnsConf: {},
- data: sample,
- getComponent,
- getCellValueFn,
- getColumnDefsFn,
- getPinnedColumnDefsFn,
- getRowDataFn,
- };
-
- shallow();
- expect(getColumnDefsFn).toHaveBeenCalledWith(sample, props.columnsConf);
- expect(getPinnedColumnDefsFn).toHaveBeenCalledWith(sample);
- expect(getRowDataFn).toHaveBeenCalledWith(sample, 0);
- });
-
- it('should render one Skeleton is InProgress', () => {
- const wrapper = shallow();
-
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-});
-
-describe('#AgGrid API', () => {
- it('should set the AgGrid API when the ag-grid is loaded', () => {
- const api = {};
- const wrapper = shallow();
-
- wrapper.find('AgGridReact').props().onGridReady({ api });
-
- expect(wrapper.instance().gridAPI).toBe(api);
- });
-});
-
-describe('#Datagrid method', () => {
- it('should set the current grid ref', () => {
- const element = {};
- const wrapper = shallow();
-
- wrapper.instance().setGridInstance(element);
-
- expect(wrapper.instance().gridInstance).toBe(element);
- });
-
- it('should set the current selected column', () => {
- const currentColumn = 'colId';
- const wrapper = shallow();
-
- wrapper.instance().setCurrentFocusedColumn(currentColumn);
-
- expect(wrapper.instance().currentColId).toBe(currentColumn);
- });
-
- it('should remove the focus on the column', () => {
- const { document } = new JSDOM(
- '',
- ).window;
- const gridElement = document.querySelector('.grid-element');
- const wrapper = shallow();
- wrapper.instance().setGridInstance({
- [AG_GRID.ELEMENT]: gridElement,
- });
-
- wrapper.instance().removeFocusColumn();
-
- expect(gridElement.outerHTML).toBe(
- '',
- );
- });
-
- it('should set the focus on the column', () => {
- const { document } = new JSDOM(
- ``,
- ).window;
- const gridElement = document.querySelector('.grid-element');
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setGridInstance({
- [AG_GRID.ELEMENT]: gridElement,
- });
- instance.currentColId = `${NAMESPACE_DATA}colId`;
-
- wrapper.instance().updateStyleFocusColumn();
-
- expect(gridElement.outerHTML).toBe(
- ``,
- );
- });
-
- it('should not set the focus on the column when any defined column', () => {
- const { document } = new JSDOM(
- ``,
- ).window;
- const gridElement = document.querySelector('.grid-element');
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setGridInstance({
- [AG_GRID.ELEMENT]: gridElement,
- });
-
- wrapper.instance().updateStyleFocusColumn();
-
- expect(gridElement.outerHTML).toBe(
- ``,
- );
- });
-
- it('should not set the focus on the column when the selected column is an pinned column', () => {
- const { document } = new JSDOM(
- ``,
- ).window;
- const gridElement = document.querySelector('.grid-element');
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setGridInstance({
- [AG_GRID.ELEMENT]: gridElement,
- });
- instance.currentColId = `${NAMESPACE_INDEX}index`;
-
- wrapper.instance().updateStyleFocusColumn();
-
- expect(gridElement.outerHTML).toBe(
- ``,
- );
- });
-
- it('should manage the cells with keyboard', () => {
- const setSelected = jest.fn();
- const api = {
- getDisplayedRowAtIndex() {
- return {
- setSelected,
- };
- },
- };
- const wrapper = shallow();
- const nextCellPosition = {
- rowIndex: 1,
- };
-
- const previousCellPosition = {
- rowIndex: 2,
- };
-
- wrapper.find('AgGridReact').props().onGridReady({ api });
-
- const nextFocusedCell = wrapper.instance().handleKeyboard({
- nextCellPosition,
- previousCellPosition,
- });
-
- expect(nextFocusedCell).toBe(nextCellPosition);
- expect(setSelected).toHaveBeenCalledWith(true, true);
- });
-
- it('should not manage the cells with keyboard if any nextCellPosition', () => {
- const setSelected = jest.fn();
- const api = {
- getDisplayedRowAtIndex() {
- return {
- setSelected,
- };
- },
- };
- const wrapper = shallow();
- const nextCellPosition = null;
-
- const previousCellPosition = {
- rowIndex: 2,
- };
-
- wrapper.find('AgGridReact').props().onGridReady({ api });
-
- const nextFocusedCell = wrapper.instance().handleKeyboard({
- nextCellPosition,
- previousCellPosition,
- });
-
- expect(nextFocusedCell).toBe(null);
- expect(setSelected).not.toHaveBeenCalled();
- });
-
- it('should not manage the cells with keyboard if any api', () => {
- const setSelected = jest.fn();
- const api = null;
- const wrapper = shallow();
- const nextCellPosition = {
- rowIndex: 1,
- };
-
- const previousCellPosition = {
- rowIndex: 2,
- };
-
- wrapper.find('AgGridReact').props().onGridReady({ api });
-
- const nextFocusedCell = wrapper.instance().handleKeyboard({
- nextCellPosition,
- previousCellPosition,
- });
-
- expect(nextFocusedCell).toBe(nextCellPosition);
- expect(setSelected).not.toHaveBeenCalled();
- });
-
- it('should set the current selected column from props', () => {
- const wrapper = shallow();
- wrapper.instance().onFocusedColumn = jest.fn();
- wrapper.instance().onGridReady({ api: {} });
-
- expect(wrapper.instance().onFocusedColumn).toHaveBeenCalledWith('field3');
- });
-
- it('should update current selected column from props', () => {
- const wrapper = shallow();
- const deselectAll = jest.fn();
- const clearFocusedCell = jest.fn();
- const ensureColumnVisible = jest.fn();
- const api = {
- deselectAll,
- clearFocusedCell,
- ensureColumnVisible,
- };
- const instance = wrapper.instance();
- instance.onGridReady({ api });
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- wrapper.setProps({
- focusedColumnId: 'field2',
- });
-
- expect(instance.currentColId).toEqual('field2');
- });
-
- it('should not update local state on click when in controlled mode', () => {
- const wrapper = shallow();
- const deselectAll = jest.fn();
- const clearFocusedCell = jest.fn();
- const ensureColumnVisible = jest.fn();
- const api = {
- deselectAll,
- clearFocusedCell,
- ensureColumnVisible,
- };
- const instance = wrapper.instance();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
- instance.onGridReady({ api });
-
- instance.onFocusedColumn('field4');
-
- expect(instance.currentColId).toEqual(null);
- });
-
- it('should scroll to focused column', () => {
- const deselectAll = jest.fn();
- const clearFocusedCell = jest.fn();
- const ensureColumnVisible = jest.fn();
- const api = {
- deselectAll,
- clearFocusedCell,
- ensureColumnVisible,
- };
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setCurrentFocusedColumn = jest.fn();
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
- instance.onGridReady({
- api,
- });
-
- expect(api.ensureColumnVisible).toHaveBeenCalled();
- });
-
- it('should focus a column', () => {
- const deselectAll = jest.fn();
- const clearFocusedCell = jest.fn();
- const api = {
- deselectAll,
- clearFocusedCell,
- };
- const currentColId = 'colId';
- const onFocusedColumn = jest.fn();
- const wrapper = shallow(
- ,
- );
- const instance = wrapper.instance();
-
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- wrapper.find('AgGridReact').props().onGridReady({ api });
-
- instance.onFocusedColumn(currentColId);
-
- expect(instance.setCurrentFocusedColumn).toHaveBeenCalledWith(currentColId);
- expect(instance.updateStyleFocusColumn).toHaveBeenCalled();
- expect(instance.removeFocusColumn).toHaveBeenCalled();
- expect(deselectAll).toHaveBeenCalled();
- expect(clearFocusedCell).toHaveBeenCalled();
- expect(onFocusedColumn).toHaveBeenCalledWith({ colId: currentColId });
- });
-
- it('should focus a column when an another column is focused', () => {
- const currentColId = 'colId';
- const focusedColId = 'colId2';
- const column = {
- colId: focusedColId,
- pinned: false,
- };
- const onFocusedCell = jest.fn();
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setCurrentFocusedColumn(currentColId);
-
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- instance.onFocusedCell({
- column,
- });
-
- expect(instance.setCurrentFocusedColumn).toHaveBeenCalledWith(focusedColId);
- expect(instance.updateStyleFocusColumn).toHaveBeenCalled();
- expect(instance.removeFocusColumn).toHaveBeenCalled();
- expect(onFocusedCell).toHaveBeenCalledWith({ column });
- });
-
- it('should focus a column when an another column is focused and not call onFocusedCell if undefined', () => {
- const currentColId = 'colId';
- const focusedColId = 'colId2';
- const column = {
- colId: focusedColId,
- pinned: false,
- };
- const onFocusedCell = jest.fn();
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setCurrentFocusedColumn(currentColId);
-
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- instance.onFocusedCell({
- column,
- });
-
- expect(instance.setCurrentFocusedColumn).toHaveBeenCalledWith(focusedColId);
- expect(instance.updateStyleFocusColumn).toHaveBeenCalled();
- expect(instance.removeFocusColumn).toHaveBeenCalled();
- expect(onFocusedCell).not.toHaveBeenCalled();
- });
-
- it('should focus a column when the same column is focused without remove the previous style', () => {
- const currentColId = 'colId';
- const column = {
- colId: currentColId,
- pinned: false,
- };
- const onFocusedCell = jest.fn();
- const wrapper = shallow();
- const instance = wrapper.instance();
- instance.setCurrentFocusedColumn(currentColId);
-
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- instance.onFocusedCell({
- column,
- });
-
- expect(instance.setCurrentFocusedColumn).toHaveBeenCalledWith(currentColId);
- expect(instance.updateStyleFocusColumn).toHaveBeenCalled();
- expect(instance.removeFocusColumn).not.toHaveBeenCalled();
- expect(onFocusedCell).toHaveBeenCalledWith({ column });
- });
-
- it('should not focus a column when there is no column', () => {
- const column = null;
- const onFocusedCell = jest.fn();
- const wrapper = shallow();
- const instance = wrapper.instance();
-
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- instance.onFocusedCell({
- column,
- });
-
- expect(instance.setCurrentFocusedColumn).not.toHaveBeenCalled();
- expect(instance.updateStyleFocusColumn).not.toHaveBeenCalled();
- expect(instance.removeFocusColumn).not.toHaveBeenCalled();
- expect(onFocusedCell).not.toHaveBeenCalledWith({ column });
- });
-
- it('should not focus a column when the selected column is pinned', () => {
- const currentColId = 'colId';
- const column = {
- colId: currentColId,
- pinned: true,
- };
- const onFocusedCell = jest.fn();
- const wrapper = shallow();
- const instance = wrapper.instance();
-
- instance.setCurrentFocusedColumn = jest.fn();
- instance.removeFocusColumn = jest.fn();
- instance.updateStyleFocusColumn = jest.fn();
-
- instance.onFocusedCell({
- column,
- });
-
- expect(instance.setCurrentFocusedColumn).toHaveBeenCalledWith(currentColId);
- expect(instance.updateStyleFocusColumn).not.toHaveBeenCalled();
- expect(instance.removeFocusColumn).toHaveBeenCalled();
- expect(onFocusedCell).not.toHaveBeenCalledWith({ column });
- });
-
- it('should focus on the first cell when DOWN is triggered', () => {
- const preventDefault = jest.fn();
- const setFocusedCell = jest.fn();
- const ensureIndexVisible = jest.fn();
- const api = {
- setFocusedCell,
- ensureIndexVisible,
- };
- const colId = 'colId';
- const wrapper = shallow();
- const instance = wrapper.instance();
-
- wrapper.find('AgGridReact').props().onGridReady({ api });
-
- instance.onKeyDownHeaderColumn(
- {
- keyCode: keycode('down'),
- preventDefault,
- },
- colId,
- );
-
- expect(setFocusedCell).toHaveBeenCalledWith(0, colId);
- expect(ensureIndexVisible).toHaveBeenCalledWith(0);
- });
-
- it('should not focus on the first cell when other key is triggered', () => {
- const preventDefault = jest.fn();
- const setFocusedCell = jest.fn();
- const ensureIndexVisible = jest.fn();
- const colId = 'colId';
- const wrapper = shallow();
- const instance = wrapper.instance();
-
- wrapper.find('AgGridReact').props().onGridReady({
- setFocusedCell,
- ensureIndexVisible,
- });
-
- instance.onKeyDownHeaderColumn(
- {
- keyCode: keycode('up'),
- preventDefault,
- },
- colId,
- );
-
- expect(setFocusedCell).not.toHaveBeenCalledWith(0, colId);
- expect(ensureIndexVisible).not.toHaveBeenCalledWith(0);
- });
-
- it('should trigger an event when the grid scroll vertical', () => {
- const firstIndex = 0;
- const lastIndex = 20;
- const event = {
- direction: AG_GRID.SCROLL_VERTICAL_DIRECTION,
- };
- const api = {
- getFirstDisplayedRow: () => firstIndex,
- getLastDisplayedRow: () => lastIndex,
- };
- const onVerticalScroll = jest.fn();
- const wrapper = shallow(
- ,
- );
- const instance = wrapper.instance();
-
- wrapper.find('AgGridReact').props().onGridReady({
- api,
- });
-
- instance.onBodyScroll(event);
-
- expect(onVerticalScroll).toHaveBeenCalledWith(event, {
- firstDisplayedRowIndex: firstIndex,
- lastDisplayedRowIndex: lastIndex,
- });
- });
-
- it('should not trigger an event when the grid scroll horizontal', () => {
- const event = {
- direction: 'horizontal',
- };
- const onVerticalScroll = jest.fn();
- const wrapper = shallow(
- ,
- );
- const instance = wrapper.instance();
-
- instance.onBodyScroll(event);
-
- expect(onVerticalScroll).not.toHaveBeenCalled();
- });
-});
-
-describe('#injectHeaderRenderer', () => {
- const Component = () => {};
- const onFocusedColumn = jest.fn();
- const onKeyDown = jest.fn();
-
- it('should injected the header renderer', () => {
- const getCellComponent = jest.fn(() => Component);
- const componentId = 'header';
- const InjectedComponent = injectHeaderRenderer(
- getCellComponent,
- 'header',
- onFocusedColumn,
- onKeyDown,
- );
-
- const wrapper = shallow();
- wrapper.props().onFocusedColumn();
- wrapper.props().onKeyDown();
-
- expect(wrapper.props().myProps).toBe('myProps');
- expect(getCellComponent).toHaveBeenCalledWith(componentId);
- expect(onFocusedColumn).toHaveBeenCalled();
- expect(onKeyDown).toHaveBeenCalled();
- });
-
- it('should injected the default header renderer', () => {
- const InjectedComponent = injectHeaderRenderer(null, 'header', onFocusedColumn);
-
- const wrapper = shallow();
-
- expect(wrapper.find('DefaultHeaderRenderer').length).toBe(1);
- });
-});
-
-describe('#forceRedraw', () => {
- it('should not call forceRedrawRows when the DataGrid is loading', () => {
- const forceRedrawRows = jest.fn(() => true);
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().componentDidUpdate({});
- expect(forceRedrawRows).not.toHaveBeenCalled();
- });
-
- it('should not call forceRedrawRows when the DataGrid is not ready', () => {
- const forceRedrawRows = jest.fn(() => true);
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().componentDidUpdate({});
- expect(forceRedrawRows).not.toHaveBeenCalled();
- });
-
- it('should call redrawRows when forceRedrawRows return true', () => {
- const forceRedrawRows = jest.fn(() => true);
- const redrawRows = jest.fn();
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().onGridReady({
- api: {
- redrawRows,
- },
- });
- wrapper.instance().componentDidUpdate({});
-
- expect(forceRedrawRows).toHaveBeenCalled();
- expect(redrawRows).toHaveBeenCalled();
- });
-
- it('should not call redrawRows when forceRedrawRows return false', () => {
- const forceRedrawRows = jest.fn(() => false);
- const redrawRows = jest.fn();
- const wrapper = shallow(
- ,
- );
-
- wrapper.instance().onGridReady({
- api: {
- redrawRows,
- },
- });
- wrapper.instance().componentDidUpdate({});
-
- expect(forceRedrawRows).toHaveBeenCalled();
- expect(redrawRows).not.toHaveBeenCalled();
+ it('should render DataGrid', async () => {
+ // add globals
+ window.React = React;
+ window.ReactDOM = ReactDOM;
+ window.agGrid = agGrid;
+ window.AgGridReact = { AgGridReact, AgGridColumn };
+ render();
+ await waitFor(
+ () =>
+ new Promise(resolve => {
+ setTimeout(() => {
+ resolve(true);
+ }, 30);
+ }),
+ );
+ const column = await screen.findByText('Aéroport Charles de Gaulle 2 TGV');
+ expect(column).toBeInTheDocument();
});
});
diff --git a/packages/datagrid/src/components/DataGrid/__snapshots__/DataGrid.test.js.snap b/packages/datagrid/src/components/DataGrid/__snapshots__/DataGrid.test.js.snap
deleted file mode 100644
index 385f2d05f7..0000000000
--- a/packages/datagrid/src/components/DataGrid/__snapshots__/DataGrid.test.js.snap
+++ /dev/null
@@ -1,308 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`#DataGrid should render DataGrid 1`] = `
-
-`;
-
-exports[`#DataGrid should render DataGrid with columnsDefs and rowData 1`] = `
-
-`;
-
-exports[`#DataGrid should render one Skeleton is InProgress 1`] = `
-
-`;
diff --git a/packages/dataviz/src/components/GeoChart/maps/CA.topo.json b/packages/dataviz/assets/maps/CA.topo.json
similarity index 100%
rename from packages/dataviz/src/components/GeoChart/maps/CA.topo.json
rename to packages/dataviz/assets/maps/CA.topo.json
diff --git a/packages/dataviz/src/components/GeoChart/maps/FR.topo.json b/packages/dataviz/assets/maps/FR.topo.json
similarity index 94%
rename from packages/dataviz/src/components/GeoChart/maps/FR.topo.json
rename to packages/dataviz/assets/maps/FR.topo.json
index 441000a73a..3daa76bfca 100644
--- a/packages/dataviz/src/components/GeoChart/maps/FR.topo.json
+++ b/packages/dataviz/assets/maps/FR.topo.json
@@ -4083,35 +4083,8 @@
{
"arcs": [
[
- 42,
- -41,
- -40,
- -39,
- -36,
- 197,
- -229,
- -104,
- 241,
- 286,
- 288,
- -201,
- -206,
- -186,
- -185,
- -222,
- -221,
- 251,
- 252,
- 253,
- 247,
- 239,
- 87,
- 88,
- 89,
- 84,
- 49,
- 47,
- 46
+ 42, -41, -40, -39, -36, 197, -229, -104, 241, 286, 288, -201, -206, -186, -185, -222,
+ -221, 251, 252, 253, 247, 239, 87, 88, 89, 84, 49, 47, 46
],
[199]
],
@@ -4122,32 +4095,8 @@
"arcs": [
[
[
- 50,
- 111,
- 115,
- 119,
- 120,
- -129,
- -262,
- -261,
- -208,
- -215,
- 181,
- -214,
- 219,
- 220,
- 221,
- 184,
- 185,
- 186,
- -205,
- -204,
- -190,
- -176,
- 114,
- 52,
- 53,
- 54
+ 50, 111, 115, 119, 120, -129, -262, -261, -208, -215, 181, -214, 219, 220, 221, 184,
+ 185, 186, -205, -204, -190, -176, 114, 52, 53, 54
]
],
[[124]]
@@ -4158,31 +4107,8 @@
{
"arcs": [
[
- 55,
- 64,
- -54,
- -53,
- -115,
- 175,
- 189,
- 203,
- 204,
- -187,
- 205,
- 200,
- -289,
- -287,
- -242,
- 103,
- 104,
- -98,
- 99,
- 105,
- 109,
- 70,
- 68,
- 67,
- 62
+ 55, 64, -54, -53, -115, 175, 189, 203, 204, -187, 205, 200, -289, -287, -242, 103,
+ 104, -98, 99, 105, 109, 70, 68, 67, 62
]
],
"type": "Polygon",
@@ -4191,26 +4117,8 @@
{
"arcs": [
[
- 79,
- -76,
- 80,
- 81,
- 90,
- -89,
- -88,
- -240,
- -248,
- -254,
- -253,
- -284,
- -259,
- -258,
- 297,
- -264,
- -263,
- -232,
- -231,
- -241
+ 79, -76, 80, 81, 90, -89, -88, -240, -248, -254, -253, -284, -259, -258, 297, -264,
+ -263, -232, -231, -241
]
],
"type": "Polygon",
@@ -4219,22 +4127,7 @@
{
"arcs": [
[
- 125,
- 129,
- 130,
- 131,
- -145,
- -144,
- -149,
- 223,
- 225,
- 226,
- -216,
- -210,
- -209,
- 260,
- 261,
- 128,
+ 125, 129, 130, 131, -145, -144, -149, 223, 225, 226, -216, -210, -209, 260, 261, 128,
-121
]
],
@@ -4263,25 +4156,8 @@
{
"arcs": [
[
- 207,
- 208,
- 209,
- 215,
- -227,
- 284,
- -158,
- -281,
- 285,
- 255,
- 256,
- 257,
- 258,
- 283,
- -252,
- -220,
- 213,
- -182,
- 214
+ 207, 208, 209, 215, -227, 284, -158, -281, 285, 255, 256, 257, 258, 283, -252, -220,
+ 213, -182, 214
]
],
"type": "Polygon",
@@ -4326,28 +4202,8 @@
{
"arcs": [
[
- 42,
- -41,
- -40,
- -39,
- -36,
- 197,
- -229,
- -104,
- 241,
- 242,
- 244,
- 245,
- 246,
- 247,
- 239,
- 87,
- 88,
- 89,
- 84,
- 49,
- 47,
- 46
+ 42, -41, -40, -39, -36, 197, -229, -104, 241, 242, 244, 245, 246, 247, 239, 87, 88,
+ 89, 84, 49, 47, 46
],
[199]
],
@@ -4364,28 +4220,8 @@
{
"arcs": [
[
- 55,
- 64,
- -54,
- -53,
- -115,
- 175,
- 189,
- 203,
- 204,
- -187,
- 205,
- 200,
- 201,
- -102,
- -109,
- -108,
- -111,
- 60,
- 65,
- 66,
- 67,
- 62
+ 55, 64, -54, -53, -115, 175, 189, 203, 204, -187, 205, 200, 201, -102, -109, -108,
+ -111, 60, 65, 66, 67, 62
]
],
"type": "Polygon",
@@ -4394,25 +4230,8 @@
{
"arcs": [
[
- 68,
- -67,
- -66,
- -61,
- 110,
- 107,
- 108,
- 101,
- -202,
- -289,
- -287,
- -242,
- 103,
- 104,
- -98,
- 99,
- 105,
- 109,
- 70
+ 68, -67, -66, -61, 110, 107, 108, 101, -202, -289, -287, -242, 103, 104, -98, 99, 105,
+ 109, 70
]
],
"type": "Polygon",
@@ -4439,22 +4258,7 @@
{
"arcs": [
[
- 125,
- 129,
- 130,
- 131,
- -145,
- -144,
- -149,
- 223,
- 225,
- 226,
- -216,
- -210,
- -209,
- 260,
- 261,
- 128,
+ 125, 129, 130, 131, -145, -144, -149, 223, 225, 226, -216, -210, -209, 260, 261, 128,
-121
]
],
@@ -4493,25 +4297,8 @@
{
"arcs": [
[
- 207,
- 208,
- 209,
- 215,
- -227,
- 284,
- -158,
- -281,
- 285,
- 255,
- 256,
- 257,
- 258,
- 283,
- -252,
- -220,
- 213,
- -182,
- 214
+ 207, 208, 209, 215, -227, 284, -158, -281, 285, 255, 256, 257, 258, 283, -252, -220,
+ 213, -182, 214
]
],
"type": "Polygon",
diff --git a/packages/dataviz/src/components/GeoChart/maps/MX.topo.json b/packages/dataviz/assets/maps/MX.topo.json
similarity index 100%
rename from packages/dataviz/src/components/GeoChart/maps/MX.topo.json
rename to packages/dataviz/assets/maps/MX.topo.json
diff --git a/packages/dataviz/src/components/GeoChart/maps/US.topo.json b/packages/dataviz/assets/maps/US.topo.json
similarity index 100%
rename from packages/dataviz/src/components/GeoChart/maps/US.topo.json
rename to packages/dataviz/assets/maps/US.topo.json
diff --git a/packages/dataviz/src/components/GeoChart/maps/US_CA.topo.json b/packages/dataviz/assets/maps/US_CA.topo.json
similarity index 100%
rename from packages/dataviz/src/components/GeoChart/maps/US_CA.topo.json
rename to packages/dataviz/assets/maps/US_CA.topo.json
diff --git a/packages/dataviz/src/components/GeoChart/maps/continents.topo.json b/packages/dataviz/assets/maps/continents.topo.json
similarity index 100%
rename from packages/dataviz/src/components/GeoChart/maps/continents.topo.json
rename to packages/dataviz/assets/maps/continents.topo.json
diff --git a/packages/dataviz/src/components/GeoChart/maps/world.topo.json b/packages/dataviz/assets/maps/world.topo.json
similarity index 99%
rename from packages/dataviz/src/components/GeoChart/maps/world.topo.json
rename to packages/dataviz/assets/maps/world.topo.json
index cfbc53b7c7..a3a4478b8a 100644
--- a/packages/dataviz/src/components/GeoChart/maps/world.topo.json
+++ b/packages/dataviz/assets/maps/world.topo.json
@@ -10596,29 +10596,8 @@
"arcs": [
[
[
- -17,
- -425,
- 607,
- -491,
- 608,
- -489,
- -355,
- -488,
- 609,
- -317,
- 610,
- -134,
- -427,
- -435,
- -242,
- -373,
- -240,
- -326,
- 611,
- 612,
- 613,
- 614,
- 615
+ -17, -425, 607, -491, 608, -489, -355, -488, 609, -317, 610, -134, -427, -435, -242,
+ -373, -240, -326, 611, 612, 613, 614, 615
]
],
[[616]]
diff --git a/packages/dataviz/package.json b/packages/dataviz/package.json
index c52053a1f9..f14d5d97a9 100644
--- a/packages/dataviz/package.json
+++ b/packages/dataviz/package.json
@@ -17,7 +17,7 @@
"lint:es": "talend-scripts lint:es --format json -o eslint-report.json",
"lint:style": "talend-scripts lint:style -f json -o stylelint-report.json",
"start": "talend-scripts start-storybook -p 6006",
- "test": "cross-env TZ=Europe/Paris talend-scripts test --silent",
+ "test": "cross-env TZ=Europe/Paris talend-scripts test",
"test:watch": "cross-env TZ=Europe/Paris talend-scripts test --watch",
"test:cov": "cross-env TZ=Europe/Paris talend-scripts test --coverage",
"test:demo": "talend-scripts build-storybook --quiet"
@@ -37,6 +37,7 @@
"url": "https://github.com/Talend/ui.git"
},
"dependencies": {
+ "@talend/assets-api": "^1.0.0",
"@talend/react-components": "^6.44.14",
"@talend/design-tokens": "^2.1.0",
"classnames": "^2.3.1",
diff --git a/packages/dataviz/src/components/GeoChart/GeoChart.test.js b/packages/dataviz/src/components/GeoChart/GeoChart.test.js
index 250f0f3469..fbf702284f 100644
--- a/packages/dataviz/src/components/GeoChart/GeoChart.test.js
+++ b/packages/dataviz/src/components/GeoChart/GeoChart.test.js
@@ -4,10 +4,18 @@ import GeoChart from './GeoChart.component';
import { getGeoChartConfig } from './GeoChart.utils';
import styles from './GeoChart.scss';
+function getTopo(url) {
+ const last = url.split('/').pop();
+ return require(`../../../assets/maps/${last}`);
+}
+
describe('GeoChart component', () => {
let defaultProps;
-
+ let originalfetch;
beforeEach(async () => {
+ jest.resetAllMocks();
+ originalfetch = global.fetch;
+ global.fetch = jest.fn(url => ({ ok: true, json: () => Promise.resolve(getTopo(url)) }));
defaultProps = {
data: [
{ key: 'Occitanie', value: 10 },
@@ -18,6 +26,9 @@ describe('GeoChart component', () => {
onSelection: jest.fn(),
};
});
+ afterEach(() => {
+ global.fetch = originalfetch;
+ });
it('Should match data', () => {
const component = mount().render();
@@ -47,6 +58,7 @@ describe('GeoChart component', () => {
]}
/>,
).render();
+ expect(global.fetch).toHaveBeenCalled();
expect(component.find('[data-key="TX"]')).toHaveLength(1);
expect(component.find('[data-key="New York"]')).toHaveLength(0);
diff --git a/packages/dataviz/src/components/GeoChart/GeoChart.utils.ts b/packages/dataviz/src/components/GeoChart/GeoChart.utils.ts
index 6b55eb7e3c..ba495df7c7 100644
--- a/packages/dataviz/src/components/GeoChart/GeoChart.utils.ts
+++ b/packages/dataviz/src/components/GeoChart/GeoChart.utils.ts
@@ -1,25 +1,9 @@
import { GeoChartConfig } from './GeoChart.component';
-import CA from './maps/CA.topo.json';
-import continents from './maps/continents.topo.json';
-import FR from './maps/FR.topo.json';
-import MX from './maps/MX.topo.json';
-import US_CA from './maps/US_CA.topo.json';
-import US from './maps/US.topo.json';
-import world from './maps/world.topo.json';
+import assetsAPI from '@talend/assets-api';
const DEFAULT_LABEL_PROPERTY = 'name';
const STATE_CODE_VALUE_PROPERTIES = ['iso_3166_2'];
-const MAPS: { [key: string]: any } = {
- CA,
- continents,
- FR,
- MX,
- US,
- US_CA,
- world,
-};
-
// Define file name only, will be used in a dynamic import()
type SupportedGeoChart = Omit & { file: string };
const SUPPORTED_CHARTS: { [key: string]: SupportedGeoChart } = {
@@ -97,11 +81,22 @@ export function getGeoChartSupportedDomains(): string[] {
return Object.keys(SUPPORTED_CHARTS);
}
-export async function getGeoChartConfig(domain: string): Promise {
+export async function getGeoChartConfig(domain: string): Promise {
const { file, ...chartConfig } = SUPPORTED_CHARTS[domain];
- return {
- ...chartConfig,
- labelProperty: chartConfig.labelProperty || DEFAULT_LABEL_PROPERTY,
- topology: MAPS[file],
- };
+ try {
+ const topology: GeoChartConfig['topology'] | undefined = await assetsAPI.getJSON(
+ `/dist/assets/maps/${file}.topo.json`,
+ );
+ if (!topology) {
+ throw new Error('GeoChart topology undefined');
+ }
+ return {
+ ...chartConfig,
+ labelProperty: chartConfig.labelProperty || DEFAULT_LABEL_PROPERTY,
+ topology,
+ };
+ } catch (e) {
+ console.error(`can't get requested topology ${file}`, e);
+ }
+ return;
}
diff --git a/packages/dataviz/talend-scripts.json b/packages/dataviz/talend-scripts.json
index 4d78bcf08f..a6810de062 100755
--- a/packages/dataviz/talend-scripts.json
+++ b/packages/dataviz/talend-scripts.json
@@ -1,3 +1,4 @@
{
- "preset": "@talend/scripts-preset-react-lib"
+ "preset": "@talend/scripts-preset-react-lib",
+ "copy": [{ "from": "assets/**" }]
}
diff --git a/packages/design-system/README.md b/packages/design-system/README.md
index 2ce7dedb1d..43e5743bee 100644
--- a/packages/design-system/README.md
+++ b/packages/design-system/README.md
@@ -63,6 +63,10 @@ Limit changes to styled-components scope.
Visual non-regression testing will be covered by Chromatic.
Use Cypress if you have to perform interaction tests, in real browsers.
+To launch non the tests you first need to have cypress installed on your environment. Then you can just execute the corresponding npm scripts:
+
+ yarn workspace @talend/design-system run test:cy
+
## License
[Apache 2.0](https://github.com/Talend/design-system/blob/master/LICENSE)
diff --git a/packages/design-system/package.json b/packages/design-system/package.json
index 7f956967e1..6cd2780ca3 100644
--- a/packages/design-system/package.json
+++ b/packages/design-system/package.json
@@ -33,6 +33,7 @@
"access": "public"
},
"dependencies": {
+ "@talend/assets-api": "^1.0.0",
"@talend/design-tokens": "^2.1.0",
"classnames": "^2.3.1",
"modern-css-reset": "^1.4.0",
diff --git a/packages/design-system/src/components/IconsProvider/IconsProvider.tsx b/packages/design-system/src/components/IconsProvider/IconsProvider.tsx
index 36e0a9ec18..ebabea663a 100644
--- a/packages/design-system/src/components/IconsProvider/IconsProvider.tsx
+++ b/packages/design-system/src/components/IconsProvider/IconsProvider.tsx
@@ -1,6 +1,7 @@
import React, { ReactElement, RefObject, useState, useEffect, useRef } from 'react';
+import assetsAPI from '@talend/assets-api';
-const DEFAULT_BUNDLES = ['/all.svg'];
+const DEFAULT_BUNDLES = [assetsAPI.getURL('/dist/svg-bundle/all.svg', '@talend/icons')];
const FETCHING_BUNDLES: { [url: string]: Promise } = {};
const ICONS_PROVIDER_CLASS = '.tc-iconsprovider';
diff --git a/packages/design-system/src/components/Stepper/docs/Stepper.stories.mdx b/packages/design-system/src/components/Stepper/docs/Stepper.stories.mdx
index e177c26a63..18221ae1bc 100644
--- a/packages/design-system/src/components/Stepper/docs/Stepper.stories.mdx
+++ b/packages/design-system/src/components/Stepper/docs/Stepper.stories.mdx
@@ -95,9 +95,9 @@ The sub-steps option is not available with the horizontal stepper.
## Content
-Use nouns to create one-word labels for steps. Go for 2-word step labels when necessary. Step labels should describe the purpose of each step and let users know where they are in their setup.
+Use nouns to create one-word labels for steps. Go for 2-word step labels when necessary. Step labels should describe the purpose of each step and let users know where they are in their setup.
-**In vertical steppers**, each step opens a section to the right of the stepper. Start the section title with a verb and tell users what to do and why. For example, a step label "Engine" could have a section title "Add the engine on which to process data".
+**In vertical steppers**, each step opens a section to the right of the stepper. Start the section title with a verb and tell users what to do and why. For example, a step label "Engine" could have a section title "Add the engine on which to process data".
Step sections can also have subtitles, if necessary, to provide users with extra important information—as in complicated steps for example.
**In horizontal steppers**, no sections are used. Once a step is selected, user input shows below. Avoid using long nouns in horizontal steppers
diff --git a/packages/design-system/tsconfig.build.json b/packages/design-system/tsconfig.build.json
index c1e6a1eb9e..bb854f9c9a 100644
--- a/packages/design-system/tsconfig.build.json
+++ b/packages/design-system/tsconfig.build.json
@@ -1,6 +1,7 @@
{
"extends": "./tsconfig.json",
"include": ["src/index.ts", "src/styled.d.ts", "custom.d.ts"],
+ "exclude": ["*.spec.*"],
"compilerOptions": {
"declaration": true
}
diff --git a/packages/faceted-search/package.json b/packages/faceted-search/package.json
index ed037fcc2a..614fa9d8d6 100644
--- a/packages/faceted-search/package.json
+++ b/packages/faceted-search/package.json
@@ -10,7 +10,7 @@
"build:prod": "talend-scripts build:lib:umd --prod",
"pre-release": "yarn build:dev && yarn build:prod",
"build:lib": "talend-scripts build:lib",
- "test": "cross-env TZ=Europe/Paris talend-scripts test --silent",
+ "test": "cross-env TZ=Europe/Paris talend-scripts test",
"test:watch": "cross-env TZ=Europe/Paris talend-scripts test --watch",
"test:cov": "cross-env TZ=Europe/Paris talend-scripts test --coverage",
"test:demo": "talend-scripts build-storybook --quiet --docs",
diff --git a/packages/forms/package.json b/packages/forms/package.json
index 687a5fcfde..d79bbc8cdd 100644
--- a/packages/forms/package.json
+++ b/packages/forms/package.json
@@ -36,6 +36,7 @@
"url": "https://github.com/Talend/ui.git"
},
"dependencies": {
+ "@talend/assets-api": "^1.0.0",
"@talend/design-system": "^2.4.0",
"@talend/json-schema-form-core": "1.0.5",
"@talend/react-components": "^6.45.0",
diff --git a/packages/forms/src/UIForm/fields/Code/Code.component.js b/packages/forms/src/UIForm/fields/Code/Code.component.js
index 3676e033a8..b354f6516e 100644
--- a/packages/forms/src/UIForm/fields/Code/Code.component.js
+++ b/packages/forms/src/UIForm/fields/Code/Code.component.js
@@ -1,143 +1,123 @@
+/* eslint-disable react/jsx-no-bind */
import PropTypes from 'prop-types';
-import React from 'react';
+import React, { Suspense, useEffect } from 'react';
import { withTranslation } from 'react-i18next';
import keyCode from 'keycode';
+import assetsApi from '@talend/assets-api';
+import { Skeleton } from '@talend/react-components';
import FieldTemplate from '../FieldTemplate';
-import TextArea from '../TextArea';
+
import { generateId, generateDescriptionId, generateErrorId } from '../../Message/generateId';
import getDefaultT from '../../../translate';
import { I18N_DOMAIN_FORMS } from '../../../constants';
-let CodeWidget = TextArea;
-let AceEditor;
+const ReactAce = React.lazy(() =>
+ assetsApi.getUMD('react-ace').then(mod => assetsApi.toDefaultModule(mod.default)),
+);
+
+function CodeSkeleton() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+
const DEFAULT_SET_OPTIONS = {
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
};
-class WrappedTextArea extends React.PureComponent {
- constructor() {
- super();
- // eslint-disable-next-line no-console
- console.warn('CodeWidget react-ace not found, fallback to Textarea');
- }
-
- render() {
- return ;
- }
-}
-
-// eslint-disable-next-line react/no-multi-comp
-class Code extends React.Component {
- constructor(props) {
- super(props);
- this.onChange = this.onChange.bind(this);
- this.onFinish = this.onFinish.bind(this);
- this.onLoad = this.onLoad.bind(this);
- this.onBlur = this.onBlur.bind(this);
- this.onKeyDown = this.onKeyDown.bind(this);
-
- // this hold the last time the ESC is pressed to offer an escape solution from keyboard trap
- this.lastEsc = null;
- }
-
- componentDidUpdate() {
- this.attachTextareaAttributes();
- }
+function Code(props) {
+ const { id, isValid, errorMessage, schema, value, valueIsUpdating, t } = props;
+ const { autoFocus, description, options, readOnly = false, title, labelProps } = schema;
+ const descriptionId = generateDescriptionId(id);
+ const errorId = generateErrorId(id);
+ const instructionsId = generateId(id, 'instructions');
+ const containerRef = React.useRef(null);
+ const [editor, setEditor] = React.useState(null);
+
+ useEffect(() => {
+ if (editor) {
+ const textarea = editor.textInput.getElement();
+ textarea.setAttribute('id', id);
+ textarea.setAttribute('aria-describedby', `${instructionsId} ${descriptionId} ${errorId}`);
+ }
+ }, [editor, instructionsId, descriptionId, errorId, id]);
- onChange(value, event) {
- this.props.onChange(event, { schema: this.props.schema, value });
+ function onChange(newValue, event) {
+ props.onChange(event, { schema: props.schema, value: newValue });
}
- onFinish(event) {
- this.props.onFinish(event, { schema: this.props.schema });
+ function onFinish(event) {
+ props.onFinish(event, { schema: props.schema });
}
- onKeyDown(event) {
+ function onKeyDown(event) {
if (event.keyCode === keyCode.codes.esc) {
const now = Date.now();
- if (this.lastEsc && this.lastEsc - now < 1000) {
- this.lastEsc = null;
- this.ref.focus();
- this.editor.textInput.getElement().setAttribute('tabindex', -1);
+
+ if (containerRef.current.lastEsc && containerRef.current.lastEsc - now < 1000) {
+ containerRef.current.lastEsc = null;
+ containerRef.current.focus();
+ editor.textInput.getElement().setAttribute('tabindex', -1);
} else {
- this.lastEsc = now;
+ containerRef.current.lastEsc = now;
}
} else {
- this.lastEsc = null;
+ containerRef.current.lastEsc = null;
}
}
- onBlur() {
- this.editor.textInput.getElement().removeAttribute('tabindex');
- }
-
- onLoad(editor) {
- this.editor = editor;
- this.attachTextareaAttributes();
+ function onBlur() {
+ editor.textInput.getElement().removeAttribute('tabindex');
}
- attachTextareaAttributes() {
- if (this.editor) {
- const textarea = this.editor.textInput.getElement();
- textarea.setAttribute('id', this.props.id);
- textarea.setAttribute(
- 'aria-describedby',
- `${this.ids.instructionsId} ${this.ids.descriptionId} ${this.ids.errorId}`,
- );
- }
+ function onLoad(ace) {
+ setEditor(ace);
}
- render() {
- const { id, isValid, errorMessage, schema, value, valueIsUpdating, t } = this.props;
- const { autoFocus, description, options, readOnly = false, title, labelProps } = schema;
- const descriptionId = generateDescriptionId(id);
- const errorId = generateErrorId(id);
- const instructionsId = generateId(id, 'instructions');
- this.ids = {
- descriptionId,
- errorId,
- instructionsId,
- };
-
- return (
-
+
-
{
- this.ref = ref;
- }}
- tabIndex="-1"
- >
-
- {t('TF_CODE_ESCAPE', {
- defaultValue: 'To focus out of the editor, press ESC key twice.',
- })}
-
-
+ {t('TF_CODE_ESCAPE', {
+ defaultValue: 'To focus out of the editor, press ESC key twice.',
+ })}
+
+
}>
+
-
-
- );
- }
-}
-if (process.env.NODE_ENV !== 'production') {
- WrappedTextArea.propTypes = TextArea.propTypes;
- Code.propTypes = {
- id: PropTypes.string,
- isValid: PropTypes.bool,
- errorMessage: PropTypes.string,
- onChange: PropTypes.func.isRequired,
- onFinish: PropTypes.func.isRequired,
- schema: PropTypes.shape({
- autoFocus: PropTypes.bool,
- description: PropTypes.string,
- disabled: PropTypes.bool,
- options: PropTypes.object,
- readOnly: PropTypes.bool,
- required: PropTypes.bool,
- title: PropTypes.string,
- labelProps: PropTypes.object,
- type: PropTypes.string,
- }),
- t: PropTypes.func,
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- valueIsUpdating: PropTypes.bool,
- };
+
+
+
+ );
}
+Code.propTypes = {
+ id: PropTypes.string,
+ isValid: PropTypes.bool,
+ errorMessage: PropTypes.string,
+ onChange: PropTypes.func.isRequired,
+ onFinish: PropTypes.func.isRequired,
+ schema: PropTypes.shape({
+ autoFocus: PropTypes.bool,
+ description: PropTypes.string,
+ disabled: PropTypes.bool,
+ options: PropTypes.object,
+ readOnly: PropTypes.bool,
+ required: PropTypes.bool,
+ title: PropTypes.string,
+ labelProps: PropTypes.object,
+ type: PropTypes.string,
+ }),
+ t: PropTypes.func,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ valueIsUpdating: PropTypes.bool,
+};
+
Code.defaultProps = {
isValid: true,
schema: {},
t: getDefaultT(),
};
-try {
- /* eslint-disable global-require, import/no-extraneous-dependencies */
- AceEditor = require('react-ace').default;
- require('brace/ext/language_tools'); // https://github.com/securingsincity/react-ace/issues/95
- /* eslint-enable global-require, import/no-extraneous-dependencies */
- CodeWidget = Code;
-} catch (error) {
- CodeWidget = WrappedTextArea;
-}
-
-export default withTranslation(I18N_DOMAIN_FORMS)(CodeWidget);
+export default withTranslation(I18N_DOMAIN_FORMS)(Code);
diff --git a/packages/forms/src/UIForm/fields/Code/Code.component.test.js b/packages/forms/src/UIForm/fields/Code/Code.component.test.js
index a33f4240e6..0fddae6c8b 100644
--- a/packages/forms/src/UIForm/fields/Code/Code.component.test.js
+++ b/packages/forms/src/UIForm/fields/Code/Code.component.test.js
@@ -1,9 +1,14 @@
+/* eslint-disable testing-library/no-container */
import React from 'react';
-import { shallow, mount } from 'enzyme';
-import keyCode from 'keycode';
-
+import ReactDOM from 'react-dom';
+import { render, waitFor, screen } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import ReactAce from 'react-ace';
import Code from './Code.component';
+// fix cannot read appendChild of null;
+jest.mock('ally.js');
+
describe('Code field', () => {
const schema = {
autoFocus: true,
@@ -20,121 +25,26 @@ describe('Code field', () => {
value: 'toto',
};
- afterEach(() => {
- // clear JSDOM to avoid tests that mount on document.body to pollute other tests
- document.documentElement.innerHTML = '';
- });
-
- it('should render ace-editor in FieldTemplate', () => {
- // when
- const wrapper = shallow();
-
- // then
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-
- it('should render disabled input', () => {
- // given
- const disabledSchema = { ...schema, disabled: true };
-
- // when
- const wrapper = shallow();
-
- // then
- expect(wrapper.find('ReactAce').prop('readOnly')).toBe(true);
- });
-
- it('should render readonly input', () => {
- // given
- const readOnlySchema = { ...schema, readOnly: true };
-
- // when
- const wrapper = shallow();
-
- // then
- expect(wrapper.find('ReactAce').prop('readOnly')).toBe(true);
- });
-
- it('should trigger onChange', () => {
- // given
- const wrapper = shallow();
- expect(props.onChange).not.toBeCalled();
- const event = { target: { value: 'totoa' } };
-
- // when
- wrapper.find('ReactAce').prop('onChange')('totoa', event);
-
- // then
- expect(props.onChange).toBeCalledWith(event, { schema, value: 'totoa' });
- });
-
- it('should trigger onFinish on input blur', () => {
- // given
- const wrapper = shallow();
- expect(props.onFinish).not.toBeCalled();
- const event = { target: { value: 'totoa' } };
-
- // when
- wrapper.find('ReactAce').prop('onBlur')(event);
-
- // then
- expect(props.onFinish).toBeCalledWith(event, { schema });
- });
-
- it('should add the field id to the textarea on load', () => {
- // given
- const wrapper = shallow();
- const textAreaSetAttribute = jest.fn();
- const editor = {
- textInput: {
- getElement() {
- return { setAttribute: textAreaSetAttribute };
- },
- },
- };
-
- // when
- wrapper.find('ReactAce').prop('onLoad')(editor);
-
- // then
- expect(textAreaSetAttribute).toBeCalledWith('id', props.id);
- });
-
- it('should focus on the wrapping div on double esc keydown', () => {
- // given
- const containerId = 'myCodeWidget-editor-container';
- const wrapper = mount(, { attachTo: document.body });
- const editor = wrapper.find('#myCodeWidget_wrapper');
- expect(document.activeElement.getAttribute('id')).not.toBe(containerId);
-
- // when
- editor.simulate('keydown', { keyCode: keyCode.codes.esc });
- expect(document.activeElement.getAttribute('id')).not.toBe(containerId);
- editor.simulate('keydown', { keyCode: keyCode.codes.esc });
-
- // then
- expect(document.activeElement.getAttribute('id')).toBe(containerId);
- });
-
- it('should manage tabindex on textarea', () => {
- // given
- const wrapper = mount(, { attachTo: document.body });
- const editor = wrapper.find('#myCodeWidget_wrapper');
- const textarea = document.activeElement;
- expect(textarea.getAttribute('tabindex')).not.toBe('-1');
-
- // when
- editor.simulate('keydown', { keyCode: keyCode.codes.esc });
- editor.simulate('keydown', { keyCode: keyCode.codes.esc });
-
- // then
- expect(textarea.getAttribute('tabindex')).toBe('-1');
-
- // when
- const container = wrapper.find('#myCodeWidget-editor-container');
- container.simulate('blur');
-
- // then
- expect(textarea.getAttribute('tabindex')).not.toBe('-1');
+ async function initWith(dprops) {
+ window.React = React;
+ window.ReactDOM = ReactDOM;
+ window.ReactAce = { default: ReactAce };
+ render();
+ await waitFor(
+ () =>
+ new Promise(resolve => {
+ setTimeout(() => {
+ resolve(true);
+ }, 10);
+ }),
+ );
+ }
+ it('should render ace-editor in FieldTemplate', async () => {
+ // when
+
+ await initWith(props);
+ const input = await screen.findByLabelText('My input title');
+ expect(input).toBeInTheDocument();
+ expect(input.tagName).toBe('TEXTAREA');
});
});
diff --git a/packages/forms/src/UIForm/fields/Code/__snapshots__/Code.component.test.js.snap b/packages/forms/src/UIForm/fields/Code/__snapshots__/Code.component.test.js.snap
deleted file mode 100644
index ea71fb4847..0000000000
--- a/packages/forms/src/UIForm/fields/Code/__snapshots__/Code.component.test.js.snap
+++ /dev/null
@@ -1,74 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Code field should render ace-editor in FieldTemplate 1`] = `
-
-
-
-`;
diff --git a/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.component.js b/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.component.js
index 833e700b4d..a71d178db9 100644
--- a/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.component.js
+++ b/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.component.js
@@ -1,51 +1,62 @@
import React from 'react';
import PropTypes from 'prop-types';
-import TextareaWidget from 'react-jsonschema-form/lib/components/widgets/TextareaWidget';
+import assetsApi from '@talend/assets-api';
+import { Skeleton } from '@talend/react-components';
-let CodeWidget; // eslint-disable-line import/no-mutable-exports
+const ReactAce = React.lazy(() =>
+ assetsApi.getUMD('react-ace').then(mod => assetsApi.toDefaultModule(mod.default)),
+);
-try {
- // eslint-disable-next-line import/no-extraneous-dependencies, global-require
- const AceEditor = require('react-ace').default;
+function CodeSkeleton() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+const SET_OPTIONS = {
+ enableBasicAutocompletion: true,
+ enableLiveAutocompletion: true,
+ enableSnippets: true,
+};
- const SET_OPTIONS = {
- enableBasicAutocompletion: true,
- enableLiveAutocompletion: true,
- enableSnippets: true,
- };
+class AceCodeWidget extends React.Component {
+ static displayName = 'AceCodeWidget';
- class AceCodeWidget extends React.Component {
- static displayName = 'AceCodeWidget';
+ constructor(props) {
+ super(props);
+ this.onChange = this.onChange.bind(this);
+ this.onLoad = this.onLoad.bind(this);
+ }
- constructor(props) {
- super(props);
- this.onChange = this.onChange.bind(this);
- this.onLoad = this.onLoad.bind(this);
+ onChange(value) {
+ if (this.props.onChange) {
+ this.props.onChange(value);
}
+ }
- onChange(value) {
- if (this.props.onChange) {
- this.props.onChange(value);
- }
+ onLoad(event) {
+ if (this.props.formContext.codeWidgetOnLoad) {
+ this.props.formContext.codeWidgetOnLoad(event.env.editor);
}
+ }
- onLoad(event) {
- if (this.props.formContext.codeWidgetOnLoad) {
- this.props.formContext.codeWidgetOnLoad(event.env.editor);
- }
+ render() {
+ const { id, options, value, disabled, readonly, autofocus } = this.props;
+ // allow override using
+ const contextProps = this.props.formContext && this.props.formContext.codeWidgetProps;
+ let setOptions = SET_OPTIONS;
+ if (contextProps && contextProps.setOptions) {
+ setOptions = { ...SET_OPTIONS, ...contextProps.setOptions };
+ delete contextProps.setOptions;
}
-
- render() {
- const { id, options, value, disabled, readonly, autofocus } = this.props;
- // allow override using
- const contextProps = this.props.formContext && this.props.formContext.codeWidgetProps;
- let setOptions = SET_OPTIONS;
- if (contextProps && contextProps.setOptions) {
- setOptions = { ...SET_OPTIONS, ...contextProps.setOptions };
- delete contextProps.setOptions;
- }
- return (
- }>
+
- );
- }
- }
-
- if (process.env.NODE_ENV !== 'production') {
- AceCodeWidget.propTypes = {
- onChange: PropTypes.func,
- formContext: PropTypes.shape({
- codeWidgetProps: PropTypes.object,
- codeWidgetOnLoad: PropTypes.func,
- }),
- id: PropTypes.string,
- options: PropTypes.shape({
- language: PropTypes.string,
- }),
- value: PropTypes.string,
- disabled: PropTypes.bool,
- readonly: PropTypes.bool,
- autofocus: PropTypes.bool,
- };
+
+ );
}
+}
- CodeWidget = AceCodeWidget;
-} catch (error) {
- // Fallback to TextareaWidget
- // eslint-disable-next-line react/no-multi-comp
- class TextareaCodeWidget extends React.PureComponent {
- constructor() {
- super();
- // eslint-disable-next-line no-console
- console.warn('CodeWidget react-ace not found, fallback to TextareaWidget', TextareaWidget);
- }
-
- render() {
- return ;
- }
- }
-
- TextareaCodeWidget.displayName = 'TextareaCodeWidget';
-
- CodeWidget = TextareaWidget;
+if (process.env.NODE_ENV !== 'production') {
+ AceCodeWidget.propTypes = {
+ onChange: PropTypes.func,
+ formContext: PropTypes.shape({
+ codeWidgetProps: PropTypes.object,
+ codeWidgetOnLoad: PropTypes.func,
+ }),
+ id: PropTypes.string,
+ options: PropTypes.shape({
+ language: PropTypes.string,
+ }),
+ value: PropTypes.string,
+ disabled: PropTypes.bool,
+ readonly: PropTypes.bool,
+ autofocus: PropTypes.bool,
+ };
}
-export default CodeWidget;
+export default AceCodeWidget;
diff --git a/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.test.js b/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.test.js
index acad621959..7ef7afa37e 100644
--- a/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.test.js
+++ b/packages/forms/src/deprecated/widgets/CodeWidget/CodeWidget.test.js
@@ -1,36 +1,37 @@
import React from 'react';
-import { shallow, mount } from 'enzyme';
-
+import ReactDOM from 'react-dom';
+import { render, waitFor } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import ReactAce from 'react-ace';
import CodeWidget from './CodeWidget.component';
+jest.mock('ally.js');
+
describe('CodeWidget', () => {
it('should be AceCodeWidget', () => {
expect(CodeWidget.displayName).toBe('AceCodeWidget');
});
- it('should render ReactAce', () => {
- const wrapper = shallow();
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-
- it('should check config props', () => {
- const wrapper = shallow();
- expect(wrapper.props().height).toEqual('250px');
- });
-
- it('should support formContext.codeWidgetProps customization', () => {
- const formContext = {
- codeWidgetProps: { foo: 'bar' },
- };
- const wrapper = shallow();
- expect(wrapper.props().foo).toBe('bar');
- });
-
- it('should call formContext.codeWidgetOnLoad', () => {
+ it('should render ReactAce', async () => {
+ window.React = React;
+ window.ReactDOM = ReactDOM;
+ window.ReactAce = { default: ReactAce };
const formContext = {
codeWidgetOnLoad: jest.fn(),
};
- mount();
- expect(formContext.codeWidgetOnLoad).toHaveBeenCalled();
+ const wrapper = render();
+ await waitFor(
+ () =>
+ new Promise(resolve => {
+ setTimeout(() => {
+ resolve(true);
+ }, 200);
+ }),
+ { timeout: 300 },
+ );
+ // eslint-disable-next-line testing-library/no-container
+ const input = wrapper.container.querySelector('textarea');
+ expect(input).toBeInTheDocument();
+ expect(input.tagName).toBe('TEXTAREA');
});
});
diff --git a/packages/forms/src/deprecated/widgets/CodeWidget/__snapshots__/CodeWidget.test.js.snap b/packages/forms/src/deprecated/widgets/CodeWidget/__snapshots__/CodeWidget.test.js.snap
deleted file mode 100644
index 727660c500..0000000000
--- a/packages/forms/src/deprecated/widgets/CodeWidget/__snapshots__/CodeWidget.test.js.snap
+++ /dev/null
@@ -1,48 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`CodeWidget should render ReactAce 1`] = `
-
-`;
diff --git a/packages/playground/src/app/components/DataGrid.js b/packages/playground/src/app/components/DataGrid.js
index 93996fd4c3..0243e068cf 100644
--- a/packages/playground/src/app/components/DataGrid.js
+++ b/packages/playground/src/app/components/DataGrid.js
@@ -1,3 +1,5 @@
+import React from 'react';
+// eslint-disable-next-line @talend/import-depth
import data from '@talend/react-datagrid/stories/sample.json';
import DataGrid from '@talend/react-datagrid';
import Layout from '@talend/react-components/lib/Layout';
diff --git a/packages/playground/src/app/components/Dataviz.js b/packages/playground/src/app/components/Dataviz.js
index dde8b4538d..4c40fc16df 100644
--- a/packages/playground/src/app/components/Dataviz.js
+++ b/packages/playground/src/app/components/Dataviz.js
@@ -7,6 +7,7 @@ import {
TooltipContent,
ValueType,
} from '@talend/react-dataviz';
+import { ErrorBoundary } from '@talend/react-cmf';
import Layout from '@talend/react-components/lib/Layout';
import SidePanel from '@talend/react-containers/lib/SidePanel';
import HeaderBar from '@talend/react-containers/lib/HeaderBar';
@@ -59,14 +60,18 @@ export function Dataviz() {
/>
- (
-
- )}
- />
+
+ (
+
+ )}
+ />
+
);
diff --git a/packages/playground/src/app/i18n.js b/packages/playground/src/app/i18n.js
index 1145dfa6cc..867d585299 100644
--- a/packages/playground/src/app/i18n.js
+++ b/packages/playground/src/app/i18n.js
@@ -3,18 +3,27 @@
import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import HttpApi from 'i18next-http-backend';
+import assetsApi from '@talend/assets-api';
import { namespaces as tuiComponentsNamespaces } from '@talend/locales-tui-components/namespaces';
import { namespaces as tuiContainersNamespaces } from '@talend/locales-tui-containers/namespaces';
import { namespaces as tuiDatagridNamespaces } from '@talend/locales-tui-datagrid/namespaces';
import { namespaces as tuiFormsNamespaces } from '@talend/locales-tui-forms/namespaces';
const LOCALES_MAP = {
- 'tui-components': 'https://unpkg.com/@talend/locales-tui-components/locales/{{lng}}/{{ns}}.json',
- 'tui-containers': 'https://unpkg.com/@talend/locales-tui-containers/locales/{{lng}}/{{ns}}.json',
- 'tui-forms': 'https://unpkg.com/@talend/locales-tui-forms/locales/{{lng}}/{{ns}}.json',
- 'tui-datagrid': 'https://unpkg.com/@talend/locales-tui-datagrid/locales/{{lng}}/{{ns}}.json',
- 'tui-faceted-search':
- 'https://unpkg.com/@talend/locales-tui-faceted-search/locales/{{lng}}/{{ns}}.json',
+ 'tui-components': assetsApi.getURL(
+ '/locales/{{lng}}/{{ns}}.json',
+ '@talend/locales-tui-components',
+ ),
+ 'tui-containers': assetsApi.getURL(
+ '/locales/{{lng}}/{{ns}}.json',
+ '@talend/locales-tui-containers',
+ ),
+ 'tui-forms': assetsApi.getURL('/locales/{{lng}}/{{ns}}.json', '@talend/locales-tui-forms'),
+ 'tui-datagrid': assetsApi.getURL('/locales/{{lng}}/{{ns}}.json', '@talend/locales-tui-datagrid'),
+ 'tui-faceted-search': assetsApi.getURL(
+ '/locales/{{lng}}/{{ns}}.json',
+ '@talend/locales-tui-faceted-search',
+ ),
};
function loadPath(languages, namespaces) {
diff --git a/packages/playground/src/assets/inject.js b/packages/playground/src/assets/inject.js
index 2c3abf8c87..7017036cba 100644
--- a/packages/playground/src/assets/inject.js
+++ b/packages/playground/src/assets/inject.js
@@ -1,21 +1,42 @@
// custom inject to UMD from surge and the others from unpkg
+// eslint-disable-next-line func-names
(function () {
const CDN_URL_REGEX = /^(\/?.*\/cdn)\//;
+ function removeIntegrity(info) {
+ if (info.name && info.name.startsWith('@talend')) {
+ // eslint-disable-next-line no-param-reassign
+ delete info.integrity;
+ }
+ return info;
+ }
function prepareUrl(url) {
let newUrl;
const m = CDN_URL_REGEX.exec(url);
if (m !== null) {
// return base ? url.slice(1) : url;
-
if (!url.includes('/cdn/@talend')) {
newUrl = url.replace(m[1], 'https://statics.cloud.talend.com');
}
}
return newUrl || url;
}
+ window.Talend.CDN_URL = 'https://statics.cloud.talend.com';
- window.talendAddStyles(window.cssFiles, prepareUrl);
- window.talendAddScripts(window.jsFiles, prepareUrl);
+ // let's override the assets-api's getCDNUrl to serve local package
+ window.Talend.getCDNUrl = function getCDNUrl(pkg = {}) {
+ // if local to the repository load from /cdn
+ if (['@talend/react-dataviz', '@talend/icons'].includes(pkg.name)) {
+ const baseTag = document.querySelector('base');
+ if (baseTag) {
+ const root = baseTag.getAttribute('href') || '';
+ return `${root}/cdn/${pkg.name}/${pkg.version}${pkg.path}`;
+ }
+ return `/cdn/${pkg.name}/${pkg.version}${pkg.path}`;
+ }
+ return `${window.Talend.CDN_URL}/${pkg.name}/${pkg.version}${pkg.path}`;
+ };
+ window.talendAddStyles(window.Talend.cssBuild.map(removeIntegrity), prepareUrl);
+ window.talendAddScripts(window.Talend.build.map(removeIntegrity), prepareUrl);
})();
diff --git a/packages/playground/webpack.config.dev.js b/packages/playground/webpack.config.dev.js
index a8fd673488..ea672a25d5 100644
--- a/packages/playground/webpack.config.dev.js
+++ b/packages/playground/webpack.config.dev.js
@@ -17,6 +17,7 @@ const mockBackend = require('./mockBackend/server');
function getPath(pkg) {
const pkgPath = resolve(pkg, { cwd: process.cwd() });
return pkgPath
+ .replace('main.js', '')
.replace('lib/index.js', '')
.replace('dist/bootstrap.js', '')
.replace('dist/TalendIcons.js', '');
@@ -29,6 +30,7 @@ function getVersion(pkg) {
const PKGS = [
'@talend/design-tokens',
'@talend/design-system',
+ '@talend/design-tokens',
'@talend/react-components',
'@talend/react-containers',
'@talend/react-cmf',
diff --git a/packages/stepper/package.json b/packages/stepper/package.json
index 6d8190a775..ca864a9476 100644
--- a/packages/stepper/package.json
+++ b/packages/stepper/package.json
@@ -9,7 +9,7 @@
"build:prod": "talend-scripts build:lib:umd --prod",
"pre-release": "yarn build:dev && yarn build:prod",
"build:lib": "talend-scripts build:lib",
- "test": "cross-env TZ=Europe/Paris talend-scripts test --silent",
+ "test": "cross-env TZ=Europe/Paris talend-scripts test",
"test:noisy": "cross-env TZ=Europe/Paris talend-scripts test",
"test:watch": "cross-env TZ=Europe/Paris talend-scripts test --watch",
"test:cov": "cross-env TZ=Europe/Paris talend-scripts test --coverage",
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 337f8712f0..30dde39279 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -13,7 +13,7 @@
"scripts": {
"build:lib": "talend-scripts build:ts:lib",
"lint:es": "talend-scripts lint:es --format json -o eslint-report.json",
- "test": "cross-env TZ=Europe/Paris talend-scripts test --silent",
+ "test": "cross-env TZ=Europe/Paris talend-scripts test",
"test:cov": "cross-env TZ=Europe/Paris talend-scripts test --coverage --silent",
"test:noisy": "cross-env TZ=Europe/Paris talend-scripts test",
"test:watch": "cross-env TZ=Europe/Paris talend-scripts test --watch",
diff --git a/tools/scripts-config-react-webpack/src/inject.js b/tools/scripts-config-react-webpack/src/inject.js
index 7181bd273d..4e459b76c0 100644
--- a/tools/scripts-config-react-webpack/src/inject.js
+++ b/tools/scripts-config-react-webpack/src/inject.js
@@ -1,3 +1,4 @@
+// eslint-disable-next-line func-names
(function () {
const jsFiles = window.jsFiles || [];
const cssFiles = window.cssFiles || [];
@@ -61,4 +62,5 @@
talendAddScripts(jsFiles, prepareUrl);
}
});
+ window.Talend.CDN_URL = '/cdn';
})();