mohawk 0.1.4 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/.gitmodules +3 -3
  2. data/Changelog +6 -1
  3. data/Rakefile +2 -3
  4. data/cucumber.yml +1 -1
  5. data/features/combo_box.feature +8 -0
  6. data/features/menu.feature +8 -0
  7. data/features/step_definitions/button_steps.rb +1 -1
  8. data/features/step_definitions/combo_box_steps.rb +13 -1
  9. data/features/step_definitions/control_steps.rb +1 -1
  10. data/features/step_definitions/menu_steps.rb +7 -2
  11. data/features/support/WindowsForms.exe +0 -0
  12. data/features/support/screens/main_screen.rb +3 -0
  13. data/features/table.feature +7 -7
  14. data/features/text.feature +4 -0
  15. data/lib/mohawk/accessors.rb +3 -0
  16. data/lib/mohawk/adapters/uia/button.rb +14 -0
  17. data/lib/mohawk/adapters/uia/checkbox.rb +22 -0
  18. data/lib/mohawk/adapters/uia/control.rb +83 -0
  19. data/lib/mohawk/adapters/uia/element_locator.rb +19 -0
  20. data/lib/mohawk/adapters/uia/menu_item.rb +48 -0
  21. data/lib/mohawk/adapters/uia/radio.rb +22 -0
  22. data/lib/mohawk/adapters/uia/select_list.rb +53 -0
  23. data/lib/mohawk/adapters/uia/spinner.rb +30 -0
  24. data/lib/mohawk/adapters/uia/tab_control.rb +26 -0
  25. data/lib/mohawk/adapters/uia/table.rb +62 -0
  26. data/lib/mohawk/adapters/uia/table_row.rb +73 -0
  27. data/lib/mohawk/adapters/uia/text_box.rb +47 -0
  28. data/lib/mohawk/adapters/uia/tree_view.rb +22 -0
  29. data/lib/mohawk/adapters/uia/value_control.rb +20 -0
  30. data/lib/mohawk/adapters/uia/window.rb +64 -0
  31. data/lib/mohawk/adapters/uia_adapter.rb +36 -50
  32. data/lib/mohawk/version.rb +1 -1
  33. data/lib/mohawk/waiter.rb +18 -0
  34. data/lib/mohawk/win_32.rb +12 -0
  35. data/lib/mohawk.rb +26 -14
  36. data/mohawk.gemspec +2 -2
  37. data/spec/lib/mohawk/adapters/uia/control_spec.rb +46 -0
  38. data/spec/lib/mohawk/adapters/uia/table_row_spec.rb +36 -0
  39. data/spec/lib/mohawk/waiter_spec.rb +39 -0
  40. data/spec/lib/mohawk_spec.rb +115 -92
  41. data/spec/lib/navigation_spec.rb +14 -20
  42. data/spec/spec_helper.rb +1 -1
  43. metadata +49 -67
  44. data/lib/mohawk/accessors/button.rb +0 -20
  45. data/lib/mohawk/accessors/checkbox.rb +0 -24
  46. data/lib/mohawk/accessors/combo.rb +0 -37
  47. data/lib/mohawk/accessors/control.rb +0 -24
  48. data/lib/mohawk/accessors/label.rb +0 -15
  49. data/lib/mohawk/accessors/link.rb +0 -9
  50. data/lib/mohawk/accessors/menu_item.rb +0 -21
  51. data/lib/mohawk/accessors/radio.rb +0 -19
  52. data/lib/mohawk/accessors/spinner.rb +0 -27
  53. data/lib/mohawk/accessors/table.rb +0 -69
  54. data/lib/mohawk/accessors/table_row.rb +0 -62
  55. data/lib/mohawk/accessors/tabs.rb +0 -30
  56. data/lib/mohawk/accessors/text.rb +0 -29
  57. data/lib/mohawk/accessors/tree_view.rb +0 -32
  58. data/spec/lib/mohawk/accessors/button_spec.rb +0 -45
  59. data/spec/lib/mohawk/accessors/checkbox_spec.rb +0 -46
  60. data/spec/lib/mohawk/accessors/combo_spec.rb +0 -119
  61. data/spec/lib/mohawk/accessors/control_spec.rb +0 -47
  62. data/spec/lib/mohawk/accessors/label_spec.rb +0 -29
  63. data/spec/lib/mohawk/accessors/link_spec.rb +0 -34
  64. data/spec/lib/mohawk/accessors/menu_spec.rb +0 -32
  65. data/spec/lib/mohawk/accessors/radio_spec.rb +0 -35
  66. data/spec/lib/mohawk/accessors/spinner_spec.rb +0 -43
  67. data/spec/lib/mohawk/accessors/table_row_spec.rb +0 -28
  68. data/spec/lib/mohawk/accessors/table_spec.rb +0 -262
  69. data/spec/lib/mohawk/accessors/tabs_spec.rb +0 -58
  70. data/spec/lib/mohawk/accessors/text_spec.rb +0 -51
  71. data/spec/lib/mohawk/accessors/tree_view_spec.rb +0 -98
  72. data/spec/lib/mohawk/adapters/uia_adapter_spec.rb +0 -55
  73. data/spec/table_stubber.rb +0 -55
data/.gitmodules CHANGED
@@ -1,3 +1,3 @@
1
- [submodule "mohawk-testing-app"]
2
- path = mohawk-testing-app
3
- url = git://github.com/leviwilson/mohawk-testing-app.git
1
+ [submodule "mohawk-testing-app"]
2
+ path = mohawk-testing-app
3
+ url = git://github.com/leviwilson/mohawk-testing-app.git
data/Changelog CHANGED
@@ -1,6 +1,11 @@
1
- === Version 0.1.4
1
+ === Version 0.2 / 2014-05-09
2
+ * Enhancements
3
+ * Swapped out the underlying driver to use the uia gem
4
+
5
+ === Version 0.1.4 / 2014-02-05
2
6
  * Enhancements
3
7
  * make it more explicit if you want to add a row to the selection
8
+ * added another adapter that uses the uia gem
4
9
 
5
10
  === Version 0.1.0 / 2013-10-03
6
11
  * Enhancments
data/Rakefile CHANGED
@@ -1,3 +1,4 @@
1
+ require 'bundler/setup'
1
2
  require 'bundler/gem_tasks'
2
3
  require 'rspec/core/rake_task'
3
4
  require 'rubygems'
@@ -11,8 +12,6 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
11
12
  end
12
13
  task :spec
13
14
 
14
- Cucumber::Rake::Task.new(:features) do |t|
15
- t.profile = 'default'
16
- end
15
+ Cucumber::Rake::Task.new(:features)
17
16
 
18
17
  task :default => :spec
data/cucumber.yml CHANGED
@@ -1 +1 @@
1
- default: --no-source --color --format pretty
1
+ default: --no-source --color --format pretty
@@ -8,6 +8,10 @@ Feature: Working with combo boxes
8
8
  When I select the value "Orange" from the "fruits" combo box
9
9
  Then the "Orange" option should be selected in the "fruits" combo box
10
10
 
11
+ Scenario: Selecting items by regex
12
+ When I select the regex value "[Or]an" from the "fruits" combo box
13
+ Then the "Orange" option should be selected in the "fruits" combo box
14
+
11
15
  Scenario: Selecting multiple items
12
16
  Given we toggle the multi-select button
13
17
  When I select indexes "0, 1, 2" from the "fruits_list" combo box
@@ -34,3 +38,7 @@ Feature: Working with combo boxes
34
38
  | Coconut |
35
39
  | Orange |
36
40
  | Passion Fruit |
41
+
42
+ Scenario: Interacting with ListBox controls
43
+ When I select the value "Orange" from the "fruits_list" combo box
44
+ Then the application should know that "Orange" was selected
@@ -1,5 +1,13 @@
1
1
  Feature: Working with menu items
2
2
 
3
+ Scenario: Selecting a menu item by text
4
+ When I select the menu item by text
5
+ Then I should see the "About" window
6
+
3
7
  Scenario: Selecting an item from the menu
4
8
  When I select the menu item in the path "File | Roundabout Way | To | About"
5
9
  Then I should see the "About" window
10
+
11
+ Scenario: Clicking an item from the menu
12
+ When I click the menu item in the path "File | Roundabout Way | To | About"
13
+ Then I should see the "About" window
@@ -3,7 +3,7 @@ When /^I click the "(.*?)" button$/ do |name|
3
3
  end
4
4
 
5
5
  Then /^I should see the "(.*?)" window$/ do |window_title|
6
- RAutomation::Window.new(:title => window_title).wait_until_exists
6
+ Mohawk::Waiter.wait_until { Uia.find_element title: window_title }
7
7
  end
8
8
 
9
9
  When /^I look at the value of the "(.*?)" control$/ do |name|
@@ -10,6 +10,10 @@ When /^I select the value "(.*?)" from the "(.*?)" combo box$/ do |index, name|
10
10
  on(MainScreen).send "#{name.to_field}=", index
11
11
  end
12
12
 
13
+ When(/^I select the regex value "([^"]*)" from the "([^"]*)" combo box$/) do |regex, name|
14
+ on(MainScreen).send "#{name.to_field}=", /#{regex}/
15
+ end
16
+
13
17
  When(/^I clear the item at index "([^"]*)" from the "([^"]*)" combo box$/) do |which, name|
14
18
  on(MainScreen).send("clear_#{name.to_field}", which.to_i)
15
19
  end
@@ -19,7 +23,11 @@ When(/^I clear item "([^"]*)" from the "([^"]*)" combo box$/) do |which, name|
19
23
  end
20
24
 
21
25
  Then /^the "(.*?)" option(s)? should be selected in the "(.*?)" combo box$/ do |value, has_multiple, name|
22
- on(MainScreen).send("#{name.to_field}_selections").should eq(value.split(', '))
26
+ if has_multiple
27
+ on(MainScreen).send("#{name.to_field}_selections").should eq(value.split(', '))
28
+ else
29
+ on(MainScreen).send("#{name.to_field}").should eq(value)
30
+ end
23
31
  end
24
32
 
25
33
  When /^I look at the options for the "(.*?)" combo box"$/ do |name|
@@ -34,3 +42,7 @@ end
34
42
  Given(/^we toggle the multi-select button$/) do
35
43
  on(MainScreen).toggle_multi
36
44
  end
45
+
46
+ Then(/^the application should know that "([^"]*)" was selected$/) do |expected_value|
47
+ on(MainScreen).fruits_label.should eq(expected_value)
48
+ end
@@ -7,5 +7,5 @@ When(/^I click the control identified by "([^"]*)"$/) do |what|
7
7
  end
8
8
 
9
9
  Then(/^the "([^"]*)" screen should be shown$/) do |screen|
10
- on(AboutScreen).should be_active
10
+ on(AboutScreen).should be_present
11
11
  end
@@ -1,5 +1,10 @@
1
- When /^I select the menu item in the path "(.*?)"$/ do |menu_path|
1
+ When(/^I select the menu item by text$/) do
2
+ on(MainScreen).menu_item_by_text
3
+ end
4
+
5
+ When /^I (select|click) the menu item in the path "(.*?)"$/ do |select_or_click, menu_path|
2
6
  menu_item_method = menu_path.gsub(/ (\| )?/, "_").downcase
7
+ menu_item_method.prepend('click_') if select_or_click == 'click'
3
8
  on(MainScreen).send menu_item_method
4
- end
9
+ end
5
10
 
Binary file
@@ -3,6 +3,7 @@ class MainScreen
3
3
  window(:title => /MainFormWindow/)
4
4
 
5
5
  text(:text_field, :id => "textField")
6
+ text(:text_box_field, :id => "multiLineTextField")
6
7
  text(:masked_text_field, :id => "maskedTextBox")
7
8
  button(:data_entry_form_button, :value => "Data Entry Form")
8
9
  button(:about, :value => "About")
@@ -16,8 +17,10 @@ class MainScreen
16
17
  checkbox(:first_checkbox, :id => "checkBox")
17
18
  radio(:first_radio, :id => "radioButton1")
18
19
  label(:label_control, :id => "label1")
20
+ label(:fruits_label, :id => 'fruitsLabel')
19
21
  link(:link_control, :id => "linkLabel1")
20
22
  menu_item(:file_roundabout_way_to_about, :path => ["File", "Roundabout Way", "To", "About"])
23
+ menu_item(:menu_item_by_text, text: 'About')
21
24
  tree_view(:tree_view, :id => "treeView")
22
25
  control(:value_control_field, :id => "automatableMonthCalendar1")
23
26
  spinner(:spinner, :id => 'numericUpDown1')
@@ -13,14 +13,14 @@ Feature: Working with tables
13
13
 
14
14
  Scenario: Selecting a row by matching cell information
15
15
  When we select the table row with the following information:
16
- | name | date_of_birth |
17
- | Anna Doe | 3/4/1975 |
16
+ | full_name | date_of_birth |
17
+ | Anna Doe | 3/4/1975 |
18
18
  Then the row with index "1" should be selected
19
19
 
20
20
  Scenario: Finding a row
21
21
  Then we can find the row with the following information:
22
- | name | date_of_birth | state |
23
- | John Doe | 12/15/1967 | FL |
22
+ | full_name | date_of_birth | state |
23
+ | John Doe | 12/15/1967 | FL |
24
24
 
25
25
  Scenario: Selecting a row from a child item
26
26
  When we select the "1"th table row
@@ -41,8 +41,8 @@ Feature: Working with tables
41
41
  Scenario: Clearing a row by matching cell information
42
42
  Given we add rows "0, 1" to the selection
43
43
  When we clear the table row with the following information:
44
- | name | date_of_birth |
45
- | Anna Doe | 3/4/1975 |
44
+ | full_name | date_of_birth |
45
+ | Anna Doe | 3/4/1975 |
46
46
  Then the row with index "1" should not be selected
47
47
 
48
48
  Scenario: Rows have cells
@@ -57,7 +57,7 @@ Feature: Working with tables
57
57
  | Anna Doe | 1 |
58
58
 
59
59
  Scenario: Retrieving the headers
60
- Then the table headers are "Name, Date of birth, State"
60
+ Then the table headers are "Full Name, Date of birth, State"
61
61
 
62
62
  Scenario: Retrieving a row value by its header
63
63
  Then the "date_of_birth" for the row at index "1" is "3/4/1975"
@@ -4,6 +4,10 @@ Scenario: Setting and getting text
4
4
  When I set the "text field" to the value "Some text"
5
5
  Then the "text field" should be "Some text"
6
6
 
7
+ Scenario: Setting and getting text from a text box control
8
+ When I set the "text box field" to the value "Some text"
9
+ Then the "text box field" should be "Some text"
10
+
7
11
  Scenario: Clearing text
8
12
  When I set the "text field" to the value "Text to be cleared"
9
13
  And I clear the "text field"
@@ -226,6 +226,9 @@ module Mohawk
226
226
  define_method("#{name}") do
227
227
  adapter.menu_item(locator).select
228
228
  end
229
+ define_method("click_#{name}") do
230
+ adapter.menu_item(locator).click
231
+ end
229
232
  end
230
233
 
231
234
  # Generates methods for working with table or list view controls
@@ -0,0 +1,14 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class Button < Control
5
+ include Mohawk::Waiter
6
+ valid_patterns :invoke
7
+
8
+ def click
9
+ element.as(:invoke).invoke
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class CheckBox < Control
5
+ valid_patterns :toggle
6
+
7
+ def set_check(should_check)
8
+ toggle.toggle_state = should_check ? :on : :off
9
+ end
10
+
11
+ def checked?
12
+ toggle.toggle_state == :on
13
+ end
14
+
15
+ private
16
+ def toggle
17
+ element.as :toggle
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,83 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class Control
5
+ include Mohawk::Waiter
6
+
7
+ class << self
8
+ attr_reader :patterns
9
+
10
+ def valid_patterns(*patterns)
11
+ @patterns = patterns
12
+ end
13
+ end
14
+
15
+ def initialize(adapter, locator)
16
+ @parent = adapter.window.element
17
+ @locator = locator
18
+ end
19
+
20
+ def click
21
+ element.click
22
+ end
23
+
24
+ def focus
25
+ element.focus
26
+ end
27
+
28
+ def exist?
29
+ locate_element != nil
30
+ end
31
+ alias_method :exists?, :exist?
32
+
33
+ def enabled?
34
+ exist? && element.enabled?
35
+ end
36
+
37
+ def disabled?
38
+ !enabled?
39
+ end
40
+
41
+ def visible?
42
+ exist? && element.visible?
43
+ end
44
+
45
+ def element
46
+ @element ||= wait_until { locate_element }
47
+ end
48
+
49
+ def handle
50
+ element.handle
51
+ end
52
+
53
+ def value
54
+ element.name
55
+ end
56
+ alias_method :control_name, :value
57
+
58
+ def view
59
+ self
60
+ end
61
+
62
+ def method_missing(meth, *args, &block)
63
+ if element.respond_to? meth
64
+ element.send meth, *args, &block
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ private
71
+ def locate_element
72
+ scope = (@locator.delete(:children_only) && :children) || :descendants
73
+ locator = @locator.merge(scope: scope)
74
+
75
+ patterns = @locator.delete(:pattern) || self.class.patterns
76
+ locator.merge!(pattern: patterns) if patterns
77
+
78
+ @parent.find locator
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,19 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ module ElementLocator
5
+ private
6
+ def find_element(value)
7
+ case value
8
+ when Regexp
9
+ all_items.find { |e| e.name =~ value }
10
+ when String
11
+ all_items.find { |e| e.name == value }
12
+ when Fixnum
13
+ all_items[value]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,48 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class MenuItem < Control
5
+ class MenuItemNotFound < StandardError; end
6
+
7
+ def select
8
+ menu_item.as(:invoke).invoke
9
+ end
10
+
11
+ def click
12
+ menu_item.click_center
13
+ end
14
+
15
+ def exist?
16
+ !!menu_item
17
+ rescue MenuItemNotFound
18
+ false
19
+ end
20
+ alias_method :exists?, :exist?
21
+
22
+ private
23
+ def menu_item
24
+ current_item = @parent
25
+ path.each_with_index do |menu_item, index|
26
+ current_item = current_item.filter(control_type: :menu_item, name: menu_item).first
27
+ raise MenuItemNotFound, menu_item unless current_item
28
+ try_to_expand current_item unless index == path.count - 1
29
+ end
30
+ current_item
31
+ end
32
+
33
+ def path
34
+ [@locator[:path] || @locator[:text]].flatten
35
+ end
36
+
37
+ def try_to_expand(item)
38
+ case
39
+ when item.patterns.include?(:expand_collapse)
40
+ item.as(:expand_collapse).expand
41
+ else
42
+ item.as(:invoke).invoke
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,22 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class Radio < Control
5
+ valid_patterns :selection_item
6
+
7
+ def set
8
+ selection_item.select
9
+ end
10
+
11
+ def set?
12
+ selection_item.selected?
13
+ end
14
+
15
+ private
16
+ def selection_item
17
+ element.as :selection_item
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,53 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class SelectList < Control
5
+ include ElementLocator
6
+
7
+ def set(value)
8
+ which = find_element(value)
9
+ if select_list.multi_select?
10
+ which.add_to_selection
11
+ else
12
+ click_or_select which
13
+ end
14
+ end
15
+
16
+ def clear(value)
17
+ find_element(value).remove_from_selection
18
+ end
19
+
20
+ def value
21
+ values.first || ''
22
+ end
23
+
24
+ def values
25
+ selected_items.map &:name
26
+ end
27
+
28
+ def selected_items
29
+ select_list.selected_items
30
+ end
31
+
32
+ def options
33
+ all_items.map &:name
34
+ end
35
+
36
+ private
37
+ def select_list
38
+ element.as :selection
39
+ end
40
+
41
+ def all_items
42
+ select_list.selection_items
43
+ end
44
+
45
+ def click_or_select(item)
46
+ item.click
47
+ rescue
48
+ item.select
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class Spinner < Control
5
+ valid_patterns :range_value
6
+
7
+ def value=(value)
8
+ spinner.value = value
9
+ end
10
+
11
+ def value
12
+ spinner.value
13
+ end
14
+
15
+ def increment
16
+ self.value = value + spinner.small_change
17
+ end
18
+
19
+ def decrement
20
+ self.value = value - spinner.small_change
21
+ end
22
+
23
+ private
24
+ def spinner
25
+ element.as :range_value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class TabControl < Control
5
+ include ElementLocator
6
+
7
+ def selected_tab=(which)
8
+ find_element(which).select
9
+ end
10
+
11
+ def value
12
+ all_items.find(&:selected?).name
13
+ end
14
+
15
+ def items
16
+ all_items.map &:name
17
+ end
18
+
19
+ private
20
+ def all_items
21
+ element.filter(control_type: :tab_item).map {|e| e.as :selection_item }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,62 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class Table < Control
5
+ include ElementLocator, Enumerable
6
+ valid_patterns :table
7
+
8
+ def select(which)
9
+ find_row_with(which).select
10
+ end
11
+
12
+ def add(which)
13
+ find_row_with(which).add
14
+ end
15
+
16
+ def clear(which)
17
+ find_row_with(which).clear
18
+ end
19
+
20
+ def headers
21
+ element.headers.map &:name
22
+ end
23
+
24
+ def [](index)
25
+ row_at(index)
26
+ end
27
+
28
+ def each
29
+ all_items.each { |row| yield row }
30
+ end
31
+
32
+ def find_row_with(row_info)
33
+ found_row = case row_info
34
+ when Hash
35
+ find_by_hash(row_info)
36
+ else
37
+ find_element(row_info)
38
+ end
39
+ raise "A row with #{row_info} was not found" unless found_row
40
+ found_row
41
+ end
42
+
43
+ def element
44
+ super.as(:table)
45
+ end
46
+
47
+ private
48
+ def find_by_hash(hash)
49
+ find { |r| r.all_match? hash }
50
+ end
51
+
52
+ def row_at(index)
53
+ TableRow.new self, index
54
+ end
55
+
56
+ def all_items
57
+ element.row_count.times.map { |index| TableRow.new self, index }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,73 @@
1
+ module Mohawk
2
+ module Adapters
3
+ module UIA
4
+ class TableRow
5
+ attr_reader :index
6
+
7
+ def initialize(table, index)
8
+ @table, @index = table, index
9
+ end
10
+
11
+ def name
12
+ element.name
13
+ end
14
+
15
+ def cells
16
+ element.items.map &:name
17
+ end
18
+
19
+ def select
20
+ selection_item.select
21
+ self
22
+ end
23
+
24
+ def add
25
+ selection_item.add_to_selection
26
+ self
27
+ end
28
+
29
+ def clear
30
+ selection_item.remove_from_selection
31
+ self
32
+ end
33
+
34
+ def selected?
35
+ selection_item.selected?
36
+ end
37
+
38
+ def all_match?(hash)
39
+ hash.all? do |key, value|
40
+ value_from_header(key) == "#{value}"
41
+ end
42
+ end
43
+
44
+ def to_hash
45
+ {text: element.name, row: index}
46
+ end
47
+
48
+ def method_missing(name, *args)
49
+ value_from_header name
50
+ end
51
+
52
+ def value_from_header(name)
53
+ which_column = header_methods.find_index {|h| h.to_s == name.to_s }
54
+ raise ArgumentError, "#{name} column does not exist in #{header_methods}" if which_column.nil?
55
+ cells[which_column]
56
+ end
57
+
58
+ private
59
+ def element
60
+ @element ||= @table.element.row_at(@index)
61
+ end
62
+
63
+ def selection_item
64
+ element.as :selection_item
65
+ end
66
+
67
+ def header_methods
68
+ @headers ||= @table.headers.map(&:to_method)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end