furter 0.0.3

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.
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