cucumber-salad 0.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.
- data/lib/cucumber/salad/conversions.rb +31 -0
- data/lib/cucumber/salad/table.rb +73 -0
- data/lib/cucumber/salad/version.rb +5 -0
- data/lib/cucumber/salad/widgets/form.rb +73 -0
- data/lib/cucumber/salad/widgets/list.rb +53 -0
- data/lib/cucumber/salad/widgets/table.rb +81 -0
- data/lib/cucumber/salad/widgets/text.rb +19 -0
- data/lib/cucumber/salad/widgets/widget.rb +80 -0
- data/lib/cucumber/salad/widgets.rb +3 -0
- data/lib/cucumber/salad.rb +5 -0
- metadata +103 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
module Conversions
|
4
|
+
def Boolean(val)
|
5
|
+
case val
|
6
|
+
when 'yes', 'true', true
|
7
|
+
true
|
8
|
+
when 'no', 'false', false, nil
|
9
|
+
false
|
10
|
+
else
|
11
|
+
raise ArgumentError, "can't convert #{val.inspect} to boolean"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def List(valstr, &block)
|
16
|
+
vs = valstr.strip.split(/\s*,\s*/)
|
17
|
+
|
18
|
+
block ? vs.map(&block) : vs
|
19
|
+
end
|
20
|
+
|
21
|
+
def Timeish(val)
|
22
|
+
raise ArgumentError, "can't convert nil to Timeish" if val.nil?
|
23
|
+
|
24
|
+
return val if Date === val || Time === val || DateTime === val
|
25
|
+
|
26
|
+
Chronic.parse(val) or
|
27
|
+
raise ArgumentError, "can't parse #{val.inspect} to Timeish"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
class Table
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
include Enumerable
|
7
|
+
include Conversions
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def header_mappings
|
11
|
+
@header_mappings ||=
|
12
|
+
with_parent_mappings(:header) { |h, k|
|
13
|
+
h[k] = k.squeeze(' ').strip.gsub(' ', '_').to_sym
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def map(name, options = {}, &block)
|
18
|
+
header_mappings[name.to_s] = options[:to].to_sym if options[:to]
|
19
|
+
value_mappings[name.to_s] = block if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
def value_mappings
|
23
|
+
@value_mappings ||=
|
24
|
+
with_parent_mappings(:value) { |h, k|
|
25
|
+
h[k] = ->(value) { value }
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def with_parent_mappings(name, &init)
|
32
|
+
m = "#{name}_mappings"
|
33
|
+
|
34
|
+
if superclass.respond_to?(m)
|
35
|
+
superclass.send(m).dup
|
36
|
+
else
|
37
|
+
Hash.new(&init)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def_delegators 'self.class', :header_mappings, :value_mappings
|
43
|
+
|
44
|
+
def initialize(table)
|
45
|
+
self.table = table
|
46
|
+
end
|
47
|
+
|
48
|
+
def each(&block)
|
49
|
+
rows.each(&block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def rows
|
53
|
+
@rows ||= table.hashes.map { |h| new_row(h) }
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
attr_accessor :table
|
59
|
+
|
60
|
+
def key_for(header)
|
61
|
+
header_mappings[header]
|
62
|
+
end
|
63
|
+
|
64
|
+
def new_row(hash)
|
65
|
+
hash.each_with_object({}) { |(k, v), h| h[key_for(k)] = value_for(k, v) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def value_for(key, value)
|
69
|
+
instance_exec(value, &value_mappings[key])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
module Widgets
|
4
|
+
class Form < Widget
|
5
|
+
def self.check_box(name, label = nil)
|
6
|
+
define_method "#{name}=" do |val|
|
7
|
+
l = label || name_to_label(name)
|
8
|
+
|
9
|
+
if val
|
10
|
+
root.check l
|
11
|
+
else
|
12
|
+
root.uncheck l
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.select_box(name, *args)
|
18
|
+
opts = args.extract_options!
|
19
|
+
label, = args
|
20
|
+
|
21
|
+
define_method "#{name}=" do |val|
|
22
|
+
l = label || name_to_label(name)
|
23
|
+
w = opts.fetch(:writer) { ->(v) { v } }
|
24
|
+
|
25
|
+
root.select w.(val).to_s, from: l
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.submit(attrs)
|
30
|
+
new.fill_all(attrs).submit
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.text(name, label = nil)
|
34
|
+
define_method "#{name}=" do |val|
|
35
|
+
l = label || name_to_label(name)
|
36
|
+
|
37
|
+
root.fill_in l, with: val.to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(*super_args)
|
42
|
+
super(*super_args)
|
43
|
+
|
44
|
+
if block_given?
|
45
|
+
yield self
|
46
|
+
|
47
|
+
submit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def fill_all(attrs)
|
52
|
+
attrs.each do |k, v|
|
53
|
+
send "#{k}=", v
|
54
|
+
end
|
55
|
+
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def submit
|
60
|
+
root.find('[name = "commit"]').click
|
61
|
+
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def name_to_label(name)
|
68
|
+
name.to_s.humanize
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
module Widgets
|
4
|
+
class List < Widget
|
5
|
+
DEFAULT_TYPE = Text
|
6
|
+
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def_delegators :items, :size, :include?, :each, :empty?
|
12
|
+
|
13
|
+
def self.item(selector, type = DEFAULT_TYPE, &item_for)
|
14
|
+
define_method :item_selector do
|
15
|
+
@item_selector ||= selector
|
16
|
+
end
|
17
|
+
|
18
|
+
if block_given?
|
19
|
+
define_method :item_for, &item_for
|
20
|
+
else
|
21
|
+
define_method :item_factory do
|
22
|
+
lookup(type)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_table
|
28
|
+
items.map { |e| Array(e) }
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
attr_writer :item_selector
|
34
|
+
|
35
|
+
def item_factory
|
36
|
+
DEFAULT_TYPE
|
37
|
+
end
|
38
|
+
|
39
|
+
def item_for(node)
|
40
|
+
item_factory.new(root: node)
|
41
|
+
end
|
42
|
+
|
43
|
+
def item_selector
|
44
|
+
'li'
|
45
|
+
end
|
46
|
+
|
47
|
+
def items
|
48
|
+
root.all(item_selector).map { |node| item_for(node) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
module Widgets
|
4
|
+
class Table < Widget
|
5
|
+
def self.row_class
|
6
|
+
Row
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_table
|
10
|
+
[headers, *rows.map { |r| Array(r) }]
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def header_for(node)
|
16
|
+
node.text.strip.downcase
|
17
|
+
end
|
18
|
+
|
19
|
+
def header_selector
|
20
|
+
'thead th'
|
21
|
+
end
|
22
|
+
|
23
|
+
def headers
|
24
|
+
items(header_selector, :header_for)
|
25
|
+
end
|
26
|
+
|
27
|
+
def items(selector, builder)
|
28
|
+
root.all(selector).map { |e| send(builder, e) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def row_factory
|
32
|
+
self.class.row_class
|
33
|
+
end
|
34
|
+
|
35
|
+
def row_for(node)
|
36
|
+
row_factory.new(root: node)
|
37
|
+
end
|
38
|
+
|
39
|
+
def row_selector
|
40
|
+
'tbody tr'
|
41
|
+
end
|
42
|
+
|
43
|
+
def rows
|
44
|
+
items(row_selector, :row_for)
|
45
|
+
end
|
46
|
+
|
47
|
+
class Row < Widget
|
48
|
+
def self.cell(name, selector, type = Text, &block)
|
49
|
+
widget name, selector, type, &block
|
50
|
+
|
51
|
+
cells << name
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.cells
|
55
|
+
@cells ||= []
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_a
|
59
|
+
declared_row || generated_row
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def cell_selector
|
65
|
+
'td'
|
66
|
+
end
|
67
|
+
|
68
|
+
def declared_row
|
69
|
+
cells = self.class.cells
|
70
|
+
|
71
|
+
cells.map { |c| send(c).to_s } if cells.present?
|
72
|
+
end
|
73
|
+
|
74
|
+
def generated_row
|
75
|
+
root.all(cell_selector).map { |c| c.text.strip }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
module Widgets
|
4
|
+
class Widget
|
5
|
+
include Salad::Conversions
|
6
|
+
|
7
|
+
def self.root(selector)
|
8
|
+
define_method :default_root_selector do
|
9
|
+
selector
|
10
|
+
end
|
11
|
+
|
12
|
+
private :default_root_selector
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.widget(name, selector, type = Text, &block)
|
16
|
+
body = if block_given?
|
17
|
+
->{ block.(find(selector)) }
|
18
|
+
else
|
19
|
+
->{ lookup(type).new(root: root.find(selector)) }
|
20
|
+
end
|
21
|
+
|
22
|
+
define_method name, &body
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(settings = {})
|
26
|
+
self.root = settings[:root] if settings[:root]
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
xml = Nokogiri::HTML(page.body).at(root.path).to_xml
|
31
|
+
|
32
|
+
"<!-- #{self.class.name}: -->\n" <<
|
33
|
+
Nokogiri::XML(xml, &:noblanks).to_xhtml
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_writer :root_selector
|
39
|
+
|
40
|
+
def default_root_selector
|
41
|
+
raise NotImplementedError,
|
42
|
+
"#{self.class.name}: default root selector undefined"
|
43
|
+
end
|
44
|
+
|
45
|
+
def lookup(type)
|
46
|
+
if Class === type
|
47
|
+
type
|
48
|
+
else
|
49
|
+
self.class.const_get(type.to_s.classify)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def page
|
54
|
+
Capybara.current_session
|
55
|
+
end
|
56
|
+
|
57
|
+
def root
|
58
|
+
@root || page.find(root_selector)
|
59
|
+
end
|
60
|
+
|
61
|
+
def root=(selector_or_node)
|
62
|
+
case selector_or_node
|
63
|
+
when String
|
64
|
+
self.root_selector = selector_or_node
|
65
|
+
when Capybara::Node::Element, Capybara::Node::Simple
|
66
|
+
@root = selector_or_node
|
67
|
+
else
|
68
|
+
msg = "can't convert #{selector_or_node.inspect} to root node"
|
69
|
+
|
70
|
+
raise ArgumentError, msg
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def root_selector
|
75
|
+
@root_selector || default_root_selector
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cucumber-salad
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Leal
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
none: false
|
21
|
+
name: cucumber
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ! '>='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
none: false
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
version_requirements: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ! '>='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
none: false
|
37
|
+
name: chronic
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
none: false
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
version_requirements: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 2.11.0
|
52
|
+
none: false
|
53
|
+
name: rspec
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 2.11.0
|
61
|
+
none: false
|
62
|
+
description: See https://github.com/mojotech/cucumber-salad/README.md
|
63
|
+
email:
|
64
|
+
- dleal@mojotech.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- lib/cucumber/salad.rb
|
70
|
+
- lib/cucumber/salad/conversions.rb
|
71
|
+
- lib/cucumber/salad/table.rb
|
72
|
+
- lib/cucumber/salad/version.rb
|
73
|
+
- lib/cucumber/salad/widgets.rb
|
74
|
+
- lib/cucumber/salad/widgets/form.rb
|
75
|
+
- lib/cucumber/salad/widgets/list.rb
|
76
|
+
- lib/cucumber/salad/widgets/table.rb
|
77
|
+
- lib/cucumber/salad/widgets/text.rb
|
78
|
+
- lib/cucumber/salad/widgets/widget.rb
|
79
|
+
homepage: https://github.com/mojotech/cucumber-salad
|
80
|
+
licenses: []
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
none: false
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
none: false
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project: ! '[none]'
|
99
|
+
rubygems_version: 1.8.23
|
100
|
+
signing_key:
|
101
|
+
specification_version: 3
|
102
|
+
summary: A set of helpers to ease writing cucumber features
|
103
|
+
test_files: []
|