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.
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/.travis.yml +2 -0
- data/Changelog +3 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -0
- data/Rakefile +30 -0
- data/app/FurterApp/Frank/features/my_first.feature +12 -0
- data/app/FurterApp/Frank/features/step_definitions/launch_steps.rb +20 -0
- data/app/FurterApp/Frank/features/support/env.rb +8 -0
- data/app/FurterApp/Frank/frankify.xcconfig +6 -0
- data/app/FurterApp/Frank/libCocoaAsyncSocket.a +0 -0
- data/app/FurterApp/Frank/libCocoaAsyncSocketMac.a +0 -0
- data/app/FurterApp/Frank/libCocoaHTTPServer.a +0 -0
- data/app/FurterApp/Frank/libCocoaHTTPServerMac.a +0 -0
- data/app/FurterApp/Frank/libCocoaLumberjack.a +0 -0
- data/app/FurterApp/Frank/libCocoaLumberjackMac.a +0 -0
- data/app/FurterApp/Frank/libFrank.a +0 -0
- data/app/FurterApp/Frank/libFrankMac.a +0 -0
- data/app/FurterApp/Frank/libShelley.a +0 -0
- data/app/FurterApp/Frank/libShelleyMac.a +0 -0
- data/app/FurterApp/FurterApp.xcodeproj/project.pbxproj +807 -0
- data/app/FurterApp/FurterApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/app/FurterApp/FurterApp.xcodeproj/project.xcworkspace/xcuserdata/lwilson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/app/FurterApp/FurterApp.xcodeproj/xcuserdata/lwilson.xcuserdatad/xcschemes/FurterApp.xcscheme +86 -0
- data/app/FurterApp/FurterApp.xcodeproj/xcuserdata/lwilson.xcuserdatad/xcschemes/xcschememanagement.plist +22 -0
- data/app/FurterApp/FurterApp/AppDelegate.h +22 -0
- data/app/FurterApp/FurterApp/AppDelegate.m +161 -0
- data/app/FurterApp/FurterApp/Default-568h@2x.png +0 -0
- data/app/FurterApp/FurterApp/Default.png +0 -0
- data/app/FurterApp/FurterApp/Default@2x.png +0 -0
- data/app/FurterApp/FurterApp/DetailViewController.h +23 -0
- data/app/FurterApp/FurterApp/DetailViewController.m +80 -0
- data/app/FurterApp/FurterApp/FurterApp-Info.plist +59 -0
- data/app/FurterApp/FurterApp/FurterApp-Prefix.pch +15 -0
- data/app/FurterApp/FurterApp/FurterApp.xcdatamodeld/.xccurrentversion +8 -0
- data/app/FurterApp/FurterApp/FurterApp.xcdatamodeld/FurterApp.xcdatamodel/contents +9 -0
- data/app/FurterApp/FurterApp/MasterViewController.h +22 -0
- data/app/FurterApp/FurterApp/MasterViewController.m +235 -0
- data/app/FurterApp/FurterApp/en.lproj/InfoPlist.strings +2 -0
- data/app/FurterApp/FurterApp/en.lproj/MainStoryboard_iPad.storyboard +260 -0
- data/app/FurterApp/FurterApp/en.lproj/MainStoryboard_iPhone.storyboard +129 -0
- data/app/FurterApp/FurterApp/main.m +18 -0
- data/cucumber.yml +2 -0
- data/features/button.feature +12 -0
- data/features/label.feature +10 -0
- data/features/navigation.feature +5 -0
- data/features/step_definitions/button_steps.rb +7 -0
- data/features/step_definitions/label_steps.rb +8 -0
- data/features/step_definitions/navigation_steps.rb +7 -0
- data/features/step_definitions/switches_steps.rb +12 -0
- data/features/step_definitions/text_steps.rb +25 -0
- data/features/support/core_ext/string.rb +9 -0
- data/features/support/env.rb +25 -0
- data/features/support/hooks.rb +3 -0
- data/features/support/screens/detail.rb +15 -0
- data/features/support/screens/elsewhere_page.rb +7 -0
- data/features/switches.feature +7 -0
- data/features/text.feature +15 -0
- data/furter.gemspec +26 -0
- data/lib/furter.rb +53 -0
- data/lib/furter/accessors.rb +87 -0
- data/lib/furter/accessors/alert_button.rb +18 -0
- data/lib/furter/accessors/button.rb +17 -0
- data/lib/furter/accessors/label.rb +13 -0
- data/lib/furter/accessors/map_pin.rb +18 -0
- data/lib/furter/accessors/switch.rb +20 -0
- data/lib/furter/accessors/table.rb +15 -0
- data/lib/furter/accessors/table_item.rb +10 -0
- data/lib/furter/accessors/text.rb +27 -0
- data/lib/furter/accessors/view.rb +46 -0
- data/lib/furter/navigation.rb +25 -0
- data/lib/furter/version.rb +3 -0
- data/spec/lib/furter/accessors/button_spec.rb +23 -0
- data/spec/lib/furter/accessors/label_spec.rb +24 -0
- data/spec/lib/furter/accessors/switch_spec.rb +28 -0
- data/spec/lib/furter/accessors/text_spec.rb +39 -0
- data/spec/lib/furter/accessors/view_spec.rb +43 -0
- data/spec/lib/furter/accessors_spec.rb +116 -0
- data/spec/spec_helper.rb +18 -0
- 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,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,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,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,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,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,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
|