require "rails_helper"

RSpec.describe "Signup", type: :feature do
  let(:user) { create :user }

  describe "Invitation handling" do
    before do
      @unused_invitation = Invitation.create(user: user)
      @used_invitation   = Invitation.create(user: user)
      @used_invitation.update_attribute :used_at, DateTime.now - 1.day
    end

    scenario "Follow link for non-existing invitation" do
      visit invitation_url(id: "123")

      within ".flash-msg.alert" do
        expect(page).to have_content("doesn't exist")
      end
    end

    scenario "Follow link for used invitation" do
      visit invitation_url(id: @used_invitation.token)

      within ".flash-msg.alert" do
        expect(page).to have_content("has already been used")
      end
    end

    scenario "Follow link for unused invitation" do
      visit invitation_url(id: @unused_invitation.token)

      expect(current_url).to eq(signup_url)
      expect(page).to have_content("Welcome")
    end
  end

  describe "Signup steps" do
    before do
      @invitation = Invitation.create(user: user)
      visit invitation_url(id: @invitation.token)
      click_link "Get started"
    end

    scenario "Successful signup (happy path galore)" do
      expect(page).to have_content("Choose a username")

      fill_in "user_cn", with: "tony"
      click_button "Continue"
      expect(page).to have_content("What's your email?")

      fill_in "user_email", with: "tony@example.com"
      click_button "Continue"
      expect(page).to have_content("Choose a password")

      expect(CreateAccount).to receive(:call)
        .with(account: {
          username: "tony", domain: "kosmos.org",
          email: "tony@example.com", password: "a-valid-password",
          invitation: Invitation.last
        }).and_return(true)

      fill_in "user_password", with: "a-valid-password"
      click_button "Create account"
      within ".flash-msg.notice" do
        expect(page).to have_content("confirm your address")
      end
      expect(page).to have_content("close this window or tab now")
    end

    scenario "Validation errors" do
      fill_in "user_cn", with: "t"
      click_button "Continue"
      expect(page).to have_content("Username is too short")
      fill_in "user_cn", with: "-tony"
      click_button "Continue"
      expect(page).to have_content("Username is invalid")
      fill_in "user_cn", with: "$atoshi"
      click_button "Continue"
      expect(page).to have_content("Username is invalid")
      fill_in "user_cn", with: "jimmy"
      click_button "Continue"
      expect(page).to have_content("Username has already been taken")
      fill_in "user_cn", with: "tony"
      click_button "Continue"

      fill_in "user_email", with: "tony@"
      click_button "Continue"
      expect(page).to have_content("Email is invalid")
      fill_in "user_email", with: ""
      click_button "Continue"
      expect(page).to have_content("Email can't be blank")
      fill_in "user_email", with: "tony@example.com"
      click_button "Continue"

      fill_in "user_password", with: "123456"
      click_button "Create account"
      expect(page).to have_content("Password is too short")

      expect(CreateAccount).to receive(:call)
        .with(account: {
          username: "tony", domain: "kosmos.org",
          email: "tony@example.com", password: "a-valid-password",
          invitation: Invitation.last
        }).and_return(true)

      fill_in "user_password", with: "a-valid-password"
      click_button "Create account"
      within ".flash-msg.notice" do
        expect(page).to have_content("confirm your address")
      end
    end

    scenario "Reserved usernames" do
      fill_in "user_cn", with: "accounts"
      click_button "Continue"
      expect(page).to have_content("Username has already been taken")
    end
  end
end
