require 'test_helper'

class ApiKeysControllerTest < ActionDispatch::IntegrationTest
  context "An api keys controller" do
    setup do
      @user = create(:user)
      @api_key = create(:api_key, user: @user, request: nil)
    end

    context "#index action" do
      should "let a user see their own API keys" do
        get_auth user_api_keys_path(@user.id), @user

        assert_response :success
        assert_select "#api-key-#{@api_key.id}", count: 1
      end

      should "not let a user see API keys belonging to other users" do
        get_auth user_api_keys_path(@user.id), create(:user)

        assert_response :success
        assert_select "#api-key-#{@api_key.id}", count: 0
      end

      should "let the owner see all API keys" do
        get_auth user_api_keys_path(@user.id), create(:owner_user)

        assert_response :success
        assert_select "#api-key-#{@api_key.id}", count: 1
      end

      should "not return the key in the API" do
        get_auth user_api_keys_path(@user.id), @user, as: :json

        assert_response :success
        assert_nil response.parsed_body.first["key"]
      end

      should "redirect to the confirm password page if the user hasn't recently authenticated" do
        login_as(@user)
        travel_to 2.hours.from_now do
          get user_api_keys_path(@user.id)
        end

        assert_redirected_to confirm_password_session_path(url: user_api_keys_path(@user.id))
      end
    end

    context "#new action" do
      should "render for a Member user" do
        get_auth new_user_api_key_path(@user.id), @user
        assert_response :success
      end

      should "fail for an Anonymous user" do
        get new_user_api_key_path(@user.id)
        assert_response 403
      end
    end

    context "#create action" do
      should "create a new API key" do
        post_auth user_api_keys_path(@user.id), @user, params: { api_key: { name: "blah" }}

        assert_redirected_to user_api_keys_path(@user.id)
        assert_equal("blah", @user.api_keys.last.name)
        assert_equal(true, @user.user_events.api_key_create.exists?(login_session_id: @user.login_sessions.last.login_id))
      end
    end

    context "#edit action" do
      should "render for the API key owner" do
        get_auth edit_api_key_path(@api_key.id), @user
        assert_response :success
      end

      should "fail for someone else" do
        get_auth edit_api_key_path(@api_key.id), create(:user)
        assert_response 403
      end
    end

    context "#update action" do
      should "render for the API key owner" do
        put_auth api_key_path(@api_key.id), @user, params: { api_key: { name: "blah", permitted_ip_addresses: "1.2.3.4" }}

        assert_redirected_to user_api_keys_path(@user.id)
        assert_equal("blah", @api_key.reload.name)
        assert_equal(["1.2.3.4"], @api_key.permitted_ip_addresses.map(&:to_s))
        assert_equal(true, @user.user_events.api_key_update.exists?(login_session_id: @user.login_sessions.last.login_id))
      end

      should "fail for someone else" do
        put_auth api_key_path(@api_key.id), create(:user)
        assert_response 403
      end
    end

    context "#destroy" do
      should "delete the user's API key" do
        delete_auth api_key_path(@api_key.id), @user

        assert_redirected_to user_api_keys_path(@user.id)
        assert_raise(ActiveRecord::RecordNotFound) { @api_key.reload }
        assert_equal(true, @user.user_events.api_key_delete.exists?(login_session_id: @user.login_sessions.last.login_id))
      end

      should "not allow deleting another user's API key" do
        delete_auth api_key_path(@api_key.id), create(:user)

        assert_response 403
        assert_not_nil(@api_key.reload)
      end
    end
  end
end
