src/query/__tests__/RelayFragmentPointer-test.js
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @emails oncall+relay
*/
'use strict';
require('configureForRelayOSS');
jest.unmock('RelayFragmentPointer');
const RelayFragmentPointer = require('RelayFragmentPointer');
const Relay = require('Relay');
const RelayRecordStore = require('RelayRecordStore');
const RelayTestUtils = require('RelayTestUtils');
describe('RelayFragmentPointer', () => {
const {getNode, getRefNode} = RelayTestUtils;
beforeEach(() => {
jest.resetModuleRegistry();
jasmine.addMatchers(RelayTestUtils.matchers);
jasmine.addMatchers({
toEqualPointer() {
return {
compare(actual, expected) {
return {
pass: actual.equals(expected),
};
},
};
},
});
});
describe('create()', () => {
const dataID = '123';
it('creates a fragment prop for a singular fragment', () => {
const fragment = getNode(Relay.QL`fragment on Node { id }`);
const fragmentProp = RelayFragmentPointer.create(dataID, fragment);
expect(fragmentProp).toEqual({
__dataID__: dataID,
__fragments__: {
[fragment.getConcreteFragmentID()]: [{}],
},
});
});
it('adds plural fragments to objects', () => {
const pluralFragment = getNode(
Relay.QL`fragment on Node @relay(plural:true) { id }`
);
const fragmentProp = RelayFragmentPointer.create(dataID, pluralFragment);
expect(fragmentProp).toEqual({
__dataID__: dataID,
__fragments__: {
[pluralFragment.getConcreteFragmentID()]: [{}],
},
});
});
it('distinguishes fragments with different variables', () => {
const fragment = Relay.QL`fragment on Node { id }`;
const fragment1 = getNode(fragment, {foo: 'bar'});
const fragment2 = getNode(fragment, {sizes: [42]});
const fragmentProp = RelayFragmentPointer.create(dataID, fragment1);
RelayFragmentPointer.addFragment(fragmentProp, fragment2, dataID);
expect(fragmentProp).toEqual({
__dataID__: dataID,
__fragments__: {
[fragment1.getConcreteFragmentID()]: [
{foo: 'bar'},
{sizes: [42]},
],
},
});
});
});
describe('createForRoot', () => {
let recordStore;
beforeEach(() => {
const records = {};
recordStore = new RelayRecordStore({records});
});
it('creates a wrapped fragment pointer', () => {
const rootFragment = Relay.QL`fragment on Node{id}`;
const root = getNode(Relay.QL`query{node(id:"123"){${rootFragment}}}`);
const result = RelayFragmentPointer.createForRoot(recordStore, root);
expect(result).toEqual({
__dataID__: '123',
__fragments__: {
[getNode(rootFragment).getConcreteFragmentID()]: [{}],
},
});
});
it('throws if multiple root fragments are present', () => {
const rootFragmentA = Relay.QL`fragment on Node{id}`;
const rootFragmentB = Relay.QL`fragment on Node{id}`;
const root = getNode(Relay.QL`
query {
username(name:"foo"){${rootFragmentA},${rootFragmentB}}
}
`);
expect(() => {
RelayFragmentPointer.createForRoot(recordStore, root);
}).toFailInvariant(
'Queries supplied at the root should contain exactly one fragment ' +
'(e.g. `${Component.getFragment(\'...\')}`). Query ' +
'`RelayFragmentPointer` contains more than one fragment.'
);
});
it('throws if non-fragments are present', () => {
const root = getNode(Relay.QL`query{username(name:"foo"){name}}`);
expect(() => {
RelayFragmentPointer.createForRoot(recordStore, root);
}).toFailInvariant(
'Queries supplied at the root should contain exactly one fragment ' +
'and no fields. Query `RelayFragmentPointer` contains a field, ' +
'`name`. If you need to fetch fields, declare them in a Relay ' +
'container.',
);
});
it('throws for unknown ref queries', () => {
const rootFragment = Relay.QL`fragment on Node{id}`;
const root = getRefNode(
Relay.QL`query{nodes(ids:$ref_q0){${rootFragment}}}`,
{path: '$.*.id'}
);
expect(() => {
RelayFragmentPointer.createForRoot(recordStore, root);
}).toFailInvariant(
'Queries supplied at the root cannot have batch call variables. ' +
'Query `RelayFragmentPointer` has a batch call variable, `ref_q0`.'
);
});
it('returns null when the root call was not fetched', () => {
// When a root call is not fetched since it only contained empty
// fragments, we shouldn't throw.
const ref = Relay.QL`fragment on Viewer { actor { id } }`;
const root = getNode(Relay.QL`query{viewer{${ref}}}`);
expect(
RelayFragmentPointer.createForRoot(recordStore, root)
).toBeNull();
});
});
describe('addFragment()', () => {
const dataID = '123';
let obj;
beforeEach(() => {
obj = {foo: 'bar'};
});
it('adds singular fragments to objects', () => {
const fragment = getNode(Relay.QL`fragment on Node { id }`);
RelayFragmentPointer.addFragment(obj, fragment, dataID);
expect(obj).toEqual({
foo: 'bar',
__fragments__: {
[fragment.getConcreteFragmentID()]: [{}],
},
});
});
it('adds plural fragments to objects', () => {
const pluralFragment = getNode(
Relay.QL`fragment on Node @relay(plural:true) { id }`
);
RelayFragmentPointer.addFragment(obj, pluralFragment, dataID);
expect(obj).toEqual({
foo: 'bar',
__fragments__: {
[pluralFragment.getConcreteFragmentID()]: [{}],
},
});
});
});
});