Skip to content

Commit

Permalink
Support route conditional fragments returning an array
Browse files Browse the repository at this point in the history
Summary:
Gave #896 a try.

modifies `createNode` and `getChildren` to possibly return an array of nodes when a route conditional fragment reference returns an array.

Let me know what you think, It's seems weird to have `createNode` possibly return an Array but I'm not sure how it could be done without it!

[Updates to original PR from wincent: switched `var` to `let`/`const`, avoided an array allocation in `getChildren`.]

Closes #915

Reviewed By: josephsavona

Differential Revision: D3484897

Pulled By: wincent

fbshipit-source-id: 0d101bf63e1a7e5669fc4bd9094e0d35c17c8c40
  • Loading branch information
xuorig authored and Facebook Github Bot 7 committed Jun 25, 2016
1 parent a3075fa commit dd18ca4
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 12 deletions.
30 changes: 19 additions & 11 deletions src/query/RelayQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,19 @@ class RelayQueryNode {
if (concreteChild == null) {
return;
}
const node = createNode(
const nodeOrNodes = createNode(
concreteChild,
this.__route__,
this.__variables__
);
if (node && node.isIncluded()) {
nextChildren.push(node);
if (Array.isArray(nodeOrNodes)) {
nodeOrNodes.forEach(node => {
if (node && node.isIncluded()) {
nextChildren.push(node);
}
});
} else if (nodeOrNodes && nodeOrNodes.isIncluded()) {
nextChildren.push(nodeOrNodes);
}
});
}
Expand Down Expand Up @@ -1328,7 +1334,7 @@ function createNode(
concreteNode: mixed,
route: RelayMetaRoute,
variables: Variables
): ?RelayQueryNode {
): ?RelayQueryNode | Array<?RelayQueryNode> {
invariant(
typeof concreteNode === 'object' &&
concreteNode !== null,
Expand Down Expand Up @@ -1366,13 +1372,15 @@ function createNode(
type = RelayQuerySubscription;
} else if (concreteNode instanceof RelayRouteFragment) {
const fragment = concreteNode.getFragmentForRoute(route);
if (fragment) {
// may be null if no value was defined for this route.
return createNode(
fragment,
route,
variables
);
// May be null if no value was defined for this route.
if (Array.isArray(fragment)) {
// A route-conditional function may return a single fragment reference
// or an array of fragment references.
return fragment.map(frag => {
return createNode(frag, route, variables);
});
} else if (fragment) {
return createNode(fragment, route, variables);
}
return null;
} else if (concreteNode instanceof RelayFragmentReference) {
Expand Down
59 changes: 58 additions & 1 deletion src/query/__tests__/RelayQuery-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ describe('RelayQuery', () => {
type: 'Node',
});
expect(field.canHaveSubselections()).toBe(true);
var children = field.getChildren();
const children = field.getChildren();
expect(children.length).toBe(2);
expect(children[0]).toBe(child);
expect(children[1]).toBe(fragment);
Expand Down Expand Up @@ -486,5 +486,62 @@ describe('RelayQuery', () => {
{name: 'size', value: 'override'},
]);
});

it('expands route conditional fragments', () => {
const innerFragment1 = Relay.QL`
fragment on User {
id,
profilePicture(size:$size) {
uri,
},
}
`;
const innerFragment2 = Relay.QL`
fragment on User {
id,
firstName
}
`;
const reference1 = new RelayFragmentReference(
() => innerFragment1,
{
size: 'default',
},
{
size: QueryBuilder.createCallVariable('outerSize'),
}
);
const reference2 = new RelayFragmentReference(() => innerFragment2, {}, {});
const fragment = getNode(Relay.QL`
fragment on User {
id,
${route => reference1},
${route => [reference2]}
}
`, {
outerSize: 'override',
});

const children = fragment.getChildren();
expect(children.length).toBe(3);
expect(children[0].getSchemaName()).toBe('id');

expect(children[1] instanceof RelayQuery.Fragment);
expect(children[1].getType()).toBe('User');
let grandchildren = children[1].getChildren();
expect(grandchildren.length).toBe(2);
expect(grandchildren[0].getSchemaName()).toBe('id');
expect(grandchildren[1].getSchemaName()).toBe('profilePicture');
expect(grandchildren[1].getCallsWithValues()).toEqual([
{name: 'size', value: 'override'},
]);

expect(children[2] instanceof RelayQuery.Fragment);
expect(children[2].getType()).toBe('User');
grandchildren = children[2].getChildren();
expect(grandchildren.length).toBe(2);
expect(grandchildren[0].getSchemaName()).toBe('id');
expect(grandchildren[1].getSchemaName()).toBe('firstName');
});
});
});

0 comments on commit dd18ca4

Please sign in to comment.