summaryrefslogtreecommitdiffstats
path: root/test/lib/spec/runner/context.rb
blob: 3155e169ae4f89ace12c7cfdb437a64997f3cb5e (plain)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
module Spec
  module Runner
    class ContextEvalModule < Module
    end
    class Context
      module InstanceMethods
        def initialize(description, &context_block)
          @description = description

          @context_eval_module = ContextEvalModule.new
          @context_eval_module.extend ContextEval::ModuleMethods
          @context_eval_module.include ContextEval::InstanceMethods
          before_context_eval
          @context_eval_module.class_eval(&context_block)
        end

        def before_context_eval
        end

        def inherit_context_eval_module_from(klass)
          @context_eval_module.inherit klass
        end
        alias :inherit :inherit_context_eval_module_from
        
        def include(mod)
          @context_eval_module.include(mod)
        end

        def run(reporter, dry_run=false)
          reporter.add_context(@description)
          prepare_execution_context_class
          errors = run_context_setup(reporter, dry_run)

          specifications.each do |specification|
            specification_execution_context = execution_context(specification)
            specification_execution_context.copy_instance_variables_from(@once_only_execution_context_instance, []) unless context_setup_block.nil?
            specification.run(reporter, setup_block, teardown_block, dry_run, specification_execution_context)
          end unless errors.length > 0
          
          run_context_teardown(reporter, dry_run)
        end

        def number_of_specs
          specifications.length
        end

        def matches?(full_description)
          matcher ||= SpecMatcher.new(@description)
          specifications.each do |spec|
            return true if spec.matches?(matcher, full_description)
          end
          return false
        end

        def run_single_spec(full_description)
          return if @description == full_description
          matcher = SpecMatcher.new(@description)
          specifications.reject! do |spec|
            !spec.matches?(matcher, full_description)
          end
        end

        def methods
          my_methods = super
          my_methods |= @context_eval_module.methods
          my_methods
        end

        protected

        def method_missing(*args)
          @context_eval_module.method_missing(*args)
        end

        def context_setup_block
          @context_eval_module.send :context_setup_block
        end

        def context_teardown_block
          @context_eval_module.send :context_teardown_block
        end

        def specifications
          @context_eval_module.send :specifications
        end

        def setup_block
          @context_eval_module.send :setup_block
        end

        def teardown_block
          @context_eval_module.send :teardown_block
        end

        def prepare_execution_context_class
          weave_in_context_modules
          execution_context_class
        end

        def weave_in_context_modules
          mods = context_modules
          context_eval_module = @context_eval_module
          execution_context_class.class_eval do
            include context_eval_module
            mods.each do |mod|
              include mod
            end
          end
        end

        def context_modules
          @context_eval_module.send :context_modules
        end

        def execution_context_class
          @context_eval_module.send :execution_context_class
        end

        def execution_context specification
          execution_context_class.new(specification)
        end

        def run_context_setup(reporter, dry_run)
          errors = []
          unless dry_run
            begin
              @once_only_execution_context_instance = execution_context(nil)
              @once_only_execution_context_instance.instance_eval(&context_setup_block)
            rescue => e
              errors << e
              location = "context_setup"
              reporter.spec_finished(location, e, location) if reporter
            end
          end
          errors
        end
        
        def run_context_teardown(reporter, dry_run)
          unless dry_run
            begin 
              @once_only_execution_context_instance ||= execution_context(nil) 
              @once_only_execution_context_instance.instance_eval(&context_teardown_block) 
            rescue => e
              location = "context_teardown"
              reporter.spec_finished(location, e, location) if reporter
            end
          end
        end

      end
      include InstanceMethods
    end
  end
end