require 'spec_helper'

describe Signup do
  it "complies with the activemodel api" do
    subject.class.should be_kind_of(ActiveModel::Naming)
    should_not be_persisted
    should be_kind_of(ActiveModel::Conversion)
    should be_kind_of(ActiveModel::Validations)
  end
end

describe Signup, "with attributes in the constructor" do
  subject { Signup.new(:user_name => 'Joe', :account_name => 'blokes', :keyword => 'blk') }
  it "assigns attributes" do
    subject.user_name.should == 'Joe'
    subject.account_name.should == 'blokes'
    subject.keyword.should == 'blk'
  end
end

share_examples_for "invalid signup" do
  before { @previous_user_count = User.count }

  it "returns false" do
    @result.should be_false
  end

  it "doesn't create a user" do
    User.count.should == @previous_user_count
  end

  it "doesn't create an account" do
    subject.account.should be_new_record
  end
end

share_examples_for "valid signup" do
  it "returns true" do
    @result.should be_true
  end

  it "saves the account" do
    subject.account.should be_persisted
  end
end

describe Signup, "with a valid user and account" do
  it_should_behave_like "valid signup"
  let(:email) { "user@example.com" }
  subject { Factory.build(:signup, :email => email) }

  before do
    @result = subject.save
  end

  it "saves the user" do
    subject.user.should be_persisted
  end

  it "assigns the user to the account" do
    subject.user.reload.accounts.should include(subject.account)
  end

  it "creates an admin user" do
    subject.user.should be_admin_of(subject.account)
  end
end

describe Signup, "with a valid user but invalid account" do
  it_should_behave_like "invalid signup"
  subject { Factory.build(:signup, :account_name => "") }

  before do
    @result = subject.save
  end

  it "adds error messages" do
    subject.errors[:account_name].should_not be_empty
  end
end

describe Signup, "with an invalid user but valid account" do
  subject { Factory.build(:signup, :user_name => nil) }
  it_should_behave_like "invalid signup"

  before do
    @result = subject.save
  end

  it "adds error messages" do
    subject.errors[:user_name].should_not be_empty
  end
end

describe Signup, "with an invalid user and nvalid account" do
  subject { Factory.build(:signup, :user_name => nil, :account_name => nil) }
  it_should_behave_like "invalid signup"

  before do
    @result = subject.save
  end

  it "adds error messages for both" do
    subject.errors[:user_name].should_not be_empty
    subject.errors[:account_name].should_not be_empty
  end
end

describe Signup, "valid with an existing user and correct password" do
  it_should_behave_like "valid signup"
  let(:email) { "user@example.com" }
  let(:password) { "test" }
  let!(:user) { Factory(:user, :email                 => email,
                               :password              => password,
                               :password_confirmation => password) }
  subject { Factory.build(:signup, :email => email, :password => password) }
  before { @result = subject.save }

  it "doesn't create a user" do
    User.count.should == 1
  end

  it "assigns the user to the account as an admin" do
    user.reload.accounts.should include(subject.account)
    user.should be_admin_of(subject.account)
  end
end

describe Signup, "valid with a signed in user" do
  it_should_behave_like "valid signup"
  let!(:user) { Factory(:user) }
  subject { Factory.build(:signup, :user => user, :password => '') }
  before { @result = subject.save }

  it "doesn't create a user" do
    User.count.should == 1
  end

  it "assigns the user to the account as an admin" do
    user.reload.accounts.should include(subject.account)
    user.should be_admin_of(subject.account)
  end
end

describe Signup, "valid with an existing user and incorrect password" do
  it_should_behave_like "invalid signup"
  let(:email) { "user@example.com" }
  let(:password) { "test" }
  let!(:user) { Factory(:user, :email                 => email,
                               :password              => password,
                               :password_confirmation => password) }
  subject { Factory.build(:signup, :email => email, :password => 'wrong') }
  before { @result = subject.save }

  it "adds error messages" do
    subject.errors.full_messages.should include("Password is incorrect")
  end
end

describe Signup, "invalid with an existing user and correct password" do
  it_should_behave_like "invalid signup"
  let(:email) { "user@example.com" }
  let(:password) { "test" }
  let!(:user) { Factory(:user, :email                 => email,
                               :password              => password,
                               :password_confirmation => password) }
  subject { Factory.build(:signup, :account_name => '',
                                   :email        => email,
                                   :password     => password) }
  before { @result = subject.save }

  it "doesn't assign the user to the account" do
    user.reload.accounts.should_not include(subject.account)
  end
end