tomitrescak / corporator

BPMN marvel
1 stars 0 forks source link

Creating and Testing Server Objects #8

Closed tomitrescak closed 5 years ago

tomitrescak commented 6 years ago

DRAFT:

This is a guide on how to implement and test server business objects

Goal Implement a notification

Creating Object

On server, we need to prepare a query that loads notifications for the user. User is authenticated by apollo server and user details are stored in the context.

Step 0: Define Graphql Type

  1. If it is a completely new type, create a new file in the data/prisma folder, for example notifications.graphql
  2. Refreference that file in data/prisma/prisma.yml file
  3. Define the type in the notifications.graphql file

Step 1: Define Queries and Mutations

We define a server graphql query in data/yoga/notifications.graphql' and reference it indata/yoga/schema.graphql`. Each queryable/mutable business entity will be separated in its own file

File: data/schema.graphql

#import Query.* from './schema/notifications.graphql'

File: data/yoga/schema/notifications.graphql.

#import './schema/notifications.graphql'

type Query {
  notifications(start: Int, end: Int): Notification!
}

type Mutation {
  notify(
    userId: ID
    processInstanceId: ID
    code: NotificationCode
    params: [String!]!
  ): Notification!
}

Step 2: Generate Types

We need to generate Typescript types that we will use in resolvers to make everything type safe

npm run prisma

Step 3: Define resolvers

Now, we need to define resolvers for the query and a mutation Because this is a new business entity, we define a new model for it in data/yoga/models/notifications.ts. Following is the code for the model. All, query, mutation and resolvers are implemented:

import { getUserId, Mutation, Notification, Query, Resolver } from './utils';

export const query: Query = {
  notifications(_parent, { start, end }, ctx, info) {
    return ctx.db.query.notifications(
      { where: { owner: { id: getUserId(ctx) } }, skip: start, last: end },
      info
    );
  }
};

export const mutation: Mutation = {
  async notify(_parent, args, ctx, info) {
    return ctx.db.mutation.createNotification(
      {
        data: {
          code: args.code,
          owner: {
            connect: {
              id: args.userId
            }
          },
          params: { set: args.params },
          processInstance: {
            connect: {
              id: args.processInstanceId
            }
          },
          visible: true
        }
      },
      info
    );
  }
};

export const resolver: Resolver<Notification> = {
  Notification: {
    text: async (parent, _args, ctx, info) => {
      const results = await ctx.db.query.localisations({
        where: { code: parent.code, language: ctx.session.language }
      });
      return results[0];
    }
  }
};

Step 4: Import the resolver into server

In the data/yoga/model/index.ts file import and add custom resolver

import * as notifications from './notifications_model';

// ...
addResolver(resolvers, notifications);

Writing Tests

I've made writing tests EASY PEASY. Use the tsc helper provided to run database queries in the live database. its expects three parameters. An exemplary implementation follows:

import { mutation, query, resolver } from '../notifications_model';
import { create, its } from './test_utils';

its(
  'insert a new node into database',
  {
    clear: ['BpmnProcessInstance', 'Notification'],
    user: {}
  },
  async (ctx, user) => {
    const bpmn = await create.bpmnProcessInstance(ctx);
    await mutation.notify(
      null,
      { userId: user.id, code: 'ServiceStarted', params: ['a'], processInstanceId: bpmn.id },
      ctx
    );
  }
);