cucumber-tag_expressions 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/cucumber-tag-expressions +27 -0
- data/lib/cucumber/tag_expressions/expressions.rb +2 -2
- data/lib/cucumber/tag_expressions/parser.rb +57 -35
- data/spec/expressions_spec.rb +13 -1
- data/spec/parser_spec.rb +13 -8
- metadata +10 -13
- data/.rspec +0 -1
- data/.travis.yml +0 -15
- data/Gemfile +0 -3
- data/Makefile +0 -8
- data/Rakefile +0 -13
- data/cucumber-tag_expressions.gemspec +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e5a0bcac8bfcc6f2dc1106c1137dc0680230ffb
|
4
|
+
data.tar.gz: ca8e096362f13513df653e454ad22978249acece
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62fed4362ef18098c1640e13c73f1f7a241b29abe6e5aa07156871c1ccf596859158684874cb4e8528937fef53a8b54111a288317da32df57591a0fcc5eae1af
|
7
|
+
data.tar.gz: cc6d23a76a4d0ea419c01c451509acbfe798648287e49da4e65b9cff2dfa8618a8a900bfecc73c34795e7d1fb2f411488140ccd35ddda9c0112c4dc46fbbb901
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script reads NDJSON-encoded Cucumber events from STDIN and prints
|
4
|
+
# the location of each pickle (scenario) matching a tag expression. If
|
5
|
+
# no tag expression is specified, all pickle locations are printed.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# gherkin features/*.feature | cucumber-tag-expressions "@foo and not @bar"
|
10
|
+
#
|
11
|
+
require 'json'
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"../lib"))
|
13
|
+
require 'cucumber/tag_expressions'
|
14
|
+
|
15
|
+
tag_expression_parser = Cucumber::TagExpressions::Parser.new
|
16
|
+
tag_expression = ARGV[0] ? tag_expression_parser.parse(ARGV[0]) : nil
|
17
|
+
|
18
|
+
STDIN.each do |json|
|
19
|
+
event = JSON.parse(json)
|
20
|
+
if event['type'] == 'pickle'
|
21
|
+
tag_names = event['pickle']['tags'].map {|tag| tag['name']}
|
22
|
+
if tag_expression.nil? || tag_expression.evaluate(tag_names)
|
23
|
+
location = "#{event['uri']}:#{event['pickle']['locations'][0]['line']}"
|
24
|
+
puts location
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -3,7 +3,7 @@ module Cucumber
|
|
3
3
|
# Literal expression node
|
4
4
|
class Literal
|
5
5
|
def initialize(value)
|
6
|
-
@value = value
|
6
|
+
@value = value.gsub(/\\\(/, '(').gsub(/\\\)/, ')')
|
7
7
|
end
|
8
8
|
|
9
9
|
def evaluate(variables)
|
@@ -11,7 +11,7 @@ module Cucumber
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_s
|
14
|
-
@value
|
14
|
+
@value.gsub(/\(/, '\\(').gsub(/\)/, '\\)')
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -6,22 +6,22 @@ module Cucumber
|
|
6
6
|
class Parser
|
7
7
|
def initialize
|
8
8
|
@expressions = []
|
9
|
-
@
|
10
|
-
|
11
|
-
@
|
12
|
-
'or' => { type: :
|
13
|
-
'and' => { type: :
|
14
|
-
'not' => { type: :
|
15
|
-
')' => { type: :close_paren,
|
16
|
-
'(' => { type: :open_paren,
|
9
|
+
@operators = []
|
10
|
+
|
11
|
+
@operator_types = {
|
12
|
+
'or' => { type: :binary_operator, precedence: 0, assoc: :left },
|
13
|
+
'and' => { type: :binary_operator, precedence: 1, assoc: :left },
|
14
|
+
'not' => { type: :unary_operator, precedence: 2, assoc: :right },
|
15
|
+
')' => { type: :close_paren, precedence: -1 },
|
16
|
+
'(' => { type: :open_paren, precedence: 1 }
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
20
20
|
def parse(infix_expression)
|
21
21
|
process_tokens!(infix_expression)
|
22
|
-
while @
|
23
|
-
raise '
|
24
|
-
push_expression(pop(@
|
22
|
+
while @operators.any?
|
23
|
+
raise 'Syntax error. Unmatched (' if @operators.last == '('
|
24
|
+
push_expression(pop(@operators))
|
25
25
|
end
|
26
26
|
expression = pop(@expressions)
|
27
27
|
@expressions.empty? ? expression : raise('Not empty')
|
@@ -33,34 +33,36 @@ module Cucumber
|
|
33
33
|
# Helpers
|
34
34
|
#
|
35
35
|
def assoc_of(token, value)
|
36
|
-
@
|
36
|
+
@operator_types[token][:assoc] == value
|
37
37
|
end
|
38
38
|
|
39
39
|
def lower_precedence?(operation)
|
40
40
|
(assoc_of(operation, :left) &&
|
41
|
-
|
41
|
+
precedence(operation) <= precedence(@operators.last)) ||
|
42
42
|
(assoc_of(operation, :right) &&
|
43
|
-
|
43
|
+
precedence(operation) < precedence(@operators.last))
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
47
|
-
@
|
46
|
+
def operator?(token)
|
47
|
+
@operator_types[token][:type] == :unary_operator ||
|
48
|
+
@operator_types[token][:type] == :binary_operator
|
48
49
|
end
|
49
50
|
|
50
|
-
def
|
51
|
-
@
|
51
|
+
def precedence(token)
|
52
|
+
@operator_types[token][:precedence]
|
52
53
|
end
|
53
54
|
|
54
55
|
def tokens(infix_expression)
|
55
|
-
infix_expression.gsub(
|
56
|
+
infix_expression.gsub(/(?<!\\)\(/, ' ( ').gsub(/(?<!\\)\)/, ' ) ').strip.split(/\s+/)
|
56
57
|
end
|
57
58
|
|
58
59
|
def process_tokens!(infix_expression)
|
60
|
+
expected_token_type = :operand
|
59
61
|
tokens(infix_expression).each do |token|
|
60
|
-
if @
|
61
|
-
send("handle_#{@
|
62
|
+
if @operator_types[token]
|
63
|
+
expected_token_type = send("handle_#{@operator_types[token][:type]}", token, expected_token_type)
|
62
64
|
else
|
63
|
-
handle_literal(token)
|
65
|
+
expected_token_type = handle_literal(token, expected_token_type)
|
64
66
|
end
|
65
67
|
end
|
66
68
|
end
|
@@ -81,28 +83,48 @@ module Cucumber
|
|
81
83
|
############################################################################
|
82
84
|
# Handlers
|
83
85
|
#
|
84
|
-
def
|
85
|
-
|
86
|
+
def handle_unary_operator(token, expected_token_type)
|
87
|
+
check(expected_token_type, :operand)
|
88
|
+
@operators.push(token)
|
89
|
+
:operand
|
86
90
|
end
|
87
91
|
|
88
|
-
def
|
89
|
-
|
92
|
+
def handle_binary_operator(token, expected_token_type)
|
93
|
+
check(expected_token_type, :operator)
|
94
|
+
while @operators.any? && operator?(@operators.last) &&
|
90
95
|
lower_precedence?(token)
|
91
|
-
push_expression(pop(@
|
96
|
+
push_expression(pop(@operators))
|
92
97
|
end
|
93
|
-
@
|
98
|
+
@operators.push(token)
|
99
|
+
:operand
|
100
|
+
end
|
101
|
+
|
102
|
+
def handle_open_paren(token, expected_token_type)
|
103
|
+
check(expected_token_type, :operand)
|
104
|
+
@operators.push(token)
|
105
|
+
:operand
|
94
106
|
end
|
95
107
|
|
96
|
-
def handle_close_paren(_token)
|
97
|
-
|
98
|
-
|
108
|
+
def handle_close_paren(_token, expected_token_type)
|
109
|
+
check(expected_token_type, :operator)
|
110
|
+
while @operators.any? && @operators.last != '('
|
111
|
+
push_expression(pop(@operators))
|
99
112
|
end
|
100
|
-
raise '
|
101
|
-
pop(@
|
113
|
+
raise 'Syntax error. Unmatched )' if @operators.empty?
|
114
|
+
pop(@operators) if @operators.last == '('
|
115
|
+
:operator
|
102
116
|
end
|
103
117
|
|
104
|
-
def
|
105
|
-
|
118
|
+
def handle_literal(token, expected_token_type)
|
119
|
+
check(expected_token_type, :operand)
|
120
|
+
push_expression(token)
|
121
|
+
:operator
|
122
|
+
end
|
123
|
+
|
124
|
+
def check(expected_token_type, token_type)
|
125
|
+
if expected_token_type != token_type
|
126
|
+
raise "Syntax error. Expected #{expected_token_type}"
|
127
|
+
end
|
106
128
|
end
|
107
129
|
|
108
130
|
def pop(array, n = 1)
|
data/spec/expressions_spec.rb
CHANGED
@@ -3,8 +3,8 @@ require 'cucumber/tag_expressions/parser'
|
|
3
3
|
describe 'Expression node' do
|
4
4
|
shared_examples 'expression node' do |infix_expression, data|
|
5
5
|
data.each do |tags, result|
|
6
|
-
expression = Cucumber::TagExpressions::Parser.new.parse(infix_expression)
|
7
6
|
it "#{infix_expression.inspect} with variables: #{tags.inspect}'" do
|
7
|
+
expression = Cucumber::TagExpressions::Parser.new.parse(infix_expression)
|
8
8
|
expect(expression.evaluate(tags)).to eq(result)
|
9
9
|
end
|
10
10
|
end
|
@@ -40,4 +40,16 @@ describe 'Expression node' do
|
|
40
40
|
include_examples 'expression node', infix_expression, data
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
describe Cucumber::TagExpressions::Or do
|
45
|
+
context '#evaluate' do
|
46
|
+
infix_expression = 'x\\(1\\) or (y\\(2\\))'
|
47
|
+
data = [[%w(), false],
|
48
|
+
[%w(x), false],
|
49
|
+
[%w(y), false],
|
50
|
+
[%w(x(1)), true],
|
51
|
+
[%w(y(2)), true]]
|
52
|
+
include_examples 'expression node', infix_expression, data
|
53
|
+
end
|
54
|
+
end
|
43
55
|
end
|
data/spec/parser_spec.rb
CHANGED
@@ -7,15 +7,20 @@ describe Cucumber::TagExpressions::Parser do
|
|
7
7
|
['not a', 'not ( a )'],
|
8
8
|
['( a and b ) or ( c and d )', '( ( a and b ) or ( c and d ) )'],
|
9
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 ) )']
|
10
|
+
'( ( ( not ( a ) or ( b and not ( c ) ) ) or not ( d ) ) or ( e and f ) )'],
|
11
|
+
['not a\\(\\) or b and not c or not d or e and f',
|
12
|
+
'( ( ( not ( a\\(\\) ) or ( b and not ( c ) ) ) or not ( d ) ) or ( e and f ) )']
|
11
13
|
]
|
12
14
|
|
13
15
|
error_test_data = [
|
14
|
-
['
|
15
|
-
['a
|
16
|
-
['
|
17
|
-
['a
|
18
|
-
['or or',
|
16
|
+
['@a @b or', 'Syntax error. Expected operator'],
|
17
|
+
['@a and (@b not)', 'Syntax error. Expected operator'],
|
18
|
+
['@a and (@b @c) or', 'Syntax error. Expected operator'],
|
19
|
+
['@a and or', 'Syntax error. Expected operand'],
|
20
|
+
['or or', 'Syntax error. Expected operand'],
|
21
|
+
['a b', 'Syntax error. Expected operator'],
|
22
|
+
['( a and b ) )', 'Syntax error. Unmatched )'],
|
23
|
+
['( ( a and b )', 'Syntax error. Unmatched ('],
|
19
24
|
]
|
20
25
|
|
21
26
|
context '#parse' do
|
@@ -29,11 +34,11 @@ describe Cucumber::TagExpressions::Parser do
|
|
29
34
|
end
|
30
35
|
|
31
36
|
context 'with error test data' do
|
32
|
-
error_test_data.each do |infix_expression,
|
37
|
+
error_test_data.each do |infix_expression, message|
|
33
38
|
parser = Cucumber::TagExpressions::Parser.new
|
34
39
|
it "raises an error parsing #{infix_expression.inspect}" do
|
35
40
|
expect { parser.parse(infix_expression) }
|
36
|
-
.to raise_error(
|
41
|
+
.to raise_error(RuntimeError, message)
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-tag_expressions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrea Nodari
|
8
|
+
- Aslak Hellesøy
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2017-
|
12
|
+
date: 2017-11-28 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
@@ -44,14 +45,14 @@ dependencies:
|
|
44
45
|
requirements:
|
45
46
|
- - "~>"
|
46
47
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
48
|
+
version: '3.7'
|
48
49
|
type: :development
|
49
50
|
prerelease: false
|
50
51
|
version_requirements: !ruby/object:Gem::Requirement
|
51
52
|
requirements:
|
52
53
|
- - "~>"
|
53
54
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
55
|
+
version: '3.7'
|
55
56
|
- !ruby/object:Gem::Dependency
|
56
57
|
name: coveralls
|
57
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -68,18 +69,14 @@ dependencies:
|
|
68
69
|
version: '0'
|
69
70
|
description: Cucumber tag expressions for ruby
|
70
71
|
email: cukes@googlegroups.com
|
71
|
-
executables:
|
72
|
+
executables:
|
73
|
+
- cucumber-tag-expressions
|
72
74
|
extensions: []
|
73
75
|
extra_rdoc_files: []
|
74
76
|
files:
|
75
|
-
- ".rspec"
|
76
|
-
- ".travis.yml"
|
77
|
-
- Gemfile
|
78
77
|
- LICENSE
|
79
|
-
- Makefile
|
80
78
|
- README.md
|
81
|
-
-
|
82
|
-
- cucumber-tag_expressions.gemspec
|
79
|
+
- bin/cucumber-tag-expressions
|
83
80
|
- lib/cucumber/tag_expressions.rb
|
84
81
|
- lib/cucumber/tag_expressions/expressions.rb
|
85
82
|
- lib/cucumber/tag_expressions/parser.rb
|
@@ -110,8 +107,8 @@ rubyforge_project:
|
|
110
107
|
rubygems_version: 2.6.8
|
111
108
|
signing_key:
|
112
109
|
specification_version: 4
|
113
|
-
summary: cucumber-tag_expressions-1.0
|
110
|
+
summary: cucumber-tag_expressions-1.1.0
|
114
111
|
test_files:
|
112
|
+
- spec/parser_spec.rb
|
115
113
|
- spec/coverage.rb
|
116
114
|
- spec/expressions_spec.rb
|
117
|
-
- spec/parser_spec.rb
|
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Makefile
DELETED
data/Rakefile
DELETED
@@ -1,13 +0,0 @@
|
|
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']
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
Gem::Specification.new do |s|
|
3
|
-
s.name = 'cucumber-tag_expressions'
|
4
|
-
s.version = '1.0.1'
|
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'
|
15
|
-
s.add_development_dependency 'rake', '~> 10.5'
|
16
|
-
s.add_development_dependency 'rspec', '~> 3.5'
|
17
|
-
|
18
|
-
# For coverage reports
|
19
|
-
s.add_development_dependency 'coveralls'
|
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
|