furter 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/.gitignore +21 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +2 -0
  4. data/Changelog +3 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +25 -0
  8. data/Rakefile +30 -0
  9. data/app/FurterApp/Frank/features/my_first.feature +12 -0
  10. data/app/FurterApp/Frank/features/step_definitions/launch_steps.rb +20 -0
  11. data/app/FurterApp/Frank/features/support/env.rb +8 -0
  12. data/app/FurterApp/Frank/frankify.xcconfig +6 -0
  13. data/app/FurterApp/Frank/libCocoaAsyncSocket.a +0 -0
  14. data/app/FurterApp/Frank/libCocoaAsyncSocketMac.a +0 -0
  15. data/app/FurterApp/Frank/libCocoaHTTPServer.a +0 -0
  16. data/app/FurterApp/Frank/libCocoaHTTPServerMac.a +0 -0
  17. data/app/FurterApp/Frank/libCocoaLumberjack.a +0 -0
  18. data/app/FurterApp/Frank/libCocoaLumberjackMac.a +0 -0
  19. data/app/FurterApp/Frank/libFrank.a +0 -0
  20. data/app/FurterApp/Frank/libFrankMac.a +0 -0
  21. data/app/FurterApp/Frank/libShelley.a +0 -0
  22. data/app/FurterApp/Frank/libShelleyMac.a +0 -0
  23. data/app/FurterApp/FurterApp.xcodeproj/project.pbxproj +807 -0
  24. data/app/FurterApp/FurterApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  25. data/app/FurterApp/FurterApp.xcodeproj/project.xcworkspace/xcuserdata/lwilson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  26. data/app/FurterApp/FurterApp.xcodeproj/xcuserdata/lwilson.xcuserdatad/xcschemes/FurterApp.xcscheme +86 -0
  27. data/app/FurterApp/FurterApp.xcodeproj/xcuserdata/lwilson.xcuserdatad/xcschemes/xcschememanagement.plist +22 -0
  28. data/app/FurterApp/FurterApp/AppDelegate.h +22 -0
  29. data/app/FurterApp/FurterApp/AppDelegate.m +161 -0
  30. data/app/FurterApp/FurterApp/Default-568h@2x.png +0 -0
  31. data/app/FurterApp/FurterApp/Default.png +0 -0
  32. data/app/FurterApp/FurterApp/Default@2x.png +0 -0
  33. data/app/FurterApp/FurterApp/DetailViewController.h +23 -0
  34. data/app/FurterApp/FurterApp/DetailViewController.m +80 -0
  35. data/app/FurterApp/FurterApp/FurterApp-Info.plist +59 -0
  36. data/app/FurterApp/FurterApp/FurterApp-Prefix.pch +15 -0
  37. data/app/FurterApp/FurterApp/FurterApp.xcdatamodeld/.xccurrentversion +8 -0
  38. data/app/FurterApp/FurterApp/FurterApp.xcdatamodeld/FurterApp.xcdatamodel/contents +9 -0
  39. data/app/FurterApp/FurterApp/MasterViewController.h +22 -0
  40. data/app/FurterApp/FurterApp/MasterViewController.m +235 -0
  41. data/app/FurterApp/FurterApp/en.lproj/InfoPlist.strings +2 -0
  42. data/app/FurterApp/FurterApp/en.lproj/MainStoryboard_iPad.storyboard +260 -0
  43. data/app/FurterApp/FurterApp/en.lproj/MainStoryboard_iPhone.storyboard +129 -0
  44. data/app/FurterApp/FurterApp/main.m +18 -0
  45. data/cucumber.yml +2 -0
  46. data/features/button.feature +12 -0
  47. data/features/label.feature +10 -0
  48. data/features/navigation.feature +5 -0
  49. data/features/step_definitions/button_steps.rb +7 -0
  50. data/features/step_definitions/label_steps.rb +8 -0
  51. data/features/step_definitions/navigation_steps.rb +7 -0
  52. data/features/step_definitions/switches_steps.rb +12 -0
  53. data/features/step_definitions/text_steps.rb +25 -0
  54. data/features/support/core_ext/string.rb +9 -0
  55. data/features/support/env.rb +25 -0
  56. data/features/support/hooks.rb +3 -0
  57. data/features/support/screens/detail.rb +15 -0
  58. data/features/support/screens/elsewhere_page.rb +7 -0
  59. data/features/switches.feature +7 -0
  60. data/features/text.feature +15 -0
  61. data/furter.gemspec +26 -0
  62. data/lib/furter.rb +53 -0
  63. data/lib/furter/accessors.rb +87 -0
  64. data/lib/furter/accessors/alert_button.rb +18 -0
  65. data/lib/furter/accessors/button.rb +17 -0
  66. data/lib/furter/accessors/label.rb +13 -0
  67. data/lib/furter/accessors/map_pin.rb +18 -0
  68. data/lib/furter/accessors/switch.rb +20 -0
  69. data/lib/furter/accessors/table.rb +15 -0
  70. data/lib/furter/accessors/table_item.rb +10 -0
  71. data/lib/furter/accessors/text.rb +27 -0
  72. data/lib/furter/accessors/view.rb +46 -0
  73. data/lib/furter/navigation.rb +25 -0
  74. data/lib/furter/version.rb +3 -0
  75. data/spec/lib/furter/accessors/button_spec.rb +23 -0
  76. data/spec/lib/furter/accessors/label_spec.rb +24 -0
  77. data/spec/lib/furter/accessors/switch_spec.rb +28 -0
  78. data/spec/lib/furter/accessors/text_spec.rb +39 -0
  79. data/spec/lib/furter/accessors/view_spec.rb +43 -0
  80. data/spec/lib/furter/accessors_spec.rb +116 -0
  81. data/spec/spec_helper.rb +18 -0
  82. metadata +234 -0
@@ -0,0 +1,129 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="2.0" toolsVersion="3084" systemVersion="12D78" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="3">
3
+ <dependencies>
4
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="2083"/>
5
+ </dependencies>
6
+ <scenes>
7
+ <!--Navigation Controller-->
8
+ <scene sceneID="11">
9
+ <objects>
10
+ <navigationController id="3" sceneMemberID="viewController">
11
+ <navigationBar key="navigationBar" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="4">
12
+ <autoresizingMask key="autoresizingMask"/>
13
+ </navigationBar>
14
+ <connections>
15
+ <segue destination="12" kind="relationship" relationship="rootViewController" id="19"/>
16
+ </connections>
17
+ </navigationController>
18
+ <placeholder placeholderIdentifier="IBFirstResponder" id="10" sceneMemberID="firstResponder"/>
19
+ </objects>
20
+ <point key="canvasLocation" x="-1" y="64"/>
21
+ </scene>
22
+ <!--Master View Controller - Master-->
23
+ <scene sceneID="18">
24
+ <objects>
25
+ <tableViewController storyboardIdentifier="" title="Master" id="12" customClass="MasterViewController" sceneMemberID="viewController">
26
+ <tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="13">
27
+ <rect key="frame" x="0.0" y="64" width="320" height="504"/>
28
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
29
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
30
+ <prototypes>
31
+ <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="phq-AM-6qj" style="IBUITableViewCellStyleDefault" id="lJ0-d7-vTF">
32
+ <rect key="frame" x="0.0" y="22" width="320" height="44"/>
33
+ <autoresizingMask key="autoresizingMask"/>
34
+ <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
35
+ <rect key="frame" x="0.0" y="0.0" width="300" height="43"/>
36
+ <autoresizingMask key="autoresizingMask"/>
37
+ <subviews>
38
+ <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="phq-AM-6qj">
39
+ <rect key="frame" x="10" y="0.0" width="280" height="43"/>
40
+ <autoresizingMask key="autoresizingMask"/>
41
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
42
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
43
+ <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
44
+ </label>
45
+ </subviews>
46
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
47
+ </view>
48
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
49
+ <connections>
50
+ <segue destination="21" kind="push" identifier="showDetail" id="jZb-fq-zAk"/>
51
+ </connections>
52
+ </tableViewCell>
53
+ </prototypes>
54
+ <sections/>
55
+ <connections>
56
+ <outlet property="dataSource" destination="12" id="16"/>
57
+ <outlet property="delegate" destination="12" id="15"/>
58
+ </connections>
59
+ </tableView>
60
+ <navigationItem key="navigationItem" title="Master" id="36"/>
61
+ </tableViewController>
62
+ <placeholder placeholderIdentifier="IBFirstResponder" id="17" sceneMemberID="firstResponder"/>
63
+ </objects>
64
+ <point key="canvasLocation" x="459" y="64"/>
65
+ </scene>
66
+ <!--Detail View Controller - Detail-->
67
+ <scene sceneID="24">
68
+ <objects>
69
+ <viewController storyboardIdentifier="" title="Detail" id="21" customClass="DetailViewController" sceneMemberID="viewController">
70
+ <view key="view" contentMode="scaleToFill" id="22">
71
+ <rect key="frame" x="0.0" y="64" width="320" height="504"/>
72
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
73
+ <subviews>
74
+ <label clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Detail view content goes here" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="27">
75
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
76
+ <fontDescription key="fontDescription" type="system" size="system"/>
77
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
78
+ <nil key="highlightedColor"/>
79
+ </label>
80
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BGA-y0-odx">
81
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
82
+ <state key="normal" title="Button">
83
+ <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
84
+ <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
85
+ </state>
86
+ <state key="highlighted">
87
+ <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
88
+ </state>
89
+ </button>
90
+ </subviews>
91
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
92
+ <constraints>
93
+ <constraint firstAttribute="bottom" secondItem="BGA-y0-odx" secondAttribute="bottom" constant="107" id="Oz5-UI-e4N"/>
94
+ <constraint firstItem="27" firstAttribute="leading" secondItem="22" secondAttribute="leading" constant="20" symbolic="YES" type="default" id="R0m-z7-TWk"/>
95
+ <constraint firstItem="BGA-y0-odx" firstAttribute="leading" secondItem="22" secondAttribute="leading" constant="20" symbolic="YES" type="default" id="a4V-WS-rvQ"/>
96
+ <constraint firstItem="27" firstAttribute="top" secondItem="22" secondAttribute="top" constant="9" id="fqs-Iu-ZEi"/>
97
+ <constraint firstAttribute="trailing" secondItem="27" secondAttribute="trailing" constant="20" symbolic="YES" type="default" id="pRe-qY-58T"/>
98
+ </constraints>
99
+ </view>
100
+ <navigationItem key="navigationItem" title="Detail" id="26"/>
101
+ <connections>
102
+ <outlet property="detailDescriptionLabel" destination="27" id="28"/>
103
+ </connections>
104
+ </viewController>
105
+ <placeholder placeholderIdentifier="IBFirstResponder" id="23" sceneMemberID="firstResponder"/>
106
+ </objects>
107
+ <point key="canvasLocation" x="902" y="64"/>
108
+ </scene>
109
+ </scenes>
110
+ <classes>
111
+ <class className="DetailViewController" superclassName="UIViewController">
112
+ <source key="sourceIdentifier" type="project" relativePath="./Classes/DetailViewController.h"/>
113
+ <relationships>
114
+ <relationship kind="outlet" name="detailDescriptionLabel" candidateClass="UILabel"/>
115
+ </relationships>
116
+ </class>
117
+ <class className="MasterViewController" superclassName="UITableViewController">
118
+ <source key="sourceIdentifier" type="project" relativePath="./Classes/MasterViewController.h"/>
119
+ </class>
120
+ <class className="NSLayoutConstraint" superclassName="NSObject">
121
+ <source key="sourceIdentifier" type="project" relativePath="./Classes/NSLayoutConstraint.h"/>
122
+ </class>
123
+ </classes>
124
+ <simulatedMetricsContainer key="defaultSimulatedMetrics">
125
+ <simulatedStatusBarMetrics key="statusBar"/>
126
+ <simulatedOrientationMetrics key="orientation"/>
127
+ <simulatedScreenMetrics key="destination" type="retina4"/>
128
+ </simulatedMetricsContainer>
129
+ </document>
@@ -0,0 +1,18 @@
1
+ //
2
+ // main.m
3
+ // FurterApp
4
+ //
5
+ // Created by Levi Wilson on 3/20/13.
6
+ // Copyright (c) 2013 Levi Wilson. All rights reserved.
7
+ //
8
+
9
+ #import <UIKit/UIKit.h>
10
+
11
+ #import "AppDelegate.h"
12
+
13
+ int main(int argc, char *argv[])
14
+ {
15
+ @autoreleasepool {
16
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17
+ }
18
+ }
data/cucumber.yml ADDED
@@ -0,0 +1,2 @@
1
+ default: --no-source --color --format pretty
2
+ wip: --no-source --color --format pretty --tag @wip
@@ -0,0 +1,12 @@
1
+ Feature: Working with buttons
2
+
3
+ Scenario: Clicking buttons by text
4
+ When I click the button identified by "text"
5
+ Then the text identified by "label" should be "The button was clicked!"
6
+
7
+ Scenario: Clicking buttons by label
8
+ When I click the button identified by "label"
9
+ Then the text identified by "label" should be "The labeled button was clicked!"
10
+
11
+ Scenario: Working with the raw button view
12
+ Then we can interact with the raw view of the button identified by "label"
@@ -0,0 +1,10 @@
1
+ Feature: Working with label controls
2
+
3
+ Scenario: Getting the value of a label by accessibility label
4
+ Then I know that the label identified by "id" is "Detail view content goes here"
5
+
6
+ Scenario: Accessing the raw view properties of a label
7
+ Then the label identified by "id" should be "visible"
8
+
9
+ Scenario: Finding labels by their text
10
+ Then the label identified by "text" should be "visible"
@@ -0,0 +1,5 @@
1
+ Feature: Navigating through the application
2
+
3
+ Scenario: Using routes for navigation
4
+ When I navigate to the "ElsewherePage" using the "crazy route" route
5
+ Then I should end up on the "ElsewherePage"
@@ -0,0 +1,7 @@
1
+ When /^I click the button identified by "([^"]*)"$/ do |how|
2
+ on(DetailPage).send("button_#{how}")
3
+ end
4
+
5
+ Then /^we can interact with the raw view of the button identified by "([^"]*)"$/ do |how|
6
+ on(DetailPage).send("button_#{how}_view").should be_kind_of(Furter::Accessors::View)
7
+ end
@@ -0,0 +1,8 @@
1
+ Then /^I know that the label identified by "([^"]*)" is "([^"]*)"$/ do |how, what|
2
+ on(DetailPage).send("label_#{how}").should eq(what)
3
+ end
4
+
5
+ Then /^the label identified by "([^"]*)" should be "([^"]*)"$/ do |how, property|
6
+ which_method = "#{property}?".to_sym
7
+ on(DetailPage).send("label_#{how}_view").send(which_method).should be_true
8
+ end
@@ -0,0 +1,7 @@
1
+ When /^I navigate to the "([^"]*)" using the "([^"]*)" route$/ do |where, which_route|
2
+ navigate_to(where.to_class, :using => which_route.to_method)
3
+ end
4
+
5
+ Then /^I should end up on the "([^"]*)"$/ do |where|
6
+ on(where.to_class).should be_active
7
+ end
@@ -0,0 +1,12 @@
1
+ Then(/^switches can be toggled both on or off$/) do
2
+ on(DetailPage) do |screen|
3
+ [true, false].each do |what_now|
4
+ screen.switch_toggle = what_now
5
+ screen.switch_toggle.should eq(what_now)
6
+ end
7
+ end
8
+ end
9
+
10
+ Then /^we have access to the switch view$/ do
11
+ on(DetailPage).switch_toggle_view.should be_kind_of(Furter::Accessors::View)
12
+ end
@@ -0,0 +1,25 @@
1
+ When(/^I set the text identified by "(.*?)" to "(.*?)"$/) do |how, text|
2
+ on(DetailPage).send("text_#{how}=", text)
3
+ end
4
+
5
+ Then(/^the text identified by "(.*?)" should be "(.*?)"$/) do |how, text|
6
+ on(DetailPage).send("text_#{how}").should eq(text)
7
+ end
8
+
9
+ Then(/^we know if a text field is both editable and not editable$/) do
10
+ first_field = "textField placeholder:'First Field'"
11
+
12
+ on(DetailPage) do |screen|
13
+ frankly_map(first_field, 'setEnabled:', false)
14
+ screen.should_not be_text_placeholder_editable
15
+
16
+ frankly_map(first_field, 'setEnabled:', true)
17
+ screen.should be_text_placeholder_editable
18
+ end
19
+ end
20
+
21
+ Then(/^we can interact with the raw text view identified by "(.*?)"$/) do |how|
22
+ text_view = on(DetailPage).send("text_#{how}_view")
23
+ text_view.should be_kind_of(Furter::Accessors::View)
24
+ end
25
+
@@ -0,0 +1,9 @@
1
+ class String
2
+ def to_class
3
+ Object.const_get self
4
+ end
5
+
6
+ def to_method
7
+ self.gsub(/\W+/,'_').downcase.to_sym
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../../', 'lib'))
2
+
3
+ require 'furter'
4
+ require 'require_all'
5
+
6
+ require 'rspec-expectations'
7
+
8
+ World(Furter::Navigation)
9
+
10
+ require_rel '/screens'
11
+
12
+ APP_BUNDLE_PATH = File.expand_path( '../../../app/FurterApp/Frank/frankified_build/FurterApp.app', __FILE__ )
13
+
14
+ Frank::Cucumber::FrankHelper.use_shelley_from_now_on
15
+
16
+ Furter::Navigation.routes = {
17
+ :default => [],
18
+ :crazy_route => [
19
+ [DetailPage, :button_text],
20
+ [DetailPage, :button_label],
21
+ [DetailPage, :switch_toggle],
22
+ [DetailPage, :go_elsewhere],
23
+ [ElsewherePage, :active?]
24
+ ]
25
+ }
@@ -0,0 +1,3 @@
1
+ Before do
2
+ launch_app APP_BUNDLE_PATH, '6.1', 'ipad'
3
+ end
@@ -0,0 +1,15 @@
1
+ class DetailPage
2
+ include Furter
3
+
4
+ text(:text_placeholder, :placeholder => 'First Field')
5
+ text(:text_label, :label => 'textByLabel')
6
+
7
+ label(:label_id, :label => 'labelByAccessibilityLabel')
8
+ label(:label_text, :text => 'Placeholder')
9
+
10
+ button(:button_text, :text => 'Some Button')
11
+ button(:button_label, :label => 'labeledButtonId')
12
+ button(:go_elsewhere, :text => 'Go Elsewhere')
13
+
14
+ switch(:switch_toggle, :label => 'switchToggle')
15
+ end
@@ -0,0 +1,7 @@
1
+ class ElsewherePage
2
+ include Furter
3
+
4
+ def active?
5
+ has_text? 'You are now elsewhere.'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ Feature: Working with switch controls
2
+
3
+ Scenario: Getting and setting a switch value
4
+ Then switches can be toggled both on or off
5
+
6
+ Scenario: Working with the raw switch view
7
+ Then we have access to the switch view
@@ -0,0 +1,15 @@
1
+ Feature: Working with text controls
2
+
3
+ Scenario: Getting and setting text by placeholder
4
+ When I set the text identified by "placeholder" to "The first field's text"
5
+ Then the text identified by "placeholder" should be "The first field's text"
6
+
7
+ Scenario: Getting and setting text by label
8
+ When I set the text identified by "label" to "the label text"
9
+ Then the text identified by "label" should be "the label text"
10
+
11
+ Scenario: Determining if a text field is editable
12
+ Then we know if a text field is both editable and not editable
13
+
14
+ Scenario: Working with the raw view
15
+ Then we can interact with the raw text view identified by "placeholder"
data/furter.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'furter/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "furter"
8
+ gem.version = Furter::VERSION
9
+ gem.authors = ["Levi Wilson"]
10
+ gem.email = ["levi@leviwilson.com"]
11
+ gem.description = %q{Higher-level abstraction around iOS drivers}
12
+ gem.summary = %q{Higher-level abstraction around iOS drivers}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'frank-cucumber', '~> 1.1.8'
21
+ gem.add_dependency 'page_navigation', '>= 0.7'
22
+
23
+ gem.add_development_dependency 'rspec'
24
+ gem.add_development_dependency 'rake'
25
+ gem.add_development_dependency 'require_all'
26
+ end
data/lib/furter.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'frank-cucumber'
2
+ require 'furter/navigation'
3
+ require 'furter/accessors'
4
+ require 'furter/accessors/view'
5
+ require 'furter/accessors/alert_button'
6
+ require 'furter/accessors/button'
7
+ require 'furter/accessors/map_pin'
8
+ require 'furter/accessors/switch'
9
+ require 'furter/accessors/table'
10
+ require 'furter/accessors/table_item'
11
+ require 'furter/accessors/text'
12
+ require 'furter/accessors/label'
13
+
14
+ module Furter
15
+ include Frank::Cucumber::FrankHelper
16
+
17
+ TIMEOUT = 30
18
+
19
+ def self.included(cls)
20
+ cls.extend Furter::Accessors
21
+ end
22
+
23
+ def has_text?(text)
24
+ Furter::Accessors::Text.new.has_text? text
25
+ end
26
+
27
+ def wait_for_text(text)
28
+ wait_until(:message => "Timed out waiting for text \"#{text}\"", :timeout => Furter::TIMEOUT) do
29
+ has_text? text
30
+ end
31
+ end
32
+
33
+ def exists?(locator)
34
+ element_exists locator
35
+ end
36
+
37
+ def wait_for(locator, &block)
38
+ wait_until(:message => "Timed out waiting for \"#{locator}\"", :timeout => Furter::TIMEOUT) do
39
+ exists? locator
40
+ end
41
+ block.call locator if block
42
+ end
43
+
44
+ def wait_for_and_touch(locator)
45
+ wait_for(locator) do |locator|
46
+ touch locator
47
+ end
48
+ end
49
+
50
+ def active?
51
+ true
52
+ end
53
+ end
@@ -0,0 +1,87 @@
1
+ module Furter
2
+ module Accessors
3
+ def text(name, locator)
4
+ define_method("#{name}") do
5
+ Furter::Accessors::Text.new(locator).get_text
6
+ end
7
+ define_method("#{name}_editable?") do
8
+ Furter::Accessors::Text.new(locator).editable?
9
+ end
10
+ define_method("#{name}=") do |text|
11
+ Furter::Accessors::Text.new(locator).set_text text
12
+ end
13
+ define_method("#{name}_view") do
14
+ Furter::Accessors::Text.new(locator)
15
+ end
16
+ end
17
+
18
+ def label(name, locator)
19
+ define_method("#{name}") do
20
+ Furter::Accessors::Label.new(locator).text
21
+ end
22
+ define_method("#{name}_view") do
23
+ Furter::Accessors::Label.new(locator)
24
+ end
25
+ end
26
+
27
+ def view(name, locator)
28
+ define_method("#{name}") do
29
+ Furter::Accessors::View.new(locator).click
30
+ end
31
+ define_method("#{name}_view") do
32
+ Furter::Accessors::View.new(locator)
33
+ end
34
+ end
35
+
36
+ def button(name, locator)
37
+ define_method("#{name}") do
38
+ Furter::Accessors::Button.new(locator).click
39
+ end
40
+ define_method("#{name}_view") do
41
+ Furter::Accessors::Button.new(locator)
42
+ end
43
+ end
44
+
45
+ def alert_button(name, locator)
46
+ define_method("#{name}") do
47
+ Furter::Accessors::AlertButton.new(locator).click
48
+ end
49
+ end
50
+
51
+ def table(name, locator)
52
+ define_method("#{name}=") do |which|
53
+ Furter::Accessors::TableItem.new(:text => which).click
54
+ end
55
+ define_method("#{name}_options") do
56
+ Furter::Accessors::Table.new(locator).options
57
+ end
58
+ define_method("#{name}_view") do
59
+ Furter::Accessors::Table.new(locator)
60
+ end
61
+ end
62
+
63
+ def table_item(name, locator)
64
+ define_method("#{name}") do
65
+ Furter::Accessors::TableItem.new(locator).click
66
+ end
67
+ end
68
+
69
+ def map_pin(name, locator)
70
+ define_method("#{name}") do
71
+ Furter::Accessors::MapPin.new(locator).click
72
+ end
73
+ end
74
+
75
+ def switch(name, locator)
76
+ define_method("#{name}") do
77
+ Furter::Accessors::Switch.new(locator).on?
78
+ end
79
+ define_method("#{name}=") do |on_or_off|
80
+ Furter::Accessors::Switch.new(locator).set on_or_off
81
+ end
82
+ define_method("#{name}_view") do
83
+ Furter::Accessors::Switch.new(locator)
84
+ end
85
+ end
86
+ end
87
+ end