Skip to content

Commit

Permalink
fix(TypeComposer): setFields now works with projection property in …
Browse files Browse the repository at this point in the history
…fieldConfig

Also was refactored tests a little bit
  • Loading branch information
nodkz committed Mar 9, 2017
1 parent d5461fc commit 8bfac40
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 90 deletions.
189 changes: 108 additions & 81 deletions src/__tests__/typeComposer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('TypeComposer', () => {
});

describe('fields manipulation', () => {
it('should has `getFields` method', () => {
it('getFields()', () => {
const fieldNames = Object.keys(tc.getFields());
expect(fieldNames).to.have.members(['field1', 'field2']);

Expand All @@ -39,84 +39,91 @@ describe('TypeComposer', () => {
});


it('should has `addFields` method', () => {
tc.setField('field3', { type: GraphQLString });
const fieldNames = Object.keys(objectType.getFields());
expect(fieldNames).to.include('field3');
});

describe('setFields()', () => {
it('should add field with standart config', () => {
tc.setFields({
field3: { type: GraphQLString },
});
const fields = objectType.getFields();
expect(Object.keys(fields)).to.include('field3');
expect(fields.field3.type).to.equal(GraphQLString);
});

it('should add fields with converting types from string to object', () => {
tc.setField('field3', { type: 'String' });
tc.addFields({
field4: { type: '[Int]' },
field5: { type: 'Boolean!' },
it('should add fields with converting types from string to object', () => {
tc.setFields({
field3: { type: 'String' },
field4: { type: '[Int]' },
field5: 'Boolean!',
});

expect(tc.getField('field3').type).to.equal(GraphQLString);
expect(tc.getField('field4').type).instanceof(GraphQLList);
expect(tc.getField('field4').type.ofType).to.equal(GraphQLInt);
expect(tc.getField('field5').type).instanceof(GraphQLNonNull);
expect(tc.getField('field5').type.ofType).to.equal(GraphQLBoolean);
});

expect(tc.getField('field3').type).to.equal(GraphQLString);
expect(tc.getField('field4').type).instanceof(GraphQLList);
expect(tc.getField('field4').type.ofType).to.equal(GraphQLInt);
expect(tc.getField('field5').type).instanceof(GraphQLNonNull);
expect(tc.getField('field5').type.ofType).to.equal(GraphQLBoolean);
});

it('should add fields with converting args types from string to object', () => {
tc.setFields({
field3: {
type: 'String',
args: {
arg1: { type: 'String!' },
arg2: '[Float]',
},
},
});

it('should add fields with converting args types from string to object', () => {
tc.setField('field3', {
type: 'String',
args: {
arg1: { type: 'String!' },
arg2: '[Float]',
},
expect(tc.getFieldArg('field3', 'arg1').type).instanceof(GraphQLNonNull);
expect(tc.getFieldArg('field3', 'arg1').type.ofType).to.equal(GraphQLString);
expect(tc.getFieldArg('field3', 'arg2').type).instanceof(GraphQLList);
expect(tc.getFieldArg('field3', 'arg2').type.ofType).to.equal(GraphQLFloat);
});

expect(tc.getFieldArg('field3', 'arg1').type).instanceof(GraphQLNonNull);
expect(tc.getFieldArg('field3', 'arg1').type.ofType).to.equal(GraphQLString);
expect(tc.getFieldArg('field3', 'arg2').type).instanceof(GraphQLList);
expect(tc.getFieldArg('field3', 'arg2').type.ofType).to.equal(GraphQLFloat);
it('should add projection via `setField` and `addFields`', () => {
tc.setFields({
field3: {
type: GraphQLString,
projection: { field1: true, field2: true },
},
field4: { type: GraphQLString },
field5: { type: GraphQLString, projection: { field4: true } },
});

expect(tc.getProjectionMapper()).to.deep.equal({
field3: { field1: true, field2: true },
field5: { field4: true },
});
});
});


it('should add projection via `setField` and `addFields`', () => {
tc.setField('field3', {
type: GraphQLString,
projection: { field1: true, field2: true },
});
it('addFields()', () => {
tc.addFields({
field4: { type: GraphQLString },
field5: { type: GraphQLString, projection: { field4: true } },
});

expect(tc.getProjectionMapper()).to.deep.equal({
field3: { field1: true, field2: true },
field5: { field4: true },
field3: { type: GraphQLString },
field4: { type: '[Int]' },
field5: 'Boolean!',
});
expect(tc.getField('field3').type).to.equal(GraphQLString);
expect(tc.getField('field4').type).instanceof(GraphQLList);
expect(tc.getField('field4').type.ofType).to.equal(GraphQLInt);
expect(tc.getField('field5').type).instanceof(GraphQLNonNull);
expect(tc.getField('field5').type.ofType).to.equal(GraphQLBoolean);
});


it('should clone projection for fields', () => {
tc.setField('field3', {
type: GraphQLString,
projection: { field1: true, field2: true },
describe('removeField()', () => {
it('should remove one field', () => {
tc.removeField('field1');
expect(tc.getFieldNames()).to.have.members(['field2']);
});

const tc2 = tc.clone('newObject');
expect(tc2.getProjectionMapper()).to.deep.equal({
field3: { field1: true, field2: true },
it('should remove list of fields', () => {
tc.removeField(['field1', 'field2']);
expect(tc.getFieldNames()).to.have.members([]);
});
});

it('should remove one field', () => {
tc.removeField('field1');
expect(tc.getFieldNames()).to.have.members(['field2']);
});

it('should remove list of fields', () => {
tc.removeField(['field1', 'field2']);
expect(tc.getFieldNames()).to.have.members([]);
});

it('should extend field by name', () => {
it('extendField()', () => {
tc.setField('field3', {
type: GraphQLString,
projection: { field1: true, field2: true },
Expand All @@ -134,40 +141,46 @@ describe('TypeComposer', () => {
});

describe('interfaces manipulation', () => {
it('should has `getInterfaces` method', () => {
expect(tc.getInterfaces()).to.have.members([]);
const iface = new GraphQLInterfaceType({
name: 'Node',
description: '',
fields: () => ({}),
resolveType: () => {},
});
const iface2 = new GraphQLInterfaceType({
name: 'Node',
description: '',
fields: () => ({}),
resolveType: () => {},
});

it('getInterfaces()', () => {
tc.gqType._typeConfig.interfaces = [iface];
expect(tc.getInterfaces()).to.have.members([iface]);
});

it('should has working `addInterface`, `hasInterface`, `removeInterface` methods', () => {
const iface = new GraphQLInterfaceType({
name: 'Node',
description: '',
fields: () => ({}),
resolveType: () => {},
});
it('hasInterface()', () => {
tc.gqType._typeConfig.interfaces = [iface];
expect(tc.hasInterface(iface)).to.be.true;
});

it('addInterface()', () => {
tc.addInterface(iface);
expect(tc.getInterfaces()).to.have.members([iface]);
expect(tc.hasInterface(iface)).to.be.true;
const iface2 = new GraphQLInterfaceType({
name: 'Node',
description: '',
fields: () => ({}),
resolveType: () => {},
});
tc.addInterface(iface2);
expect(tc.getInterfaces()).to.have.members([iface, iface2]);
expect(tc.hasInterface(iface2)).to.be.true;
});

it('removeInterface()', () => {
tc.addInterface(iface);
tc.addInterface(iface2);
expect(tc.getInterfaces()).to.have.members([iface, iface2]);
tc.removeInterface(iface);
expect(tc.hasInterface(iface)).to.be.false;
expect(tc.hasInterface(iface2)).to.be.true;
});

it('should remove interface', () => {
tc.removeField('field1');
expect(tc.getFieldNames()).to.have.members(['field2']);
});
});

describe('create() [static method]', () => {
Expand Down Expand Up @@ -225,6 +238,20 @@ describe('TypeComposer', () => {
});
});

describe('clone()', () => {
it('should clone projection for fields', () => {
tc.setField('field3', {
type: GraphQLString,
projection: { field1: true, field2: true },
});

const tc2 = tc.clone('newObject');
expect(tc2.getProjectionMapper()).to.deep.equal({
field3: { field1: true, field2: true },
});
});
});

describe('get()', () => {
it('should return type by path', () => {
const myTC = new TypeComposer(new GraphQLObjectType({
Expand Down
18 changes: 9 additions & 9 deletions src/typeComposer.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ export default class TypeComposer {
);

this.gqType._typeConfig.fields = () => prepearedFields;
// if field has a projection option, then add it to projection mapper
Object.keys(prepearedFields).forEach((name) => {
if (prepearedFields[name].projection) {
// $FlowFixMe
const projection: ProjectionType = prepearedFields[name].projection;
this.addProjectionMapper(name, projection);
}
});

delete this.gqType._fields; // clear builded fields in type
}

Expand Down Expand Up @@ -150,15 +159,6 @@ export default class TypeComposer {
*/
addFields(newFields: GraphQLFieldConfigMap<*, *>): void {
this.setFields(Object.assign({}, this.getFields(), newFields));

// if field has a projection option, then add it to projection mapper
Object.keys(newFields).forEach((name) => {
if (newFields[name].projection) {
// $FlowFixMe
const projection: ProjectionType = newFields[name].projection;
this.addProjectionMapper(name, projection);
}
});
}

/**
Expand Down

0 comments on commit 8bfac40

Please sign in to comment.