Manual Reference Source Test

test/unit/helpers.flow.js

import test from 'ava';
import nock from 'nock';
import FLOW_REAL_1 from './data/flow_real_1';
import {
  client,
  User,
  Flow,
} from '../../src';

test.before('start server', () => {
  client.apiBaseUrl = 'https://somesite.Clinical6.com';
  client.config = {
    track: {
      flows: false,
      gps: false
    }
  };
  client.user = new User({ id: 1 });
});

test.after('server shut down', () => {});

test.beforeEach((t) => {
  client.authToken = 'valid_token';
  nock(client.apiBaseUrl).post('/api/v2/data_collection/flow_processes/1/collect').reply(200, {});
  nock(client.apiBaseUrl).post('/v3/data_collection/flow_process_values').reply(200, {});
  nock(client.apiBaseUrl).post('/api/status/transition').reply(200, { status: { value: 'completed' } });
  nock(client.apiBaseUrl).get(/\/v3\/discuss\/threads\/([0-9]*)\/comments$/).reply(200, {
    data: [
      {
        id: '10',
        type: 'commentable__comments',
        attributes: {
          body: 'Voluptatem cumque ducimus incidunt dolore.',
          created_at: '2017-07-26T15:04:23Z'
        },
        relationships: {
          thread: {
            data: {
              id: '4',
              type: 'commentable__threads'
            }
          },
          author: {
            data: {
              id: '2',
              type: 'users'
            }
          }
        }
      },
      {
        id: '11',
        type: 'commentable__comments',
        attributes: {
          body: 'Voluptate aliquid consequatur unde libero sequi illo est.',
          created_at: '2017-07-26T15:04:23Z'
        },
        relationships: {
          thread: {
            data: {
              id: '4',
              type: 'commentable__threads'
            }
          },
          author: {
            data: {
              id: '3',
              type: 'users'
            }
          }
        }
      },
      {
        id: '12',
        type: 'commentable__comments',
        attributes: {
          body: 'Voluptate aliquid consequatur unde libero sequi illo est.',
          created_at: '2017-07-26T15:04:23Z'
        },
        relationships: {
          thread: {
            data: {
              id: '4',
              type: 'commentable__threads'
            }
          },
          author: {
            data: {
              id: '3',
              type: 'users'
            }
          }
        }
      }
    ]
  });

  nock(client.apiBaseUrl).patch('/v3/data_collection/flow_processes/6')
    .reply(201, {
      data: {
        id: '6',
        type: 'data_collection__flow_processes',
        attributes: {
          name: 'Updated',
          permanent_link: 'dummy_77',
          consent_credentials: null,
          created_at: '2018-08-19T22:03:19Z',
          updated_at: '2018-08-19T22:03:20Z',
          owner_type: 'MobileUser',
          published_at: null,
          conditional_paths: null,
          description: 'Updated flow description'
        },
        relationships: {
          linked_steps: {
            data: []
          },
          published: {
            data: null
          },
          draft: {
            data: null
          },
          initial_step: {
            data: null
          }
        }
      }
    });

  // get threads
  nock(client.apiBaseUrl).get('/v3/discuss/threads?filters[commentable_type]=data_collection__flow_processes&filters[commentable_id]=1').reply(200, {
    data: [
      {
        id: '4',
        type: 'commentable__threads',
        attributes: {
          status: 'open',
          created_at: '2017-07-25T20:32:54Z',
          resolved_at: null
        },
        relationships: {
          commentable: {
            data: {
              id: '1',
              type: 'data_collection__flow_processes'
            }
          },
          owner: {
            data: null
          },
          comments: {
            data: [
              {
                id: '10',
                type: 'commentable__comments'
              },
              {
                id: '11',
                type: 'commentable__comments'
              },
              {
                id: '12',
                type: 'commentable__comments'
              }
            ]
          }
        }
      }
    ]
  });

  // add comment to thread
  nock(client.apiBaseUrl).post('/v3/discuss/threads/4/comments').reply(200, {
    data: {
      id: '1',
      type: 'commentable__comments',
      attributes: {
        body: 'That\'s one bad hat Harry.',
        created_at: '2017-07-26T15:04:23Z'
      },
      relationships: {
        thread: {
          data: {
            id: '1',
            type: 'commentable__threads'
          }
        },
        author: {
          data: {
            id: '3',
            type: 'mobile_users'
          }
        }
      }
    }
  });

  // add thread
  nock(client.apiBaseUrl).post('/v3/discuss/threads').reply(200, {
    data: {
      id: '4',
      type: 'commentable__threads',
      attributes: {
        status: null,
        created_at: '2017-07-26T15:04:37Z',
        resolved_at: null
      },
      relationships: {
        commentable: {
          data: {
            id: '1',
            type: 'data_collection__flow_processes'
          }
        },
        owner: {
          data: null
        },
        comments: {
          data: []
        }
      }
    }
  });

  t.context.flowSimple = new Flow({ id: 1, permanent_link: '1', steps: [] });
  client.storageUtility.set(t.context.flowSimple.type, t.context.flowSimple, {
    id: t.context.flowSimple.id
  });

  t.context.flow1 = new Flow({
    id: 1,
    name: 'Dummy Flow',
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'Age',
            question_type: 'text',
            style: 'text',
            choice_list: [],
            id: 'first_name',
          },
          {
            id: 271,
            title: 'Is your facility affiliated with an SMO?',
            question_type: 'single_choice',
            style: 'radio_buttons',
            required: false,
            validation_expression: null,
            instructions: 'Is your facility affiliated with an SMO?',
            choice_list: [
              {
                id: 371,
                body: 'Yes',
              },
              {
                id: 372,
                body: 'No',
              },
            ],
            locked: null,
          },
        ],
        paths: [
          {
            capture: true,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '271',
                    operator: '=',
                    value: '371',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: true,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });

  t.context.flow1A = new Flow({
    id: 1,
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'Age',
            question_type: 'text',
            style: 'text',
            choice_list: [],
            id: 'first_name',
          },
          {
            id: 271,
            title: 'Is your facility affiliated with an SMO?',
            question_type: 'single_choice',
            style: 'radio_buttons',
            required: false,
            validation_expression: null,
            instructions: 'Is your facility affiliated with an SMO?',
            choice_list: [
              {
                id: 371,
                body: 'Yes',
              },
              {
                id: 372,
                body: 'No',
              },
            ],
            locked: null,
          },
        ],
        paths: [
          {
            capture: true,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '271',
                    operator: '<>',
                    value: '371',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '271',
                    operator: '=',
                    value: '371',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });

  t.context.flowCond = new Flow({
    id: 1,
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'Age',
            question_type: 'text',
            style: 'text',
            choice_list: [],
            id: 'first_name',
          },
          {
            id: 271,
            title: 'Is your facility affiliated with an SMO?',
            question_type: 'single_choice',
            style: 'radio_buttons',
            required: false,
            validation_expression: null,
            instructions: 'Is your facility affiliated with an SMO?',
            choice_list: [
              {
                id: 371,
                code: 'Yes',
                body: 'Yes',
              },
              {
                id: 372,
                code: 'No',
                body: 'No',
              },
            ],
            locked: null,
          },
        ],
        paths: [
          {
            capture: true,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '2',
                    operator: '<>',
                    value: '5',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '4',
                    operator: '=',
                    value: '3',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        instructions: 'do something on this step',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });

  t.context.flowInsights = new Flow({ id: 25, permanent_link: '25', steps: [] });

  t.context.flowReset = new Flow({
    id: 1,
    first_step: 11,
    name: 'Dummy Flow',
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        send_on_capture: true,
        image: { },
        inputs: [
          {
            id: 'first_name',
            title: 'Age',
            question_type: 'text',
            required: false,
            style: 'text',
            instructions: 'Age needs to be typed in',
            choice_list: [],
          },
          {
            id: 271,
            title: 'Is your facility affiliated with an SMO?',
            question_type: 'single_choice',
            style: 'radio_buttons',
            required: false,
            validation_expression: null,
            instructions: 'Is your facility affiliated with an SMO?',
            choice_list: [
              {
                id: 371,
                code: 'Yes',
                body: 'Yes',
              },
              {
                id: 372,
                code: 'No',
                body: 'No',
              },
            ],
            locked: null,
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '2',
                    operator: '<>',
                    value: '5',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '4',
                    operator: '=',
                    value: '3',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        instructions: 'do something on this step',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });

  t.context.flowPatch = new Flow(
    {
      id: 6,
      type: 'data_collection__flow_processes',
      attributes: {
        name: 'Updated',
        description: 'Updated flow description',
        permanent_link: 'dummy_77',
        steps: []
      }
    }
  );
});

// test.afterEach(t => t.context.server.restore());

// Add Comment
/**
 * @test {Flow.addComment}
 */
test('[unit] Flow.addComment method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.addComment);
});

// /**
//  * @test {Flow.addComment}
//  */
// test('[unit] Flow.addComment method should return a promise', async (t) => {
//   const { flowSimple } = t.context;
//   t.truthy(await flowSimple.addComment('test').then);
// });

/**
 * @test {Flow.addComment}
 */
test('[unit] Flow.addComment method should return a comment object', async (t) => {
  const { flowSimple } = t.context;
  const thread = await flowSimple.addComment('Some Comment');
  // console.log('add comment', thread);
  t.is(thread.id, 4);
});

// Clone
/**
 * @test {Flow.clone}
 */
test('[unit] Flow.clone method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.clone);
});

/**
 * @test {Flow.clone}
 */
test('[unit] Flow.clone method should clone id, name, first, and steps', (t) => {
  const { flow1 } = t.context;
  const clone = flow1.clone();
  t.is(clone.id, 1);
  t.is(clone.name, 'Dummy Flow');
  t.is(clone.first.id, 11);
  t.is(clone.steps.length, 3);
});

// Connect Graph
/**
 * @test {Flow.connectGraph}
 */
test('[unit] Flow.connectGraph method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.connectGraph);
});

// First Field
/**
 * @test {Flow.first}
 */
test('[unit] Flow.first field should be the first flowstep', (t) => {
  const { flow1 } = t.context;
  t.truthy(flow1.first.id);
});

/**
 * @test {Flow.first}
 */
test('[unit] Flow.first field should have paths flow field to be the next flowstep', async (t) => {
  const { flow1A } = t.context;
  const { first } = flow1A;
  first.set(271, '371');
  const step = await first.go('Next');
  t.is(step.id, 13);
});

// Get Comments
/**
 * @test {Flow.getComments}
 */
test('[unit] Flow.getComments method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.getComments);
});

// /**
//  * @test {Flow.getComments}
//  */
// test('[unit] Flow.getComments method should return a promise', (t) => {
//   const { flowSimple } = t.context;
//   t.truthy(flowSimple.getComments().then);
// });

/**
 * @test {Flow.getComments}
 */
test('[unit] Flow.getComments method should return an array of comment objects', async (t) => {
  const { flowSimple } = t.context;
  const threads = await flowSimple.getComments();
  // console.log('get comments: thread', threads);
  // console.log('get comments: comments', threads[0].comments);
  t.is(threads[0].id, 4);
  t.is(threads[0].commentable.id, flowSimple.id);
});

// Get Longest Distance
/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.getLongestDistance should return the distance', (t) => {
  const flow = new Flow(FLOW_REAL_1);
  // console.log('getBFS', flow.getBFS(flow.first));
  // console.log('getJohnsonMatrix', flow.getJohnsonMatrix());
  // console.log('getLongestDistance', flow.getLongestDistance(flow.first));
  // console.log(flow.toPlantUML());
  t.is(flow.getLongestDistance(flow.first), 8);
});

// Go
/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path with incorrect condition statements', async (t) => {
  const { flowCond } = t.context;
  const { first } = flowCond;
  first.set(271, '371');
  const step = await first.go('Next');
  t.is(step.id, 12);
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path should change _toSave', async (t) => {
  const flow = new Flow({
    id: 1,
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        send_on_capture: true,
        image: { },
        inputs: [
          {
            id: 'first_name',
            title: 'Age',
            question_type: 'text',
            required: false,
            style: 'text',
            instructions: 'Age needs to be typed in',
            choice_list: [],
          },
          {
            id: 271,
            title: 'Is your facility affiliated with an SMO?',
            question_type: 'single_choice',
            style: 'radio_buttons',
            required: false,
            validation_expression: null,
            instructions: 'Is your facility affiliated with an SMO?',
            choice_list: [
              {
                id: 371,
                body: 'Yes',
              },
              {
                id: 372,
                body: 'No',
              },
            ],
            locked: null,
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '2',
                    operator: '<>',
                    value: '5',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '4',
                    operator: '=',
                    value: '3',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        instructions: 'do something on this step',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });
  const { first } = flow;
  first.set(271, '371');
  first.set('first_name', 'My Name');
  await first.go('Next');
  t.is(flow._toSave.length, 2);
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path should have labels for range or sliders', async (t) => {
  const flow = new Flow({
    id: 1,
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        send_on_capture: true,
        image: { },
        inputs: [
          {
            id: 'first_name',
            title: 'Age',
            question_type: 'text',
            required: false,
            style: 'text',
            instructions: 'Age needs to be typed in',
            choice_list: [],
          },
          {
            id: 1453,
            storage_attribute: '',
            title: '',
            body: '',
            question_type: 'numeric',
            style: 'range',
            required: true,
            validation_expression: null,
            validation_details: null,
            instructions: '',
            choice_list: [],
            locked: null,
            max: 100,
            min: 0,
            max_label: 'Hurting a lot<br>Very uncomfortable<br>Severe pain',
            min_label: 'Not hurting<br>Not discomfort<br>No pain',
            interval: 1,
            labels: []
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '2',
                    operator: '<>',
                    value: '5',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '4',
                    operator: '=',
                    value: '3',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        instructions: 'do something on this step',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });
  const { first } = flow;
  first.set(1453, 23);
  first.set('first_name', 'My Name');
  await t.is(first.inputs[1].minLabel, 'Not hurting<br>Not discomfort<br>No pain');
  await t.is(first.inputs[1].maxLabel, 'Hurting a lot<br>Very uncomfortable<br>Severe pain');
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path should have min and max values for numeric text validations', async (t) => {
  const flow = new Flow({
    id: 1,
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        send_on_capture: true,
        image: { },
        inputs: [
          {
            id: 'first_name',
            title: 'Age',
            question_type: 'text',
            required: false,
            style: 'text',
            instructions: 'Age needs to be typed in',
            choice_list: [],
          },
          {
            id: 1453,
            storage_attribute: '',
            title: '',
            body: '',
            question_type: 'numeric',
            style: 'range',
            required: true,
            validation_expression: null,
            validation_details: null,
            instructions: '',
            choice_list: [],
            locked: null,
            max: 10,
            min: 5,
            max_label: 'Maximum value',
            min_label: 'Minimum value',
            interval: 1,
            labels: []
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '2',
                    operator: '<>',
                    value: '5',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '4',
                    operator: '=',
                    value: '3',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        instructions: 'do something on this step',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });
  const { first } = flow;
  first.set(1453, 23);
  first.set('first_name', 'My Name');
  await t.deepEqual(first.inputs[1].min, 5);
  await t.deepEqual(first.inputs[1].max, 10);
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path should throw error with empty required field', async (t) => {
  const flow = new Flow({
    id: 1,
    first_step: 11,
    steps: [
      {
        id: 11,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        send_on_capture: true,
        image: { },
        inputs: [
          {
            id: 'first_name',
            title: 'First Name',
            question_type: 'text',
            required: true,
            style: 'text',
            instructions: 'Age needs to be typed in',
            choice_list: [],
          },
          {
            id: 271,
            title: 'Is your facility affiliated with an SMO?',
            question_type: 'single_choice',
            style: 'radio_buttons',
            required: false,
            validation_expression: null,
            instructions: 'Is your facility affiliated with an SMO?',
            choice_list: [
              {
                id: 371,
                body: 'Yes',
              },
              {
                id: 372,
                body: 'No',
              },
            ],
            locked: null,
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 12,
                conditions: [
                  {
                    criteria: '2',
                    operator: '<>',
                    value: '5',
                  },
                ],
              },
              {
                step: 13,
                conditions: [
                  {
                    criteria: '4',
                    operator: '=',
                    value: '3',
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 12,
        title: 'dummy_5',
        description: 'dummy_6',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [
          {
            capture: false,
            button_name: 'Next',
            steps: [
              {
                step: 13,
                conditions: [],
              },
            ],
          },
        ],
      },
      {
        id: 13,
        title: 'dummy_5',
        description: 'dummy_6',
        instructions: 'do something on this step',
        content_type: 'info_screen_with_help',
        help: 'ALL text',
        image: { },
        inputs: [
          {
            title: 'First Name',
            question_type: 'text',
            style: '',
            choice_list: [],
            id: 'first_name',
          },
        ],
        paths: [],
      },
    ],
  });
  const { first } = flow;
  first.set(271, '371');
  first.set('first_name', '');
  try {
    await first.go('Next');
  } catch (e) {
    t.is(e.message, `Clinical6 FlowStep Helper error:`
    + ` cannot proceed to path 'Next' with empty required field(s)`
    + ` 'First Name' (id: first_name)`);
  }
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path with incorrect condition statements on flow.set', async (t) => {
  const { flowCond } = t.context;
  const { first } = flowCond;
  first.set(271, '371');
  first.set('first_name', 'My Name');
  const step = await first.go('Next');
  t.is(step.id, 12);
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path with incorrect condition statements on flowstep.set text', async (t) => {
  const { flowCond } = t.context;
  const { first } = flowCond;
  first.set(271, 'Yes');
  const step = await first.go('Next');
  t.is(step.id, 12);
  t.is(first.get(271), 371);
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path with incorrect condition statements on flow.set text', async (t) => {
  const { flowCond } = t.context;
  const { first } = flowCond;
  first.set(271, 'Yes');
  const step = await first.go('Next');
  t.is(step.id, 12);
  t.is(first.get(271), 371);
});

/**
 * @test {FlowStep.go}
 */
test('[unit] FlowStep.go to path ignoring case on flow.set text', async (t) => {
  const { flowCond } = t.context;
  const { first } = flowCond;
  first.set(271, 'yes');
  const step = await first.go('Next');
  t.is(step.id, 12);
  t.is(first.get(271), 371);
});

// Post Insights
/**
 * @test {Flow.postInsights}
 */
test('[unit] Flow.postInsights method should exist', (t) => {
  const { flowInsights } = t.context;
  t.truthy(flowInsights.postInsights);
});

// Save
/**
 * @test {Flow.save}
 */
test('[unit] Flow.save method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.save);
});

/**
 * @test {Flow.save}
 */
test('[unit] Flow.save method should return a promise', (t) => {
  const { flowSimple } = t.context;
  flowSimple.set('username', 'jdoe');
  t.truthy(flowSimple.save().then);
});

/**
 * @test {Flow.saveFlowAttributes}
 */
test('[unit] Flow.saveFlowAttributes method should update a flow', async (t) => {
  const { flowPatch } = t.context;
  const response = await flowPatch.saveFlowAttributes();

  t.is(response.id, 6);
  t.is(response.type, 'data_collection__flow_processes');
  t.is(response.name, 'Updated');
  t.is(response.description, 'Updated flow description');
  t.is(response.permanentLink, 'dummy_77');
  t.is(response.consentCredentials, null);
  t.is(response.createdAt, '2018-08-19T22:03:19Z');
  t.is(response.updatedAt, '2018-08-19T22:03:20Z');
  t.is(response.ownerType, 'MobileUser');
  t.is(response.publishedAt, null);
  t.is(response.conditionalPaths, null);
  t.is(response.steps.length, 0);
  t.deepEqual(response.steps, []);
  t.is(response.published, null);
  t.is(response.draft, null);
  t.is(response.first_step, null);
});

// Set
/**
 * @test {Flow.set}
 */
test('[unit] Flow.set method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.set);
});

// Reset
/**
 * @test {Flow.reset}
 */
test('[unit] Flow.reset method should exist', (t) => {
  const { flowSimple } = t.context;
  t.truthy(flowSimple.reset);
});

/**
 * @test {Flow.reset}
 */
test('[unit] Flow.reset method should reset to id, name, first, and steps', async (t) => {
  client.config.track.flows = false;
  const { flowReset } = t.context;
  const { first } = flowReset;
  first.set(271, '371');
  first.set('first_name', 'My Name');
  await first.go('Next');
  t.is(flowReset._toSave.length, 2);
  t.is(flowReset._fields.first_name.value, 'My Name');
  flowReset.reset();
  t.is(flowReset._toSave.length, 0);
  t.falsy(flowReset._fields.first_name.value);
  t.is(flowReset.id, 1);
  t.is(flowReset.name, 'Dummy Flow');
  t.is(flowReset.first.id, 11);
  t.is(flowReset.steps.length, 3);
});