<commit_before>require 'spec_helper'

class WechatController < ApplicationController
  wechat_responder
end

RSpec.describe WechatController, type: :controller do
  def xml_to_hash(response)
    Hash.from_xml(response.body)['xml'].symbolize_keys
  end

  render_views

  let(:signature_params) do
    timestamp = '1234567'
    nonce = 'nonce'
    signature = Digest::SHA1.hexdigest([ENV['WECHAT_TOKEN'], timestamp, nonce].sort.join)
    { timestamp: timestamp, nonce: nonce, signature: signature }
  end

  let(:message_base) do
    {
      ToUserName: 'toUser',
      FromUserName: 'fromUser',
      CreateTime: '1348831860',
      MsgId: '1234567890123456'
    }
  end

  let(:text_message) { message_base.merge(MsgType: 'text', Content: 'text message') }

  specify 'config responder using global config' do
    expect(controller.class.wechat).to eq(Wechat.api)
    expect(controller.class.token).to eq(Wechat.config.token)
  end

  describe 'config responder using per controller configuration' do
    controller do
      wechat_responder appid: 'controller_appid', secret: 'controller_secret', token: 'controller_token',
                       access_token: 'controller_access_token',
                       agentid: 1, encoding_aes_key: 'encoding_aes_key'
    end
    specify 'will set controller wechat api and token' do
      access_token = controller.class.wechat.access_token
      expect(access_token.appid).to eq('controller_appid')
      expect(access_token.secret).to eq('controller_secret')
      expect(access_token.token_file).to eq('controller_access_token')
      expect(controller.class.token).to eq('controller_token')
      expect(controller.class.agentid).to eq(1)
      expect(controller.class.encrypt_mode).to eq(false)
      expect(controller.class.encoding_aes_key).to eq('encoding_aes_key')
    end
  end

  describe 'Verify signature' do
    specify 'on show action' do
      get :show, signature_params.merge(signature: 'invalid_signature')
      expect(response.code).to eq('403')
    end

    specify 'on create action' do
      post :create, signature_params.merge(signature: 'invalid_signature')
      expect(response.code).to eq('403')
    end
  end

  specify "echo 'echostr' param when show" do
    get :show, signature_params.merge(echostr: 'hello')
    expect(response.body).to eq('hello')
  end

  describe 'responders' do
    specify 'responders only accept :text, :image, :voice, :video, :location, :link, :event, :fallback message type' do
      [:text, :image, :voice, :video, :location, :link, :event, :fallback].each do |message_type|
        controller.class.on message_type, respond: 'response'
      end
    end

    specify 'will raise error if message type is unkonwn' do
      expect { controller.class.on :unkonwn, respond: 'response' }.to raise_error
    end

    specify 'responder take :with argument only for :text and :event message_type' do
      expect(controller.class.on :text, with: 'command', respond: 'response').to eq(with: 'command', respond: 'response')
      expect(controller.class.on :event, with: 'subscribe').to eq(with: 'subscribe')
      expect { controller.class.on :image, with: 'with' }.to raise_error
    end
  end

  describe 'responder_for' do
    controller do
      wechat_responder
      on :text,  with: 'command', respond: 'string matched'
      on :text,  with: /^cmd:(.*)$/, respond: 'regex matched'
      on :text,  respond: 'text content'
      on :event, with: 'subscribe', respond: 'subscribe event'
      on :image, respond: 'image content'
    end

    specify 'find first responder for matched type' do
      expect do |b|
        controller.class.responder_for(MsgType: 'image', &b)
      end.to yield_with_args(respond: 'image content')
    end

    specify "find 'general text' responder if none of the text responders matches request content" do
      expect do |b|
        controller.class.responder_for(MsgType: 'text', Content: 'some text', &b)
      end.to yield_with_args({ respond: 'text content' }, 'some text')
    end

    specify "find 'string matched' responder if request content matches string" do
      expect do |b|
        controller.class.responder_for(MsgType: 'text', Content: 'command', &b)
      end.to yield_with_args({ respond: 'string matched', with: 'command' }, 'command')
    end

    specify "find 'regex mached' responder if request content matches regex" do
      expect do |b|
        controller.class.responder_for(MsgType: 'text', Content: 'cmd:my_command', &b)
      end.to yield_with_args({ respond: 'regex matched', with: /^cmd:(.*)$/ }, 'my_command')
    end

    specify "find 'subscribe event' responder if event request matches event" do
      expect do |b|
        controller.class.responder_for(MsgType: 'event', Event: 'subscribe', &b)
      end.to yield_with_args({ respond: 'subscribe event', with: 'subscribe' }, 'subscribe')
    end
  end

  specify 'will respond empty if no responder for the message type' do
    post :create, signature_params.merge(xml: text_message)
    expect(response.code).to eq('200')
    expect(response.body.strip).to be_empty
  end

  describe 'respond_to wechat_url helper' do
    controller do
      wechat_responder
      on :text do |_message, _content|
        wechat_url
      end
    end

    specify 'will return normal' do
      expect do
        post :create, signature_params.merge(xml: text_message)
      end.not_to raise_error
    end
  end

  describe 'fallback responder' do<commit_msg>Two new test case to cover wechat helper and click in public account<commit_after>require 'spec_helper'

class WechatController < ApplicationController
  wechat_responder
end

RSpec.describe WechatController, type: :controller do
  def xml_to_hash(response)
    Hash.from_xml(response.body)['xml'].symbolize_keys
  end

  render_views

  let(:signature_params) do
    timestamp = '1234567'
    nonce = 'nonce'
    signature = Digest::SHA1.hexdigest([ENV['WECHAT_TOKEN'], timestamp, nonce].sort.join)
    { timestamp: timestamp, nonce: nonce, signature: signature }
  end

  let(:message_base) do
    {
      ToUserName: 'toUser',
      FromUserName: 'fromUser',
      CreateTime: '1348831860',
      MsgId: '1234567890123456'
    }
  end

  let(:text_message) { message_base.merge(MsgType: 'text', Content: 'text message') }

  specify 'config responder using global config' do
    expect(controller.class.wechat).to eq(Wechat.api)
    expect(controller.class.token).to eq(Wechat.config.token)
  end

  describe 'config responder using per controller configuration' do
    controller do
      wechat_responder appid: 'controller_appid', secret: 'controller_secret', token: 'controller_token',
                       access_token: 'controller_access_token',
                       agentid: 1, encoding_aes_key: 'encoding_aes_key'
    end
    specify 'will set controller wechat api and token' do
      access_token = controller.class.wechat.access_token
      expect(access_token.appid).to eq('controller_appid')
      expect(access_token.secret).to eq('controller_secret')
      expect(access_token.token_file).to eq('controller_access_token')
      expect(controller.class.token).to eq('controller_token')
      expect(controller.class.agentid).to eq(1)
      expect(controller.class.encrypt_mode).to eq(false)
      expect(controller.class.encoding_aes_key).to eq('encoding_aes_key')
    end
  end

  describe 'Verify signature' do
    specify 'on show action' do
      get :show, signature_params.merge(signature: 'invalid_signature')
      expect(response.code).to eq('403')
    end

    specify 'on create action' do
      post :create, signature_params.merge(signature: 'invalid_signature')
      expect(response.code).to eq('403')
    end
  end

  specify "echo 'echostr' param when show" do
    get :show, signature_params.merge(echostr: 'hello')
    expect(response.body).to eq('hello')
  end

  describe 'responders' do
    specify 'responders only accept :text, :image, :voice, :video, :location, :link, :event, :fallback message type' do
      [:text, :image, :voice, :video, :location, :link, :event, :fallback].each do |message_type|
        controller.class.on message_type, respond: 'response'
      end
    end

    specify 'will raise error if message type is unkonwn' do
      expect { controller.class.on :unkonwn, respond: 'response' }.to raise_error
    end

    specify 'responder take :with argument only for :text and :event message_type' do
      expect(controller.class.on :text, with: 'command', respond: 'response').to eq(with: 'command', respond: 'response')
      expect(controller.class.on :event, with: 'subscribe').to eq(with: 'subscribe')
      expect { controller.class.on :image, with: 'with' }.to raise_error
    end
  end

  describe 'responder_for' do
    controller do
      wechat_responder
      on :text,  with: 'command', respond: 'string matched'
      on :text,  with: /^cmd:(.*)$/, respond: 'regex matched'
      on :text,  respond: 'text content'
      on :event, with: 'subscribe', respond: 'subscribe event'
      on :click, with: 'EVENTKEY', respond: 'EVENTKEY clicked'
      on :image, respond: 'image content'
    end

    specify 'find first responder for matched type' do
      expect do |b|
        controller.class.responder_for(MsgType: 'image', &b)
      end.to yield_with_args(respond: 'image content')
    end

    specify "find 'general text' responder if none of the text responders matches request content" do
      expect do |b|
        controller.class.responder_for(MsgType: 'text', Content: 'some text', &b)
      end.to yield_with_args({ respond: 'text content' }, 'some text')
    end

    specify "find 'string matched' responder if request content matches string" do
      expect do |b|
        controller.class.responder_for(MsgType: 'text', Content: 'command', &b)
      end.to yield_with_args({ respond: 'string matched', with: 'command' }, 'command')
    end

    specify "find 'regex mached' responder if request content matches regex" do
      expect do |b|
        controller.class.responder_for(MsgType: 'text', Content: 'cmd:my_command', &b)
      end.to yield_with_args({ respond: 'regex matched', with: /^cmd:(.*)$/ }, 'my_command')
    end

    specify "find 'subscribe event' responder if event request matches event" do
      expect do |b|
        controller.class.responder_for(MsgType: 'event', Event: 'subscribe', &b)
      end.to yield_with_args({ respond: 'subscribe event', with: 'subscribe' }, 'subscribe')
    end

    specify "find 'click' responder if event request matches click" do
      expect do |b|
        controller.class.responder_for(MsgType: 'event', Event: 'click', EventKey: 'EVENTKEY', &b)
      end.to yield_with_args({ respond: 'EVENTKEY clicked', with: 'EVENTKEY' }, 'EVENTKEY')
    end
  end

  specify 'will respond empty if no responder for the message type' do
    post :create, signature_params.merge(xml: text_message)
    expect(response.code).to eq('200')
    expect(response.body.strip).to be_empty
  end

  describe 'respond_to wechat helper' do
    controller do
      wechat_responder
      on :text do |_message, _content|
        wechat
      end
    end

    specify 'will return normal' do
      expect do
        post :create, signature_params.merge(xml: text_message)
      end.not_to raise_error
    end
  end

  describe 'respond_to wechat_url helper' do
    controller do
      wechat_responder
      on :text do |_message, _content|
        wechat_url
      end
    end

    specify 'will return normal' do
      expect do
        post :create, signature_params.merge(xml: text_message)
      end.not_to raise_error
    end
  end

  describe 'fallback responder' do
{'fraction_non_alphanumeric': 0.10859883521754025, 'fraction_numerical': 0.007708119218910586, 'mean_word_length': 3.468809797168006, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 11}, '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': '1666127', 'n_tokens_mistral': 3599, 'n_tokens_neox': 3501, 'n_words': 1030}