require 'test_helper'

class DeveloperPortal::InvitationSignupTest < ActionDispatch::IntegrationTest
  include DeveloperPortal::Engine.routes.url_helpers

  Oauth2 = Authentication::Strategy::Oauth2

  def setup
    @provider   = FactoryGirl.create(:simple_provider)
    @buyer      = FactoryGirl.create(:simple_buyer, provider_account: @provider)
    @invitation = FactoryGirl.create(:invitation, account: @buyer)
    @auth_provider = FactoryGirl.create(:authentication_provider, account: @provider)

    host! @provider.domain
  end

  def test_request_formats
    get invitee_signup_path(invitation_token: @invitation.token, format: :html)
    assert_response :success
    
    assert_raise(ActionController::UnknownFormat) do
      get invitee_signup_path(invitation_token: @invitation.token, format: :xml)
    end
  end

  def test_builtin_page
    get invitee_signup_path(invitation_token: @invitation.token)
    assert_match 'Invitation sign in', response.body
    assert_not_match 'Custom title', response.body

    root = FactoryGirl.create(:root_cms_section, provider: @provider)
    FactoryGirl.create(:cms_builtin_page,
      provider:    @provider,
      section:     root,
      system_name: 'accounts/invitee_signups/show',
      published:   'Custom title'
    )

    get invitee_signup_path(invitation_token: @invitation.token)
    assert_not_match 'Invitation sign in', response.body
    assert_match 'Custom title', response.body
  end

  def test_auth0_sso_create
    user = FactoryGirl.create(:simple_user, account: @buyer)
    Oauth2.any_instance.expects(:authenticate).returns(user).at_least_once
    get "/auth/invitations/auth0/auth0_ab1234/callback?state=#{@invitation.token}"
    assert_response :redirect
    assert_equal 'Signed up successfully', flash[:notice]
  end

  def test_sso_create
    Oauth2.any_instance.stubs(:authentication_provider).returns(@auth_provider)
    Oauth2.any_instance.expects(:authenticate).returns(false).at_least_once
    get "/auth/invitations/#{@invitation.token}/github/callback"
    assert_response :success
    assert session[:invitation_sso_uid].blank?
    refute assigns(:user).valid?

    Oauth2.any_instance.expects(:user_data).returns({ uid: '12345' })
    get "/auth/invitations/#{@invitation.token}/github/callback"
    assert_response :success
    assert_equal '12345', session[:invitation_sso_uid]
    refute assigns(:user).valid?

    user = FactoryGirl.create(:simple_user, account: @buyer)
    Oauth2.any_instance.expects(:authenticate).returns(user).at_least_once
    get "/auth/invitations/#{@invitation.token}/github/callback"
    assert_response :redirect
    assert_equal 'Signed up successfully', flash[:notice]
  end

  def test_create
    Oauth2.any_instance.stubs(:authentication_provider).returns(@auth_provider)

    assert_difference '@buyer.users.count' do
      post invitee_signup_path(invitation_token: @invitation.token, user: user_valid_params)
      assert_response :redirect
      assert_empty @buyer.users(true).last.sso_authorizations
    end

    client = mock('client')
    client.stubs(authenticate!: { uid: 'alaska' })
    ThreeScale::OAuth2::Client.expects(:build).with(@auth_provider).returns(client)
    get "/auth/invitations/#{@invitation.token}/#{@auth_provider.system_name}/callback"

    assert_difference '@buyer.users.count' do
      post invitee_signup_path(invitation_token: @invitation.token, user: user_valid_params)
      assert_response :redirect
      assert_not_empty authorizations = @buyer.users(true).last.sso_authorizations
      assert_equal ['alaska'], authorizations.pluck(:uid)
    end
  end

  private

  def user_valid_params
    index = User.maximum(:id)

    {
      email:    "alex_#{index}@gmail.com",
      username: "alexander_#{index}",
      password: '123456'
    }
  end
end
