File: compiler.rb

package info (click to toggle)
ruby-cucumber-core 16.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 764 kB
  • sloc: ruby: 5,074; makefile: 2
file content (113 lines) | stat: -rw-r--r-- 3,581 bytes parent folder | download
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
# frozen_string_literal: true

require 'cucumber/core/test/case'
require 'cucumber/core/test/data_table'
require 'cucumber/core/test/doc_string'
require 'cucumber/core/test/empty_multiline_argument'
require 'cucumber/core/test/hook_step'
require 'cucumber/core/test/step'
require 'cucumber/core/test/tag'
require 'cucumber/messages'

module Cucumber
  module Core
    # Compiles the Pickles into test cases
    class Compiler
      attr_reader :receiver, :gherkin_query, :id_generator
      private     :receiver, :gherkin_query, :id_generator

      def initialize(receiver, gherkin_query, event_bus = nil)
        @receiver = receiver
        @id_generator = Cucumber::Messages::Helpers::IdGenerator::UUID.new
        @gherkin_query = gherkin_query
        @event_bus = event_bus
      end

      def pickle(pickle)
        test_case = create_test_case(pickle)
        test_case.describe_to(receiver)
      end

      def done
        receiver.done
        self
      end

      private

      def create_test_case(pickle)
        uri = pickle.uri
        test_steps = pickle.steps.map { |step| create_test_step(step, uri) }
        location = location_from_pickle(pickle)
        parent_locations = parent_locations_from_pickle(pickle)
        tags = tags_from_pickle(pickle, uri)
        Test::Case.new(id_generator.new_id, pickle.name, test_steps, location, parent_locations, tags, pickle.language).tap do |test_case|
          @event_bus&.test_case_created(test_case, pickle)
        end
      end

      def create_test_step(pickle_step, uri)
        location = location_from_pickle_step(pickle_step, uri)
        multiline_arg = create_multiline_arg(pickle_step, uri)
        Test::Step.new(id_generator.new_id, pickle_step.text, location, multiline_arg).tap do |test_step|
          @event_bus&.test_step_created(test_step, pickle_step)
        end
      end

      def create_multiline_arg(pickle_step, _uri)
        if pickle_step.argument
          if pickle_step.argument.doc_string
            doc_string_from_pickle_step(pickle_step)
          elsif pickle_step.argument.data_table
            data_table_from_pickle_step(pickle_step)
          end
        else
          Test::EmptyMultilineArgument.new
        end
      end

      def location_from_pickle(pickle)
        lines = pickle.ast_node_ids.map { |id| source_line(id) }
        Test::Location.new(pickle.uri, lines.sort.reverse)
      end

      def parent_locations_from_pickle(pickle)
        parent_lines = gherkin_query.scenario_parent_locations(pickle.ast_node_ids[0]).map(&:line)
        Test::Location.new(pickle.uri, parent_lines)
      end

      def location_from_pickle_step(pickle_step, uri)
        lines = pickle_step.ast_node_ids.map { |id| source_line(id) }
        Test::Location.new(uri, lines.sort.reverse)
      end

      def tags_from_pickle(pickle, uri)
        pickle.tags.map do |tag|
          location = Test::Location.new(uri, source_line(tag.ast_node_id))
          Test::Tag.new(location, tag.name)
        end
      end

      def source_line(id)
        gherkin_query.location(id).line
      end

      def doc_string_from_pickle_step(pickle_step)
        doc_string = pickle_step.argument.doc_string
        Test::DocString.new(
          doc_string.content,
          doc_string.media_type
        )
      end

      def data_table_from_pickle_step(pickle_step)
        data_table = pickle_step.argument.data_table
        Test::DataTable.new(
          data_table.rows.map do |row|
            row.cells.map(&:value)
          end
        )
      end
    end
  end
end