<commit_before>import MockDate from 'mockdate';
import initState from '../handlers/initState';
import choosingArticle from '../handlers/choosingArticle';
import choosingReply from '../handlers/choosingReply';
import askingReplyFeedback from '../handlers/askingReplyFeedback';
import askingArticleSubmissionConsent from '../handlers/askingArticleSubmissionConsent';
import askingReplyRequestReason from '../handlers/askingReplyRequestReason';
import { ManipulationError } from '../handlers/utils';
import handleInput from '../handleInput';
import tutorial, { TUTORIAL_STEPS } from '../handlers/tutorial';

import {
  SOURCE_PREFIX_FRIST_SUBMISSION,
  SOURCE_PREFIX_NOT_YET_REPLIED,
  REASON_PREFIX,
  DOWNVOTE_PREFIX,
  UPVOTE_PREFIX,
  VIEW_ARTICLE_PREFIX,
  getArticleURL,
  ARTICLE_SOURCE_OPTIONS,
} from 'src/lib/sharedUtils';

jest.mock('../handlers/initState');
jest.mock('../handlers/choosingArticle');
jest.mock('../handlers/choosingReply');
jest.mock('../handlers/askingReplyFeedback');
jest.mock('../handlers/askingArticleSubmissionConsent');
jest.mock('../handlers/askingReplyRequestReason');
jest.mock('../handlers/tutorial');

// Original session ID in context
const FIXED_DATE = 612964800000;

// If session is renewed, sessionId will become this value
const NOW = 1561982400000;

beforeEach(() => {
  initState.mockClear();
  choosingArticle.mockClear();
  choosingReply.mockClear();
  askingReplyFeedback.mockClear();
  askingArticleSubmissionConsent.mockClear();
  askingReplyRequestReason.mockClear();
  tutorial.mockClear();
  MockDate.set(NOW);
});

afterEach(() => {
  MockDate.reset();
});

it('rejects undefined input', () => {
  const data = {};
  const event = {};

  return expect(handleInput(data, event)).rejects.toMatchInlineSnapshot(
    `[Error: input undefined]`
  );
});

it('invokes state handler specified by event.postbackHandlerState', async () => {
  const context = {
    data: { sessionId: FIXED_DATE },
  };
  const event = {
    type: 'postback',
    postbackHandlerState: 'CHOOSING_REPLY',
    input: 'reply-id',
  };

  choosingReply.mockImplementationOnce(params => {
    // it doesn't return `state`, discard it
    // eslint-disable-next-line no-unused-vars
    const { state, ...restParams } = params;
    return Promise.resolve({
      ...restParams,
      isSkipUser: false,
      replies: 'Foo replies',
    });
  });

  await expect(handleInput(context, event)).resolves.toMatchInlineSnapshot(`
          Object {
            "context": Object {
              "data": Object {
                "sessionId": 612964800000,
              },
            },
            "replies": "Foo replies",
          }
        `);

  expect(choosingArticle).not.toHaveBeenCalled();
  expect(choosingReply).toHaveBeenCalledTimes(1);
});

it('shows reply list when VIEW_ARTICLE_PREFIX is sent', async () => {
  const context = {
    data: { sessionId: FIXED_DATE },
  };
  const event = {
    type: 'message',<commit_msg>[handleInput] extend postback test case to cover article submission flow<commit_after>import MockDate from 'mockdate';
import initState from '../handlers/initState';
import choosingArticle from '../handlers/choosingArticle';
import choosingReply from '../handlers/choosingReply';
import askingReplyFeedback from '../handlers/askingReplyFeedback';
import askingArticleSource from '../handlers/askingArticleSource';
import askingArticleSubmissionConsent from '../handlers/askingArticleSubmissionConsent';
import askingReplyRequestReason from '../handlers/askingReplyRequestReason';
import { ManipulationError } from '../handlers/utils';
import handleInput from '../handleInput';
import tutorial, { TUTORIAL_STEPS } from '../handlers/tutorial';

import {
  SOURCE_PREFIX_FRIST_SUBMISSION,
  SOURCE_PREFIX_NOT_YET_REPLIED,
  REASON_PREFIX,
  DOWNVOTE_PREFIX,
  UPVOTE_PREFIX,
  VIEW_ARTICLE_PREFIX,
  getArticleURL,
  ARTICLE_SOURCE_OPTIONS,
} from 'src/lib/sharedUtils';

jest.mock('../handlers/initState');
jest.mock('../handlers/choosingArticle');
jest.mock('../handlers/choosingReply');
jest.mock('../handlers/askingReplyFeedback');
jest.mock('../handlers/askingArticleSource');
jest.mock('../handlers/askingArticleSubmissionConsent');
jest.mock('../handlers/askingReplyRequestReason');
jest.mock('../handlers/tutorial');

// Original session ID in context
const FIXED_DATE = 612964800000;

// If session is renewed, sessionId will become this value
const NOW = 1561982400000;

beforeEach(() => {
  initState.mockClear();
  choosingArticle.mockClear();
  choosingReply.mockClear();
  askingReplyFeedback.mockClear();
  askingArticleSubmissionConsent.mockClear();
  askingReplyRequestReason.mockClear();
  tutorial.mockClear();
  MockDate.set(NOW);
});

afterEach(() => {
  MockDate.reset();
});

it('rejects undefined input', () => {
  const data = {};
  const event = {};

  return expect(handleInput(data, event)).rejects.toMatchInlineSnapshot(
    `[Error: input undefined]`
  );
});

it('invokes state handler specified by event.postbackHandlerState', async () => {
  const context = {
    data: { sessionId: FIXED_DATE },
  };

  for (const { postbackState, expectedHandler } of [
    // The states that are triggered by postback
    {
      postbackState: 'CHOOSING_REPLY',
      expectedHandler: choosingReply,
    },
    {
      postbackState: 'ASKING_ARTICLE_SOURCE',
      expectedHandler: askingArticleSource,
    },
    {
      postbackState: 'ASKING_ARTICLE_SUBMISSION_CONSENT',
      expectedHandler: askingArticleSubmissionConsent,
    },
  ]) {
    const event = {
      type: 'postback',
      postbackHandlerState: postbackState,
      input: 'Foo',
    };

    expectedHandler.mockImplementationOnce(() => {
      return Promise.resolve({
        // Bare minimal return values by handlers for handleInput to work without crash
        isSkipUser: false,
        replies: [],
      });
    });

    await handleInput(context, event);
    expect(expectedHandler).toHaveBeenCalledTimes(1);
  }

  // Expect that default state is not invoked
  expect(choosingArticle).not.toHaveBeenCalled();
});

it('shows reply list when VIEW_ARTICLE_PREFIX is sent', async () => {
  const context = {
    data: { sessionId: FIXED_DATE },
  };
  const event = {
    type: 'message',
{'fraction_non_alphanumeric': 0.13295910184442664, 'fraction_numerical': 0.010264635124298316, 'mean_word_length': 4.115668580803938, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4542940', 'n_tokens_mistral': 1983, 'n_tokens_neox': 1877, 'n_words': 383}