cucumber-tag_expressions 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|