cucumber-tag_expressions 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c110df95d190c0a1d3b095047f4cb8a5405f24fe
4
+ data.tar.gz: e7aebcd8817b969606fd48198c4278cdf857bf12
5
+ SHA512:
6
+ metadata.gz: 4fbb8f528b3aaa7a2834c507bacadd14280d5dd4fb6574bf70040de7e82557653e7d821687dbbd3d8469453fe36d5c7a486a563f3e63e2d2ec3ade5ed444d701
7
+ data.tar.gz: 8456e8c30676c993b153643658b77da11d5b31ef2a2faee2e3ce62f65c7901d3f26460a0aa5417db4effafe8876e53aaed6b467e97b717858e16dc4160e073cd
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,17 @@
1
+ # manyrepo: cucumber/tag-expressions-ruby
2
+ language: ruby
3
+ sudo: false
4
+
5
+ rvm:
6
+ - 2.3.1
7
+ - 2.2
8
+ - 2.1
9
+ - 2.0
10
+ - jruby-9.1.2.0
11
+
12
+ before_install:
13
+ - gem update bundler
14
+
15
+ notifications:
16
+ email:
17
+ - cukes-devs@googlegroups.com
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Cucumber Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ LICENSE: ../../LICENSE
2
+ cp $< $@
3
+
4
+ .PHONY: release
5
+ release:
6
+ gem push cucumber-tag_expressions.gemspec
7
+ version=$$(cat cucumber-tag_expressions.gemspec | grep -m 1 ".version *= *" | sed "s/.*= *'\([^']*\)'.*/\1/"); \
8
+ git tag --annotate v$$version --message "Release $$version"
@@ -0,0 +1,3 @@
1
+ # Cucumber Tag Expressions for Ruby
2
+
3
+ [The docs are here](http://docs.cucumber.io/tag-expressions/).
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
7
+
8
+ require 'rspec/core/rake_task'
9
+ RSpec::Core::RakeTask.new(:spec) do |t|
10
+ t.ruby_opts = %w(-r./spec/coverage -w)
11
+ end
12
+
13
+ task default: ['spec']
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |s|
3
+ s.name = 'cucumber-tag_expressions'
4
+ s.version = '1.0.0'
5
+ s.authors = ['Andrea Nodari']
6
+ s.description = 'Cucumber tag expressions for ruby'
7
+ s.summary = "#{s.name}-#{s.version}"
8
+ s.email = 'cukes@googlegroups.com'
9
+ s.homepage = 'https://docs.cucumber.io/tag-expressions/'
10
+ s.platform = Gem::Platform::RUBY
11
+ s.license = 'MIT'
12
+ s.required_ruby_version = '>= 1.9.3'
13
+
14
+ s.add_development_dependency 'bundler', '>= 1.12.5'
15
+ s.add_development_dependency 'rake', '>= 10.5.0'
16
+ s.add_development_dependency 'rspec', '~> 3.5'
17
+
18
+ # For coverage reports
19
+ s.add_development_dependency 'coveralls', '~> 0.7'
20
+
21
+ s.rubygems_version = '>= 1.6.1'
22
+ s.files = `git ls-files`.split("\n").reject { |path| path =~ /\.gitignore$/ }
23
+ s.test_files = `git ls-files -- spec/*`.split("\n")
24
+ s.rdoc_options = ['--charset=UTF-8']
25
+ s.require_path = 'lib'
26
+ end
@@ -0,0 +1 @@
1
+ require 'cucumber/tag_expressions/parser'
@@ -0,0 +1,65 @@
1
+ module Cucumber
2
+ module TagExpressions
3
+ # Literal expression node
4
+ class Literal
5
+ def initialize(value)
6
+ @value = value
7
+ end
8
+
9
+ def evaluate(variables)
10
+ variables.include?(@value)
11
+ end
12
+
13
+ def to_s
14
+ @value
15
+ end
16
+ end
17
+
18
+ # Not expression node
19
+ class Not
20
+ def initialize(expression)
21
+ @expression = expression
22
+ end
23
+
24
+ def evaluate(variables)
25
+ !@expression.evaluate(variables)
26
+ end
27
+
28
+ def to_s
29
+ "not ( #{@expression} )"
30
+ end
31
+ end
32
+
33
+ # Or expression node
34
+ class Or
35
+ def initialize(left, right)
36
+ @left = left
37
+ @right = right
38
+ end
39
+
40
+ def evaluate(variables)
41
+ @left.evaluate(variables) || @right.evaluate(variables)
42
+ end
43
+
44
+ def to_s
45
+ "( #{@left} or #{@right} )"
46
+ end
47
+ end
48
+
49
+ # And expression node
50
+ class And
51
+ def initialize(left, right)
52
+ @left = left
53
+ @right = right
54
+ end
55
+
56
+ def evaluate(variables)
57
+ @left.evaluate(variables) && @right.evaluate(variables)
58
+ end
59
+
60
+ def to_s
61
+ "( #{@left} and #{@right} )"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,115 @@
1
+ require 'cucumber/tag_expressions/expressions.rb'
2
+
3
+ module Cucumber
4
+ module TagExpressions
5
+ # Ruby tag expression parser
6
+ class Parser
7
+ def initialize
8
+ @expressions = []
9
+ @operations = []
10
+
11
+ @components = {
12
+ 'or' => { type: :operation, precedence: 0, assoc: :left },
13
+ 'and' => { type: :operation, precedence: 1, assoc: :left },
14
+ 'not' => { type: :operation, precedence: 2, assoc: :right },
15
+ ')' => { type: :close_paren, precedence: -1 },
16
+ '(' => { type: :open_paren, precedence: 1 }
17
+ }
18
+ end
19
+
20
+ def parse(infix_expression)
21
+ process_tokens!(infix_expression)
22
+ while @operations.any?
23
+ raise 'Unclosed (' if @operations.last == '('
24
+ push_expression(pop(@operations))
25
+ end
26
+ expression = pop(@expressions)
27
+ @expressions.empty? ? expression : raise('Not empty')
28
+ end
29
+
30
+ private
31
+
32
+ ############################################################################
33
+ # Helpers
34
+ #
35
+ def assoc_of(token, value)
36
+ @components[token][:assoc] == value
37
+ end
38
+
39
+ def lower_precedence?(operation)
40
+ (assoc_of(operation, :left) &&
41
+ prec(operation) <= prec(@operations.last)) ||
42
+ (assoc_of(operation, :right) &&
43
+ prec(operation) < prec(@operations.last))
44
+ end
45
+
46
+ def operation?(token)
47
+ @components[token][:type] == :operation
48
+ end
49
+
50
+ def prec(token)
51
+ @components[token][:precedence]
52
+ end
53
+
54
+ def tokens(infix_expression)
55
+ infix_expression.gsub(/\(/, ' ( ').gsub(/\)/, ' ) ').strip.split(/\s+/)
56
+ end
57
+
58
+ def process_tokens!(infix_expression)
59
+ tokens(infix_expression).each do |token|
60
+ if @components[token]
61
+ send("handle_#{@components[token][:type]}", token)
62
+ else
63
+ handle_literal(token)
64
+ end
65
+ end
66
+ end
67
+
68
+ def push_expression(token)
69
+ case token
70
+ when 'and'
71
+ @expressions.push(And.new(*pop(@expressions, 2)))
72
+ when 'or'
73
+ @expressions.push(Or.new(*pop(@expressions, 2)))
74
+ when 'not'
75
+ @expressions.push(Not.new(pop(@expressions)))
76
+ else
77
+ @expressions.push(Literal.new(token))
78
+ end
79
+ end
80
+
81
+ ############################################################################
82
+ # Handlers
83
+ #
84
+ def handle_literal(token)
85
+ push_expression(token)
86
+ end
87
+
88
+ def handle_operation(token)
89
+ while @operations.any? && operation?(@operations.last) &&
90
+ lower_precedence?(token)
91
+ push_expression(pop(@operations))
92
+ end
93
+ @operations.push(token)
94
+ end
95
+
96
+ def handle_close_paren(_token)
97
+ while @operations.any? && @operations.last != '('
98
+ push_expression(pop(@operations))
99
+ end
100
+ raise 'Unclosed (' if @operations.empty?
101
+ pop(@operations) if @operations.last == '('
102
+ end
103
+
104
+ def handle_open_paren(token)
105
+ @operations.push(token)
106
+ end
107
+
108
+ def pop(array, n = 1)
109
+ result = array.pop(n)
110
+ raise('Empty stack') if result.size != n
111
+ n == 1 ? result.first : result
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ require 'simplecov'
3
+ formatters = [SimpleCov::Formatter::HTMLFormatter]
4
+
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(*formatters)
6
+ SimpleCov.start
@@ -0,0 +1,43 @@
1
+ require 'cucumber/tag_expressions/parser'
2
+
3
+ describe 'Expression node' do
4
+ shared_examples 'expression node' do |infix_expression, data|
5
+ data.each do |tags, result|
6
+ expression = Cucumber::TagExpressions::Parser.new.parse(infix_expression)
7
+ it "#{infix_expression.inspect} with variables: #{tags.inspect}'" do
8
+ expect(expression.evaluate(tags)).to eq(result)
9
+ end
10
+ end
11
+ end
12
+
13
+ describe Cucumber::TagExpressions::Not do
14
+ context '#evaluate' do
15
+ infix_expression = 'not x'
16
+ data = [[%w(x), false],
17
+ [%w(y), true]]
18
+ include_examples 'expression node', infix_expression, data
19
+ end
20
+ end
21
+
22
+ describe Cucumber::TagExpressions::And do
23
+ context '#evaluate' do
24
+ infix_expression = 'x and y'
25
+ data = [[%w(x y), true],
26
+ [%w(x), false],
27
+ [%w(y), false]]
28
+ include_examples 'expression node', infix_expression, data
29
+ end
30
+ end
31
+
32
+ describe Cucumber::TagExpressions::Or do
33
+ context '#evaluate' do
34
+ infix_expression = 'x or y'
35
+ data = [[%w(), false],
36
+ [%w(x), true],
37
+ [%w(y), true],
38
+ [%w(x q), true],
39
+ [%w(x y), true]]
40
+ include_examples 'expression node', infix_expression, data
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'cucumber/tag_expressions/parser'
2
+
3
+ describe Cucumber::TagExpressions::Parser do
4
+ correct_test_data = [
5
+ ['a and b', '( a and b )'],
6
+ ['a or (b)', '( a or b )'],
7
+ ['not a', 'not ( a )'],
8
+ ['( a and b ) or ( c and d )', '( ( a and b ) or ( c and d ) )'],
9
+ ['not a or b and not c or not d or e and f',
10
+ '( ( ( not ( a ) or ( b and not ( c ) ) ) or not ( d ) ) or ( e and f ) )']
11
+ ]
12
+
13
+ error_test_data = [
14
+ ['( a and b ))', RuntimeError, 'Unclosed ('],
15
+ ['a not ( and )', RuntimeError, 'Empty stack'],
16
+ ['( ( a and b )', RuntimeError, 'Unclosed ('],
17
+ ['a b', RuntimeError, 'Not empty'],
18
+ ['or or', RuntimeError, 'Empty stack']
19
+ ]
20
+
21
+ context '#parse' do
22
+ context 'with correct test data' do
23
+ correct_test_data.each do |infix_expression, to_string|
24
+ parser = Cucumber::TagExpressions::Parser.new
25
+ it "parses correctly #{infix_expression.inspect}" do
26
+ expect(parser.parse(infix_expression).to_s).to eq(to_string)
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'with error test data' do
32
+ error_test_data.each do |infix_expression, error_type, message|
33
+ parser = Cucumber::TagExpressions::Parser.new
34
+ it "raises an error parsing #{infix_expression.inspect}" do
35
+ expect { parser.parse(infix_expression) }
36
+ .to raise_error(error_type, message)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber-tag_expressions
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrea Nodari
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.12.5
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.12.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 10.5.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 10.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.7'
69
+ description: Cucumber tag expressions for ruby
70
+ email: cukes@googlegroups.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".rspec"
76
+ - ".travis.yml"
77
+ - Gemfile
78
+ - LICENSE
79
+ - Makefile
80
+ - README.md
81
+ - Rakefile
82
+ - cucumber-tag_expressions.gemspec
83
+ - lib/cucumber/tag_expressions.rb
84
+ - lib/cucumber/tag_expressions/expressions.rb
85
+ - lib/cucumber/tag_expressions/parser.rb
86
+ - spec/coverage.rb
87
+ - spec/expressions_spec.rb
88
+ - spec/parser_spec.rb
89
+ homepage: https://docs.cucumber.io/tag-expressions/
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options:
95
+ - "--charset=UTF-8"
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 1.9.3
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.5.1
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: cucumber-tag_expressions-1.0.0
114
+ test_files:
115
+ - spec/coverage.rb
116
+ - spec/expressions_spec.rb
117
+ - spec/parser_spec.rb