mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
@@ -0,0 +1,39 @@
|
||||
# Javascript Node CircleCI 2.0 configuration file
|
||||
#
|
||||
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
|
||||
#
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
# specify the version you desire here
|
||||
- image: circleci/node:7.10
|
||||
|
||||
# Specify service dependencies here if necessary
|
||||
# CircleCI maintains a library of pre-built images
|
||||
# documented at https://circleci.com/docs/2.0/circleci-images/
|
||||
# - image: circleci/mongo:3.4.4
|
||||
|
||||
working_directory: ~/repo
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
# Download and cache dependencies
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v1-dependencies-{{ checksum "package.json" }}
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- v1-dependencies-
|
||||
|
||||
- run: yarn install
|
||||
|
||||
- save_cache:
|
||||
paths:
|
||||
- node_modules
|
||||
key: v1-dependencies-{{ checksum "package.json" }}
|
||||
|
||||
- run: yarn prettier:ci
|
||||
- run: yarn lint:ci
|
||||
- run: yarn flow
|
||||
- run: yarn test
|
||||
@@ -1,5 +1,6 @@
|
||||
node_modules
|
||||
|
||||
flow-typed
|
||||
shells/browser/chrome/build
|
||||
shells/browser/firefox/build
|
||||
shells/dev/build
|
||||
|
||||
@@ -8,5 +8,9 @@
|
||||
},
|
||||
"settings": {
|
||||
"version": "detect"
|
||||
},
|
||||
"globals": {
|
||||
"__DEV__": "readonly",
|
||||
"jasmine": "readonly"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ shells/dev/build/*
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
/flow-typed/
|
||||
./flow.js
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -9,3 +9,4 @@ yarn-error.log
|
||||
yarn-error.log
|
||||
.vscode
|
||||
.idea
|
||||
.watchmanconfig
|
||||
Vendored
+1183
File diff suppressed because it is too large
Load Diff
@@ -9,3 +9,12 @@ declare module 'events' {
|
||||
|
||||
declare export default typeof EventEmitter;
|
||||
}
|
||||
|
||||
declare var __DEV__: boolean;
|
||||
|
||||
declare var jasmine: {|
|
||||
getEnv: () => {|
|
||||
afterEach: (callback: Function) => void,
|
||||
beforeEach: (callback: Function) => void,
|
||||
|},
|
||||
|};
|
||||
|
||||
+29
-7
@@ -9,6 +9,24 @@
|
||||
"jest": {
|
||||
"modulePathIgnorePatterns": [
|
||||
"<rootDir>/shells"
|
||||
],
|
||||
"modulePaths": [
|
||||
"<rootDir>"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^src/(.*)$": "<rootDir>/src/$1"
|
||||
},
|
||||
"setupFiles": [
|
||||
"<rootDir>/src/__tests__/setupEnv"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/src/__tests__/setupTests"
|
||||
],
|
||||
"snapshotSerializers": [
|
||||
"<rootDir>/src/__tests__/storeSerializer"
|
||||
],
|
||||
"testMatch": [
|
||||
"**/__tests__/*-test.js"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
@@ -22,10 +40,13 @@
|
||||
"deploy:firefox": "node ./shells/browser/firefox/deploy",
|
||||
"linc": "lint-staged",
|
||||
"lint": "eslint '**/*.js'",
|
||||
"lint:ci": "eslint '**/*.js' --max-warnings 0",
|
||||
"precommit": "lint-staged",
|
||||
"prettier": "prettier --write '**/*.{js,json,css}'",
|
||||
"prettier:ci": "prettier --check '**/*.{js,json,css}'",
|
||||
"start": "cd ./shells/dev && opener ./index.html && webpack --config webpack.config.js --watch",
|
||||
"test": "jest",
|
||||
"test-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
|
||||
"test:chrome": "node ./shells/browser/chrome/test",
|
||||
"test:firefox": "node ./shells/browser/firefox/test",
|
||||
"test:standalone": "cd packages/react-devtools && yarn start",
|
||||
@@ -52,7 +73,7 @@
|
||||
"adm-zip": "^0.4.7",
|
||||
"babel-core": "^7.0.0-bridge",
|
||||
"babel-eslint": "^9.0.0",
|
||||
"babel-jest": "^23.6.0",
|
||||
"babel-jest": "^24.7.1",
|
||||
"babel-loader": "^8.0.4",
|
||||
"child-process-promise": "^2.2.1",
|
||||
"chrome-launch": "^1.1.4",
|
||||
@@ -86,9 +107,10 @@
|
||||
"gh-pages": "^1.0.0",
|
||||
"html2canvas": "^1.0.0-alpha.12",
|
||||
"immutable": "3.7.6",
|
||||
"jest": "22.1.4",
|
||||
"jest": "^24.7.1",
|
||||
"lerna": "^2.8.0",
|
||||
"lint-staged": "^7.0.5",
|
||||
"local-storage-fallback": "^4.1.1",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"log-update": "^2.0.0",
|
||||
"lru-cache": "^4.1.3",
|
||||
@@ -97,15 +119,15 @@
|
||||
"nullthrows": "^1.0.0",
|
||||
"object-assign": "4.0.1",
|
||||
"opener": "^1.5.1",
|
||||
"prettier": "^1.16.1",
|
||||
"prettier": "^1.16.4",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.4",
|
||||
"react": "^16.9.0-alpha.0",
|
||||
"react-color": "^2.11.7",
|
||||
"react-dom": "^16.8.4",
|
||||
"react-is": "^16.8.4",
|
||||
"react-dom": "^16.9.0-alpha.0",
|
||||
"react-is": "^16.9.0-alpha.0",
|
||||
"react-virtualized-auto-sizer": "^1.0.2",
|
||||
"react-window": "^1.7.2",
|
||||
"scheduler": "^0.13",
|
||||
"scheduler": "^0.14.0-alpha.0",
|
||||
"semver": "^5.5.1",
|
||||
"style-loader": "^0.23.1",
|
||||
"web-ext": "^1.10.1",
|
||||
|
||||
@@ -10,7 +10,7 @@ import React, {
|
||||
unstable_ConcurrentMode as ConcurrentMode,
|
||||
Fragment,
|
||||
// $FlowFixMe Flow doesn't know about the Profiler import yet
|
||||
unstable_Profiler as Profiler,
|
||||
Profiler,
|
||||
StrictMode,
|
||||
Suspense,
|
||||
} from 'react';
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Store should display Suspense nodes properly in various states: 1: loading 1`] = `
|
||||
[root]
|
||||
▾ <Wrapper>
|
||||
<Component key="Outside">
|
||||
▾ <Suspense>
|
||||
<Loading>
|
||||
`;
|
||||
|
||||
exports[`Store should display Suspense nodes properly in various states: 2: resolved 1`] = `
|
||||
[root]
|
||||
▾ <Wrapper>
|
||||
<Component key="Outside">
|
||||
▾ <Suspense>
|
||||
<Component key="Inside">
|
||||
`;
|
||||
|
||||
exports[`Store should filter DOM nodes from the store tree: 1: mount 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▾ <Parent>
|
||||
<Child>
|
||||
▾ <Parent>
|
||||
<Child>
|
||||
`;
|
||||
|
||||
exports[`Store should support collapsing parts of the tree: 1: mount 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
`;
|
||||
|
||||
exports[`Store should support collapsing parts of the tree: 2: collapse first Parent 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▸ <Parent>
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
`;
|
||||
|
||||
exports[`Store should support collapsing parts of the tree: 3: collapse second Parent 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▸ <Parent>
|
||||
▸ <Parent>
|
||||
`;
|
||||
|
||||
exports[`Store should support collapsing parts of the tree: 4: expand first Parent 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
▸ <Parent>
|
||||
`;
|
||||
|
||||
exports[`Store should support collapsing parts of the tree: 5: collapse Grandparent 1`] = `
|
||||
[root]
|
||||
▸ <Grandparent>
|
||||
`;
|
||||
|
||||
exports[`Store should support collapsing parts of the tree: 6: expand Grandparent 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
▸ <Parent>
|
||||
`;
|
||||
|
||||
exports[`Store should support mount and update operations for multiple roots: 1: mount 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
<Child key="2">
|
||||
[root]
|
||||
▾ <Parent key="B">
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
`;
|
||||
|
||||
exports[`Store should support mount and update operations for multiple roots: 2: update 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
<Child key="2">
|
||||
<Child key="3">
|
||||
[root]
|
||||
▾ <Parent key="B">
|
||||
<Child key="0">
|
||||
`;
|
||||
|
||||
exports[`Store should support mount and update operations for multiple roots: 3: unmount B 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
<Child key="2">
|
||||
<Child key="3">
|
||||
`;
|
||||
|
||||
exports[`Store should support mount and update operations for multiple roots: 4: unmount A 1`] = ``;
|
||||
|
||||
exports[`Store should support mount and update operations: 1: mount 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
<Child key="2">
|
||||
<Child key="3">
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
<Child key="2">
|
||||
<Child key="3">
|
||||
`;
|
||||
|
||||
exports[`Store should support mount and update operations: 2: update 1`] = `
|
||||
[root]
|
||||
▾ <Grandparent>
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
▾ <Parent>
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
`;
|
||||
|
||||
exports[`Store should support mount and update operations: 3: unmount 1`] = ``;
|
||||
@@ -0,0 +1,14 @@
|
||||
// @flow
|
||||
|
||||
import storage from 'local-storage-fallback';
|
||||
|
||||
// In case async/await syntax is used in a test.
|
||||
import 'regenerator-runtime/runtime';
|
||||
|
||||
// DevTools stores preferences between sessions in localStorage
|
||||
if (!global.hasOwnProperty('localStorage')) {
|
||||
global.localStorage = storage;
|
||||
}
|
||||
|
||||
// Mimic the global we set with Webpack's DefinePlugin
|
||||
global.__DEV__ = process.env.NODE_ENV !== 'production';
|
||||
@@ -0,0 +1,40 @@
|
||||
// @flow
|
||||
|
||||
import Agent from 'src/backend/agent';
|
||||
import { initBackend } from 'src/backend';
|
||||
import Bridge from 'src/bridge';
|
||||
import Store from 'src/devtools/store';
|
||||
import { installHook } from 'src/hook';
|
||||
|
||||
const env = jasmine.getEnv();
|
||||
env.beforeEach(() => {
|
||||
// It's important to reset modules between test runs;
|
||||
// Without this, ReactDOM won't re-inject itself into the new hook.
|
||||
jest.resetModules();
|
||||
|
||||
// Fake timers let us flush Bridge operations between setup and assertions.
|
||||
jest.useFakeTimers();
|
||||
|
||||
installHook(global);
|
||||
|
||||
const bridgeListeners = [];
|
||||
|
||||
const bridge = new Bridge({
|
||||
listen(callback) {
|
||||
bridgeListeners.push(callback);
|
||||
},
|
||||
send(event: string, payload: any, transferable?: Array<any>) {
|
||||
bridgeListeners.forEach(callback => callback({ event, payload }));
|
||||
},
|
||||
});
|
||||
|
||||
const agent = new Agent();
|
||||
agent.addBridge(bridge);
|
||||
|
||||
initBackend(global.__REACT_DEVTOOLS_GLOBAL_HOOK__, agent, global);
|
||||
|
||||
global.store = new Store(bridge);
|
||||
});
|
||||
env.afterEach(() => {
|
||||
delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
});
|
||||
@@ -0,0 +1,166 @@
|
||||
// @flow
|
||||
|
||||
describe('Store', () => {
|
||||
let React;
|
||||
let ReactDOM;
|
||||
let TestUtils;
|
||||
let store;
|
||||
|
||||
const act = (callback: Function) => {
|
||||
TestUtils.act(() => {
|
||||
callback();
|
||||
});
|
||||
|
||||
jest.runAllTimers(); // Flush Bridge operations
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
store = global.store;
|
||||
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
TestUtils = require('react-dom/test-utils');
|
||||
});
|
||||
|
||||
it('should support mount and update operations', () => {
|
||||
const Grandparent = ({ count }) => (
|
||||
<React.Fragment>
|
||||
<Parent count={count} />
|
||||
<Parent count={count} />
|
||||
</React.Fragment>
|
||||
);
|
||||
const Parent = ({ count }) =>
|
||||
new Array(count).fill(true).map((_, index) => <Child key={index} />);
|
||||
const Child = () => <div>Hi!</div>;
|
||||
|
||||
const container = document.createElement('div');
|
||||
|
||||
act(() => ReactDOM.render(<Grandparent count={4} />, container));
|
||||
expect(store).toMatchSnapshot('1: mount');
|
||||
|
||||
act(() => ReactDOM.render(<Grandparent count={2} />, container));
|
||||
expect(store).toMatchSnapshot('2: update');
|
||||
|
||||
act(() => ReactDOM.unmountComponentAtNode(container));
|
||||
expect(store).toMatchSnapshot('3: unmount');
|
||||
});
|
||||
|
||||
it('should support mount and update operations for multiple roots', () => {
|
||||
const Parent = ({ count }) =>
|
||||
new Array(count).fill(true).map((_, index) => <Child key={index} />);
|
||||
const Child = () => <div>Hi!</div>;
|
||||
|
||||
const containerA = document.createElement('div');
|
||||
const containerB = document.createElement('div');
|
||||
|
||||
act(() => {
|
||||
ReactDOM.render(<Parent key="A" count={3} />, containerA);
|
||||
ReactDOM.render(<Parent key="B" count={2} />, containerB);
|
||||
});
|
||||
expect(store).toMatchSnapshot('1: mount');
|
||||
|
||||
act(() => {
|
||||
ReactDOM.render(<Parent key="A" count={4} />, containerA);
|
||||
ReactDOM.render(<Parent key="B" count={1} />, containerB);
|
||||
});
|
||||
expect(store).toMatchSnapshot('2: update');
|
||||
|
||||
act(() => ReactDOM.unmountComponentAtNode(containerB));
|
||||
expect(store).toMatchSnapshot('3: unmount B');
|
||||
|
||||
act(() => ReactDOM.unmountComponentAtNode(containerA));
|
||||
expect(store).toMatchSnapshot('4: unmount A');
|
||||
});
|
||||
|
||||
it('should filter DOM nodes from the store tree', () => {
|
||||
const Grandparent = () => (
|
||||
<div>
|
||||
<div>
|
||||
<Parent />
|
||||
</div>
|
||||
<Parent />
|
||||
</div>
|
||||
);
|
||||
const Parent = () => (
|
||||
<div>
|
||||
<Child />
|
||||
</div>
|
||||
);
|
||||
const Child = () => <div>Hi!</div>;
|
||||
|
||||
act(() =>
|
||||
ReactDOM.render(<Grandparent count={4} />, document.createElement('div'))
|
||||
);
|
||||
expect(store).toMatchSnapshot('1: mount');
|
||||
});
|
||||
|
||||
// TODO We should write more complex Suspense tests than just this
|
||||
it('should display Suspense nodes properly in various states', async done => {
|
||||
const Loading = () => <div>Loading...</div>;
|
||||
const SuspendingComponent = () => {
|
||||
throw new Promise(() => {});
|
||||
};
|
||||
const Component = () => {
|
||||
return <div>Hello</div>;
|
||||
};
|
||||
const Wrapper = ({ shouldSuspense }) => (
|
||||
<React.Fragment>
|
||||
<Component key="Outside" />
|
||||
<React.Suspense fallback={<Loading />}>
|
||||
{shouldSuspense ? (
|
||||
<SuspendingComponent />
|
||||
) : (
|
||||
<Component key="Inside" />
|
||||
)}
|
||||
</React.Suspense>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
const container = document.createElement('div');
|
||||
act(() => ReactDOM.render(<Wrapper shouldSuspense={true} />, container));
|
||||
expect(store).toMatchSnapshot('1: loading');
|
||||
|
||||
act(async () => {
|
||||
ReactDOM.render(<Wrapper shouldSuspense={false} />, container);
|
||||
});
|
||||
expect(store).toMatchSnapshot('2: resolved');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should support collapsing parts of the tree', () => {
|
||||
const Grandparent = ({ count }) => (
|
||||
<React.Fragment>
|
||||
<Parent count={count} />
|
||||
<Parent count={count} />
|
||||
</React.Fragment>
|
||||
);
|
||||
const Parent = ({ count }) =>
|
||||
new Array(count).fill(true).map((_, index) => <Child key={index} />);
|
||||
const Child = () => <div>Hi!</div>;
|
||||
|
||||
act(() =>
|
||||
ReactDOM.render(<Grandparent count={2} />, document.createElement('div'))
|
||||
);
|
||||
expect(store).toMatchSnapshot('1: mount');
|
||||
|
||||
const grandparentID = store.getElementIDAtIndex(0);
|
||||
const parentOneID = store.getElementIDAtIndex(1);
|
||||
const parentTwoID = store.getElementIDAtIndex(4);
|
||||
|
||||
act(() => store.toggleIsCollapsed(parentOneID, true));
|
||||
expect(store).toMatchSnapshot('2: collapse first Parent');
|
||||
|
||||
act(() => store.toggleIsCollapsed(parentTwoID, true));
|
||||
expect(store).toMatchSnapshot('3: collapse second Parent');
|
||||
|
||||
act(() => store.toggleIsCollapsed(parentOneID, false));
|
||||
expect(store).toMatchSnapshot('4: expand first Parent');
|
||||
|
||||
act(() => store.toggleIsCollapsed(grandparentID, true));
|
||||
expect(store).toMatchSnapshot('5: collapse Grandparent');
|
||||
|
||||
act(() => store.toggleIsCollapsed(grandparentID, false));
|
||||
expect(store).toMatchSnapshot('6: expand Grandparent');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import Store from 'src/devtools/store';
|
||||
|
||||
export function test(value) {
|
||||
return value instanceof Store;
|
||||
}
|
||||
|
||||
export function print(value, serialize, indent) {
|
||||
return value.__toSnapshot();
|
||||
}
|
||||
@@ -35,7 +35,6 @@ export default class Bridge extends EventEmitter {
|
||||
// - if there *has* been a message flushed in the last BATCH_DURATION ms
|
||||
// (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
|
||||
// be set, and we'll simply add to the queue and wait for that
|
||||
|
||||
this._messageQueue.push(event, payload, transferable);
|
||||
if (!this._timeoutID) {
|
||||
this._timeoutID = setTimeout(this._flush, 0);
|
||||
|
||||
+33
-32
@@ -836,39 +836,40 @@ export default class Store extends EventEmitter {
|
||||
this._bridge.removeListener('shutdown', this.onBridgeShutdown);
|
||||
};
|
||||
|
||||
// DEBUG
|
||||
__printTree = () => {
|
||||
if (__DEBUG__) {
|
||||
console.group('__printTree()');
|
||||
this._roots.forEach((rootID: number) => {
|
||||
const printElement = (id: number) => {
|
||||
const element = ((this._idToElement.get(id): any): Element);
|
||||
console.log(
|
||||
`${'•'.repeat(element.depth)}${element.id}:${element.displayName ||
|
||||
''} ${element.key ? `key:"${element.key}"` : ''} (${
|
||||
element.weight
|
||||
})`
|
||||
);
|
||||
element.children.forEach(printElement);
|
||||
};
|
||||
const root = ((this._idToElement.get(rootID): any): Element);
|
||||
console.group(`${rootID}:root (${root.weight})`);
|
||||
root.children.forEach(printElement);
|
||||
console.groupEnd();
|
||||
});
|
||||
console.group(`List of ${this.numElements} elements`);
|
||||
for (let i = 0; i < this.numElements; i++) {
|
||||
//if (i === 4) { debugger }
|
||||
const element = this.getElementAtIndex(i);
|
||||
if (element != null) {
|
||||
console.log(
|
||||
`${'•'.repeat(element.depth)}${i}: ${element.displayName ||
|
||||
'Unknown'}`
|
||||
);
|
||||
// Used for Jest snapshot testing.
|
||||
// May also be useful for visually debugging the tree, so it lives on the Store.
|
||||
__toSnapshot = () => {
|
||||
const snapshotLines = [];
|
||||
|
||||
let rootWeight = 0;
|
||||
|
||||
this._roots.forEach(rootID => {
|
||||
snapshotLines.push('[root]');
|
||||
|
||||
const { weight } = ((this.getElementByID(rootID): any): Element);
|
||||
|
||||
for (let i = rootWeight; i < rootWeight + weight; i++) {
|
||||
const element = ((this.getElementAtIndex(i): any): Element);
|
||||
|
||||
let prefix = ' ';
|
||||
if (element.children.length > 0) {
|
||||
prefix = element.isCollapsed ? '▸' : '▾';
|
||||
}
|
||||
|
||||
let key = '';
|
||||
if (element.key !== null) {
|
||||
key = ` key="${element.key}"`;
|
||||
}
|
||||
|
||||
snapshotLines.push(
|
||||
`${' '.repeat(element.depth + 1)}${prefix} <${element.displayName ||
|
||||
'null'}${key}>`
|
||||
);
|
||||
}
|
||||
console.groupEnd();
|
||||
console.groupEnd();
|
||||
}
|
||||
|
||||
rootWeight += weight;
|
||||
});
|
||||
|
||||
return snapshotLines.join('\n');
|
||||
};
|
||||
}
|
||||
|
||||
@@ -189,6 +189,9 @@ export function installHook(target: any): DevToolsHook | null {
|
||||
target,
|
||||
'__REACT_DEVTOOLS_GLOBAL_HOOK__',
|
||||
({
|
||||
// This property needs to be configurable for the test environment,
|
||||
// else we won't be able to delete and recreate it beween tests.
|
||||
configurable: __DEV__,
|
||||
enumerable: false,
|
||||
get() {
|
||||
return hook;
|
||||
|
||||
Reference in New Issue
Block a user