aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test/concern_test.rb
blob: 4b3cfcd1d2edadc6f40562046f70fc6c3a65cfa0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# frozen_string_literal: true

require "abstract_unit"
require "active_support/concern"

class ConcernTest < ActiveSupport::TestCase
  module Baz
    extend ActiveSupport::Concern

    class_methods do
      def baz
        "baz"
      end

      def included_ran=(value)
        @@included_ran = value
      end

      def included_ran
        @@included_ran
      end
    end

    included do
      self.included_ran = true
    end

    def baz
      "baz"
    end
  end

  module Bar
    extend ActiveSupport::Concern

    include Baz

    module ClassMethods
      def baz
        "bar's baz + " + super
      end
    end

    def bar
      "bar"
    end

    def baz
      "bar+" + super
    end
  end

  module Foo
    extend ActiveSupport::Concern

    include Bar, Baz
  end

  module Qux
    module ClassMethods
    end
  end

  def setup
    @klass = Class.new
  end

  def test_module_is_included_normally
    @klass.include(Baz)
    assert_equal "baz", @klass.new.baz
    assert_includes @klass.included_modules, ConcernTest::Baz
  end

  def test_class_methods_are_extended
    @klass.include(Baz)
    assert_equal "baz", @klass.baz
    assert_equal ConcernTest::Baz::ClassMethods, (class << @klass; included_modules; end)[0]
  end

  def test_class_methods_are_extended_only_on_expected_objects
    ::Object.include(Qux)
    Object.extend(Qux::ClassMethods)
    # module needs to be created after Qux is included in Object or bug won't
    # be triggered
    test_module = Module.new do
      extend ActiveSupport::Concern

      class_methods do
        def test
        end
      end
    end
    @klass.include test_module
    assert_not_respond_to Object, :test
    Qux.class_eval do
      remove_const :ClassMethods
    end
  end

  def test_included_block_is_ran
    @klass.include(Baz)
    assert_equal true, @klass.included_ran
  end

  def test_modules_dependencies_are_met
    @klass.include(Bar)
    assert_equal "bar", @klass.new.bar
    assert_equal "bar+baz", @klass.new.baz
    assert_equal "bar's baz + baz", @klass.baz
    assert_includes @klass.included_modules, ConcernTest::Bar
  end

  def test_dependencies_with_multiple_modules
    @klass.include(Foo)
    assert_equal [ConcernTest::Foo, ConcernTest::Bar, ConcernTest::Baz], @klass.included_modules[0..2]
  end

  def test_raise_on_multiple_included_calls
    assert_raises(ActiveSupport::Concern::MultipleIncludedBlocks) do
      Module.new do
        extend ActiveSupport::Concern

        included do
        end

        included do
        end
      end
    end
  end

  def test_no_raise_on_same_included_call
    assert_nothing_raised do
      2.times do
        load File.expand_path("../fixtures/concern/some_concern.rb", __FILE__)
      end
    end
  end
end