# frozen_string_literal: true require "assert" require "much-mixin" module MuchMixin class UnitTests < Assert::Context desc "MuchMixin" setup do @block1 = proc{ 1 } @block2 = proc{ 2 } @muchmixin = Module.new{ include MuchMixin } end subject{ @muchmixin } should have_imeths :much_mixin_included_detector should have_imeths :much_mixin_included_blocks should have_imeths :mixin_included, :after_mixin_included should "know its included detector" do mixin = subject.much_mixin_included_detector assert_instance_of Module, mixin assert_same mixin, subject.much_mixin_included_detector exp = subject::MuchMixinIncludedDetector assert_same exp, subject.much_mixin_included_detector end should "have no mix-in included blocks by default" do assert_empty subject.much_mixin_included_blocks assert_empty subject.much_mixin_after_included_blocks end should "append blocks" do subject.mixin_included(&@block1) subject.mixin_included(&@block2) assert_equal @block1, subject.much_mixin_included_blocks.first assert_equal @block2, subject.much_mixin_included_blocks.last end end class MixedInTests < UnitTests desc "when mixed in" setup do @receiver = Class.new do def self.inc_block1 @block1_count ||= 0 @block1_count += 1 end def self.block1_count @block1_count ||= 0 end def self.inc_block2 @block2_count ||= 0 @block2_count += 1 end def self.block2_count @block2_count ||= 0 end def self.do_something_count @do_something_count ||= 0 end end end should "call the mix-in included blocks" do assert_equal 0, @receiver.block1_count assert_equal 0, @receiver.block2_count assert_equal 0, @receiver.do_something_count @receiver.send(:include, TestMuchMixin) assert_equal 1, @receiver.block1_count assert_equal 1, @receiver.block2_count assert_equal 1, @receiver.do_something_count end should "call blocks only once no matter even if previously mixed in" do @receiver.send(:include, TestMuchMixin) assert_equal 1, @receiver.block1_count assert_equal 1, @receiver.block2_count assert_equal 1, @receiver.do_something_count @receiver.send(:include, TestMuchMixin) assert_equal 1, @receiver.block1_count assert_equal 1, @receiver.block2_count assert_equal 1, @receiver.do_something_count end should "call blocks only once even if mixed in by a 3rd party" do third_party = Module.new do def self.included(receiver) receiver.send(:include, TestMuchMixin) end end @receiver.send(:include, third_party) assert_equal 1, @receiver.block1_count assert_equal 1, @receiver.block2_count assert_equal 1, @receiver.do_something_count @receiver.send(:include, TestMuchMixin) assert_equal 1, @receiver.block1_count assert_equal 1, @receiver.block2_count assert_equal 1, @receiver.do_something_count @receiver.send(:include, third_party) assert_equal 1, @receiver.block1_count assert_equal 1, @receiver.block2_count assert_equal 1, @receiver.do_something_count end end TestMuchMixin = Module.new do include MuchMixin mixin_included{ inc_block1 } after_mixin_included do inc_block2 do_something end mixin_class_methods do def do_something @do_something_count ||= 0 @do_something_count += 1 end end end end