Skip to content

Commit

Permalink
Resolve merge conflict: two added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marcvberg committed May 6, 2022
1 parent 8f9fc88 commit c2961fa
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IndexTransformer, PrimaryKeyTransformer } from '@aws-amplify/graphql-index-transformer';
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer';
import { ConflictHandlerType, GraphQLTransform, validateModelSchema } from '@aws-amplify/graphql-transformer-core';
import { Kind, parse } from 'graphql';
import { DocumentNode, Kind, parse } from 'graphql';
import { BelongsToTransformer, HasManyTransformer, HasOneTransformer } from '..';

test('fails if used as a has one relation', () => {
Expand Down Expand Up @@ -778,3 +778,43 @@ test('has many with queries null generate correct filter input objects for enum
expect(statusField).toBeDefined();
expect(statusField.type.name.value).toMatch('ModelIssueStatusInput');
});

describe('Pre Processing Has Many Tests', () => {
let transformer: GraphQLTransform;
const hasGeneratedField = (doc: DocumentNode, objectType: string, fieldName: string): boolean => {
let hasField = false;
doc?.definitions?.forEach(def => {
if ((def.kind === 'ObjectTypeDefinition' || def.kind === 'ObjectTypeExtension') && def.name.value === objectType) {
def?.fields?.forEach(field => {
if (field.name.value === fieldName) {
hasField = true;
}
});
}
});
return hasField;
};

beforeEach(() => {
transformer = new GraphQLTransform({
transformers: [new ModelTransformer(), new HasManyTransformer()],
});
});

test('Should generate connecting field when one is not provided', () => {
const schema = `
type Blog @model {
id: ID!
postsField: [Post] @hasMany
}
type Post @model {
id: ID!
}
`;

const updatedSchemaDoc = transformer.preProcessSchema(parse(schema));
expect(hasGeneratedField(updatedSchemaDoc, 'Post', 'blogPostsFieldId')).toBeTruthy();
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ test('recursive @hasOne relationships are supported if DataStore is enabled', ()
validateModelSchema(schema);
});

describe('Pre Processing Tests', () => {
describe('Pre Processing Has One Tests', () => {
let transformer: GraphQLTransform;
const hasGeneratedField = (doc: DocumentNode, objectType: string, fieldName: string): boolean => {
let hasField = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import {
TransformerSchemaVisitStepContextProvider,
TransformerTransformSchemaStepContextProvider,
} from '@aws-amplify/graphql-transformer-interfaces';
import { DirectiveNode, FieldDefinitionNode, InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import {
DirectiveNode,
DocumentNode,
FieldDefinitionNode,
InterfaceTypeDefinitionNode,
ObjectTypeDefinitionNode,
ObjectTypeExtensionNode,
} from 'graphql';
import { getBaseType, isListType } from 'graphql-transformer-common';
import { makeGetItemConnectionWithKeyResolver } from './resolvers';
import { ensureBelongsToConnectionField } from './schema';
Expand All @@ -19,6 +26,9 @@ import {
validateModelDirective,
validateRelatedModelDirective,
} from './utils';
import { TransformerPreProcessContextProvider } from '@aws-amplify/graphql-transformer-interfaces/lib/transformer-context/transformer-context-provider';
import produce from 'immer';
import { WritableDraft } from 'immer/dist/types/types-external';

const directiveName = 'belongsTo';
const directiveDefinition = `
Expand Down Expand Up @@ -50,6 +60,45 @@ export class BelongsToTransformer extends TransformerPluginBase {
this.directiveList.push(args);
};

/** During the preProcess step, modify the document node and return it
* so that it represents any schema modifications the plugin needs
*/
preProcess = (context: TransformerPreProcessContextProvider): DocumentNode => {
const resultDoc: DocumentNode = produce(context.inputDocument, draftDoc => {
const objectTypeMap = new Map<string, WritableDraft<ObjectTypeDefinitionNode | ObjectTypeExtensionNode>>(); // key: type name | value: object type node
// First iteration builds a map of the object types to reference for relation types
draftDoc?.definitions?.forEach(def => {
if (def.kind === 'ObjectTypeExtension' || def.kind === 'ObjectTypeDefinition') {
objectTypeMap.set(def.name.value, def);
}
});

draftDoc?.definitions?.forEach(def => {
if (def.kind === 'ObjectTypeExtension' || def.kind === 'ObjectTypeDefinition') {
def?.fields?.forEach(field => {
field?.directives?.forEach(dir => {
if (dir.name.value === directiveName) {
const relatedType = objectTypeMap.get(getBaseType(field.type));
if (relatedType) { // Validation is done in a different segment of the life cycle
const relationTypeField = relatedType?.fields?.find(relatedField => {
if (getBaseType(field.type) === def.name.value && relatedField?.directives?.some(
relatedDir => relatedDir.name.value === 'hasOne' || relatedDir.name.value === 'hasMany',
)) {
return true;
}
return false;
});
const typeOfRelation = relationTypeField // WIP
}
}
});
});
}
});
});
return resultDoc;
}

/**
* During the prepare step, register any foreign keys that are renamed due to a model rename
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import {
TransformerSchemaVisitStepContextProvider,
TransformerTransformSchemaStepContextProvider,
} from '@aws-amplify/graphql-transformer-interfaces';
import { isListType } from 'graphql-transformer-common';
import { DirectiveNode, DocumentNode, FieldDefinitionNode, InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { getBaseType, isListType, isNonNullType, makeField, makeNamedType, makeNonNullType } from 'graphql-transformer-common';
import {
DirectiveNode,
DocumentNode,
FieldDefinitionNode,
InterfaceTypeDefinitionNode,
NamedTypeNode,
ObjectTypeDefinitionNode,
} from 'graphql';
import { makeQueryConnectionWithKeyResolver, updateTableForConnection } from './resolvers';
import { ensureHasManyConnectionField, extendTypeWithConnection } from './schema';
import { HasManyDirectiveConfiguration } from './types';
import {
ensureFieldsArray,
ensureFieldsArray, getConnectionAttributeName,
getFieldsNodes,
getRelatedType,
getRelatedTypeIndex,
Expand All @@ -22,6 +29,8 @@ import {
} from './utils';
import { TransformerPreProcessContextProvider } from '@aws-amplify/graphql-transformer-interfaces/lib/transformer-context/transformer-context-provider';
import produce from 'immer';
import { Field } from '@aws-cdk/aws-appsync';
import { WritableDraft } from 'immer/dist/types/types-external';

const directiveName = 'hasMany';
const defaultLimit = 100;
Expand Down Expand Up @@ -60,7 +69,31 @@ export class HasManyTransformer extends TransformerPluginBase {
*/
preProcess = (context: TransformerPreProcessContextProvider): DocumentNode => {
const resultDoc: DocumentNode = produce(context.inputDocument, draftDoc => {
const connectingFieldsMap = new Map<string, WritableDraft<FieldDefinitionNode>>(); // key: type name | value: connecting field
// First iteration builds a map of the hasMany connecting fields that need to exist, second iteration ensures they exist
draftDoc?.definitions?.forEach(def => {
if (def.kind === 'ObjectTypeExtension' || def.kind === 'ObjectTypeDefinition') {
def?.fields?.forEach(field => {
field?.directives?.forEach(dir => {
if (dir.name.value === directiveName) {
const baseFieldType = getBaseType(field.type);
const connectionAttributeName = getConnectionAttributeName(def.name.value, field.name.value);
const newField = makeField(connectionAttributeName, [], isNonNullType(field.type) ? makeNonNullType(makeNamedType('ID')) : makeNamedType('ID'), []);
connectingFieldsMap.set(baseFieldType, newField as WritableDraft<FieldDefinitionNode>);
}
});
});
}
});

draftDoc?.definitions?.forEach(def => {
if ((def.kind === 'ObjectTypeDefinition' || def.kind === 'ObjectTypeExtension') && connectingFieldsMap.has(def.name.value)) {
const fieldToAdd = connectingFieldsMap.get(def.name.value);
if (def.fields && fieldToAdd && !def.fields.some(field => field.name.value === fieldToAdd.name.value)) {
def.fields.push(fieldToAdd);
}
}
});
});
return resultDoc;
}
Expand Down

0 comments on commit c2961fa

Please sign in to comment.