Skip to content

Commit

Permalink
Regression test for mutating complex resolver values
Browse files Browse the repository at this point in the history
Reviewed By: alunyov

Differential Revision: D50764867

fbshipit-source-id: ae20dcd9f41b00ea3d5820dc54d79dfa81dbbaf6
  • Loading branch information
tyao1 authored and facebook-github-bot committed Nov 1, 2023
1 parent 7bca4e1 commit 61c7bff
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 0 deletions.
54 changes: 54 additions & 0 deletions packages/react-relay/__tests__/RelayResolverModel-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ const {
completeTodo,
resetStore,
} = require('relay-runtime/store/__tests__/resolvers/ExampleTodoStore');
const {
chargeBattery,
resetModels,
setIsHuman,
} = require('relay-runtime/store/__tests__/resolvers/MutableModel');
const LiveResolverStore = require('relay-runtime/store/experimental-live-resolvers/LiveResolverStore.js');
const RelayModernEnvironment = require('relay-runtime/store/RelayModernEnvironment');
const RelayRecordSource = require('relay-runtime/store/RelayRecordSource');
Expand Down Expand Up @@ -494,4 +499,53 @@ describe.each([
},
});
});

test('should not mutate complex resolver values', () => {
resetModels();
// Do not deep freeze
jest.mock('relay-runtime/util/deepFreeze');

TestRenderer.act(() => {
setIsHuman(true);
});
function GetMutableEntity() {
const data = useClientQuery(
graphql`
query RelayResolverModelTestGetMutableEntityQuery {
mutable_entity
}
`,
{},
);
if (data.mutable_entity == null) {
return null;
}
return `${data.mutable_entity.type}:${data.mutable_entity.props.battery}`;
}

const renderer = TestRenderer.create(
<EnvironmentWrapper environment={environment}>
<GetMutableEntity />
</EnvironmentWrapper>,
);
expect(renderer.toJSON()).toEqual('human:0');

TestRenderer.act(() => {
setIsHuman(false);
jest.runAllImmediates();
});
expect(renderer.toJSON()).toEqual('robot:0');

TestRenderer.act(() => {
chargeBattery();
setIsHuman(true);
jest.runAllImmediates();
});
// TODO: Should be 0. Relay should not mutate the value here.
expect(renderer.toJSON()).toEqual('human:100');

TestRenderer.act(() => {
renderer.unmount();
});
});
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 93 additions & 0 deletions packages/relay-runtime/store/__tests__/resolvers/MutableModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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 strict-local
* @format
* @oncall relay
*/

'use strict';

import type {LiveState} from '../../experimental-live-resolvers/LiveResolverStore';

type Entity = {
name: string,
type: string,
props: {
battery: string,
},
};

let HUMAN: Entity = {
name: 'Alice',
type: 'human',
props: {
battery: '0',
},
};

let ROBOT: Entity = {
name: 'Bob',
type: 'robot',
props: {
battery: '0',
},
};

const subscriptions: Array<() => void> = [];
let isHuman: boolean = true;
/**
* @RelayResolver Query.mutable_entity: RelayResolverValue
* @live
*/
function mutable_entity(): LiveState<Entity> {
return {
read() {
return isHuman ? HUMAN : ROBOT;
},
subscribe(cb) {
subscriptions.push(cb);
return () => {
subscriptions.filter(x => x !== cb);
};
},
};
}

function setIsHuman(val: boolean): void {
isHuman = val;
subscriptions.forEach(x => x());
}

function chargeBattery(): void {
ROBOT.props.battery = '100';
subscriptions.forEach(x => x());
}

function resetModels(): void {
HUMAN = {
name: 'Alice',
type: 'human',
props: {
battery: '0',
},
};
ROBOT = {
name: 'Bob',
type: 'robot',
props: {
battery: '0',
},
};
}

module.exports = {
mutable_entity,
setIsHuman,
chargeBattery,
resetModels,
};

0 comments on commit 61c7bff

Please sign in to comment.