require File.dirname(__FILE__) + '/../spec_helper'

describe User do
  def valid_attributes
    {
      :full_name => 'Test User Name',
      :email => 'Test@UserName.com',
      :login => 'test',
      :time_zone => "WOW",
    
      :phone => "0408 505 1234",
  
      :password => 'test_password',
      :password_confirmation => 'test_password',
      :access_level => User::ACCESS_LEVEL_DISABLED
    }
  end
  
  it "should accept valid attributes" do
    User.new(valid_attributes).should be_valid
  end
  
  should_validate_presence_of :full_name
  should_validate_presence_of :email
  should_validate_presence_of :login
  should_validate_presence_of :time_zone
    
  describe "unique attributes" do
    before(:each) do
      User.create!(valid_attributes)
    end

    should_validate_uniqueness_of :email, :case_sensitive => false, :message=>"alread taken."    
    should_validate_uniqueness_of :login, :case_sensitive => false, :message=>"alread taken."    
  end  
  
  it "should require a password confirmation when password set" do
    user = User.new(valid_attributes.merge(:password_confirmation => '1'))
    user.should_not be_valid
  end

  it "should validate the password length as 4 characters" do
    user = User.new(valid_attributes.merge(:password => '123', :password_confirmation => '123'))
    user.should_not be_valid
    
    user = User.new(valid_attributes.merge(:password => '1234', :password_confirmation => '1234'))
    user.should be_valid
  end
    
  describe "password encryption" do    
    it "should encrypt the password before saving" do
      user = User.new(valid_attributes)
      user.crypted_password.should be_blank #receive(:make_encrypted_password) 
      user.save(false)
      user.crypted_password.should_not be_blank
    end
  
    it "should only change the encrypt password if it the password is set" do
      user = User.create(valid_attributes)
      pswd = user.crypted_password
      pswd.should_not be_blank
      user.password = nil
    
      user.save(false)
      user.crypted_password.should == pswd
    end
  
    it "should only change the encrypt password if it the password changed" do
      user = User.create(valid_attributes)
      pswd = user.crypted_password
      pswd.should_not be_blank
      user.password = 'silly_password_change'
      # user.password_confirmation = 'silly_password_change'
    
      user.save(false)
      user.crypted_password.should_not == pswd
      user.crypted_password.should_not be_blank
    end
  end
  
  describe "authenticate by email" do
    it "should fail if the email not found " do
      # user = User.create(valid_attributes)
      User.destroy_all
      User.authenticate_by_email(valid_attributes[:email], valid_attributes[:password]).should == nil
    end
    
    it "should fail if the passwords do not match" do
      user = User.create(valid_attributes)
      User.authenticate_by_email(valid_attributes[:email], valid_attributes[:password] + '_wrong').should == nil
    end
  
    it "should pass if email and password match" do
      user = User.create(valid_attributes)
      User.authenticate_by_email(valid_attributes[:email], valid_attributes[:password]).should == user
    end                   
  end

  describe "authenticate by login" do
    it "should fail if the login not found " do
      # user = User.create(valid_attributes)
      User.destroy_all
      User.authenticate_by_login(valid_attributes[:login], valid_attributes[:password]).should == nil
    end
    
    it "should fail if the passwords do not match" do
      user = User.create(valid_attributes)
      User.authenticate_by_login(valid_attributes[:login], valid_attributes[:password] + '_wrong').should == nil
    end
  
    it "should pass if login and password match" do
      user = User.create(valid_attributes)
      User.authenticate_by_login(valid_attributes[:login], valid_attributes[:password]).should == user
    end                   
  end
  
  
  describe "authenticate_by_remember_token" do
    it "should fail if the remember_token not found " do
      User.destroy_all
      User.authenticate_by_remember_token('invalid_token').should == nil
    end
    
    it "should fail if the remember_token has expired" do
      user = User.create(valid_attributes)
      now = Time.now
      
      Time.stub(:now).and_return(now - 31.days)
      user.set_remember_token
      
      Time.stub(:now).and_return(now)
      User.authenticate_by_remember_token(user.remember_token).should == nil      
    end

    it "should pass if remember token valid" do
      user = User.create(valid_attributes)
      user.set_remember_token
      User.authenticate_by_remember_token(user.remember_token).should == user
    end                   
  end

  describe "authenticate_by_reset_token" do
    it "should fail if the reset_token not found " do
      User.destroy_all
      User.authenticate_by_reset_token('invalid_token').should == nil
    end
    
    it "should fail if the reset_token has expired" do
      user = User.create(valid_attributes)
      now = Time.now
      
      Time.stub(:now).and_return(now - 3.days)
      User.set_reset_token(user.email)
      user.reload
      
      Time.stub(:now).and_return(now)
      User.authenticate_by_reset_token(user.reset_token).should == nil      
    end

    it "should pass if reset token valid" do
      user = User.create(valid_attributes)
      User.set_reset_token(user.email)
      user.reload
      
      User.authenticate_by_reset_token(user.reset_token).should == user
    end                   
  end

  describe "set remember token" do
    it "should set the remember token to expire in 30 days (UTC)" do
      now = Time.now
      Time.stub(:now).and_return(now)
      
      user = User.create(valid_attributes)
      user.set_remember_token
      user.remember_token_expires_at.should == 30.days.from_now.utc
    end
    
    it "should create a remember token" do
      user = User.create(valid_attributes)
      user.set_remember_token
      user.remember_token.should_not be_blank
    end
    
    it "should save the updated user to the database" do
      user = User.create(valid_attributes)
      user.should_receive(:save)
      user.set_remember_token
    end
  end  
  
  describe "reset remember token" do
    it "should reset the remember token and expiry" do
      user = User.create(valid_attributes)
      user.set_remember_token
      user.remember_token_expires_at.should_not be_nil
      user.remember_token.should_not be_nil
      
      user.reset_remember_token      
      user.remember_token_expires_at.should be_nil
      user.remember_token.should be_nil
    end
    
    it "should save the updated user to the database" do
      user = User.create(valid_attributes)
      user.should_receive(:save)
      user.reset_remember_token
    end
  end  

  describe "set reset token" do
    it "should return nil if the email was not found" do
      User.set_reset_token('invalid_email_address').should be_nil
    end

    it "should return the user that has been reset" do
      user = User.create(valid_attributes)
      User.set_reset_token(user.email).should == user
    end
    
    it "should set the reset token to expire in 2 days (UTC)" do
      now = Time.now
      Time.stub(:now).and_return(now)
      
      user = User.create(valid_attributes)
      User.set_reset_token(user.email).reset_token_expires_at.should == 2.days.from_now.utc
    end
    
    it "should create a reset token" do
      user = User.create(valid_attributes)
      User.set_reset_token(user.email).reset_token.should_not be_blank
    end
    
    it "should save the updated user to the database" do
      user = User.create(valid_attributes)
      User.stub(:find).and_return(user)
      user.should_receive(:save)
      
      User.set_reset_token(user.email)
    end
    
    it "should clear the reset token when the password is updated" do
      user = User.create(valid_attributes)
      User.set_reset_token(user.email)
      
      user.reload
      user.reset_token.should_not be_blank
      user.update_attributes(:password => 'new_password', :password_confirmation => 'new_password')
      
      user.reset_token.should be_blank
    end
  end  
end