Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 4

/**

* Copyright (c) Meta Platforms, Inc. and affiliates.


*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

describe('useEditableValue', () => {
let act;
let React;
let legacyRender;
let useEditableValue;

beforeEach(() => {
const utils = require('./utils');
act = utils.act;
legacyRender = utils.legacyRender;

React = require('react');

useEditableValue = require('../devtools/views/hooks').useEditableValue;
});

it('should not cause a loop with values like NaN', () => {


let state;

function Example({value = NaN}) {


const tuple = useEditableValue(value);
state = tuple[0];
return null;
}

const container = document.createElement('div');


legacyRender(<Example />, container);
expect(state.editableValue).toEqual('NaN');
expect(state.externalValue).toEqual(NaN);
expect(state.parsedValue).toEqual(NaN);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);
});

it('should override editable state when external props are updated', () => {
let state;

function Example({value}) {
const tuple = useEditableValue(value);
state = tuple[0];
return null;
}

const container = document.createElement('div');


legacyRender(<Example value={1} />, container);
expect(state.editableValue).toEqual('1');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(1);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);
// If there are NO pending changes,
// an update to the external prop value should override the local/pending
value.
legacyRender(<Example value={2} />, container);
expect(state.editableValue).toEqual('2');
expect(state.externalValue).toEqual(2);
expect(state.parsedValue).toEqual(2);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);
});

it('should not override editable state when external props are updated if there
are pending changes', () => {
let dispatch, state;

function Example({value}) {
const tuple = useEditableValue(value);
state = tuple[0];
dispatch = tuple[1];
return null;
}

const container = document.createElement('div');


legacyRender(<Example value={1} />, container);
expect(state.editableValue).toEqual('1');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(1);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);

// Update (local) editable state.


act(() =>
dispatch({
type: 'UPDATE',
editableValue: '2',
externalValue: 1,
}),
);
expect(state.editableValue).toEqual('2');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(2);
expect(state.hasPendingChanges).toBe(true);
expect(state.isValid).toBe(true);

// If there ARE pending changes,


// an update to the external prop value should NOT override the local/pending
value.
legacyRender(<Example value={3} />, container);
expect(state.editableValue).toEqual('2');
expect(state.externalValue).toEqual(3);
expect(state.parsedValue).toEqual(2);
expect(state.hasPendingChanges).toBe(true);
expect(state.isValid).toBe(true);
});

it('should parse edits to ensure valid JSON', () => {


let dispatch, state;
function Example({value}) {
const tuple = useEditableValue(value);
state = tuple[0];
dispatch = tuple[1];
return null;
}

const container = document.createElement('div');


legacyRender(<Example value={1} />, container);
expect(state.editableValue).toEqual('1');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(1);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);

// Update (local) editable state.


act(() =>
dispatch({
type: 'UPDATE',
editableValue: '"a',
externalValue: 1,
}),
);
expect(state.editableValue).toEqual('"a');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(1);
expect(state.hasPendingChanges).toBe(true);
expect(state.isValid).toBe(false);
});

it('should reset to external value upon request', () => {


let dispatch, state;

function Example({value}) {
const tuple = useEditableValue(value);
state = tuple[0];
dispatch = tuple[1];
return null;
}

const container = document.createElement('div');


legacyRender(<Example value={1} />, container);
expect(state.editableValue).toEqual('1');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(1);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);

// Update (local) editable state.


act(() =>
dispatch({
type: 'UPDATE',
editableValue: '2',
externalValue: 1,
}),
);
expect(state.editableValue).toEqual('2');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(2);
expect(state.hasPendingChanges).toBe(true);
expect(state.isValid).toBe(true);

// Reset editable state


act(() =>
dispatch({
type: 'RESET',
externalValue: 1,
}),
);
expect(state.editableValue).toEqual('1');
expect(state.externalValue).toEqual(1);
expect(state.parsedValue).toEqual(1);
expect(state.hasPendingChanges).toBe(false);
expect(state.isValid).toBe(true);
});
});

You might also like