Skip to content

Commit

Permalink
Added tests for new copy and store-as-global backend functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn committed Dec 17, 2019
1 parent 0d4842b commit 0e1ef7c
Show file tree
Hide file tree
Showing 3 changed files with 252 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
*/

import typeof ReactTestRenderer from 'react-test-renderer';
import type {GetInspectedElementPath} from 'react-devtools-shared/src/devtools/views/Components/InspectedElementContext';
import type {
CopyInspectedElementPath,
GetInspectedElementPath,
StoreAsGlobal,
} from 'react-devtools-shared/src/devtools/views/Components/InspectedElementContext';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type Store from 'react-devtools-shared/src/devtools/store';

Expand Down Expand Up @@ -1203,4 +1207,139 @@ describe('InspectedElementContext', () => {

done();
});

it('should enable inspected values to be stored as global variables', async done => {
const Example = () => null;

const nestedObject = {
a: {
value: 1,
b: {
value: 1,
c: {
value: 1,
},
},
},
};

await utils.actAsync(() =>
ReactDOM.render(
<Example nestedObject={nestedObject} />,
document.createElement('div'),
),
);

const id = ((store.getElementIDAtIndex(0): any): number);

let storeAsGlobal: StoreAsGlobal = ((null: any): StoreAsGlobal);

function Suspender({target}) {
const context = React.useContext(InspectedElementContext);
storeAsGlobal = context.storeAsGlobal;
return null;
}

await utils.actAsync(
() =>
TestRenderer.create(
<Contexts
defaultSelectedElementID={id}
defaultSelectedElementIndex={0}>
<React.Suspense fallback={null}>
<Suspender target={id} />
</React.Suspense>
</Contexts>,
),
false,
);
expect(storeAsGlobal).not.toBeNull();

const logSpy = jest.fn();
spyOn(console, 'log').and.callFake(logSpy);

// Should store the whole value (not just the hydrated parts)
storeAsGlobal(id, ['props', 'nestedObject']);
jest.runOnlyPendingTimers();
expect(logSpy).toHaveBeenCalledWith('$reactTemp1');
expect(global.$reactTemp1).toBe(nestedObject);

logSpy.mockReset();

// Should store the nested property specified (not just the outer value)
storeAsGlobal(id, ['props', 'nestedObject', 'a', 'b']);
jest.runOnlyPendingTimers();
expect(logSpy).toHaveBeenCalledWith('$reactTemp2');
expect(global.$reactTemp2).toBe(nestedObject.a.b);

done();
});

it('should enable inspected values to be copied to the clipboard', async done => {
const Example = () => null;

const nestedObject = {
a: {
value: 1,
b: {
value: 1,
c: {
value: 1,
},
},
},
};

await utils.actAsync(() =>
ReactDOM.render(
<Example nestedObject={nestedObject} />,
document.createElement('div'),
),
);

const id = ((store.getElementIDAtIndex(0): any): number);

let copyPath: CopyInspectedElementPath = ((null: any): CopyInspectedElementPath);

function Suspender({target}) {
const context = React.useContext(InspectedElementContext);
copyPath = context.copyInspectedElementPath;
return null;
}

await utils.actAsync(
() =>
TestRenderer.create(
<Contexts
defaultSelectedElementID={id}
defaultSelectedElementIndex={0}>
<React.Suspense fallback={null}>
<Suspender target={id} />
</React.Suspense>
</Contexts>,
),
false,
);
expect(copyPath).not.toBeNull();

// Should copy the whole value (not just the hydrated parts)
copyPath(id, ['props', 'nestedObject']);
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
JSON.stringify(nestedObject),
);

global.mockClipboardCopy.mockReset();

// Should copy the nested property specified (not just the outer value)
copyPath(id, ['props', 'nestedObject', 'a', 'b']);
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
JSON.stringify(nestedObject.a.b),
);

done();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,109 @@ describe('InspectedElementContext', () => {

done();
});

it('should enable inspected values to be stored as global variables', () => {
const Example = () => null;

const nestedObject = {
a: {
value: 1,
b: {
value: 1,
c: {
value: 1,
},
},
},
};

act(() =>
ReactDOM.render(
<Example nestedObject={nestedObject} />,
document.createElement('div'),
),
);

const id = ((store.getElementIDAtIndex(0): any): number);
const rendererID = ((store.getRendererIDForElement(id): any): number);

const logSpy = jest.fn();
spyOn(console, 'log').and.callFake(logSpy);

// Should store the whole value (not just the hydrated parts)
bridge.send('storeAsGlobal', {
count: 1,
id,
path: ['props', 'nestedObject'],
rendererID,
});
jest.runOnlyPendingTimers();
expect(logSpy).toHaveBeenCalledWith('$reactTemp1');
expect(global.$reactTemp1).toBe(nestedObject);

logSpy.mockReset();

// Should store the nested property specified (not just the outer value)
bridge.send('storeAsGlobal', {
count: 2,
id,
path: ['props', 'nestedObject', 'a', 'b'],
rendererID,
});
jest.runOnlyPendingTimers();
expect(logSpy).toHaveBeenCalledWith('$reactTemp2');
expect(global.$reactTemp2).toBe(nestedObject.a.b);
});

it('should enable inspected values to be copied to the clipboard', () => {
const Example = () => null;

const nestedObject = {
a: {
value: 1,
b: {
value: 1,
c: {
value: 1,
},
},
},
};

act(() =>
ReactDOM.render(
<Example nestedObject={nestedObject} />,
document.createElement('div'),
),
);

const id = ((store.getElementIDAtIndex(0): any): number);
const rendererID = ((store.getRendererIDForElement(id): any): number);

// Should copy the whole value (not just the hydrated parts)
bridge.send('copyElementPath', {
id,
path: ['props', 'nestedObject'],
rendererID,
});
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
JSON.stringify(nestedObject),
);

global.mockClipboardCopy.mockReset();

// Should copy the nested property specified (not just the outer value)
bridge.send('copyElementPath', {
id,
path: ['props', 'nestedObject', 'a', 'b'],
rendererID,
});
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
JSON.stringify(nestedObject.a.b),
);
});
});
7 changes: 7 additions & 0 deletions packages/react-devtools-shared/src/__tests__/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import type {

const env = jasmine.getEnv();
env.beforeEach(() => {
global.mockClipboardCopy = jest.fn();

// Test environment doesn't support document methods like execCommand()
// Also once the backend components below have been required,
// it's too late for a test to mock the clipboard-js modules.
jest.mock('clipboard-js', () => ({copy: global.mockClipboardCopy}));

// These files should be required (and re-reuired) before each test,
// rather than imported at the head of the module.
// That's because we reset modules between tests,
Expand Down

0 comments on commit 0e1ef7c

Please sign in to comment.