rest-assured 0.1.0

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 (67) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +17 -0
  3. data/LICENSE +22 -0
  4. data/README.markdown +78 -0
  5. data/Rakefile +4 -0
  6. data/bin/console +12 -0
  7. data/bin/rest-assured +28 -0
  8. data/cucumber.yml +3 -0
  9. data/db/migrate/20110620161740_add_fixtures.rb +12 -0
  10. data/db/migrate/20110625155332_add_redirects_table.rb +12 -0
  11. data/db/migrate/20110709150645_add_description_to_fixtures.rb +9 -0
  12. data/db/migrate/20110807222522_add_active_bit_to_fixtures.rb +9 -0
  13. data/db/migrate/20110818155555_add_position_to_redirects.rb +9 -0
  14. data/db/migrate/20110823132023_add_method_to_fixtures.rb +9 -0
  15. data/db/migrate/20110912162948_rename_url_to_fullpath.rb +9 -0
  16. data/db/migrate/20110912163705_rename_fixtures_to_doubles.rb +9 -0
  17. data/features/doubles_via_api.feature +50 -0
  18. data/features/doubles_via_ui.feature +66 -0
  19. data/features/persistence.feature +24 -0
  20. data/features/redirect_rules_via_api.feature +29 -0
  21. data/features/redirect_rules_via_ui.feature +68 -0
  22. data/features/step_definitions/doubles_steps.rb +143 -0
  23. data/features/step_definitions/persistence_steps.rb +13 -0
  24. data/features/step_definitions/redirect_rules_steps.rb +64 -0
  25. data/features/step_definitions/support/numeric_transforms.rb +3 -0
  26. data/features/support/env.rb +71 -0
  27. data/lib/rest-assured.rb +66 -0
  28. data/lib/rest-assured/config.rb +11 -0
  29. data/lib/rest-assured/init.rb +12 -0
  30. data/lib/rest-assured/models/double.rb +30 -0
  31. data/lib/rest-assured/models/redirect.rb +37 -0
  32. data/lib/rest-assured/routes/double.rb +77 -0
  33. data/lib/rest-assured/routes/redirect.rb +71 -0
  34. data/lib/rest-assured/version.rb +3 -0
  35. data/lib/sinatra/partials.rb +18 -0
  36. data/public/css/grid.inuit.css +76 -0
  37. data/public/css/inuit.css +904 -0
  38. data/public/css/jquery.jgrowl.css +132 -0
  39. data/public/css/style.css +88 -0
  40. data/public/img/css/12-grid-720.png +0 -0
  41. data/public/img/css/12-grid.png +0 -0
  42. data/public/img/css/baseline.gif +0 -0
  43. data/public/img/css/grid-720.png +0 -0
  44. data/public/img/css/grid.png +0 -0
  45. data/public/img/css/icons/error.png +0 -0
  46. data/public/img/css/icons/info.png +0 -0
  47. data/public/img/css/icons/success.png +0 -0
  48. data/public/img/css/icons/warning.png +0 -0
  49. data/public/javascript/application.js +12 -0
  50. data/public/javascript/jquery.jgrowl_minimized.js +11 -0
  51. data/rest-assured.gemspec +36 -0
  52. data/spec/functional/double_routes_spec.rb +117 -0
  53. data/spec/functional/redirect_routes_spec.rb +108 -0
  54. data/spec/models/double_spec.rb +73 -0
  55. data/spec/models/redirect_spec.rb +38 -0
  56. data/spec/spec_helper.rb +47 -0
  57. data/views/base.scss +11 -0
  58. data/views/doubles/_form.haml +16 -0
  59. data/views/doubles/edit.haml +4 -0
  60. data/views/doubles/index.haml +41 -0
  61. data/views/doubles/new.haml +3 -0
  62. data/views/layout.haml +25 -0
  63. data/views/redirects/_form.haml +11 -0
  64. data/views/redirects/edit.haml +4 -0
  65. data/views/redirects/index.haml +33 -0
  66. data/views/redirects/new.haml +3 -0
  67. metadata +250 -0
@@ -0,0 +1,132 @@
1
+
2
+ div.jGrowl {
3
+ padding: 10px;
4
+ z-index: 9999;
5
+ color: #fff;
6
+ font-size: 12px;
7
+ }
8
+
9
+ /** Special IE6 Style Positioning **/
10
+ div.ie6 {
11
+ position: absolute;
12
+ }
13
+
14
+ div.ie6.top-right {
15
+ right: auto;
16
+ bottom: auto;
17
+ left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
18
+ top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
19
+ }
20
+
21
+ div.ie6.top-left {
22
+ left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
23
+ top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
24
+ }
25
+
26
+ div.ie6.bottom-right {
27
+ left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
28
+ top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
29
+ }
30
+
31
+ div.ie6.bottom-left {
32
+ left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
33
+ top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
34
+ }
35
+
36
+ div.ie6.center {
37
+ left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
38
+ top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
39
+ width: 100%;
40
+ }
41
+
42
+ /** Normal Style Positions **/
43
+ div.jGrowl {
44
+ position: absolute;
45
+ }
46
+
47
+ body > div.jGrowl {
48
+ position: fixed;
49
+ }
50
+
51
+ div.jGrowl.top-left {
52
+ left: 0px;
53
+ top: 0px;
54
+ }
55
+
56
+ div.jGrowl.top-right {
57
+ right: 0px;
58
+ top: 0px;
59
+ }
60
+
61
+ div.jGrowl.bottom-left {
62
+ left: 0px;
63
+ bottom: 0px;
64
+ }
65
+
66
+ div.jGrowl.bottom-right {
67
+ right: 0px;
68
+ bottom: 0px;
69
+ }
70
+
71
+ div.jGrowl.center {
72
+ top: 0px;
73
+ width: 50%;
74
+ left: 25%;
75
+ }
76
+
77
+ /** Cross Browser Styling **/
78
+ div.center div.jGrowl-notification, div.center div.jGrowl-closer {
79
+ margin-left: auto;
80
+ margin-right: auto;
81
+ }
82
+
83
+ div.jGrowl div.jGrowl-notification, div.jGrowl div.jGrowl-closer {
84
+ background-color: #000;
85
+ opacity: .85;
86
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)";
87
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=85);
88
+ zoom: 1;
89
+ width: 235px;
90
+ padding: 10px;
91
+ margin-top: 5px;
92
+ margin-bottom: 5px;
93
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
94
+ font-size: 1em;
95
+ text-align: left;
96
+ display: none;
97
+ -moz-border-radius: 5px;
98
+ -webkit-border-radius: 5px;
99
+ }
100
+
101
+ div.jGrowl div.jGrowl-notification {
102
+ min-height: 40px;
103
+ }
104
+
105
+ div.jGrowl div.jGrowl-notification div.jGrowl-header {
106
+ font-weight: bold;
107
+ font-size: .85em;
108
+ }
109
+
110
+ div.jGrowl div.jGrowl-notification div.jGrowl-close {
111
+ z-index: 99;
112
+ float: right;
113
+ font-weight: bold;
114
+ font-size: 1em;
115
+ cursor: pointer;
116
+ }
117
+
118
+ div.jGrowl div.jGrowl-closer {
119
+ padding-top: 4px;
120
+ padding-bottom: 4px;
121
+ cursor: pointer;
122
+ font-size: .9em;
123
+ font-weight: bold;
124
+ text-align: center;
125
+ }
126
+
127
+ /** Hide jGrowl when printing **/
128
+ @media print {
129
+ div.jGrowl {
130
+ display: none;
131
+ }
132
+ }
@@ -0,0 +1,88 @@
1
+ /*------------------------------------*\
2
+ MAIN
3
+ \*------------------------------------*/
4
+ html{
5
+ font-family:"Helvetica Neue", Arial, sans-serif;
6
+ color:#e4eef6;
7
+ background:#4a8ec2;
8
+ background:-moz-linear-gradient(-90deg,#5998c7,#4a8ec2) fixed;
9
+ background:-webkit-gradient(linear,left top,left bottom,from(#5998c7),to(#4a8ec2)) fixed;
10
+ }
11
+ body{
12
+ background:none;
13
+ padding-top:50px;
14
+ text-shadow:0 -1px 0 rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.25);
15
+ }
16
+ #page{
17
+ margin:0 auto;
18
+ float:none;
19
+ text-align:center;
20
+ }
21
+
22
+
23
+
24
+
25
+
26
+ /*------------------------------------*\
27
+ TYPE
28
+ \*------------------------------------*/
29
+ h1{
30
+ font-weight:bold;
31
+ font-size:3em;
32
+ line-height:1;
33
+ }
34
+ a{
35
+ color:inherit;
36
+ }
37
+
38
+
39
+
40
+
41
+
42
+ /*------------------------------------*\
43
+ IMAGES
44
+ \*------------------------------------*/
45
+ #logo{
46
+ margin-bottom:1.5em;
47
+ }
48
+
49
+
50
+
51
+
52
+
53
+ /*------------------------------------*\
54
+ NARROW
55
+ \*------------------------------------*/
56
+ /*
57
+ CSS for tablets and narrower devices
58
+ */
59
+
60
+
61
+
62
+
63
+
64
+ @media (min-width: 721px) and (max-width: 960px){}
65
+ /*--- END NARROW ---*/
66
+
67
+
68
+
69
+
70
+
71
+ /*------------------------------------*\
72
+ MOBILE
73
+ \*------------------------------------*/
74
+ /*
75
+ CSS for mobile devices.
76
+ Linearise it!
77
+ */
78
+
79
+
80
+
81
+
82
+
83
+ @media (max-width: 720px){
84
+ body{
85
+ font-size:0.75em;
86
+ }
87
+ }
88
+ /*--- END MOBILE ---*/
Binary file
@@ -0,0 +1,12 @@
1
+ $(function(){
2
+ $('a.delete_link').click(function() {
3
+ if ( confirm('Really?') ) {
4
+ var f = $('<form>', { action: this.href, method: 'post' });
5
+ f.append( $('<input>', { type: 'hidden', name: '_method', value: 'delete' }) );
6
+ f.appendTo("body");
7
+ f.submit();
8
+ }
9
+
10
+ return false;
11
+ });
12
+ });
@@ -0,0 +1,11 @@
1
+
2
+ (function($){$.jGrowl=function(m,o){if($('#jGrowl').size()==0)
3
+ $('<div id="jGrowl"></div>').addClass((o&&o.position)?o.position:$.jGrowl.defaults.position).appendTo('body');$('#jGrowl').jGrowl(m,o);};$.fn.jGrowl=function(m,o){if($.isFunction(this.each)){var args=arguments;return this.each(function(){var self=this;if($(this).data('jGrowl.instance')==undefined){$(this).data('jGrowl.instance',$.extend(new $.fn.jGrowl(),{notifications:[],element:null,interval:null}));$(this).data('jGrowl.instance').startup(this);}
4
+ if($.isFunction($(this).data('jGrowl.instance')[m])){$(this).data('jGrowl.instance')[m].apply($(this).data('jGrowl.instance'),$.makeArray(args).slice(1));}else{$(this).data('jGrowl.instance').create(m,o);}});};};$.extend($.fn.jGrowl.prototype,{defaults:{pool:0,header:'',group:'',sticky:false,position:'top-right',glue:'after',theme:'default',themeState:'highlight',corners:'10px',check:250,life:3000,closeDuration:'normal',openDuration:'normal',easing:'swing',closer:true,closeTemplate:'&times;',closerTemplate:'<div>[ close all ]</div>',log:function(e,m,o){},beforeOpen:function(e,m,o){},afterOpen:function(e,m,o){},open:function(e,m,o){},beforeClose:function(e,m,o){},close:function(e,m,o){},animateOpen:{opacity:'show'},animateClose:{opacity:'hide'}},notifications:[],element:null,interval:null,create:function(message,o){var o=$.extend({},this.defaults,o);if(typeof o.speed!=='undefined'){o.openDuration=o.speed;o.closeDuration=o.speed;}
5
+ this.notifications.push({message:message,options:o});o.log.apply(this.element,[this.element,message,o]);},render:function(notification){var self=this;var message=notification.message;var o=notification.options;var notification=$('<div class="jGrowl-notification '+o.themeState+' ui-corner-all'+
6
+ ((o.group!=undefined&&o.group!='')?' '+o.group:'')+'">'+'<div class="jGrowl-close">'+o.closeTemplate+'</div>'+'<div class="jGrowl-header">'+o.header+'</div>'+'<div class="jGrowl-message">'+message+'</div></div>').data("jGrowl",o).addClass(o.theme).children('div.jGrowl-close').bind("click.jGrowl",function(){$(this).parent().trigger('jGrowl.close');}).parent();$(notification).bind("mouseover.jGrowl",function(){$('div.jGrowl-notification',self.element).data("jGrowl.pause",true);}).bind("mouseout.jGrowl",function(){$('div.jGrowl-notification',self.element).data("jGrowl.pause",false);}).bind('jGrowl.beforeOpen',function(){if(o.beforeOpen.apply(notification,[notification,message,o,self.element])!=false){$(this).trigger('jGrowl.open');}}).bind('jGrowl.open',function(){if(o.open.apply(notification,[notification,message,o,self.element])!=false){if(o.glue=='after'){$('div.jGrowl-notification:last',self.element).after(notification);}else{$('div.jGrowl-notification:first',self.element).before(notification);}
7
+ $(this).animate(o.animateOpen,o.openDuration,o.easing,function(){if($.browser.msie&&(parseInt($(this).css('opacity'),10)===1||parseInt($(this).css('opacity'),10)===0))
8
+ this.style.removeAttribute('filter');$(this).data("jGrowl").created=new Date();$(this).trigger('jGrowl.afterOpen');});}}).bind('jGrowl.afterOpen',function(){o.afterOpen.apply(notification,[notification,message,o,self.element]);}).bind('jGrowl.beforeClose',function(){if(o.beforeClose.apply(notification,[notification,message,o,self.element])!=false)
9
+ $(this).trigger('jGrowl.close');}).bind('jGrowl.close',function(){$(this).data('jGrowl.pause',true);$(this).animate(o.animateClose,o.closeDuration,o.easing,function(){$(this).remove();var close=o.close.apply(notification,[notification,message,o,self.element]);if($.isFunction(close))
10
+ close.apply(notification,[notification,message,o,self.element]);});}).trigger('jGrowl.beforeOpen');if(o.corners!=''&&$.fn.corner!=undefined)$(notification).corner(o.corners);if($('div.jGrowl-notification:parent',self.element).size()>1&&$('div.jGrowl-closer',self.element).size()==0&&this.defaults.closer!=false){$(this.defaults.closerTemplate).addClass('jGrowl-closer ui-state-highlight ui-corner-all').addClass(this.defaults.theme).appendTo(self.element).animate(this.defaults.animateOpen,this.defaults.speed,this.defaults.easing).bind("click.jGrowl",function(){$(this).siblings().trigger("jGrowl.beforeClose");if($.isFunction(self.defaults.closer)){self.defaults.closer.apply($(this).parent()[0],[$(this).parent()[0]]);}});};},update:function(){$(this.element).find('div.jGrowl-notification:parent').each(function(){if($(this).data("jGrowl")!=undefined&&$(this).data("jGrowl").created!=undefined&&($(this).data("jGrowl").created.getTime()+parseInt($(this).data("jGrowl").life))<(new Date()).getTime()&&$(this).data("jGrowl").sticky!=true&&($(this).data("jGrowl.pause")==undefined||$(this).data("jGrowl.pause")!=true)){$(this).trigger('jGrowl.beforeClose');}});if(this.notifications.length>0&&(this.defaults.pool==0||$(this.element).find('div.jGrowl-notification:parent').size()<this.defaults.pool))
11
+ this.render(this.notifications.shift());if($(this.element).find('div.jGrowl-notification:parent').size()<2){$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose,this.defaults.speed,this.defaults.easing,function(){$(this).remove();});}},startup:function(e){this.element=$(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');this.interval=setInterval(function(){$(e).data('jGrowl.instance').update();},parseInt(this.defaults.check));if($.browser.msie&&parseInt($.browser.version)<7&&!window["XMLHttpRequest"]){$(this.element).addClass('ie6');}},shutdown:function(){$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();clearInterval(this.interval);},close:function(){$(this.element).find('div.jGrowl-notification').each(function(){$(this).trigger('jGrowl.beforeClose');});}});$.jGrowl.defaults=$.fn.jGrowl.prototype.defaults;})(jQuery);
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'rest-assured/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rest-assured"
7
+ s.version = RestAssured::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Artem Avetisyan']
10
+ s.email = ['artem.avetisyan@bbc.co.uk']
11
+ s.homepage = "https://github.com/BBC/rest-assured"
12
+ s.summary = %q{A tool for high level mocking/stubbing HTTP based REST services}
13
+ #s.description = %q{TODO: Write a gem description}
14
+
15
+ s.rubyforge_project = "rest-assured"
16
+ s.required_ruby_version = '>= 1.8.7'
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = ['rest-assured']
21
+ s.require_paths = ['lib']
22
+
23
+ s.add_dependency 'sinatra'
24
+ s.add_dependency 'rack-flash'
25
+ #s.add_dependency 'sinatra-reloader'
26
+ s.add_dependency 'haml'
27
+ s.add_dependency 'sass'
28
+ s.add_dependency 'sinatra-static-assets'
29
+ s.add_dependency 'thin'
30
+ s.add_dependency 'activerecord', '~> 3.0.0'
31
+ s.add_dependency 'sinatra-activerecord'
32
+ s.add_dependency 'sqlite3'
33
+ s.add_dependency 'rake'
34
+ s.add_dependency 'meta_where'
35
+ end
36
+
@@ -0,0 +1,117 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe 'Double routes' do
4
+ let :test_double do
5
+ { :fullpath => '/api/google?a=5', :content => 'some awesome content', :method => 'POST' }
6
+ end
7
+ let :valid_params do
8
+ { 'double[fullpath]' => test_double[:fullpath], 'double[content]' => test_double[:content], 'double[method]' => test_double[:method] }
9
+ end
10
+ let :invalid_params do
11
+ { 'double[fullpath]' => test_double[:fullpath] }
12
+ end
13
+
14
+ describe "through ui", :ui => true do
15
+ it "shows doubles page by default" do
16
+ visit '/'
17
+ current_path.should == '/doubles'
18
+ end
19
+
20
+ it "shows list of doubles" do
21
+ f = Double.create test_double
22
+
23
+ visit '/doubles'
24
+
25
+ page.should have_content(f.fullpath)
26
+ end
27
+
28
+ it "shows form for creating new double" do
29
+ visit '/doubles/new'
30
+
31
+ page.should have_css('#double_fullpath')
32
+ page.should have_css('#double_content')
33
+ page.should have_css('#double_description')
34
+ end
35
+
36
+ it "creates double" do
37
+ post '/doubles', valid_params
38
+ follow_redirect!
39
+
40
+ last_request.fullpath.should == '/doubles'
41
+ last_response.body.should =~ /Double created/
42
+ Double.exists?(test_double).should be true
43
+ end
44
+
45
+ it "reports failure when creating with invalid parameters" do
46
+ post '/doubles', invalid_params
47
+
48
+ last_response.should be_ok
49
+ last_response.body.should =~ /Crumps!.*Content can't be blank/
50
+ end
51
+
52
+ it "brings up double edit form" do
53
+ f = Double.create test_double
54
+ visit "/doubles/#{f.id}/edit"
55
+
56
+ find('#double_fullpath').value.should == f.fullpath
57
+ find('#double_content').value.should == f.content
58
+ end
59
+
60
+ it "updates double" do
61
+ f = Double.create test_double
62
+
63
+ put "/doubles/#{f.id}", 'double[fullpath]' => '/some/other/api'
64
+ follow_redirect!
65
+
66
+ last_request.fullpath.should == '/doubles'
67
+ last_response.body.should =~ /Double updated/
68
+ f.reload.fullpath.should == '/some/other/api'
69
+ end
70
+
71
+ it "chooses active double" do
72
+ f = Double.create test_double.merge!(:active => false)
73
+
74
+ ajax "/doubles/#{f.id}", :as => :put, :active => true
75
+
76
+ last_response.should be_ok
77
+ last_response.body.should == 'Changed'
78
+ end
79
+
80
+ it "deletes double" do
81
+ f = Double.create test_double
82
+
83
+ delete "/doubles/#{f.id}"
84
+ follow_redirect!
85
+
86
+ last_response.should be_ok
87
+ last_response.body.should =~ /Double deleted/
88
+
89
+ Double.exists?(test_double).should be_false
90
+ end
91
+ end
92
+
93
+ describe "through REST api", :ui => false do
94
+ it "creates double" do
95
+ post '/doubles', test_double
96
+
97
+ last_response.should be_ok
98
+ Double.exists?(test_double).should be_true
99
+ end
100
+
101
+ it "reports failure when creating with invalid parameters" do
102
+ post '/doubles', test_double.except(:content)
103
+
104
+ last_response.should_not be_ok
105
+ last_response.body.should =~ /Content can't be blank/
106
+ end
107
+
108
+ it "deletes all doubles" do
109
+ Double.create test_double
110
+
111
+ delete '/doubles/all'
112
+
113
+ last_response.should be_ok
114
+ Double.count.should == 0
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,108 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe 'Redirects routes' do
4
+ let :redirect do
5
+ { :pattern => '/sdf.*', :to => 'http://google.com/api' }
6
+ end
7
+
8
+ let :valid_params do
9
+ { 'redirect[pattern]' => redirect[:pattern], 'redirect[to]' => redirect[:to] }
10
+ end
11
+
12
+ let :invalid_params do
13
+ { 'redirect[to]' => redirect[:to] }
14
+ end
15
+
16
+ context 'via ui', :ui => true do
17
+ it 'shows list of redirects' do
18
+ r = Redirect.create redirect
19
+
20
+ visit '/redirects'
21
+
22
+ page.should have_content(r.pattern)
23
+ page.should have_content(r.to)
24
+ end
25
+
26
+ it "shows form for creating new redirect" do
27
+ visit '/redirects/new'
28
+
29
+ page.should have_css('#redirect_pattern')
30
+ page.should have_css('#redirect_to')
31
+ end
32
+
33
+ it "creates redirect" do
34
+ post '/redirects', valid_params
35
+ follow_redirect!
36
+
37
+ last_request.fullpath.should == '/redirects'
38
+ last_response.body.should =~ /Redirect created/
39
+ Redirect.exists?(redirect).should be true
40
+ end
41
+
42
+ it "reports failure when creating with invalid parameters" do
43
+ post '/redirects', invalid_params
44
+
45
+ last_response.should be_ok
46
+ last_response.body.should =~ /Crumps!.*Pattern can't be blank/
47
+ end
48
+
49
+ it "brings up redirect edit form" do
50
+ r = Redirect.create redirect
51
+ visit "/redirects/#{r.id}/edit"
52
+
53
+ find('#redirect_pattern').value.should == r.pattern
54
+ find('#redirect_to').value.should == r.to
55
+ end
56
+
57
+ it "updates redirect" do
58
+ r = Redirect.create redirect
59
+
60
+ put "/redirects/#{r.id}", 'redirect[to]' => '/some/other/api'
61
+ follow_redirect!
62
+
63
+ last_request.fullpath.should == '/redirects'
64
+ last_response.body.should =~ /Redirect updated/
65
+ r.reload.to.should == '/some/other/api'
66
+ end
67
+
68
+ it "reorders redirects" do
69
+ r1 = Redirect.create! redirect
70
+ r2 = Redirect.create! redirect
71
+
72
+ put "/redirects/reorder", :redirect => [r2.id, r1.id]
73
+
74
+ last_response.should be_ok
75
+ last_response.body.should == 'Changed'
76
+ r1.reload.position.should == 1
77
+ r2.reload.position.should == 0
78
+ end
79
+
80
+ it "deletes redirect" do
81
+ f = Redirect.create redirect
82
+
83
+ delete "/redirects/#{f.id}"
84
+ follow_redirect!
85
+
86
+ last_response.should be_ok
87
+ last_response.body.should =~ /Redirect deleted/
88
+
89
+ Redirect.exists?(redirect).should be_false
90
+ end
91
+ end
92
+
93
+ context 'via api', :ui => false do
94
+ it "creates redirect" do
95
+ post '/redirects', redirect
96
+
97
+ last_response.should be_ok
98
+ Redirect.count.should == 1
99
+ end
100
+
101
+ it "reports failure when creating with invalid parameters" do
102
+ post '/redirects', redirect.except(:pattern)
103
+
104
+ last_response.should_not be_ok
105
+ last_response.body.should =~ /Pattern can't be blank/
106
+ end
107
+ end
108
+ end