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
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c902a27bce
commit
df6a8cd031
@@ -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)),
|
||||
);
|
||||
|
||||
@@ -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(), {
|
||||
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
|
||||
|
||||
@@ -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<Events, {}>) {
|
||||
return {};
|
||||
}
|
||||
|
||||
export function Component() {
|
||||
return <h1>Sandy high fives Flipper</h1>;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
}),
|
||||
|
||||
@@ -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>,
|
||||
): PluginDetails {
|
||||
return {
|
||||
id: 'TestPlugin',
|
||||
dir: '',
|
||||
name: 'TestPlugin',
|
||||
specVersion: 0,
|
||||
entry: '',
|
||||
isDefault: false,
|
||||
main: '',
|
||||
source: '',
|
||||
title: 'Testing Plugin',
|
||||
version: '',
|
||||
...details,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
45
desktop/flipper-plugin/src/__tests__/TestPlugin.tsx
Normal file
45
desktop/flipper-plugin/src/__tests__/TestPlugin.tsx
Normal file
@@ -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<number>;
|
||||
};
|
||||
|
||||
export function plugin(client: FlipperClient<Events, Methods>) {
|
||||
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 <h1>Hi from test plugin</h1>;
|
||||
}
|
||||
61
desktop/flipper-plugin/src/__tests__/test-utils.node.tsx
Normal file
61
desktop/flipper-plugin/src/__tests__/test-utils.node.tsx
Normal file
@@ -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(`
|
||||
<body>
|
||||
<div>
|
||||
<h1>
|
||||
Hi from test plugin
|
||||
</h1>
|
||||
</div>
|
||||
</body>
|
||||
`);
|
||||
// TODO: test sending updates T68683442
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<any, any>
|
||||
> = {
|
||||
/** the factory function that initializes a plugin instance */
|
||||
plugin: FlipperPluginFactory<any, any>;
|
||||
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<any>;
|
||||
details: PluginDetails;
|
||||
|
||||
// TODO: Implement T68683449
|
||||
@@ -45,7 +47,7 @@ export class SandyPluginDefinition {
|
||||
) => Promise<any /* TODO: StaticPersistedState | undefined */>)
|
||||
| undefined = undefined;
|
||||
|
||||
constructor(details: PluginDetails, module: FlipperPluginModule) {
|
||||
constructor(details: PluginDetails, module: FlipperPluginModule<any>) {
|
||||
this.id = details.id;
|
||||
this.details = details;
|
||||
if (!module.plugin || typeof module.plugin !== 'function') {
|
||||
|
||||
129
desktop/flipper-plugin/src/test-utils/test-utils.tsx
Normal file
129
desktop/flipper-plugin/src/test-utils/test-utils.tsx
Normal file
@@ -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<typeof import('testing-library__dom/queries')>;
|
||||
|
||||
interface StartPluginOptions {
|
||||
// TODO: support initial events T68683442 (and type correctly)
|
||||
// TODO: support initial state T68683449 (and type correctly)
|
||||
}
|
||||
|
||||
interface StartPluginResult<Module extends FlipperPluginModule<any>> {
|
||||
/**
|
||||
* the instantiated plugin for this test
|
||||
*/
|
||||
instance: ReturnType<Module['plugin']>;
|
||||
/**
|
||||
* 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 extends FlipperPluginModule<any>>(
|
||||
module: Module,
|
||||
_options?: StartPluginOptions,
|
||||
): StartPluginResult<Module> {
|
||||
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 extends FlipperPluginModule<any>>(
|
||||
module: Module,
|
||||
options?: StartPluginOptions,
|
||||
): StartPluginResult<Module> & {
|
||||
renderer: Renderer;
|
||||
act: (cb: () => void) => void;
|
||||
} {
|
||||
const res = startPlugin(module, options);
|
||||
// @ts-ignore hidden api
|
||||
const pluginInstance: SandyPluginInstance = res._backingInstance;
|
||||
|
||||
const renderer = render(<SandyPluginRenderer plugin={pluginInstance} />);
|
||||
|
||||
return {
|
||||
...res,
|
||||
renderer,
|
||||
act: testingLibAct,
|
||||
destroy: () => {
|
||||
renderer.unmount();
|
||||
pluginInstance.destroy();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createMockPluginDetails(
|
||||
details?: Partial<PluginDetails>,
|
||||
): PluginDetails {
|
||||
return {
|
||||
id: 'TestPlugin',
|
||||
dir: '',
|
||||
name: 'TestPlugin',
|
||||
specVersion: 0,
|
||||
entry: '',
|
||||
isDefault: false,
|
||||
main: '',
|
||||
source: '',
|
||||
title: 'Testing Plugin',
|
||||
version: '',
|
||||
...details,
|
||||
};
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user