frank-cucumber 0.9.4 → 0.9.5.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +58 -0
- data/frank-cucumber.gemspec +1 -0
- data/frank-skeleton/features/support/env.rb +2 -2
- data/frank-skeleton/frank_static_resources.bundle/_solarized_colors.scss +16 -0
- data/frank-skeleton/frank_static_resources.bundle/coffee-script.js +8 -0
- data/frank-skeleton/frank_static_resources.bundle/images/loader.gif +0 -0
- data/frank-skeleton/frank_static_resources.bundle/images/loader.png +0 -0
- data/frank-skeleton/frank_static_resources.bundle/index.haml +61 -47
- data/frank-skeleton/frank_static_resources.bundle/index.html +82 -71
- data/frank-skeleton/frank_static_resources.bundle/jquery.min.js +4 -19
- data/frank-skeleton/frank_static_resources.bundle/jquery.treeview.css +19 -17
- data/frank-skeleton/frank_static_resources.bundle/pictos/index.html +329 -0
- data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.eot +0 -0
- data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.svg +114 -0
- data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.ttf +0 -0
- data/frank-skeleton/frank_static_resources.bundle/pictos/pictos-web.woff +0 -0
- data/frank-skeleton/frank_static_resources.bundle/pictos/pictos.css +20 -0
- data/frank-skeleton/frank_static_resources.bundle/pictos/pictos_base64.css +18 -0
- data/frank-skeleton/frank_static_resources.bundle/reset.css +32 -0
- data/frank-skeleton/frank_static_resources.bundle/symbiote.css +407 -61
- data/frank-skeleton/frank_static_resources.bundle/symbiote.js +127 -54
- data/frank-skeleton/frank_static_resources.bundle/symbiote_ui.coffee +39 -0
- data/lib/frank-cucumber/cli.rb +12 -2
- data/lib/frank-cucumber/core_frank_steps.rb +11 -1
- data/lib/frank-cucumber/frank_helper.rb +142 -27
- data/lib/frank-cucumber/version.rb +1 -1
- data/lib/frank-cucumber/wait_helper.rb +26 -27
- metadata +36 -6
- data/frank-skeleton/frank_static_resources.bundle/jquery-ui.css +0 -571
@@ -1,7 +1,6 @@
|
|
1
1
|
/*jslint browser: true, white: false, devel: true */
|
2
2
|
/*global window: true, Raphael: true, $: true, _: true */
|
3
3
|
|
4
|
-
|
5
4
|
var symbiote = {};
|
6
5
|
|
7
6
|
symbiote.baseUrlFor = function(path){ return window.location.protocol + "//" + window.location.host + "/" + path; };
|
@@ -10,6 +9,7 @@ symbiote.UiLocator = function(){
|
|
10
9
|
var allViews = [],
|
11
10
|
paper = new Raphael( 'ui-locator-view'),
|
12
11
|
viewIndicator = { remove: _.identity },
|
12
|
+
viewIndicators = [],
|
13
13
|
screenshotUrl = symbiote.baseUrlFor( "screenshot" ),
|
14
14
|
backdrop = null,
|
15
15
|
erstaz = null;
|
@@ -110,27 +110,33 @@ symbiote.UiLocator = function(){
|
|
110
110
|
|
111
111
|
}
|
112
112
|
|
113
|
-
function
|
114
|
-
|
115
|
-
|
116
|
-
viewIndicator.remove();
|
113
|
+
function removeHighlights() {
|
114
|
+
_.each( viewIndicators, function(v){ v.remove(); } );
|
115
|
+
}
|
117
116
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
)
|
124
|
-
.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
117
|
+
function highlightAccessibilityFrames( frames ) {
|
118
|
+
var screenOffset = erstaz.screenOffset();
|
119
|
+
|
120
|
+
removeHighlights();
|
121
|
+
|
122
|
+
viewIndicators = _.map( frames, function(frame){
|
123
|
+
return paper.rect(
|
124
|
+
frame.origin.x,
|
125
|
+
frame.origin.y,
|
126
|
+
frame.size.width,
|
127
|
+
frame.size.height
|
128
|
+
)
|
129
|
+
.attr({
|
130
|
+
fill: '#aaff00',
|
131
|
+
opacity: 0.8,
|
132
|
+
stroke: 'black',
|
133
|
+
})
|
134
|
+
.translate( screenOffset.x, screenOffset.y );
|
135
|
+
});
|
130
136
|
}
|
131
137
|
|
132
|
-
function
|
133
|
-
|
138
|
+
function highlightAccessibilityFrame( frame ) {
|
139
|
+
highlightAccessibilityFrames( [frame] );
|
134
140
|
}
|
135
141
|
|
136
142
|
function addBackdropImage(){
|
@@ -163,17 +169,24 @@ symbiote.UiLocator = function(){
|
|
163
169
|
}
|
164
170
|
}
|
165
171
|
|
172
|
+
function updateOrientation(orientation){
|
173
|
+
// $(paper.canvas).parent().removeClass('landscape').removeClass('portrait').addClass(orientation);
|
174
|
+
$('#ui-locator-view, .the-columns').removeClass('landscape').removeClass('portrait').addClass(orientation);
|
175
|
+
}
|
176
|
+
|
166
177
|
function updateViews(views){
|
167
178
|
allViews = views;
|
168
179
|
}
|
169
180
|
|
170
181
|
|
171
182
|
return {
|
172
|
-
|
173
|
-
|
183
|
+
highlightAccessibilityFrame: highlightAccessibilityFrame,
|
184
|
+
highlightAccessibilityFrames: highlightAccessibilityFrames,
|
185
|
+
removeHighlights: removeHighlights,
|
174
186
|
updateBackdrop: updateBackdrop,
|
175
187
|
updateViews: updateViews,
|
176
|
-
updateDeviceFamily: updateDeviceFamily
|
188
|
+
updateDeviceFamily: updateDeviceFamily,
|
189
|
+
updateOrientation: updateOrientation
|
177
190
|
};
|
178
191
|
};
|
179
192
|
|
@@ -209,7 +222,7 @@ $(document).ready(function() {
|
|
209
222
|
var $domDetails = $('#dom_detail'),
|
210
223
|
$domList = $('div#dom_dump > ul'),
|
211
224
|
$domAccessibleDump = $('div#accessible-views'),
|
212
|
-
$loading = $('
|
225
|
+
$loading = $(''),
|
213
226
|
INTERESTING_PROPERTIES = ['class', 'accessibilityLabel', 'tag', 'alpha', 'isHidden'],
|
214
227
|
uiLocator = symbiote.UiLocator(),
|
215
228
|
liveView;
|
@@ -248,31 +261,31 @@ $(document).ready(function() {
|
|
248
261
|
}
|
249
262
|
|
250
263
|
function showLoadingUI() {
|
251
|
-
$
|
264
|
+
$('body').addClass('working');
|
252
265
|
}
|
253
266
|
|
254
267
|
function hideLoadingUI() {
|
255
|
-
$
|
268
|
+
$('body').removeClass('working');
|
256
269
|
}
|
257
270
|
|
258
271
|
|
259
272
|
function displayDetailsFor( view ) {
|
260
273
|
console.debug( 'displaying details for:', view );
|
261
274
|
|
262
|
-
var $
|
275
|
+
var $ul = $('<ul/>');
|
263
276
|
|
264
|
-
function
|
277
|
+
function createListItem( propertyName, propertyValue, cssClass ){
|
265
278
|
if( propertyValue === null ){
|
266
279
|
propertyValue = 'null';
|
267
280
|
}else if( typeof propertyValue === 'object' ){
|
268
281
|
propertyValue = JSON.stringify(propertyValue);
|
269
282
|
}
|
270
283
|
|
271
|
-
return $('<
|
284
|
+
return $('<li/>').addClass(cssClass)
|
272
285
|
.append(
|
273
|
-
$('<
|
274
|
-
$('<
|
275
|
-
.appendTo( $
|
286
|
+
$('<div/>').addClass('key').text(propertyName),
|
287
|
+
$('<div/>').addClass('value').text(propertyValue) )
|
288
|
+
.appendTo( $ul );
|
276
289
|
}
|
277
290
|
|
278
291
|
|
@@ -280,7 +293,7 @@ $(document).ready(function() {
|
|
280
293
|
if( !view.hasOwnProperty(propertyName) ){ return; }
|
281
294
|
|
282
295
|
var propertyValue = view[propertyName];
|
283
|
-
$
|
296
|
+
$ul.append( createListItem( propertyName, propertyValue, 'interesting' ) );
|
284
297
|
});
|
285
298
|
|
286
299
|
|
@@ -289,11 +302,11 @@ $(document).ready(function() {
|
|
289
302
|
if( _.contains( INTERESTING_PROPERTIES, propertyName ) ){ return; } // don't want to include the interesting properties twice
|
290
303
|
|
291
304
|
var propertyValue = view[propertyName];
|
292
|
-
$
|
305
|
+
$ul.append( createListItem( propertyName, propertyValue ) );
|
293
306
|
});
|
294
307
|
|
295
|
-
$domDetails.
|
296
|
-
$
|
308
|
+
$domDetails.empty();
|
309
|
+
$ul.appendTo( $domDetails );
|
297
310
|
}
|
298
311
|
|
299
312
|
function treeElementSelected(){
|
@@ -308,11 +321,11 @@ $(document).ready(function() {
|
|
308
321
|
|
309
322
|
function treeElementEntered(){
|
310
323
|
var view = $(this).data('rawView');
|
311
|
-
uiLocator.
|
324
|
+
uiLocator.highlightAccessibilityFrame( view.accessibilityFrame );
|
312
325
|
}
|
313
326
|
|
314
327
|
function treeElementLeft(){
|
315
|
-
uiLocator.
|
328
|
+
uiLocator.removeHighlights();
|
316
329
|
}
|
317
330
|
|
318
331
|
function listItemTitleFor( rawView ) {
|
@@ -379,18 +392,19 @@ $(document).ready(function() {
|
|
379
392
|
}
|
380
393
|
|
381
394
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
395
|
+
function sendMapRequest( selector, engine, method_name, method_args ) {
|
396
|
+
var deferable = new $.Deferred(),
|
397
|
+
command = {
|
398
|
+
query: selector,
|
399
|
+
selector_engine: engine ? engine : 'uiquery' ,
|
400
|
+
operation: {
|
401
|
+
method_name: method_name,
|
402
|
+
arguments: method_args || []
|
403
|
+
}
|
404
|
+
};
|
392
405
|
|
393
406
|
showLoadingUI();
|
407
|
+
|
394
408
|
$.ajax({
|
395
409
|
type: "POST",
|
396
410
|
dataType: "json",
|
@@ -399,20 +413,46 @@ $(document).ready(function() {
|
|
399
413
|
success: function(data) {
|
400
414
|
if( isErrorResponse( data ) ) {
|
401
415
|
displayErrorResponse( data );
|
416
|
+
deferable.reject(data);
|
402
417
|
}
|
418
|
+
deferable.resolve(data);
|
403
419
|
},
|
404
420
|
error: function(xhr,status,error) {
|
405
421
|
alert( "Error while talking to Frank: " + status );
|
422
|
+
deferable.reject(error);
|
406
423
|
},
|
407
424
|
complete: function(xhr,status) {
|
408
425
|
hideLoadingUI();
|
409
426
|
}
|
410
427
|
});
|
411
428
|
|
412
|
-
return
|
429
|
+
return deferable.promise();
|
430
|
+
}
|
431
|
+
|
432
|
+
function highlightViewLocations( selector, engine ){
|
433
|
+
sendMapRequest( selector, engine, 'accessibilityFrame' ).done( function(data){
|
434
|
+
locations = data.results;
|
435
|
+
if( locations.length < 1 ){
|
436
|
+
alert( 'no views found for that selector' );
|
437
|
+
return;
|
438
|
+
}
|
439
|
+
|
440
|
+
uiLocator.highlightAccessibilityFrames( locations );
|
441
|
+
window.setTimeout( function(){
|
442
|
+
uiLocator.removeHighlights();
|
443
|
+
}, 1000 );
|
444
|
+
});
|
445
|
+
}
|
446
|
+
|
447
|
+
function sendFlashCommand( selector, engine ) {
|
448
|
+
sendMapRequest(selector,engine,'FEX_flash');
|
449
|
+
}
|
450
|
+
|
451
|
+
function sendTouchCommand( selector, engine ) {
|
452
|
+
sendMapRequest(selector,engine,'touch');
|
413
453
|
}
|
414
454
|
|
415
|
-
|
455
|
+
function updateAccessibleViews( views ) {
|
416
456
|
var accessibleViews = filterAccessibleViews( views ),
|
417
457
|
divTemplate = _.template( '<div><a href="#" title="<%=selector%>"><span class="viewClass"><%=viewClass%></span> with label "<span class="viewLabel"><%=viewLabel%></span>"</a></div>' );
|
418
458
|
|
@@ -424,7 +464,9 @@ $(document).ready(function() {
|
|
424
464
|
|
425
465
|
$(divHtml)
|
426
466
|
.click( function(){
|
467
|
+
$('#query').val( selector );
|
427
468
|
sendFlashCommand( selector );
|
469
|
+
highlightViewLocations( selector );
|
428
470
|
return false;
|
429
471
|
})
|
430
472
|
.appendTo( $domAccessibleDump );
|
@@ -432,6 +474,9 @@ $(document).ready(function() {
|
|
432
474
|
}
|
433
475
|
|
434
476
|
function guessAtDeviceFamilyBasedOnViewDump(data){
|
477
|
+
var firstChildViewFrame = data.subviews[0].accessibilityFrame;
|
478
|
+
|
479
|
+
console.log( JSON.stringify( firstChildViewFrame ) ) ;
|
435
480
|
switch( data.accessibilityFrame.size.height ){
|
436
481
|
case 1024:
|
437
482
|
return 'ipad';
|
@@ -443,10 +488,30 @@ $(document).ready(function() {
|
|
443
488
|
}
|
444
489
|
}
|
445
490
|
|
491
|
+
function refreshOrientation(){
|
492
|
+
$.ajax({
|
493
|
+
type: 'GET',
|
494
|
+
dataType: 'json',
|
495
|
+
url: symbiote.baseUrlFor("/orientation"),
|
496
|
+
success: function(data) {
|
497
|
+
var orientation = data.orientation;
|
498
|
+
|
499
|
+
console.debug( 'device orientation is '+orientation );
|
500
|
+
uiLocator.updateOrientation(orientation);
|
501
|
+
},
|
502
|
+
error: function(xhr,status,error) {
|
503
|
+
alert( "Error while talking to Frank: " + status );
|
504
|
+
}
|
505
|
+
});
|
506
|
+
}
|
507
|
+
|
508
|
+
|
446
509
|
|
447
510
|
function refreshViewHeirarchy(){
|
448
511
|
showLoadingUI();
|
449
512
|
|
513
|
+
refreshOrientation();
|
514
|
+
|
450
515
|
$.ajax({
|
451
516
|
type: "POST",
|
452
517
|
dataType: "json",
|
@@ -475,15 +540,22 @@ $(document).ready(function() {
|
|
475
540
|
}
|
476
541
|
|
477
542
|
|
478
|
-
|
479
543
|
$('#dump_button').click( function(){
|
480
544
|
refreshViewHeirarchy();
|
481
545
|
uiLocator.updateBackdrop();
|
482
546
|
});
|
483
547
|
|
484
|
-
$('#
|
548
|
+
$('button#flash').click( function(){
|
485
549
|
sendFlashCommand( $("input#query").val(), $("input#selector_engine").val() );
|
486
550
|
});
|
551
|
+
|
552
|
+
$('button#touch').click( function(){
|
553
|
+
sendTouchCommand( $("input#query").val(), $("input#selector_engine").val() );
|
554
|
+
});
|
555
|
+
|
556
|
+
$('button#highlight').click( function(){
|
557
|
+
highlightViewLocations( $("input#query").val(), $("input#selector_engine").val() );
|
558
|
+
});
|
487
559
|
|
488
560
|
liveView = symbiote.LiveView( uiLocator.updateBackdrop, refreshViewHeirarchy );
|
489
561
|
|
@@ -491,17 +563,18 @@ $(document).ready(function() {
|
|
491
563
|
$(this).toggleClass('down');
|
492
564
|
if( $(this).hasClass('down') ){
|
493
565
|
liveView.start();
|
494
|
-
$(this).text('stop Live View');
|
495
566
|
}else{
|
496
567
|
liveView.stop();
|
497
|
-
$(this).text('start Live View');
|
498
568
|
}
|
499
569
|
});
|
500
570
|
|
571
|
+
$('#ui-locator-rotator').click( function(){
|
572
|
+
$('#ui-locator-view, .the-columns').toggleClass('landscape');
|
573
|
+
});
|
501
574
|
|
502
575
|
//initial UI setup
|
503
576
|
|
504
|
-
$('#loading').hide();
|
577
|
+
// $('#loading').hide();
|
505
578
|
|
506
579
|
// do initial DOM dump straight after page has finished loading
|
507
580
|
$('#dump_button').click();
|
@@ -0,0 +1,39 @@
|
|
1
|
+
setupDropdowns = ->
|
2
|
+
$extraActionsList = $('.action-buttons .extra-actions')
|
3
|
+
$se_option_list = $('ul#selector_engine_options')
|
4
|
+
$se_option_input = $('input#selector_engine')
|
5
|
+
|
6
|
+
$('button#selector_engine_dropdown').on 'click', (e)->
|
7
|
+
e.stopPropagation()
|
8
|
+
$se_option_list.toggleClass('shown')
|
9
|
+
|
10
|
+
$('li', $se_option_list).on 'click', (e)->
|
11
|
+
$se_option_input.val( $(e.target).text() )
|
12
|
+
|
13
|
+
$('.action-buttons .drop-indicator').on 'click', (e)->
|
14
|
+
e.stopPropagation()
|
15
|
+
$extraActionsList.toggleClass('shown')
|
16
|
+
|
17
|
+
$('button',$extraActionsList).on 'click', ->
|
18
|
+
$selectedButton = $(this)
|
19
|
+
$currentTopButton = $('.action-buttons > button')
|
20
|
+
|
21
|
+
return if $selectedButton[0] == $currentTopButton[0]
|
22
|
+
|
23
|
+
# shove the button that was just selected into the 'top'
|
24
|
+
# action button area
|
25
|
+
$currentTopButton.after($selectedButton)
|
26
|
+
# push the current top button to the top of the 'extra'
|
27
|
+
# action button area. This will also remove it from the 'top' area
|
28
|
+
$extraActionsList.prepend($currentTopButton)
|
29
|
+
|
30
|
+
|
31
|
+
# remove button from top and but to top of extra buttons
|
32
|
+
# move tapped butotn
|
33
|
+
|
34
|
+
$('body').on 'click', ->
|
35
|
+
$extraActionsList.removeClass('shown')
|
36
|
+
$se_option_list.removeClass('shown')
|
37
|
+
|
38
|
+
$ ->
|
39
|
+
setupDropdowns()
|
data/lib/frank-cucumber/cli.rb
CHANGED
@@ -30,7 +30,11 @@ module Frank
|
|
30
30
|
directory( 'frank_static_resources.bundle', 'Frank/frank_static_resources.bundle', :force => true )
|
31
31
|
end
|
32
32
|
|
33
|
+
XCODEBUILD_OPTIONS = %w{workspace scheme target}
|
33
34
|
desc "build", "builds a Frankified version of your native app"
|
35
|
+
XCODEBUILD_OPTIONS.each do |option|
|
36
|
+
method_option option
|
37
|
+
end
|
34
38
|
def build
|
35
39
|
|
36
40
|
in_root do
|
@@ -49,7 +53,9 @@ module Frank
|
|
49
53
|
|
50
54
|
remove_dir build_output_dir
|
51
55
|
|
52
|
-
|
56
|
+
extra_opts = XCODEBUILD_OPTIONS.map{ |o| "-#{o} #{options[o]}" if options[o] }.compact.join(' ')
|
57
|
+
|
58
|
+
run "xcodebuild -xcconfig Frank/frankify.xcconfig install #{extra_opts} -configuration Debug -sdk iphonesimulator DSTROOT=#{build_output_dir} PRODUCT_NAME=#{product_name}"
|
53
59
|
|
54
60
|
in_root do
|
55
61
|
FileUtils.cp_r(
|
@@ -114,8 +120,12 @@ module Frank
|
|
114
120
|
|
115
121
|
private
|
116
122
|
|
123
|
+
def product_name
|
124
|
+
"Frankified"
|
125
|
+
end
|
126
|
+
|
117
127
|
def app_bundle_name
|
118
|
-
"
|
128
|
+
"#{product_name}.app"
|
119
129
|
end
|
120
130
|
|
121
131
|
def build_output_dir
|
@@ -60,7 +60,7 @@ Then /I should not see the following:/ do |table|
|
|
60
60
|
end
|
61
61
|
|
62
62
|
Then /^I should see an alert view titled "([^\"]*)"$/ do |expected_mark|
|
63
|
-
values = frankly_map( 'alertView', '
|
63
|
+
values = frankly_map( 'alertView', 'title')
|
64
64
|
values.should include(expected_mark)
|
65
65
|
end
|
66
66
|
|
@@ -176,6 +176,7 @@ Then /^I rotate to the "([^\"]*)"$/ do |direction|
|
|
176
176
|
end
|
177
177
|
|
178
178
|
# -- touch -- #
|
179
|
+
# generic views
|
179
180
|
When /^I touch "([^\"]*)"$/ do |mark|
|
180
181
|
selector = "view marked:'#{mark}' first"
|
181
182
|
if element_exists(selector)
|
@@ -195,6 +196,7 @@ When /^I touch "([^\"]*)" if exists$/ do |mark|
|
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
199
|
+
# table cells
|
198
200
|
When /^I touch the first table cell$/ do
|
199
201
|
touch("tableViewCell first")
|
200
202
|
end
|
@@ -216,10 +218,12 @@ Then /I touch the following:/ do |table|
|
|
216
218
|
end
|
217
219
|
end
|
218
220
|
|
221
|
+
# buttons
|
219
222
|
When /^I touch the button marked "([^\"]*)"$/ do |mark|
|
220
223
|
touch( "button marked:'#{mark}'" )
|
221
224
|
end
|
222
225
|
|
226
|
+
# action sheets
|
223
227
|
When /^I touch the "([^\"]*)" action sheet button$/ do |mark|
|
224
228
|
touch( "actionSheet threePartButton marked:'#{mark}'" )
|
225
229
|
end
|
@@ -229,6 +233,11 @@ When /^I touch the (\d*)(?:st|nd|rd|th)? action sheet button$/ do |ordinal|
|
|
229
233
|
touch( "actionSheet threePartButton tag:#{ordinal}" )
|
230
234
|
end
|
231
235
|
|
236
|
+
# alert views
|
237
|
+
When /^I touch the "([^\"]*)" alert view button$/ do |mark|
|
238
|
+
touch( "alertView threePartButton marked:'#{mark}'" )
|
239
|
+
end
|
240
|
+
|
232
241
|
When /^I touch the (\d*)(?:st|nd|rd|th)? alert view button$/ do |ordinal|
|
233
242
|
ordinal = ordinal.to_i
|
234
243
|
touch( "alertView threePartButton tag:#{ordinal}" )
|
@@ -268,6 +277,7 @@ end
|
|
268
277
|
|
269
278
|
Then /^I navigate back$/ do
|
270
279
|
touch( "navigationItemButtonView" )
|
280
|
+
wait_for_nothing_to_be_animating
|
271
281
|
end
|
272
282
|
|
273
283
|
When /^I dump the DOM$/ do
|