rest-assured 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rest-assured (1.1.2)
4
+ rest-assured (1.1.3)
5
5
  activerecord (~> 3.2.0)
6
6
  activeresource (~> 3.2.0)
7
7
  childprocess (~> 0.3.0)
@@ -12,23 +12,23 @@ PATH
12
12
  GEM
13
13
  remote: http://rubygems.org/
14
14
  specs:
15
- activemodel (3.2.1)
16
- activesupport (= 3.2.1)
15
+ activemodel (3.2.2)
16
+ activesupport (= 3.2.2)
17
17
  builder (~> 3.0.0)
18
- activerecord (3.2.1)
19
- activemodel (= 3.2.1)
20
- activesupport (= 3.2.1)
21
- arel (~> 3.0.0)
18
+ activerecord (3.2.2)
19
+ activemodel (= 3.2.2)
20
+ activesupport (= 3.2.2)
21
+ arel (~> 3.0.2)
22
22
  tzinfo (~> 0.3.29)
23
- activeresource (3.2.1)
24
- activemodel (= 3.2.1)
25
- activesupport (= 3.2.1)
26
- activesupport (3.2.1)
23
+ activeresource (3.2.2)
24
+ activemodel (= 3.2.2)
25
+ activesupport (= 3.2.2)
26
+ activesupport (3.2.2)
27
27
  i18n (~> 0.6)
28
28
  multi_json (~> 1.0)
29
29
  addressable (2.2.7)
30
30
  archive-tar-minitar (0.5.2)
31
- arel (3.0.0)
31
+ arel (3.0.2)
32
32
  awesome_print (1.0.2)
33
33
  builder (3.0.0)
34
34
  capybara (1.1.2)
@@ -43,10 +43,10 @@ GEM
43
43
  childprocess (0.3.1)
44
44
  ffi (~> 1.0.6)
45
45
  columnize (0.3.6)
46
- cucumber (1.1.4)
46
+ cucumber (1.1.9)
47
47
  builder (>= 2.1.2)
48
48
  diff-lcs (>= 1.1.2)
49
- gherkin (~> 2.7.1)
49
+ gherkin (~> 2.9.0)
50
50
  json (>= 1.4.6)
51
51
  term-ansicolor (>= 1.0.6)
52
52
  daemons (1.1.8)
@@ -54,7 +54,7 @@ GEM
54
54
  diff-lcs (1.1.3)
55
55
  eventmachine (0.12.10)
56
56
  ffi (1.0.11)
57
- gherkin (2.7.7)
57
+ gherkin (2.9.0)
58
58
  json (>= 1.4.6)
59
59
  growl (1.0.3)
60
60
  guard (1.0.0)
@@ -72,12 +72,12 @@ GEM
72
72
  addressable (~> 2.2.6)
73
73
  linecache (0.46)
74
74
  rbx-require-relative (> 0.0.4)
75
- linecache19 (0.5.13)
75
+ linecache19 (0.5.12)
76
76
  ruby_core_source (>= 0.1.4)
77
77
  mime-types (1.17.2)
78
- multi_json (1.0.4)
78
+ multi_json (1.1.0)
79
79
  mysql2 (0.3.11)
80
- nokogiri (1.5.0)
80
+ nokogiri (1.5.2)
81
81
  pg (0.13.2)
82
82
  rack (1.4.1)
83
83
  rack-protection (1.2.0)
@@ -87,7 +87,7 @@ GEM
87
87
  rake (0.9.2.2)
88
88
  rb-fsevent (0.9.0)
89
89
  rb-readline (0.4.2)
90
- rbx-require-relative (0.0.5)
90
+ rbx-require-relative (0.0.9)
91
91
  relish (0.5.3)
92
92
  archive-tar-minitar (>= 0.5.2)
93
93
  json (>= 1.4.6)
@@ -107,7 +107,7 @@ GEM
107
107
  ruby-debug-base (~> 0.10.4.0)
108
108
  ruby-debug-base (0.10.4)
109
109
  linecache (>= 0.3)
110
- ruby-debug-base19 (0.11.26)
110
+ ruby-debug-base19 (0.11.25)
111
111
  columnize (>= 0.3.1)
112
112
  linecache19 (>= 0.5.11)
113
113
  ruby_core_source (>= 0.1.4)
@@ -118,14 +118,14 @@ GEM
118
118
  ruby_core_source (0.1.5)
119
119
  archive-tar-minitar (>= 0.5.2)
120
120
  rubyzip (0.9.6.1)
121
- selenium-webdriver (2.19.0)
121
+ selenium-webdriver (2.20.0)
122
122
  childprocess (>= 0.2.5)
123
- ffi (~> 1.0.9)
124
- multi_json (~> 1.0.4)
123
+ ffi (~> 1.0)
124
+ multi_json (~> 1.0)
125
125
  rubyzip
126
126
  shoulda-matchers (1.0.0)
127
- simplecov (0.5.4)
128
- multi_json (~> 1.0.3)
127
+ simplecov (0.6.1)
128
+ multi_json (~> 1.0)
129
129
  simplecov-html (~> 0.5.3)
130
130
  simplecov-html (0.5.3)
131
131
  sinatra (1.3.2)
@@ -146,7 +146,7 @@ GEM
146
146
  rack (>= 1.0.0)
147
147
  thor (0.14.6)
148
148
  tilt (1.3.3)
149
- tzinfo (0.3.31)
149
+ tzinfo (0.3.32)
150
150
  xpath (0.1.4)
151
151
  nokogiri (~> 1.3)
152
152
 
data/README.markdown CHANGED
@@ -5,12 +5,16 @@
5
5
  ## Overview
6
6
 
7
7
  Stub/spy http(s) based external dependencies in your integration/acceptance tests.
8
- In essense, here is what it could be useful for:
9
8
 
10
- * stub out external data sources with predefined data
11
- * verify requests to external services (aka spying)
9
+ In a nutshell, here is how you can use it:
10
+
11
+ * replace external data sources with predefined data (stubbing)
12
+ * verify requests to external services (spying)
12
13
  * simulate different behavior of external services using web UI; useful in development
13
14
 
15
+ Check out [example](https://github.com/artemave/REST-assured-example)
16
+
17
+
14
18
  ## Usage
15
19
 
16
20
  You are going to need MRI ruby >= 1.8.7 on Linux/MacOS.
@@ -32,7 +36,7 @@ Then install gem and run:
32
36
 
33
37
  Or clone and run:
34
38
 
35
- bash$ git clone git@github.com:BBC/rest-assured.git
39
+ bash$ git clone git://github.com/BBC/REST-assured.git
36
40
  bash$ cd rest-assured && bundle install
37
41
  bash$ ./bin/rest-assured -d :memory: & # in-memory sqlite db
38
42
 
@@ -42,7 +46,7 @@ Various options (such as ssl, port, db credentials, etc.) are available through
42
46
 
43
47
  You can also deploy it to heroku:
44
48
 
45
- bash$ git clone git@github.com:BBC/rest-assured.git
49
+ bash$ git clone git://github.com/BBC/REST-assured.git
46
50
  bash$ cd rest-assured
47
51
 
48
52
  bash$ gem install heroku
@@ -57,7 +61,7 @@ Double is a stub/spy of HTTP request. Create a double that has the same request
57
61
 
58
62
  ### Ruby Client API
59
63
 
60
- Rest-assured provides client library to work with doubles. Check out 'Ruby API' section in [documentation](https://www.relishapp.com/artemave/rest-assured) for full reference.
64
+ Rest-assured provides client library to work with doubles. Check out 'Ruby API' section in [live documentation](https://www.relishapp.com/artemave/rest-assured) for full reference.
61
65
 
62
66
  Start up the server:
63
67
 
@@ -209,7 +213,7 @@ Here is the rest API for managing redirects:
209
213
 
210
214
  Tests require there to be mysql database `rest_assured_test` accessible by `root` with no password. Cucumber tests also need firefox.
211
215
 
212
- bash$ git clone git@github.com:BBC/rest-assured.git
216
+ bash$ git clone git://github.com/BBC/REST-assured.git
213
217
  bash$ cd rest-assured && bundle install
214
218
  bash$ bundle exec rspec spec
215
219
  bash$ bundle exec cucumber
@@ -0,0 +1,9 @@
1
+ class ChangeFullpathToText < ActiveRecord::Migration
2
+ def self.up
3
+ change_column :doubles, :fullpath, :text
4
+ end
5
+
6
+ def self.down
7
+ change_column :doubles, :fullpath, :string
8
+ end
9
+ end
@@ -46,19 +46,17 @@ Given /^I choose to delete redirect with pattern "([^"]*)"$/ do |pattern|
46
46
  end
47
47
 
48
48
  When /^I reorder second redirect to be the first one$/ do
49
- handler = find("#redirects #redirect_#{RestAssured::Models::Redirect.last.id} td.handle")
50
- target = find('#redirects thead')
51
-
52
- handler.drag_to target
49
+ page.execute_script %{
50
+ $('#redirects #redirect_#{RestAssured::Models::Redirect.order('position').last.id}').simulateDragSortable({move: -1, handle: '.handle'})
51
+ }
52
+ sleep 2
53
53
  end
54
54
 
55
55
  Then /^"([^"]*)" should be redirected to "([^"]*)"$/ do |missing_request, url|
56
- pending('This does not pass due to Capybara/Selelium broken drag and drop support')
57
-
58
56
  get missing_request
59
57
  follow_redirect!
60
58
 
61
- last_request.url.should == "#{url}#{missing_request}"
59
+ last_request.url.should == url
62
60
  end
63
61
 
64
62
  Given /^blank slate$/ do
@@ -49,9 +49,9 @@ Feature: manage redirects via ui
49
49
  | /api/bbb | http://twitter.com/api |
50
50
  And I am on "redirects" page
51
51
  When I reorder second redirect to be the first one
52
- Then "/api/bbb" should be redirected to "http://twitter.com/api"
52
+ Then "/api/bbb/ccc" should be redirected to "http://twitter.com/api/ccc"
53
53
  When I reorder second redirect to be the first one
54
- Then "/api/bbb" should be redirected to "http://google.com/api"
54
+ Then "/api/bbb/ccc" should be redirected to "http://google.com/api"
55
55
 
56
56
  @javascript
57
57
  Scenario: delete redirect
@@ -1,3 +1,3 @@
1
1
  module RestAssured
2
- VERSION = '1.1.2'
2
+ VERSION = '1.1.3'
3
3
  end
@@ -0,0 +1,235 @@
1
+ (function($) {
2
+ /*
3
+ * Simulate drag of a JQuery UI sortable list
4
+ * Repository: https://github.com/mattheworiordan/jquery.simulate.drag-sortable.js
5
+ * Author: http://mattheworiordan.com
6
+ *
7
+ * options are:
8
+ * - move: move item up (positive) or down (negative) by Integer amount
9
+ * - dropOn: move item to a new linked list, move option now represents position in the new list (zero indexed)
10
+ * - handle: selector for the draggable handle element (optional)
11
+ * - listItem: selector to limit which sibling items can be used for reordering
12
+ * - placeHolder: if a placeholder is used during dragging, we need to consider it's height
13
+ * - tolerance: (optional) number of pixels to overlap by instead of the default 50% of the element height
14
+ *
15
+ */
16
+ $.fn.simulateDragSortable = function(options) {
17
+ // build main options before element iteration
18
+ var opts = $.extend({}, $.fn.simulateDragSortable.defaults, options);
19
+
20
+ applyDrag = function(options) {
21
+ // allow for a drag handle if item is not draggable
22
+ var that = this,
23
+ options = options || opts, // default to plugin opts unless options explicitly provided
24
+ handle = options.handle ? $(this).find(options.handle)[0] : $(this)[0],
25
+ listItem = options.listItem,
26
+ placeHolder = options.placeHolder,
27
+ sibling = $(this),
28
+ moveCounter = Math.floor(options.move),
29
+ direction = moveCounter > 0 ? 'down' : 'up',
30
+ moveVerticalAmount = 0,
31
+ initialVerticalPosition = 0,
32
+ extraDrag = !isNaN(parseInt(options.tolerance, 10)) ? function() { return Number(options.tolerance); } : function(obj) { return ($(obj).outerHeight() / 2) + 5; },
33
+ dragPastBy = 0, // represents the additional amount one drags past an element and bounce back
34
+ dropOn = options.dropOn ? $(options.dropOn) : false,
35
+ center = findCenter(handle),
36
+ x = Math.floor(center.x),
37
+ y = Math.floor(center.y),
38
+ mouseUpAfter = (opts.debug ? 2500 : 10);
39
+
40
+ if (dropOn) {
41
+ if (dropOn.length === 0) {
42
+ if (console && console.log) { console.log('simulate.drag-sortable.js ERROR: Drop on target could not be found'); console.log(options.dropOn); }
43
+ return;
44
+ }
45
+ sibling = dropOn.find('>*:last');
46
+ moveCounter = -(dropOn.find('>*').length + 1) + (moveCounter + 1); // calculate length of list after this move, use moveCounter as a positive index position in list to reverse back up
47
+ if (dropOn.offset().top - $(this).offset().top < 0) {
48
+ // moving to a list above this list, so move to just above top of last item (tried moving to top but JQuery UI wouldn't bite)
49
+ initialVerticalPosition = sibling.offset().top - $(this).offset().top - extraDrag(this);
50
+ } else {
51
+ // moving to a list below this list, so move to bottom and work up (JQuery UI does not trigger new list below unless you move past top item first)
52
+ initialVerticalPosition = sibling.offset().top - $(this).offset().top - $(this).height();
53
+ }
54
+ } else if (moveCounter === 0) {
55
+ if (console && console.log) { console.log('simulate.drag-sortable.js WARNING: Drag with move set to zero has no effect'); }
56
+ return;
57
+ } else {
58
+ while (moveCounter !== 0) {
59
+ if (direction === 'down') {
60
+ if (sibling.next(listItem).length) {
61
+ sibling = sibling.next(listItem);
62
+ moveVerticalAmount += sibling.outerHeight();
63
+ }
64
+ moveCounter -= 1;
65
+ } else {
66
+ if (sibling.prev(listItem).length) {
67
+ sibling = sibling.prev(listItem);
68
+ moveVerticalAmount -= sibling.outerHeight();
69
+ }
70
+ moveCounter += 1;
71
+ }
72
+ }
73
+ }
74
+
75
+ dispatchEvent(handle, 'mousedown', createEvent('mousedown', handle, { clientX: x, clientY: y }));
76
+ // simulate drag start
77
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x+1, clientY: y+1 }));
78
+
79
+ if (dropOn) {
80
+ // jump to top or bottom of new list but do it in increments so that JQuery UI registers the drag events
81
+ slideUpTo(x, y, initialVerticalPosition);
82
+
83
+ // reset y position to top or bottom of list and move from there
84
+ y += initialVerticalPosition;
85
+
86
+ // now call regular shift/down in a list
87
+ options = jQuery.extend(options, { move: moveCounter });
88
+ delete options.dropOn;
89
+
90
+ // add some delays to allow JQuery UI to catch up
91
+ setTimeout(function() {
92
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y }));
93
+ }, 5);
94
+ setTimeout(function() {
95
+ dispatchEvent(handle, 'mouseup', createEvent('mouseup', handle, { clientX: x, clientY: y }));
96
+ setTimeout(function() {
97
+ if (options.move) {
98
+ applyDrag.call(that, options);
99
+ }
100
+ }, 5);
101
+ }, mouseUpAfter);
102
+
103
+ // stop execution as applyDrag has been called again
104
+ return;
105
+ }
106
+
107
+ // Sortable is using a fixed height placeholder meaning items jump up and down as you drag variable height items into fixed height placeholder
108
+ placeHolder = placeHolder && $(this).parent().find(placeHolder);
109
+
110
+ if (!placeHolder && (direction === 'down')) {
111
+ // need to move at least as far as this item and or the last sibling
112
+ if ($(this).outerHeight() > $(sibling).outerHeight()) {
113
+ moveVerticalAmount += $(this).outerHeight() - $(sibling).outerHeight();
114
+ }
115
+ moveVerticalAmount += extraDrag(sibling);
116
+ dragPastBy += extraDrag(sibling);
117
+ } else if (direction === 'up') {
118
+ // move a little extra to ensure item clips into next position
119
+ moveVerticalAmount -= Math.max(extraDrag(this), 5);
120
+ } else if (direction === 'down') {
121
+ // moving down with a place holder
122
+ if (placeHolder.height() < $(this).height()) {
123
+ moveVerticalAmount += Math.max(placeHolder.height(), 5);
124
+ } else {
125
+ moveVerticalAmount += extraDrag(sibling);
126
+ }
127
+ }
128
+
129
+ if (sibling[0] !== $(this)[0]) {
130
+ // step through so that the UI controller can determine when to show the placeHolder
131
+ slideUpTo(x, y, moveVerticalAmount, dragPastBy);
132
+ } else {
133
+ if (window.console) {
134
+ console.log('simulate.drag-sortable.js WARNING: Could not move as at top or bottom already');
135
+ }
136
+ }
137
+
138
+ setTimeout(function() {
139
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + moveVerticalAmount }));
140
+ }, 5);
141
+ setTimeout(function() {
142
+ dispatchEvent(handle, 'mouseup', createEvent('mouseup', handle, { clientX: x, clientY: y + moveVerticalAmount }));
143
+ }, mouseUpAfter);
144
+ };
145
+
146
+ // iterate and move each matched element
147
+ return this.each(applyDrag);
148
+ };
149
+
150
+ // fire mouse events, go half way, then the next half, so small mouse movements near target and big at the start
151
+ function slideUpTo(x, y, targetOffset, goPastBy) {
152
+ var moveBy, offset;
153
+
154
+ if (!goPastBy) { goPastBy = 0; }
155
+ if ((targetOffset < 0) && (goPastBy > 0)) { goPastBy = -goPastBy; } // ensure go past is in the direction as often passed in from object height so always positive
156
+
157
+ // go forwards including goPastBy
158
+ for (offset = 0; Math.abs(offset) + 1 < Math.abs(targetOffset + goPastBy); offset += ((targetOffset + goPastBy - offset)/2) ) {
159
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + Math.ceil(offset) }));
160
+ }
161
+ offset = targetOffset + goPastBy;
162
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + offset }));
163
+
164
+ // now bounce back
165
+ for (; Math.abs(offset) - 1 >= Math.abs(targetOffset); offset += ((targetOffset - offset)/2) ) {
166
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + Math.ceil(offset) }));
167
+ }
168
+ dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + targetOffset }));
169
+ }
170
+
171
+ function createEvent(type, target, options) {
172
+ var evt;
173
+ var e = $.extend({
174
+ target: target,
175
+ preventDefault: function() { },
176
+ stopImmediatePropagation: function() { },
177
+ stopPropagation: function() { },
178
+ isPropagationStopped: function() { return true; },
179
+ isImmediatePropagationStopped: function() { return true; },
180
+ isDefaultPrevented: function() { return true; },
181
+ bubbles: true,
182
+ cancelable: (type != "mousemove"),
183
+ view: window,
184
+ detail: 0,
185
+ screenX: 0,
186
+ screenY: 0,
187
+ clientX: 0,
188
+ clientY: 0,
189
+ ctrlKey: false,
190
+ altKey: false,
191
+ shiftKey: false,
192
+ metaKey: false,
193
+ button: 0,
194
+ relatedTarget: undefined
195
+ }, options || {});
196
+
197
+ if ($.isFunction(document.createEvent)) {
198
+ evt = document.createEvent("MouseEvents");
199
+ evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
200
+ e.screenX, e.screenY, e.clientX, e.clientY,
201
+ e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
202
+ e.button, e.relatedTarget || document.body.parentNode);
203
+ } else if (document.createEventObject) {
204
+ evt = document.createEventObject();
205
+ $.extend(evt, e);
206
+ evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
207
+ }
208
+ return evt;
209
+ }
210
+
211
+ function dispatchEvent(el, type, evt) {
212
+ if (el.dispatchEvent) {
213
+ el.dispatchEvent(evt);
214
+ } else if (el.fireEvent) {
215
+ el.fireEvent('on' + type, evt);
216
+ }
217
+ return evt;
218
+ }
219
+
220
+ function findCenter(el) {
221
+ var elm = $(el),
222
+ o = elm.offset();
223
+ return {
224
+ x: o.left + elm.outerWidth() / 2,
225
+ y: o.top + elm.outerHeight() / 2
226
+ };
227
+ }
228
+
229
+ //
230
+ // plugin defaults
231
+ //
232
+ $.fn.simulateDragSortable.defaults = {
233
+ move: 0
234
+ };
235
+ })(jQuery);