From 36d8792cc6801c7247ed7ea7877bab86a5251a6c Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 29 Apr 2019 10:12:18 -0400 Subject: [PATCH 1/5] Organization#members has been renamed to membersWithRole --- lib/containers/user-mention-tooltip-container.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/containers/user-mention-tooltip-container.js b/lib/containers/user-mention-tooltip-container.js index f00d2a3981..aac72f133e 100644 --- a/lib/containers/user-mention-tooltip-container.js +++ b/lib/containers/user-mention-tooltip-container.js @@ -17,7 +17,7 @@ class UserMentionTooltip extends React.Component { company: PropTypes.string, // Organizations - members: PropTypes.shape({ + membersWithRole: PropTypes.shape({ totalCount: PropTypes.number.isRequired, }), }).isRequired, @@ -48,9 +48,17 @@ class UserMentionTooltip extends React.Component { export default createFragmentContainer(UserMentionTooltip, { repositoryOwner: graphql` fragment userMentionTooltipContainer_repositoryOwner on RepositoryOwner { - login avatarUrl repositories { totalCount } - ... on User { company } - ... on Organization { members { totalCount } } + login + avatarUrl + repositories { totalCount } + ... on User { + company + } + ... on Organization { + membersWithRole { + totalCount + } + } } `, }); From 6070a656155a68ea96d64e40e83e5daf1ad39ba7 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 29 Apr 2019 10:12:29 -0400 Subject: [PATCH 2/5] :gear: `npm run relay` --- ...rMentionTooltipContainer_repositoryOwner.graphql.js | 8 ++++---- .../userMentionTooltipItemQuery.graphql.js | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/containers/__generated__/userMentionTooltipContainer_repositoryOwner.graphql.js b/lib/containers/__generated__/userMentionTooltipContainer_repositoryOwner.graphql.js index 3a0c3b2550..c5f4b1e1eb 100644 --- a/lib/containers/__generated__/userMentionTooltipContainer_repositoryOwner.graphql.js +++ b/lib/containers/__generated__/userMentionTooltipContainer_repositoryOwner.graphql.js @@ -17,7 +17,7 @@ export type userMentionTooltipContainer_repositoryOwner = {| +totalCount: number |}, +company?: ?string, - +members?: {| + +membersWithRole?: {| +totalCount: number |}, +$refType: userMentionTooltipContainer_repositoryOwner$ref, @@ -73,10 +73,10 @@ return { { "kind": "LinkedField", "alias": null, - "name": "members", + "name": "membersWithRole", "storageKey": null, "args": null, - "concreteType": "UserConnection", + "concreteType": "OrganizationMemberConnection", "plural": false, "selections": (v0/*: any*/) } @@ -99,5 +99,5 @@ return { }; })(); // prettier-ignore -(node/*: any*/).hash = 'e59070cd60b11e3732403a074496e66c'; +(node/*: any*/).hash = '3ee858460adcfbee1dfc27cf8dc46332'; module.exports = node; diff --git a/lib/items/__generated__/userMentionTooltipItemQuery.graphql.js b/lib/items/__generated__/userMentionTooltipItemQuery.graphql.js index 3bd8491f4c..d85e81b776 100644 --- a/lib/items/__generated__/userMentionTooltipItemQuery.graphql.js +++ b/lib/items/__generated__/userMentionTooltipItemQuery.graphql.js @@ -1,6 +1,6 @@ /** * @flow - * @relayHash cbae41158b2bedaa2322e49d0f1da45d + * @relayHash ef326a01ce14bb3be20ff2572872ce35 */ /* eslint-disable */ @@ -46,7 +46,7 @@ fragment userMentionTooltipContainer_repositoryOwner on RepositoryOwner { company } ... on Organization { - members { + membersWithRole { totalCount } } @@ -165,10 +165,10 @@ return { { "kind": "LinkedField", "alias": null, - "name": "members", + "name": "membersWithRole", "storageKey": null, "args": null, - "concreteType": "UserConnection", + "concreteType": "OrganizationMemberConnection", "plural": false, "selections": (v2/*: any*/) } @@ -195,7 +195,7 @@ return { "operationKind": "query", "name": "userMentionTooltipItemQuery", "id": null, - "text": "query userMentionTooltipItemQuery(\n $username: String!\n) {\n repositoryOwner(login: $username) {\n __typename\n ...userMentionTooltipContainer_repositoryOwner\n id\n }\n}\n\nfragment userMentionTooltipContainer_repositoryOwner on RepositoryOwner {\n login\n avatarUrl\n repositories {\n totalCount\n }\n ... on User {\n company\n }\n ... on Organization {\n members {\n totalCount\n }\n }\n}\n", + "text": "query userMentionTooltipItemQuery(\n $username: String!\n) {\n repositoryOwner(login: $username) {\n __typename\n ...userMentionTooltipContainer_repositoryOwner\n id\n }\n}\n\nfragment userMentionTooltipContainer_repositoryOwner on RepositoryOwner {\n login\n avatarUrl\n repositories {\n totalCount\n }\n ... on User {\n company\n }\n ... on Organization {\n membersWithRole {\n totalCount\n }\n }\n}\n", "metadata": {} } }; From ef2f625a8027bb06fb3665a79f17f700a93da33a Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 29 Apr 2019 10:13:35 -0400 Subject: [PATCH 3/5] Render the correct prop --- lib/containers/user-mention-tooltip-container.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/containers/user-mention-tooltip-container.js b/lib/containers/user-mention-tooltip-container.js index aac72f133e..8e2b4b5562 100644 --- a/lib/containers/user-mention-tooltip-container.js +++ b/lib/containers/user-mention-tooltip-container.js @@ -25,7 +25,7 @@ class UserMentionTooltip extends React.Component { render() { const owner = this.props.repositoryOwner; - const {login, company, repositories, members} = owner; + const {login, company, repositories, membersWithRole} = owner; return (
@@ -36,7 +36,9 @@ class UserMentionTooltip extends React.Component { {login}
{company &&
{company}
} - {members &&
{members.totalCount} members
} + {membersWithRole && ( +
{membersWithRole.totalCount} members
+ )}
{repositories.totalCount} repositories
From f81b055d0ca9462eeb978273f06d60f53def2e29 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 29 Apr 2019 13:24:28 -0400 Subject: [PATCH 4/5] Take possession of node and selection objects within a FragmentSpec Otherwise, it turns out the `.splice()` calls modify the query directly, which can contaminate other specs in really weird ways :scream: --- test/builder/graphql/base/spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/builder/graphql/base/spec.js b/test/builder/graphql/base/spec.js index 08bbdb7c2d..c0132275ef 100644 --- a/test/builder/graphql/base/spec.js +++ b/test/builder/graphql/base/spec.js @@ -52,7 +52,7 @@ export class FragmentSpec extends Spec { ); throw new Error(`Unrecognized node kind ${node.kind}`); } else { - return fn(node); + return fn({...node}); } }); @@ -62,7 +62,6 @@ export class FragmentSpec extends Spec { for (let i = selections.length - 1; i >= 0; i--) { if (selections[i].kind === 'InlineFragment') { // Replace inline fragments in-place with their selected fields *if* the GraphQL type name matches. - if (!typeNameSet.has(selections[i].type)) { continue; } @@ -77,6 +76,7 @@ export class FragmentSpec extends Spec { }; for (const node of this.nodes) { + node.selections = node.selections.slice(); flattenFragments(node.selections); } } From a566a465cbb7108f7dca369409cf5c3999dbafc6 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 29 Apr 2019 13:24:55 -0400 Subject: [PATCH 5/5] Test coverage for UserMentionTooltipContainer --- .../user-mention-tooltip-container.js | 4 +- test/builder/graphql/user.js | 33 ++++++++++++- .../user-mention-tooltip-container.test.js | 47 +++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 test/containers/user-mention-tooltip-container.test.js diff --git a/lib/containers/user-mention-tooltip-container.js b/lib/containers/user-mention-tooltip-container.js index 8e2b4b5562..1aa60a541a 100644 --- a/lib/containers/user-mention-tooltip-container.js +++ b/lib/containers/user-mention-tooltip-container.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import Octicon from '../atom/octicon'; -class UserMentionTooltip extends React.Component { +export class BareUserMentionTooltipContainer extends React.Component { static propTypes = { repositoryOwner: PropTypes.shape({ login: PropTypes.string.isRequired, @@ -47,7 +47,7 @@ class UserMentionTooltip extends React.Component { } } -export default createFragmentContainer(UserMentionTooltip, { +export default createFragmentContainer(BareUserMentionTooltipContainer, { repositoryOwner: graphql` fragment userMentionTooltipContainer_repositoryOwner on RepositoryOwner { login diff --git a/test/builder/graphql/user.js b/test/builder/graphql/user.js index 08392b438b..48eec07ba0 100644 --- a/test/builder/graphql/user.js +++ b/test/builder/graphql/user.js @@ -1,6 +1,10 @@ -import {createSpecBuilderClass} from './base'; +import {createSpecBuilderClass, createConnectionBuilderClass, createUnionBuilderClass, defer} from './base'; import {nextID} from '../id-sequence'; +const RepositoryBuilder = defer('../repository', 'RepositoryBuilder'); + +export const RepositoryConnectionBuilder = createConnectionBuilderClass('Repository', RepositoryBuilder); + export const UserBuilder = createSpecBuilderClass('User', { __typename: {default: 'User'}, id: {default: nextID}, @@ -10,8 +14,35 @@ export const UserBuilder = createSpecBuilderClass('User', { const login = f.login || 'login'; return `https://github.com/${login}`; }}, + company: {default: 'GitHub'}, + repositories: {linked: RepositoryConnectionBuilder}, +}, +'Node & Actor & RegistryPackageOwner & RegistryPackageSearch & ProjectOwner ' + + '& RepositoryOwner & UniformResourceLocatable', +); + +export const OrganizationMemberConnectionBuilder = createConnectionBuilderClass('OrganizationMember', UserBuilder); + +export const OrganizationBuilder = createSpecBuilderClass('Organization', { + login: {default: 'someone'}, + avatarUrl: {default: 'https://avatars3.githubusercontent.com/u/17565?s=32&v=4'}, + repositories: {linked: RepositoryConnectionBuilder}, + membersWithRole: {linked: OrganizationMemberConnectionBuilder}, +}, +'Node & Actor & RegistryPackageOwner & RegistryPackageSearch & ProjectOwner ' + + '& RepositoryOwner & UniformResourceLocatable & MemberStatusable', +); + +export const RepositoryOwnerBuilder = createUnionBuilderClass('RepositoryOwner', { + beUser: UserBuilder, + beOrganization: OrganizationBuilder, + default: 'beUser', }); export function userBuilder(...nodes) { return UserBuilder.onFragmentQuery(nodes); } + +export function organizationBuilder(...nodes) { + return OrganizationBuilder.onFragmentQuery(nodes); +} diff --git a/test/containers/user-mention-tooltip-container.test.js b/test/containers/user-mention-tooltip-container.test.js new file mode 100644 index 0000000000..659c62d94b --- /dev/null +++ b/test/containers/user-mention-tooltip-container.test.js @@ -0,0 +1,47 @@ +import React from 'react'; +import {shallow} from 'enzyme'; + +import {BareUserMentionTooltipContainer} from '../../lib/containers/user-mention-tooltip-container'; +import {userBuilder, organizationBuilder} from '../builder/graphql/user'; + +import ownerQuery from '../../lib/containers/__generated__/userMentionTooltipContainer_repositoryOwner.graphql'; + +describe('UserMentionTooltipContainer', function() { + function buildApp(override = {}) { + const props = { + ...override, + }; + + return ; + } + + it('renders information about a User', function() { + const wrapper = shallow(buildApp({ + repositoryOwner: userBuilder(ownerQuery) + .login('someone') + .avatarUrl('https://i.redd.it/03xcogvbr6v21.jpg') + .company('Infinity, Ltd.') + .repositories(conn => conn.totalCount(5)) + .build(), + })); + + assert.strictEqual(wrapper.find('img').prop('src'), 'https://i.redd.it/03xcogvbr6v21.jpg'); + assert.isTrue(wrapper.find('span').someWhere(s => s.text() === 'Infinity, Ltd.')); + assert.isTrue(wrapper.find('span').someWhere(s => s.text() === '5 repositories')); + }); + + it('renders information about an Organization', function() { + const wrapper = shallow(buildApp({ + repositoryOwner: organizationBuilder(ownerQuery) + .login('acme') + .avatarUrl('https://i.redd.it/eekf8onik0v21.jpg') + .membersWithRole(conn => conn.totalCount(10)) + .repositories(conn => conn.totalCount(5)) + .build(), + })); + + assert.strictEqual(wrapper.find('img').prop('src'), 'https://i.redd.it/eekf8onik0v21.jpg'); + assert.isTrue(wrapper.find('span').someWhere(s => s.text() === '10 members')); + assert.isTrue(wrapper.find('span').someWhere(s => s.text() === '5 repositories')); + }); +});