From df6a8cd03161ce418594a6f8b2962bdbedfd339e Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Wed, 1 Jul 2020 08:58:40 -0700 Subject: [PATCH] Provide initial plugin test infra for plugin devs Summary: This sets up the initial infra that is to be used by plugin devs to test plugins. There is not much yet to see, as there is no state or message sending yet. But at least the life cycle of plugins can be test, things are strongly typed and everything is in the place where it should be :) N.b. the import difference with these utils and the createFlipperMock utilities in Flipper are 1. this testing infra is entirely inside flipper-plugin package, so that plugin devs don't need flipper as a dependency 2. this testing infra doesn't provide abstractions for plugin / device / client switching; it tests plugins purely in isolation of the rest of the world (except for firing `onConnect` / `onDisconnect` which is normally the effect of switching plugins) Reviewed By: nikoant Differential Revision: D22255262 fbshipit-source-id: b94ccbab720d2b49428a646aed3c55af71a5bc80 --- desktop/app/src/Client.tsx | 2 +- .../src/__tests__/PluginContainer.node.tsx | 17 +-- .../dispatcher/__tests__/SandyTestPlugin.tsx | 24 ---- .../src/dispatcher/__tests__/plugins.node.tsx | 5 +- .../reducers/__tests__/sandyplugins.node.tsx | 10 +- .../createMockFlipperWithPlugin.tsx | 19 --- desktop/flipper-plugin/package.json | 4 +- .../src/__tests__/TestPlugin.tsx | 45 ++++++ .../src/__tests__/test-utils.node.tsx | 61 +++++++++ desktop/flipper-plugin/src/index.ts | 16 ++- desktop/flipper-plugin/src/plugin/Plugin.tsx | 16 ++- .../src/plugin/SandyPluginDefinition.tsx | 12 +- .../src/test-utils/test-utils.tsx | 129 ++++++++++++++++++ desktop/yarn.lock | 46 +++++++ 14 files changed, 336 insertions(+), 70 deletions(-) delete mode 100644 desktop/app/src/dispatcher/__tests__/SandyTestPlugin.tsx create mode 100644 desktop/flipper-plugin/src/__tests__/TestPlugin.tsx create mode 100644 desktop/flipper-plugin/src/__tests__/test-utils.node.tsx create mode 100644 desktop/flipper-plugin/src/test-utils/test-utils.tsx diff --git a/desktop/app/src/Client.tsx b/desktop/app/src/Client.tsx index dfccf9126..6883c3925 100644 --- a/desktop/app/src/Client.tsx +++ b/desktop/app/src/Client.tsx @@ -274,7 +274,7 @@ export default class Client extends EventEmitter { async init() { this.setMatchingDevice(); await this.loadPlugins(); - // this starts all sandy enabled plugin + // this starts all sandy enabled plugins this.plugins.forEach((pluginId) => this.startPluginIfNeeded(this.getPlugin(pluginId)), ); diff --git a/desktop/app/src/__tests__/PluginContainer.node.tsx b/desktop/app/src/__tests__/PluginContainer.node.tsx index 4317ea481..8a63baa94 100644 --- a/desktop/app/src/__tests__/PluginContainer.node.tsx +++ b/desktop/app/src/__tests__/PluginContainer.node.tsx @@ -10,14 +10,12 @@ import React, {useContext} from 'react'; import produce from 'immer'; import {FlipperPlugin} from '../plugin'; -import { - renderMockFlipperWithPlugin, - createMockPluginDetails, -} from '../test-utils/createMockFlipperWithPlugin'; +import {renderMockFlipperWithPlugin} from '../test-utils/createMockFlipperWithPlugin'; import { SandyPluginContext, SandyPluginDefinition, FlipperClient, + TestUtils, } from 'flipper-plugin'; import {selectPlugin} from '../reducers/connections'; @@ -107,10 +105,13 @@ test('PluginContainer can render Sandy plugins', async () => { return {connectedStub, disconnectedStub}; }; - const definition = new SandyPluginDefinition(createMockPluginDetails(), { - plugin, - Component: MySandyPlugin, - }); + const definition = new SandyPluginDefinition( + TestUtils.createMockPluginDetails(), + { + plugin, + Component: MySandyPlugin, + }, + ); // any cast because this plugin is not enriched with the meta data that the plugin loader // normally adds. Our further sandy plugin test infra won't need this, but // for this test we do need to act a s a loaded plugin, to make sure PluginContainer itself can handle it diff --git a/desktop/app/src/dispatcher/__tests__/SandyTestPlugin.tsx b/desktop/app/src/dispatcher/__tests__/SandyTestPlugin.tsx deleted file mode 100644 index ec286894e..000000000 --- a/desktop/app/src/dispatcher/__tests__/SandyTestPlugin.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import * as React from 'react'; - -import {FlipperClient} from 'flipper-plugin'; - -type Events = { - inc: {delta: number}; -}; - -export function plugin(_client: FlipperClient) { - return {}; -} - -export function Component() { - return

Sandy high fives Flipper

; -} diff --git a/desktop/app/src/dispatcher/__tests__/plugins.node.tsx b/desktop/app/src/dispatcher/__tests__/plugins.node.tsx index 7e08f099a..2e0ca0c12 100644 --- a/desktop/app/src/dispatcher/__tests__/plugins.node.tsx +++ b/desktop/app/src/dispatcher/__tests__/plugins.node.tsx @@ -243,7 +243,10 @@ test('requirePlugin loads valid Sandy plugin', () => { const plugin = requireFn({ ...samplePluginDetails, name, - entry: path.join(__dirname, 'SandyTestPlugin'), + entry: path.join( + __dirname, + '../../../../flipper-plugin/src/__tests__/TestPlugin', + ), version: '1.0.0', flipperSDKVersion: '0.0.0', }) as SandyPluginDefinition; diff --git a/desktop/app/src/reducers/__tests__/sandyplugins.node.tsx b/desktop/app/src/reducers/__tests__/sandyplugins.node.tsx index f6ed69feb..e0bcba23f 100644 --- a/desktop/app/src/reducers/__tests__/sandyplugins.node.tsx +++ b/desktop/app/src/reducers/__tests__/sandyplugins.node.tsx @@ -7,10 +7,7 @@ * @format */ -import { - createMockFlipperWithPlugin, - createMockPluginDetails, -} from '../../test-utils/createMockFlipperWithPlugin'; +import {createMockFlipperWithPlugin} from '../../test-utils/createMockFlipperWithPlugin'; import {Store, Client} from '../../'; import {selectPlugin, starPlugin} from '../../reducers/connections'; import {registerPlugins} from '../../reducers/plugins'; @@ -18,13 +15,14 @@ import { SandyPluginDefinition, SandyPluginInstance, FlipperClient, + TestUtils, } from 'flipper-plugin'; interface PersistedState { count: 1; } -const pluginDetails = createMockPluginDetails(); +const pluginDetails = TestUtils.createMockPluginDetails(); let initialized = false; @@ -133,7 +131,7 @@ test('it should not initialize a sandy plugin if not enabled', async () => { const {client, store} = await createMockFlipperWithPlugin(TestPlugin); const Plugin2 = new SandyPluginDefinition( - createMockPluginDetails({ + TestUtils.createMockPluginDetails({ name: 'Plugin2', id: 'Plugin2', }), diff --git a/desktop/app/src/test-utils/createMockFlipperWithPlugin.tsx b/desktop/app/src/test-utils/createMockFlipperWithPlugin.tsx index ecbe07d11..f22be1d7f 100644 --- a/desktop/app/src/test-utils/createMockFlipperWithPlugin.tsx +++ b/desktop/app/src/test-utils/createMockFlipperWithPlugin.tsx @@ -34,7 +34,6 @@ import {registerPlugins} from '../reducers/plugins'; import PluginContainer from '../PluginContainer'; import {getPluginKey} from '../utils/pluginUtils'; import {getInstance} from '../fb-stubs/Logger'; -import {PluginDetails} from 'flipper-plugin-lib'; type MockFlipperResult = { client: Client; @@ -235,21 +234,3 @@ export async function renderMockFlipperWithPlugin( }, }; } - -export function createMockPluginDetails( - details?: Partial, -): PluginDetails { - return { - id: 'TestPlugin', - dir: '', - name: 'TestPlugin', - specVersion: 0, - entry: '', - isDefault: false, - main: '', - source: '', - title: 'Testing Plugin', - version: '', - ...details, - }; -} diff --git a/desktop/flipper-plugin/package.json b/desktop/flipper-plugin/package.json index 4d1e75af4..e2f1038e5 100644 --- a/desktop/flipper-plugin/package.json +++ b/desktop/flipper-plugin/package.json @@ -8,7 +8,9 @@ "types": "lib/index.d.ts", "license": "MIT", "bugs": "https://github.com/facebook/flipper/issues", - "dependencies": {}, + "dependencies": { + "@testing-library/react": "^10.4.3" + }, "devDependencies": { "typescript": "^3.9.2" }, diff --git a/desktop/flipper-plugin/src/__tests__/TestPlugin.tsx b/desktop/flipper-plugin/src/__tests__/TestPlugin.tsx new file mode 100644 index 000000000..5b74d7f38 --- /dev/null +++ b/desktop/flipper-plugin/src/__tests__/TestPlugin.tsx @@ -0,0 +1,45 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import * as React from 'react'; +import {FlipperClient} from '../plugin/Plugin'; + +type Events = { + inc: { + delta: number; + }; +}; + +type Methods = { + currentState(): Promise; +}; + +export function plugin(client: FlipperClient) { + const connectStub = jest.fn(); + const disconnectStub = jest.fn(); + const destroyStub = jest.fn(); + + // TODO: add tests for sending and receiving data T68683442 + // including typescript assertions + + client.onConnect(connectStub); + client.onDisconnect(disconnectStub); + client.onDestroy(destroyStub); + + return { + connectStub, + destroyStub, + disconnectStub, + }; +} + +export function Component() { + // TODO T69105011 add test for usePlugin including type assertions + return

Hi from test plugin

; +} diff --git a/desktop/flipper-plugin/src/__tests__/test-utils.node.tsx b/desktop/flipper-plugin/src/__tests__/test-utils.node.tsx new file mode 100644 index 000000000..8076bb42a --- /dev/null +++ b/desktop/flipper-plugin/src/__tests__/test-utils.node.tsx @@ -0,0 +1,61 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import * as TestUtils from '../test-utils/test-utils'; + +import * as testPlugin from './TestPlugin'; + +test('it can start a plugin and lifecycle events', () => { + const {instance, ...p} = TestUtils.startPlugin(testPlugin); + + // TODO T69105011 @ts-expect-error + // p.bla; + + // startPlugin starts connected + expect(instance.connectStub).toBeCalledTimes(1); + expect(instance.disconnectStub).toBeCalledTimes(0); + expect(instance.destroyStub).toBeCalledTimes(0); + + p.connect(); // noop + expect(instance.connectStub).toBeCalledTimes(1); + expect(instance.disconnectStub).toBeCalledTimes(0); + expect(instance.destroyStub).toBeCalledTimes(0); + + p.disconnect(); + p.connect(); + + expect(instance.connectStub).toBeCalledTimes(2); + expect(instance.disconnectStub).toBeCalledTimes(1); + expect(instance.destroyStub).toBeCalledTimes(0); + + p.destroy(); + expect(instance.connectStub).toBeCalledTimes(2); + expect(instance.disconnectStub).toBeCalledTimes(2); + expect(instance.destroyStub).toBeCalledTimes(1); + + // cannot interact with destroyed plugin + expect(() => { + p.connect(); + }).toThrowErrorMatchingInlineSnapshot(`"Plugin has been destroyed already"`); +}); + +test('it can render a plugin', () => { + const {renderer} = TestUtils.renderPlugin(testPlugin); + + expect(renderer.baseElement).toMatchInlineSnapshot(` + +
+

+ Hi from test plugin +

+
+ + `); + // TODO: test sending updates T68683442 +}); diff --git a/desktop/flipper-plugin/src/index.ts b/desktop/flipper-plugin/src/index.ts index c1d1a1d46..d6d6ad9c9 100644 --- a/desktop/flipper-plugin/src/index.ts +++ b/desktop/flipper-plugin/src/index.ts @@ -7,7 +7,15 @@ * @format */ -export * from './plugin/Plugin'; -export * from './plugin/SandyPluginDefinition'; -export * from './plugin/PluginRenderer'; -export * from './plugin/PluginContext'; +import * as TestUtilites from './test-utils/test-utils'; + +export {SandyPluginInstance, FlipperClient} from './plugin/Plugin'; +export {SandyPluginDefinition} from './plugin/SandyPluginDefinition'; +export {SandyPluginRenderer} from './plugin/PluginRenderer'; +export {SandyPluginContext} from './plugin/PluginContext'; + +// It's not ideal that this exists in flipper-plugin sources directly, +// but is the least pain for plugin authors. +// Probably we should make sure that testing-library doesn't end up in our final Flipper bundle (which packages flipper-plugin) +// T69106962 +export const TestUtils = TestUtilites; diff --git a/desktop/flipper-plugin/src/plugin/Plugin.tsx b/desktop/flipper-plugin/src/plugin/Plugin.tsx index e1e5de4d7..714659a17 100644 --- a/desktop/flipper-plugin/src/plugin/Plugin.tsx +++ b/desktop/flipper-plugin/src/plugin/Plugin.tsx @@ -45,7 +45,7 @@ export interface FlipperClient< * Internal API exposed by Flipper, and wrapped by FlipperPluginInstance to be passed to the * Plugin Factory. For internal purposes only */ -interface RealFlipperClient { +export interface RealFlipperClient { isBackgroundPlugin(pluginId: string): boolean; initPlugin(pluginId: string): void; deinitPlugin(pluginId: string): void; @@ -69,6 +69,7 @@ export class SandyPluginInstance { instanceApi: any; connected = false; + destroyed = false; events = new EventEmitter(); constructor( @@ -93,6 +94,7 @@ export class SandyPluginInstance { // the plugin is selected in the UI activate() { + this.assertNotDestroyed(); const pluginId = this.definition.id; if (!this.realClient.isBackgroundPlugin(pluginId)) { this.realClient.initPlugin(pluginId); // will call connect() if needed @@ -101,6 +103,7 @@ export class SandyPluginInstance { // the plugin is deselected in the UI deactivate() { + this.assertNotDestroyed(); const pluginId = this.definition.id; if (!this.realClient.isBackgroundPlugin(pluginId)) { this.realClient.deinitPlugin(pluginId); @@ -108,6 +111,7 @@ export class SandyPluginInstance { } connect() { + this.assertNotDestroyed(); if (!this.connected) { this.connected = true; this.events.emit('connect'); @@ -115,6 +119,7 @@ export class SandyPluginInstance { } disconnect() { + this.assertNotDestroyed(); if (this.connected) { this.connected = false; this.events.emit('disconnect'); @@ -122,11 +127,20 @@ export class SandyPluginInstance { } destroy() { + this.assertNotDestroyed(); this.disconnect(); this.events.emit('destroy'); + this.destroyed = true; } toJSON() { + this.assertNotDestroyed(); // TODO: T68683449 } + + private assertNotDestroyed() { + if (this.destroyed) { + throw new Error('Plugin has been destroyed already'); + } + } } diff --git a/desktop/flipper-plugin/src/plugin/SandyPluginDefinition.tsx b/desktop/flipper-plugin/src/plugin/SandyPluginDefinition.tsx index 42819ca86..1b9956db1 100644 --- a/desktop/flipper-plugin/src/plugin/SandyPluginDefinition.tsx +++ b/desktop/flipper-plugin/src/plugin/SandyPluginDefinition.tsx @@ -13,9 +13,11 @@ import {FlipperPluginFactory, FlipperPluginComponent} from './Plugin'; /** * FlipperPluginModule describe the exports that are provided by a typical Flipper Desktop plugin */ -export type FlipperPluginModule = { +export type FlipperPluginModule< + Factory extends FlipperPluginFactory +> = { /** the factory function that initializes a plugin instance */ - plugin: FlipperPluginFactory; + plugin: Factory; /** the component type that can render this plugin */ Component: FlipperPluginComponent; // TODO: support device plugins T68738317 @@ -23,14 +25,14 @@ export type FlipperPluginModule = { }; /** - * A sandy plugin definitions represents a loaded plugin definition, storing two things: + * A sandy plugin definition represents a loaded plugin definition, storing two things: * the loaded JS module, and the meta data (typically coming from package.json). * * Also delegates some of the standard plugin functionality to have a similar public static api as FlipperPlugin */ export class SandyPluginDefinition { id: string; - module: FlipperPluginModule; + module: FlipperPluginModule; details: PluginDetails; // TODO: Implement T68683449 @@ -45,7 +47,7 @@ export class SandyPluginDefinition { ) => Promise) | undefined = undefined; - constructor(details: PluginDetails, module: FlipperPluginModule) { + constructor(details: PluginDetails, module: FlipperPluginModule) { this.id = details.id; this.details = details; if (!module.plugin || typeof module.plugin !== 'function') { diff --git a/desktop/flipper-plugin/src/test-utils/test-utils.tsx b/desktop/flipper-plugin/src/test-utils/test-utils.tsx new file mode 100644 index 000000000..929fe0d46 --- /dev/null +++ b/desktop/flipper-plugin/src/test-utils/test-utils.tsx @@ -0,0 +1,129 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import * as React from 'react'; +import { + render, + RenderResult, + act as testingLibAct, +} from '@testing-library/react'; +import {PluginDetails} from 'flipper-plugin-lib'; + +import {RealFlipperClient, SandyPluginInstance} from '../plugin/Plugin'; +import { + SandyPluginDefinition, + FlipperPluginModule, +} from '../plugin/SandyPluginDefinition'; +import {SandyPluginRenderer} from '../plugin/PluginRenderer'; + +type Renderer = RenderResult; + +interface StartPluginOptions { + // TODO: support initial events T68683442 (and type correctly) + // TODO: support initial state T68683449 (and type correctly) +} + +interface StartPluginResult> { + /** + * the instantiated plugin for this test + */ + instance: ReturnType; + /** + * module, from which any other exposed methods can be accessed during testing + */ + module: Module; + /** + * Emulates the 'onConnect' event + */ + connect(): void; + /** + * Emulatese the 'onDisconnect' event + */ + disconnect(): void; + /** + * Emulates the 'destroy' event. After calling destroy this plugin instance won't be usable anymore + */ + destroy(): void; +} + +export function startPlugin>( + module: Module, + _options?: StartPluginOptions, +): StartPluginResult { + const definition = new SandyPluginDefinition( + createMockPluginDetails(), + module, + ); + + const fakeFlipper: RealFlipperClient = { + isBackgroundPlugin(_pluginId: string) { + // we only reason about non-background plugins, + // as from testing perspective the difference shouldn't matter + return false; + }, + initPlugin(_pluginId: string) {}, + deinitPlugin(_pluginId: string) {}, + }; + + const pluginInstance = new SandyPluginInstance(fakeFlipper, definition); + // we start connected + pluginInstance.connect(); + + return { + module, + instance: pluginInstance.instanceApi, + connect: () => pluginInstance.connect(), + disconnect: () => pluginInstance.disconnect(), + destroy: () => pluginInstance.destroy(), + // @ts-ignore + _backingInstance: pluginInstance, + }; +} + +export function renderPlugin>( + module: Module, + options?: StartPluginOptions, +): StartPluginResult & { + renderer: Renderer; + act: (cb: () => void) => void; +} { + const res = startPlugin(module, options); + // @ts-ignore hidden api + const pluginInstance: SandyPluginInstance = res._backingInstance; + + const renderer = render(); + + return { + ...res, + renderer, + act: testingLibAct, + destroy: () => { + renderer.unmount(); + pluginInstance.destroy(); + }, + }; +} + +export function createMockPluginDetails( + details?: Partial, +): PluginDetails { + return { + id: 'TestPlugin', + dir: '', + name: 'TestPlugin', + specVersion: 0, + entry: '', + isDefault: false, + main: '', + source: '', + title: 'Testing Plugin', + version: '', + ...details, + }; +} diff --git a/desktop/yarn.lock b/desktop/yarn.lock index e3d458537..fc3c5a7bb 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -1033,6 +1033,14 @@ pirates "^4.0.0" source-map-support "^0.5.9" +"@babel/runtime-corejs3@^7.10.2": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a" + integrity sha512-HA7RPj5xvJxQl429r5Cxr2trJwOfPjKiqhCXcdQPSqO2G0RHPZpXu4fkYmBaTKCp2c/jRaMK9GB/lN+7zvvFPw== + dependencies: + core-js-pure "^3.0.0" + regenerator-runtime "^0.13.4" + "@babel/runtime-corejs3@^7.7.4", "@babel/runtime-corejs3@^7.8.3": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.9.6.tgz#67aded13fffbbc2cb93247388cf84d77a4be9a71" @@ -1048,6 +1056,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.3.tgz#670d002655a7c366540c67f6fd3342cd09500364" + integrity sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.0.0", "@babel/template@^7.3.3", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" @@ -1765,6 +1780,16 @@ dom-accessibility-api "^0.4.2" pretty-format "^25.1.0" +"@testing-library/dom@^7.17.1": + version "7.18.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.18.1.tgz#c49530410fb184522b3b59c4f9cd6397dc5b462d" + integrity sha512-tGq4KAFjaI7j375sMM1RRVleWA0viJWs/w69B+nyDkqYLNkhdTHdV6mGkspJlkn3PUfyBDi3rERDv4PA/LrpVA== + dependencies: + "@babel/runtime" "^7.10.3" + aria-query "^4.2.2" + dom-accessibility-api "^0.4.5" + pretty-format "^25.5.0" + "@testing-library/react@^10.0.2": version "10.0.2" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.0.2.tgz#8eca7aa52d810cf7150048a2829fdc487162006d" @@ -1774,6 +1799,14 @@ "@testing-library/dom" "^7.1.0" "@types/testing-library__react" "^10.0.0" +"@testing-library/react@^10.4.3": + version "10.4.3" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.4.3.tgz#c6f356688cffc51f6b35385583d664bb11a161f4" + integrity sha512-A/ydYXcwAcfY7vkPrfUkUTf9HQLL3/GtixTefcu3OyGQtAYQ7XBQj1S9FWbLEhfWa0BLwFwTBFS3Ao1O0tbMJg== + dependencies: + "@babel/runtime" "^7.10.3" + "@testing-library/dom" "^7.17.1" + "@types/algoliasearch@^3.30.19": version "3.34.5" resolved "https://registry.yarnpkg.com/@types/algoliasearch/-/algoliasearch-3.34.5.tgz#c40e346a6c5526f9b27af7863117d1200456e7d2" @@ -2806,6 +2839,14 @@ aria-query@^4.0.2: "@babel/runtime" "^7.7.4" "@babel/runtime-corejs3" "^7.7.4" +aria-query@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -4568,6 +4609,11 @@ dom-accessibility-api@^0.4.2: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.4.3.tgz#93ca9002eb222fd5a343b6e5e6b9cf5929411c4c" integrity sha512-JZ8iPuEHDQzq6q0k7PKMGbrIdsgBB7TRrtVOUm4nSMCExlg5qQG4KXWTH2k90yggjM4tTumRGwTKJSldMzKyLA== +dom-accessibility-api@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.4.5.tgz#d9c1cefa89f509d8cf132ab5d250004d755e76e3" + integrity sha512-HcPDilI95nKztbVikaN2vzwvmv0sE8Y2ZJFODy/m15n7mGXLeOKGiys9qWVbFbh+aq/KYj2lqMLybBOkYAEXqg== + dom-helpers@^3.2.0, dom-helpers@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"