# -*- coding: utf-8 -*- require 'test_helper' class EmailCredentialTest < ActiveSupport::TestCase def setup @klass = EmailCredential @basic = @klass.new( :activation_token => "0" * @klass::TokenLength, :user_id => users(:yuya).id, :email => "foo@example.com", :hashed_password => ("0" * 8) + ":" + ("0" * 64)) @yuya_gmail = email_credentials(:yuya_gmail) @risa_example = email_credentials(:risa_example) end # # 関連 # test "belongs_to :user" do assert_equal( users(:yuya), @yuya_gmail.user) assert_equal( users(:risa), @risa_example.user) end # # 検証 # test "all fixtures are valid" do assert_equal(true, @klass.all.all?(&:valid?)) end test "basic is valid" do assert_equal(true, @basic.valid?) end test "validates_presence_of :email" do @basic.email = nil assert_equal(false, @basic.valid?) end =begin MEMO: before_validation_on_createによりテスト不可 test "validates_presence_of :activation_token" do @basic.activation_token = "" assert_equal(false, @basic.valid?) end =end test "validates_presence_of :hashed_password" do @basic.hashed_password = nil assert_equal(false, @basic.valid?) end test "validates_length_of :email" do # MEMO: 下記の制約を満たしつつ、文字列長の検証のテストを行う # * ローカルパートは64文字以内 # * ドメインパートは255文字以内 # * ドメインパートのドットで区切られたパートは63文字以内 [ ["a@b.cd.ef.com", 13, true ], [["a" * 64 + "@" + "b" * 63, "c" * 63, "d" * 3, "com"].join("."), 200, true ], [["a" * 64 + "@" + "b" * 63, "c" * 63, "d" * 4, "com"].join("."), 201, false], ].each { |value, length, expected| assert_equal(length, value.size) @basic.email = value assert_equal(expected, @basic.valid?) } end test "validates_format_of :activation_token" do [ ["0123456789abcdef0000", true ], ["0" * 19, false], ["0" * 20, true ], ["0" * 21, false], ["0" * 19 + "A", false], ["0" * 19 + "g", false], ].each { |value, expected| @basic.activation_token = value assert_equal(expected, @basic.valid?, value) } end test "validates_format_of :hashed_password" do [ # ソルト値部分 ["01234567" + ":" + "0" * 64, true ], ["89abcdef" + ":" + "0" * 64, true ], ["0000000" + ":" + "0" * 64, false], ["00000000" + ":" + "0" * 64, true ], ["000000000" + ":" + "0" * 64, false], ["0000000A" + ":" + "0" * 64, false], ["0000000g" + ":" + "0" * 64, false], # ハッシュ値部分 ["00000000" + ":" + "0123456789abcdef" + "0" * (64 - 16), true ], ["00000000" + ":" + "0" * (64 - 1), false], ["00000000" + ":" + "0" * 64, true ], ["00000000" + ":" + "0" * (64 + 1), false], ["00000000" + ":" + "0" * (64 - 1) + "A", false], ["00000000" + ":" + "0" * (64 - 1) + "g", false], ].each { |value, expected| @basic.hashed_password = value assert_equal(expected, @basic.valid?, value) } end test "validates_email_format_of :email" do [ ["foo@example.com", true ], ["foo@example.co.jp", true ], ["foo@example", false], ].each { |value, expected| @basic.email = value assert_equal( {:in => value, :out => expected}, {:in => value, :out => @basic.valid?}) } end test "validates_uniqueness_of :email, on create" do @basic.email = @yuya_gmail.email assert_equal(false, @basic.valid?) end test "validates_uniqueness_of :email, on update" do @yuya_gmail.email = @risa_example.email assert_equal(false, @yuya_gmail.valid?) end test "validates_each :user_id" do srand(0) user = users(:yuya) create_record = proc { user.email_credentials.create!( :activation_token => @klass.create_unique_activation_token, :email => "email#{rand(1000)}@example.com", :hashed_password => ("0" * 8) + ":" + ("0" * 64)) } assert_nothing_raised { (10 - user.email_credentials.size).times { record = create_record[] record.save! } } assert_raise(ActiveRecord::RecordInvalid) { create_record[] } end # # フック # test "before_validation_on_create, nil" do token = "9" * @klass::TokenLength record = @klass.new(@basic.attributes) record.activation_token = nil Kagemusha.new(@klass). defs(:create_unique_activation_token) { token }. swap { record.save! } assert_equal(token, record.reload.activation_token) end test "before_validation_on_create, empty string" do token = "9" * @klass::TokenLength record = @klass.new(@basic.attributes) record.activation_token = "" Kagemusha.new(@klass). defs(:create_unique_activation_token) { token }. swap { record.save! } assert_equal(token, record.reload.activation_token) end test "before_validation_on_create, already setting" do token = "9" * @klass::TokenLength record = @klass.new(@basic.attributes) record.activation_token = token record.save! assert_equal(token, record.reload.activation_token) end # # クラスメソッド # test "self.create_unique_activation_token, pattern" do assert_match( @klass::TokenPattern, @klass.create_unique_activation_token) end test "self.create_unique_activation_token, duplication" do dup_token1 = @yuya_gmail.activation_token dup_token2 = @risa_example.activation_token uniq_token = "f" * @klass::TokenLength tokens = [dup_token1, dup_token2, uniq_token] musha = Kagemusha.new(TokenUtil) musha.defs(:create_token) { tokens.shift } musha.swap { assert_equal( uniq_token, @klass.create_unique_activation_token) } end test "self.create_hashed_password" do assert_match( /\A[0-9a-f]{8}:[0-9a-f]{64}\z/, @klass.create_hashed_password("a")) # 異なるパスワードでは、異なる値になること assert_not_equal( @klass.create_hashed_password("a"), @klass.create_hashed_password("b")) # 同一のパスワードでも、異なる値になること assert_not_equal( @klass.create_hashed_password("a"), @klass.create_hashed_password("a")) end test "self.compare_hashed_password" do # ソルト、パスワードが一致 assert_equal( true, @klass.compare_hashed_password( "password", "00000000:" + Digest::SHA256.hexdigest("00000000:password"))) # ソルトが不一致、パスワードが一致 assert_equal( false, @klass.compare_hashed_password( "password", "00000000:" + Digest::SHA256.hexdigest("11111111:password"))) # ソルトが一致、パスワードが不一致 assert_equal( false, @klass.compare_hashed_password( "password", "00000000:" + Digest::SHA256.hexdigest("00000000:PASSWORD"))) end test "self.authenticate" do assert_equal( email_credentials(:yuya_gmail), @klass.authenticate(email_credentials(:yuya_gmail).email, "yuya_gmail")) assert_equal( nil, @klass.authenticate(email_credentials(:yuya_gmail).email, "YUYA_GMAIL")) assert_equal( nil, @klass.authenticate(nil, nil)) end # # インスタンスメソッド # test "authenticated?" do assert_equal(true, email_credentials(:yuya_gmail).authenticated?("yuya_gmail")) assert_equal(false, email_credentials(:yuya_gmail).authenticated?("YUYA_GMAIL")) assert_equal(false, email_credentials(:yuya_nayutaya).authenticated?("yuya_nayutaya")) end test "activated?" do assert_equal(true, email_credentials(:yuya_gmail).activated?) assert_equal(false, email_credentials(:yuya_nayutaya).activated?) end test "activate!" do credential = email_credentials(:yuya_nayutaya) time = Time.local(2010, 1, 1) assert_equal(false, credential.activated?) assert_equal(true, Kagemusha::DateTime.at(time) { credential.activate! }) credential.reload assert_equal(true, credential.activated?) assert_equal(time, credential.activated_at) end test "activate!, already activated" do credential = email_credentials(:yuya_gmail) time = credential.activated_at assert_equal(true, credential.activated?) assert_equal(false, credential.activate!) credential.reload assert_equal(true, credential.activated?) assert_equal(time, credential.activated_at) end test "login!" do time = Time.local(2010, 1, 1) assert_equal(nil, @risa_example.loggedin_at) Kagemusha::DateTime.at(time) { @risa_example.login! } assert_equal(time, @risa_example.reload.loggedin_at) end end