From e5cb63218faac80c0bcdf87e72cbed4dff6f59a1 Mon Sep 17 00:00:00 2001 From: enzo707 Date: Tue, 19 Nov 2024 17:12:02 -0300 Subject: [PATCH] refactor: migrate UITests to RTL --- .mocharc.json | 12 + TestResults/MochaReport.xml | 143 +++++++++ __tests__/UITests.tsx | 433 ++++++++++----------------- __tests__/data/mock-data.ts | 77 +++++ jest.config.ts | 43 +++ package-lock.json | 530 +++++++++++++++++++++++++++++++-- package.json | 42 +-- setupTests.ts | 5 + src/components/LibraryItem.tsx | 15 +- tsconfig.json | 4 +- 10 files changed, 966 insertions(+), 338 deletions(-) create mode 100644 .mocharc.json create mode 100644 TestResults/MochaReport.xml create mode 100644 __tests__/data/mock-data.ts create mode 100644 jest.config.ts create mode 100644 setupTests.ts diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 00000000..d368cf57 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,12 @@ +{ + "require": [ + "ts-node/register" + ], + "spec": "__tests__/mochatest/**/*.{ts,tsx}", + "timeout": 5000, + "extensions": ["ts", "tsx"], + "reporter": "mocha-junit-reporter", + "reporter-option": [ + "mochaFile=./TestResults/MochaReport.xml" + ] +} \ No newline at end of file diff --git a/TestResults/MochaReport.xml b/TestResults/MochaReport.xml new file mode 100644 index 00000000..50aa9b29 --- /dev/null +++ b/TestResults/MochaReport.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/__tests__/UITests.tsx b/__tests__/UITests.tsx index 7ebbd312..0d6b6ff2 100644 --- a/__tests__/UITests.tsx +++ b/__tests__/UITests.tsx @@ -1,303 +1,196 @@ -/** - * @jest-environment jsdom - */ - import * as React from 'react'; -import { mount, configure } from 'enzyme'; +import '@testing-library/jest-dom'; import * as LibraryEntryPoint from '../src/entry-point'; import { LibraryItem } from '../src/components/LibraryItem'; import { ItemData } from "../src/LibraryUtilities"; import { createLibraryItem } from "../src/utils"; -import * as Adapter from 'enzyme-adapter-react-16'; -import { expect } from 'chai'; +import { expect as expectChai} from 'chai'; import { LibraryContainer } from '../src/components/LibraryContainer'; +import { screen, fireEvent, render, waitFor } from '@testing-library/react'; +import * as data from './data/mock-data'; -configure({adapter: new Adapter()}); describe("LibraryContainer UI", function () { - let loadedTypesJson: any; - let layoutSpecsJson: any; let libController: LibraryEntryPoint.LibraryController; let libContainer: any; + let onLibraryItemClickSpy: jest.SpyInstance; beforeEach(function () { - loadedTypesJson = { - "loadedTypes": [ - { - "fullyQualifiedName": "Child1", - "iconUrl": "", - "contextData": "Input", - "itemType": "action", - "description": "First item", - "keywords": "" - }, - { - "fullyQualifiedName": "Child2", - "iconUrl": "", - "contextData": "", - "itemType": "action", - "description": "Second item", - "keywords": "" - }, - { - "fullyQualifiedName": "pkg://Clockwork.Core.Math.+1", - "iconUrl": "/src/resources/icons/ba8cd7c7-346a-45c6-857e-e47800b80818.png", - "contextData": "+1", - "parameters": null, - "itemType": "action", - "keywords": "", - "weight": 0, - "description": null - }, - ] - }; - - layoutSpecsJson = { - "sections": [ - { - "text": "default", - "iconUrl": "", - "elementType": "section", - "showHeader": false, - "include": [], - "childElements": [ - { - "text": "Parent", - "iconUrl": "", - "elementType": "category", - "include": [], - "childElements": [{ - "text": "Core", - "iconUrl": "", - "elementType": "group", - "include": [{"path": "Child1" }, { "path": "Child2" }], - "childElements":[] - }] - } - ] - }, - { - "text": "Miscellaneous", - "iconUrl": "", - "elementType": "section", - "showHeader": true, - "include": [], - "childElements": [] - }, - { - "text": "Add-ons", - "iconUrl": "", - "elementType": "section", - "showHeader": true, - "include": [ - { - "path": "pkg://" - } - ], - "childElements": [] - } - ] - }; + // //replace the onLibraryItemClicked with a mocked method. + onLibraryItemClickSpy = jest.spyOn(LibraryItem.prototype, 'onLibraryItemClicked').mockImplementation(jest.fn()); libController = LibraryEntryPoint.CreateLibraryController(); - libContainer = mount(libController.createLibraryContainer()) + libContainer = render(libController.createLibraryContainer()); + }); + + afterEach(()=> { + // restore spy so it will not interfere with other tests + onLibraryItemClickSpy.mockRestore(); + }) - it("should recognize mouse click event and change expand state", function () { - // Test data to create LibraryItem - // Parent item that will hold the child items + it("should recognize mouse click event and change expand state", async function () { + // // Test data to create LibraryItem + // // Parent item that will hold the child items let data = createLibraryItem(ItemData); - // Mount is "real" rendering that will actually render your component into a browser environment. - // If you are testing full React components, - // mount is used to do rendering and test actions are simulated on mounted html - - let libraryItem = mount(); - - expect(libraryItem).to.have.lengthOf(1); - expect(libraryItem.props().data.childItems).to.have.lengthOf(2); - expect(libraryItem.props().data.text).to.equal("TestItem"); - expect(libraryItem.props().data.showHeader).to.be.true; - expect(libraryItem.props().data.childItems[0].text).to.equal("Child0"); - expect(libraryItem.props().data.childItems[1].text).to.equal("Child1"); - let header = libraryItem.find(('div.LibraryItemHeader')).at(0);// the state of LibraryItem is changed when clicking on header - expect(header).to.have.lengthOf(1); // verify that there is a header - header.simulate('click'); // enzyme function to simulate mouse click - expect(libraryItem.state('expanded')).to.be.true; // check for if the libraryItem is expanded after mouse click + render(); + + await waitFor(()=> { + const header = screen.getByText("TestItem").closest('.LibraryItemHeader'); + if(header) { + fireEvent.click(header); + } + }); + + expect(onLibraryItemClickSpy).toHaveBeenCalled(); }); - it("should raise the onItemWillExpand when expanding", function (done) { - // Test data to create LibraryItem - // Parent item that will hold the child items - let data = createLibraryItem(ItemData); +}); + +describe("", () => { + let libController: LibraryEntryPoint.LibraryController; + let scrollToExpandedItemSpy: jest.SpyInstance; - //pass a callback which if called will end the test - let libraryItem = mount( { done() }} />); + beforeEach(() => { + const layoutSpecsJson = data.layoutSpecsJson; + const loadedTypesJson = data.loadedTypesJson; - let header = libraryItem.find(('div.LibraryItemHeader')).at(0);// the state of LibraryItem is changed when clicking on header - expect(header).to.have.lengthOf(1); // verify that there is a header - header.simulate('click'); // enzyme function to simulate mouse click - expect(libraryItem.state('expanded')).to.be.true; - }); + // //replace the scrollToExpandedItem with a mocked method. + scrollToExpandedItemSpy = jest.spyOn(LibraryContainer.prototype, 'scrollToExpandedItem').mockImplementation(jest.fn()); + + libController = LibraryEntryPoint.CreateLibraryController(); + render(libController.createLibraryContainer()); - describe("", () => { - beforeEach(() => { - libContainer = mount( - libController.createLibraryContainer() - ); - // Load the data to libController - libController.setLoadedTypesJson(loadedTypesJson, false); - libController.setLayoutSpecsJson(layoutSpecsJson, false); - libController.refreshLibraryView(); - libContainer.update(); + // Load the data to libController + libController.setLoadedTypesJson(loadedTypesJson, false); + libController.setLayoutSpecsJson(layoutSpecsJson, false); + libController.refreshLibraryView(); - }) + }) - it("scrollToElement should be called when libraryItem is expanded only", function () { - - let scrolled = false; - let header = libContainer.find('div.LibraryItemHeader').at(0); - expect(header).to.have.lengthOf(1); - - //replace the scroll method with a method which ends the test. - (libContainer.instance() as unknown as LibraryContainer).scrollToExpandedItem = () => { scrolled = !scrolled;} - header.simulate('click'); - expect(scrolled).to.be.true; - - }); - - - it("search a string in library and verify change of state and results", function () { - - // find is used to find a rendered component by css selectors, - // component constructors, display name or property selector. - let text = () => libContainer.find('input.SearchInputText'); - // Set the search text in searchbar - text().simulate('change', { target: { value: 'Child' } }); - expect(text()).to.have.lengthOf(1); - - // Search is triggered after a timeout of 300 milli seconds - // So wait before verifying the results - setTimeout(function () { - // Verify the state 'inSearchMode' is changed - expect(libContainer.state('inSearchMode')).to.be.true; - // Verify the search results are correct - let value = libContainer.find('SearchResultItem'); - expect(value).to.have.lengthOf(2); - expect((value.at(0).props() as any).data.text).to.equal("Child1"); - expect((value.at(1).props() as any).data.text).to.equal("Child2"); - }, 500); - }); - - it("search a negative scenario for search", function () { - - // find is used to find a rendered component by css selectors, - // component constructors, display name or property selector. - let text = () => libContainer.find('input.SearchInputText'); - // Set the search string 'Point' with a node name that does not exist in library - text().simulate('change', { target: { value: 'Point' } }); - expect(text()).to.have.lengthOf(1); - // Search is triggered after a timeout of 300 milli seconds - // So wait before verifying the results - - setTimeout(function () { - // Verify the state 'inSearchMode' is changed - expect(libContainer.state('inSearchMode')).to.be.true; - //let result = libContainer.find('div.LibraryItemContainer'); - // Verify the search does not return any nodes - let value = libContainer.find('SearchResultItem'); - expect(value).to.have.lengthOf(0); - }, 500); + afterEach(()=> { + // restore spy so it will not interfere with other tests + scrollToExpandedItemSpy.mockRestore(); + }) + + it("scrollToElement should be called when libraryItem is expanded only", function () { + let header = screen.getByText(/parent/i); + fireEvent.click(header); + expect(scrollToExpandedItemSpy).toHaveBeenCalled(); + }); + + + it("search a string in library and verify results", async function () { + // Looks for the searchInput element + const input = screen.getByRole('textbox'); + expect(input).toHaveClass('SearchInputText'); + + // Trigger the search + fireEvent.change(input, { target: { value: 'Child1' } }); + + // Looks for the LibraryItem element 'Child1' that should matches with search results + await waitFor(()=> { + expect(screen.queryByText('Child1')).toBeInTheDocument(); }); - - it("change state of searchbar to detail view and verify the search results display item description", function () { - - // Trigger the search so the option for detail view is enabled - let text = () => libContainer.find('input.SearchInputText'); - // Set the search string - text().simulate('change', { target: { value: 'Child' } }); - expect(text()).to.have.lengthOf(1); - // Find the div for Detailed view and click on it - let option = libContainer.find('button.SearchOptionsBtnEnabled'); - let detail = option.find('[title="Compact/Detailed View"]'); - expect(detail).to.have.lengthOf(1); - detail.simulate('click'); - // Verify the detailed view is active - expect(libContainer.state('detailed')).to.be.true; - - setTimeout(function () { // Search has timeout delay so verify results after the search is displayed - // Get the search results - let value = libContainer.find('SearchResultItem'); - expect(value).to.have.lengthOf(2); - expect((value.at(0).props() as any).data.text).to.equal("Child1"); - expect((value.at(1).props()as any).data.text).to.equal("Child2"); - // Make sure the search results has correct item description - let describe = libContainer.find('div.ItemDescription'); - expect(describe).to.have.lengthOf(2); - expect(describe.at(0).text()).to.equal('First item'); - expect(describe.at(1).text()).to.equal('Second item'); - }, 500); + + }); + + it("search a negative scenario for search", async function () { + // Looks for the searchInput element + const input = screen.getByRole('textbox'); + expect(input).toHaveClass('SearchInputText'); + + // Trigger the search so the option for detail view is enabled + fireEvent.change(input, { target: { value: 'Point' } }); + + // Looks for the LibraryItem element 'Point' that should not matches with search results + await waitFor(()=> { + expect(screen.queryByText('Point')).not.toBeInTheDocument(); }); - - it("search bar should not contain structured view button", function () { - - let buttons = libContainer.find('button'); - //detail view, filter. - expect(buttons).to.have.lengthOf(2); - - // Trigger the search so the option for detail view is enabled - let text = () => libContainer.find('input.SearchInputText'); - // Set the search string - text().simulate('change', { target: { value: 'Child' } }); - expect(text()).to.have.lengthOf(1); - // Find the buttons in the search - buttons = libContainer.find('button'); - //detail view, filter, and x button// - expect(buttons).to.have.lengthOf(3); - + + }); + + it("verify the search results display item description after select detailed view", async function () { + + // Trigger the search so the option for detail view is enabled + // Looks for the searchInput element + const input = screen.getByRole('textbox'); + expect(input).toHaveClass('SearchInputText'); + + // Set the search string + fireEvent.change(input, { target: { value: 'Child1' } }); + + // Find the div for Detailed view and click on it + const option = screen.getByTitle('Compact/Detailed View'); + + await waitFor(()=> { + expect(screen.getByText('Child1')); + fireEvent.click(option); + // Make sure the search results has correct item description + expect(screen.getByText('First item')); }); - - it("click item text on search should return to the library item", function () { - - // Trigger the search so the option for detail view is enabled - let text = () => libContainer.find('input.SearchInputText'); - // Set the search string - text().simulate('change', { target: { value: 'Child' } }); - expect(text()).to.have.lengthOf(1); - - // Find the div for Detailed view and click on it - let option = libContainer.find('button.SearchOptionsBtnEnabled'); - let detail = option.find('[title="Compact/Detailed View"]'); - expect(detail).to.have.lengthOf(1); - detail.simulate('click'); - - setTimeout(function () { // Search has timeout delay so verify results after the search is displayed - // Get the search results - let value = libContainer.find('SearchResultItem'); - expect(value).to.have.lengthOf(2); - expect((value.at(0).props() as any).data.text).to.equal("Child1"); - expect((value.at(1).props() as any).data.text).to.equal("Child2"); - - //make the library item expanded to false. - (value.at(0).props() as any).data.pathToItem[0].expanded = false; - - let detials = libContainer.find('div.ItemParent'); - //click the item text - detials.at(0).simulate('click'); - expect((value.at(0).props() as any).data.pathToItem[0].expanded).to.be.true; - }, 500); + + + }); + + it("search bar should not contain structured view button", function () { + + let buttons = screen.queryAllByRole('button'); + + //detail view, filter. + expectChai(buttons).to.have.lengthOf(2); + + // // Trigger the search so the option for detail view is enabled + const input = screen.getByRole('textbox'); + expect(input).toHaveClass('SearchInputText'); + + // // Set the search string + fireEvent.change(input,{ target: { value: 'Child' } }); + + // // Find the buttons in the search + buttons = screen.queryAllByRole('button'); + + // //detail view, filter, and x button// + expectChai(buttons).to.have.lengthOf(3); + + }); + + it("click item text on search should return to the library item", async function () { + + // Trigger the search so the option for detail view is enabled + // Looks for the searchInput element + const input = screen.getByRole('textbox'); + expect(input).toHaveClass('SearchInputText'); + + // Set the search string + fireEvent.change(input, { target: { value: 'Child1' } }); + + + await waitFor(()=> { + // Look for parent selector to be clicked + const detailWrapper = screen.getByText('Child1').closest('.ItemInfo'); + expect(detailWrapper).toBeInTheDocument(); + + const itemParent = detailWrapper?.querySelector('.ItemParent'); + if(itemParent) { + fireEvent.click(itemParent); + } + }); - - it("add-ons should auto expand", function () { - - let generatedSections = libContainer.instance().generatedSections; - expect(generatedSections).to.have.lengthOf(2); - if(!generatedSections) return; - expect(generatedSections[1].text).to.equal("Add-ons"); - expect(generatedSections[1].expanded).to.be.true; - + + await waitFor(()=> { + const header = screen.getByText(/core/i); + const itemGroup = header.closest('.LibraryItemContainerGroup'); + expect(itemGroup).toHaveClass('expanded'); }); - }) -}); + }); + + it("add-ons should auto expand", function () { + const addOns = screen.getByText(/Add-ons/i); + const sectionContainer = addOns.closest('.LibraryItemContainerSection'); + expect(sectionContainer).toHaveClass('expanded'); + }); +}) diff --git a/__tests__/data/mock-data.ts b/__tests__/data/mock-data.ts new file mode 100644 index 00000000..a9608f9e --- /dev/null +++ b/__tests__/data/mock-data.ts @@ -0,0 +1,77 @@ +export const loadedTypesJson: any = { + "loadedTypes": [ + { + "fullyQualifiedName": "Child1", + "iconUrl": "", + "contextData": "Input", + "itemType": "action", + "description": "First item", + "keywords": "" + }, + { + "fullyQualifiedName": "Child2", + "iconUrl": "", + "contextData": "", + "itemType": "action", + "description": "Second item", + "keywords": "" + }, + { + "fullyQualifiedName": "pkg://Clockwork.Core.Math.+1", + "iconUrl": "/src/resources/icons/ba8cd7c7-346a-45c6-857e-e47800b80818.png", + "contextData": "+1", + "parameters": null, + "itemType": "action", + "keywords": "", + "weight": 0, + "description": null + }, + ] +}; + +export const layoutSpecsJson: any = { + "sections": [ + { + "text": "default", + "iconUrl": "", + "elementType": "section", + "showHeader": false, + "include": [], + "childElements": [ + { + "text": "Parent", + "iconUrl": "", + "elementType": "category", + "include": [], + "childElements": [{ + "text": "Core", + "iconUrl": "", + "elementType": "group", + "include": [{"path": "Child1" }, { "path": "Child2" }], + "childElements":[] + }] + } + ] + }, + { + "text": "Miscellaneous", + "iconUrl": "", + "elementType": "section", + "showHeader": true, + "include": [], + "childElements": [] + }, + { + "text": "Add-ons", + "iconUrl": "", + "elementType": "section", + "showHeader": true, + "include": [ + { + "path": "pkg://" + } + ], + "childElements": [] + } + ] +}; \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..31facc65 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,43 @@ +import type { Config } from "jest"; + +const config: Config = { + preset:"ts-jest", + testEnvironment: "jsdom", + transform: { + ".(ts|tsx)": "ts-jest" + }, + testRegex: "(/__tests__/*/.*|\\.(test|spec))\\.(ts|tsx|js)$", + moduleFileExtensions: [ + "ts", + "tsx", + "js", + "json" + ], + moduleNameMapper: { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.ts", + "\\.(css|less)$": "/__mocks__/styleMock.ts" + }, + collectCoverageFrom: [ + "src/**/*.{ts,tsx}" + ], + testPathIgnorePatterns: [ + "__tests__/data/" + ], + snapshotSerializers: [ + "/node_modules/enzyme-to-json/serializer" + ], + reporters: [ + "default", + [ + "jest-junit", + { + "outputDirectory": "TestResults", + "outputName": "TestReport.xml", + "classNameTemplate": "{classname}", + "titleTemplate": "{title}" + } + ] + ] +} + +export default config; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 563b84b0..dc8545ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,9 @@ "version": "1.0.6", "license": "MIT", "dependencies": { + "@testing-library/jest-dom": "^6.6.2", + "@testing-library/react": "^11.2.7", + "@testing-library/user-event": "^12.8.3", "core-js": "^3.36.1", "express": "^4.19.2", "react": "^16.14.0", @@ -51,6 +54,11 @@ "webpack-cli": "^4.10.0" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==" + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -68,7 +76,6 @@ "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" @@ -258,7 +265,6 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -290,7 +296,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -489,6 +494,29 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz", + "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.9.tgz", + "integrity": "sha512-eHeq2HWhgn3aH6Gz4Dnajqp8U5DjBg3h933LlGJ52hAN6Kx34KAL7O3NzwTrldl9PrgKTyBcz0ScVIQ3A6e2fA==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -1507,6 +1535,384 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.2.tgz", + "integrity": "sha512-P6GJD4yqc9jZLbe98j/EkyQDTPgqftohZF5FBkHY5BUERZmcf4HeO2k0XaefEg329ux2p21i1A1DmyQ1kKw2Jw==", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==" + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", + "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^7.28.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@testing-library/react/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "7.31.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", + "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.6", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@testing-library/react/node_modules/@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" + }, + "node_modules/@testing-library/react/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@testing-library/react/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dependencies": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@testing-library/react/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@testing-library/react/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@testing-library/react/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/@testing-library/react/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/user-event": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", + "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -1548,6 +1954,12 @@ "optional": true, "peer": true }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "peer": true + }, "node_modules/@types/babel__core": { "version": "7.20.1", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", @@ -1672,14 +2084,12 @@ "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -1688,7 +2098,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } @@ -1723,8 +2132,7 @@ "node_modules/@types/node": { "version": "7.10.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.14.tgz", - "integrity": "sha512-29GS75BE8asnTno3yB6ubOJOO0FboExEqNJy4bpz0GSmW/8wPTNL4h9h63c6s1uTrOopCmJYe/4yJLh5r92ZUA==", - "dev": true + "integrity": "sha512-29GS75BE8asnTno3yB6ubOJOO0FboExEqNJy4bpz0GSmW/8wPTNL4h9h63c6s1uTrOopCmJYe/4yJLh5r92ZUA==" }, "node_modules/@types/prop-types": { "version": "15.7.5", @@ -1803,8 +2211,7 @@ "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", @@ -2170,7 +2577,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2179,7 +2585,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -2215,6 +2620,14 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", @@ -2735,7 +3148,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -2940,7 +3352,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -2948,8 +3359,7 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { "version": "2.0.20", @@ -3029,6 +3439,16 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-js-pure": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", + "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -3154,6 +3574,11 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -3338,6 +3763,14 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -3380,6 +3813,11 @@ "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", "dev": true }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -3827,7 +4265,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -4528,7 +4965,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -4753,6 +5189,14 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7011,8 +7455,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -7170,6 +7613,14 @@ "yallist": "^3.0.2" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -7339,6 +7790,14 @@ "node": ">=6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -8576,12 +9035,29 @@ "node": ">= 0.10" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reflect.ownkeys": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==", "dev": true }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", @@ -9215,6 +9691,17 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9258,7 +9745,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, diff --git a/package.json b/package.json index 528a9b02..3719b3f9 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "jest --coverage", - "utiltest": "mocha -r ts-node/register __tests__/mochatest/libraryUtilitiesTest.ts --reporter mocha-junit-reporter --reporter-options mochaFile=./TestResults/MochaReport.xml", + "utiltest": "npx mocha", "dev": "cross-env NODE_ENV=development webpack", "build": "cross-env NODE_ENV=production --mode=development webpack", "bundle": "cross-env NODE_ENV=production --mode=production webpack", @@ -23,6 +23,9 @@ "author": "Dynamo Team", "license": "MIT", "dependencies": { + "@testing-library/jest-dom": "^6.6.2", + "@testing-library/react": "^11.2.7", + "@testing-library/user-event": "^12.8.3", "core-js": "^3.36.1", "express": "^4.19.2", "react": "^16.14.0", @@ -66,42 +69,5 @@ }, "overrides": { "node-notifier": "^10.0.0" - }, - "jest": { - "transform": { - ".(ts|tsx)": "ts-jest" - }, - "testRegex": "(/__tests__/*/.*|\\.(test|spec))\\.(ts|tsx|js)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "json" - ], - "moduleNameMapper": { - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.ts", - "\\.(css|less)$": "/__mocks__/styleMock.ts" - }, - "collectCoverageFrom": [ - "src/**/*.{ts,tsx}" - ], - "testPathIgnorePatterns": [ - "__tests__/data/" - ], - "snapshotSerializers": [ - "/node_modules/enzyme-to-json/serializer" - ], - "reporters": [ - "default", - [ - "jest-junit", - { - "outputDirectory": "TestResults", - "outputName": "TestReport.xml", - "classNameTemplate": "{classname}", - "titleTemplate": "{title}" - } - ] - ] } } diff --git a/setupTests.ts b/setupTests.ts new file mode 100644 index 00000000..3d97e2df --- /dev/null +++ b/setupTests.ts @@ -0,0 +1,5 @@ +import "@testing-library/jest-dom" + +// // declare var global: any; +// import { expect } from 'chai'; +// // global.expect = expect; \ No newline at end of file diff --git a/src/components/LibraryItem.tsx b/src/components/LibraryItem.tsx index 110af0ad..13b781b2 100644 --- a/src/components/LibraryItem.tsx +++ b/src/components/LibraryItem.tsx @@ -28,7 +28,7 @@ export interface LibraryItemProps { libraryContainer: LibraryContainer, data: LibraryUtilities.ItemData, showItemSummary: boolean, - onItemWillExpand?: Function, + onItemWillExpand?: (args: any) => void, tooltipContent?: any } @@ -110,12 +110,12 @@ export class LibraryItem extends React.Component { return item.expanded == true; }); - if (isThereChildItemsToExpand.length == 0) { - setTimeout(() => { - let elem = ReactDOM.findDOMNode(this); - elem.scrollIntoView(false); - }, 0); - } + // if (isThereChildItemsToExpand.length == 0) { + // setTimeout(() => { + // let elem = ReactDOM.findDOMNode(this); + // elem.scrollIntoView(false); + // }, 0); + // } } } @@ -412,6 +412,7 @@ export class LibraryItem extends React.Component