ember_cli_deploy_redis 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +2 -0
  3. data/.jrubyrc +1 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +5 -0
  6. data/README.md +69 -15
  7. data/ember_cli_deploy_redis.gemspec +28 -25
  8. data/lib/ember_cli_deploy_redis.rb +8 -2
  9. data/lib/ember_cli_deploy_redis/application.rb +12 -1
  10. data/lib/ember_cli_deploy_redis/configuration.rb +31 -3
  11. data/lib/ember_cli_deploy_redis/errors.rb +1 -1
  12. data/lib/ember_cli_deploy_redis/revision.rb +17 -9
  13. data/lib/ember_cli_deploy_redis/revision_list.rb +12 -6
  14. data/lib/ember_cli_deploy_redis/version.rb +1 -1
  15. data/lib/ember_cli_deploy_redis/web.rb +59 -0
  16. data/lib/ember_cli_deploy_redis/web_helpers.rb +162 -0
  17. data/spec/lib/ember_cli_deploy_redis/application_spec.rb +12 -2
  18. data/spec/lib/ember_cli_deploy_redis/revision_list_spec.rb +34 -3
  19. data/spec/lib/ember_cli_deploy_redis/revision_spec.rb +29 -12
  20. data/spec/lib/ember_cli_deploy_redis/web_helpers_spec.rb +69 -0
  21. data/spec/lib/ember_cli_deploy_redis/web_spec.rb +164 -0
  22. data/spec/lib/ember_cli_deploy_redis_spec.rb +21 -8
  23. data/spec/spec_helper.rb +15 -5
  24. data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  25. data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  26. data/web/assets/javascripts/application.js +67 -0
  27. data/web/assets/javascripts/locales/README.md +27 -0
  28. data/web/assets/javascripts/locales/jquery.timeago.ar.js +96 -0
  29. data/web/assets/javascripts/locales/jquery.timeago.bg.js +18 -0
  30. data/web/assets/javascripts/locales/jquery.timeago.bs.js +49 -0
  31. data/web/assets/javascripts/locales/jquery.timeago.ca.js +18 -0
  32. data/web/assets/javascripts/locales/jquery.timeago.cs.js +18 -0
  33. data/web/assets/javascripts/locales/jquery.timeago.cy.js +20 -0
  34. data/web/assets/javascripts/locales/jquery.timeago.da.js +18 -0
  35. data/web/assets/javascripts/locales/jquery.timeago.de.js +18 -0
  36. data/web/assets/javascripts/locales/jquery.timeago.el.js +18 -0
  37. data/web/assets/javascripts/locales/jquery.timeago.en-short.js +20 -0
  38. data/web/assets/javascripts/locales/jquery.timeago.en.js +20 -0
  39. data/web/assets/javascripts/locales/jquery.timeago.es.js +18 -0
  40. data/web/assets/javascripts/locales/jquery.timeago.et.js +18 -0
  41. data/web/assets/javascripts/locales/jquery.timeago.fa.js +22 -0
  42. data/web/assets/javascripts/locales/jquery.timeago.fi.js +28 -0
  43. data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +16 -0
  44. data/web/assets/javascripts/locales/jquery.timeago.fr.js +17 -0
  45. data/web/assets/javascripts/locales/jquery.timeago.he.js +18 -0
  46. data/web/assets/javascripts/locales/jquery.timeago.hr.js +49 -0
  47. data/web/assets/javascripts/locales/jquery.timeago.hu.js +18 -0
  48. data/web/assets/javascripts/locales/jquery.timeago.hy.js +18 -0
  49. data/web/assets/javascripts/locales/jquery.timeago.id.js +18 -0
  50. data/web/assets/javascripts/locales/jquery.timeago.it.js +16 -0
  51. data/web/assets/javascripts/locales/jquery.timeago.ja.js +19 -0
  52. data/web/assets/javascripts/locales/jquery.timeago.ko.js +17 -0
  53. data/web/assets/javascripts/locales/jquery.timeago.lt.js +20 -0
  54. data/web/assets/javascripts/locales/jquery.timeago.mk.js +20 -0
  55. data/web/assets/javascripts/locales/jquery.timeago.nl.js +20 -0
  56. data/web/assets/javascripts/locales/jquery.timeago.no.js +18 -0
  57. data/web/assets/javascripts/locales/jquery.timeago.pl.js +31 -0
  58. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +16 -0
  59. data/web/assets/javascripts/locales/jquery.timeago.pt.js +16 -0
  60. data/web/assets/javascripts/locales/jquery.timeago.ro.js +18 -0
  61. data/web/assets/javascripts/locales/jquery.timeago.rs.js +49 -0
  62. data/web/assets/javascripts/locales/jquery.timeago.ru.js +34 -0
  63. data/web/assets/javascripts/locales/jquery.timeago.sk.js +18 -0
  64. data/web/assets/javascripts/locales/jquery.timeago.sl.js +44 -0
  65. data/web/assets/javascripts/locales/jquery.timeago.sv.js +18 -0
  66. data/web/assets/javascripts/locales/jquery.timeago.th.js +20 -0
  67. data/web/assets/javascripts/locales/jquery.timeago.tr.js +16 -0
  68. data/web/assets/javascripts/locales/jquery.timeago.uk.js +34 -0
  69. data/web/assets/javascripts/locales/jquery.timeago.uz.js +19 -0
  70. data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +20 -0
  71. data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +20 -0
  72. data/web/assets/stylesheets/application.css +580 -0
  73. data/web/assets/stylesheets/bootstrap.css +9 -0
  74. data/web/locales/en.yml +13 -0
  75. data/web/views/_footer.erb +14 -0
  76. data/web/views/application.erb +38 -0
  77. data/web/views/dashboard.erb +26 -0
  78. data/web/views/layout.erb +26 -0
  79. metadata +89 -42
  80. data/Gemfile.lock +0 -121
@@ -0,0 +1,162 @@
1
+ require 'uri'
2
+
3
+ module EmberCliDeployRedis
4
+ # This is not a public API
5
+ module WebHelpers
6
+ def strings(lang)
7
+ @@strings ||= {}
8
+ @@strings[lang] ||= begin
9
+ # Allow sidekiq-web extensions to add locale paths
10
+ # so extensions can be localized
11
+ settings.locales.each_with_object({}) do |path, global|
12
+ find_locale_files(lang).each do |file|
13
+ strs = YAML.load(File.open(file))
14
+ global.merge!(strs[lang])
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def locale_files
21
+ @@locale_files = settings.locales.flat_map do |path|
22
+ Dir["#{path}/*.yml"]
23
+ end
24
+ end
25
+
26
+ def find_locale_files(lang)
27
+ locale_files.select { |file| file =~ /\/#{lang}\.yml$/ }
28
+ end
29
+
30
+ # This view helper provide ability display you html code in
31
+ # to head of page. Example:
32
+ #
33
+ # <% add_to_head do %>
34
+ # <link rel="stylesheet" .../>
35
+ # <meta .../>
36
+ # <% end %>
37
+ #
38
+ def add_to_head(&block)
39
+ @head_html ||= []
40
+ @head_html << block if block_given?
41
+ end
42
+
43
+ def display_custom_head
44
+ return unless defined?(@head_html)
45
+ @head_html.map { |block| capture(&block) }.join
46
+ end
47
+
48
+ # Simple capture method for erb templates. The origin was
49
+ # capture method from sinatra-contrib library.
50
+ def capture(&block)
51
+ block.call
52
+ eval('', block.binding)
53
+ end
54
+
55
+ # Given a browser request Accept-Language header like
56
+ # "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2", this function
57
+ # will return "fr" since that's the first code with a matching
58
+ # locale in web/locales
59
+ def locale
60
+ @locale ||= begin
61
+ locale = 'en'.freeze
62
+ languages = request.env['HTTP_ACCEPT_LANGUAGE'.freeze] || 'en'.freeze
63
+ languages.downcase.split(','.freeze).each do |lang|
64
+ next if lang == '*'.freeze
65
+ lang = lang.split(';'.freeze)[0]
66
+ break locale = lang if find_locale_files(lang).any?
67
+ end
68
+ locale
69
+ end
70
+ end
71
+
72
+ def get_locale
73
+ strings(locale)
74
+ end
75
+
76
+ def t(msg, options={})
77
+ string = get_locale[msg] || msg
78
+ if options.empty?
79
+ string
80
+ else
81
+ string % options
82
+ end
83
+ end
84
+
85
+ def location
86
+ EmberCliDeployRedis.configuration.redis do |conn| conn.client.location end
87
+ end
88
+
89
+ def redis_connection
90
+ EmberCliDeployRedis.configuration.redis do |conn| conn.client.id end
91
+ end
92
+
93
+ def namespace
94
+ @@ns ||= EmberCliDeployRedis.configuration.redis do |conn|
95
+ conn.respond_to?(:namespace) ? conn.namespace : nil
96
+ end
97
+ end
98
+
99
+ def redis_info
100
+ EmberCliDeployRedis.configuration.redis do |conn|
101
+ # admin commands can't go through redis-namespace starting
102
+ # in redis-namespace 2.0
103
+ if conn.respond_to?(:namespace)
104
+ conn.redis.info
105
+ else
106
+ conn.info
107
+ end
108
+ end
109
+ end
110
+
111
+ def root_path
112
+ "#{env['SCRIPT_NAME']}/"
113
+ end
114
+
115
+ def relative_time(time)
116
+ %{<time datetime="#{time.getutc.iso8601}">#{time}</time>}
117
+ end
118
+
119
+ def csrf_tag
120
+ "<input type='hidden' name='authenticity_token' value='#{session[:csrf]}'/>"
121
+ end
122
+
123
+ def h(text)
124
+ ::Rack::Utils.escape_html(text)
125
+ rescue ArgumentError => e
126
+ raise unless e.message.eql?('invalid byte sequence in UTF-8')
127
+ text.encode!('UTF-16', 'UTF-8', invalid: :replace, replace: '').encode!('UTF-8', 'UTF-16')
128
+ retry
129
+ end
130
+
131
+ # Any paginated list that performs an action needs to redirect
132
+ # back to the proper page after performing that action.
133
+ def redirect_with_query(url)
134
+ r = request.referer
135
+ if r && r =~ /\?/
136
+ ref = URI(r)
137
+ redirect("#{url}?#{ref.query}")
138
+ else
139
+ redirect url
140
+ end
141
+ end
142
+
143
+ def product_version
144
+ "ember_cli_deploy_redis-ruby v#{EmberCliDeployRedis::VERSION}"
145
+ end
146
+
147
+ def redis_connection_and_namespace
148
+ @redis_connection_and_namespace ||= begin
149
+ namespace_suffix = namespace == nil ? '' : "##{namespace}"
150
+ "#{redis_connection}#{namespace_suffix}"
151
+ end
152
+ end
153
+
154
+ def revision_specifier_query_param
155
+ EmberCliDeployRedis.configuration.revision_specifier_query_param
156
+ end
157
+
158
+ def revision_test_url(revision)
159
+ "/?#{revision_specifier_query_param}[#{revision.application.name}]=#{revision.name}"
160
+ end
161
+ end
162
+ end
@@ -16,8 +16,18 @@ describe EmberCliDeployRedis::Application do
16
16
 
17
17
  describe '.latest_revision' do
18
18
  subject { application.latest_revision }
19
- it 'returns Revision.latest_from_redis' do
20
- expect(EmberCliDeployRedis::Revision).to receive(:latest_from_redis)
19
+ it 'returns Revision.active_from_redis' do
20
+ expect(EmberCliDeployRedis::Revision).to receive(:active_from_redis)
21
+ .with(application)
22
+ .and_return(:whatever)
23
+ expect(subject).to eq(:whatever)
24
+ end
25
+ end
26
+
27
+ describe '.active_revision' do
28
+ subject { application.active_revision }
29
+ it 'returns Revision.active_from_redis' do
30
+ expect(EmberCliDeployRedis::Revision).to receive(:active_from_redis)
21
31
  .with(application)
22
32
  .and_return(:whatever)
23
33
  expect(subject).to eq(:whatever)
@@ -5,9 +5,40 @@ describe EmberCliDeployRedis::RevisionList do
5
5
  let(:application) { double('application', name: 'app_name') }
6
6
  let(:revisions) { %w(one two three) }
7
7
 
8
- it { is_expected.to delegate_method(:[]).to(:revisions) }
9
- it { is_expected.to delegate_method(:first).to(:revisions) }
10
- it { is_expected.to delegate_method(:last).to(:revisions) }
8
+ describe '#[]' do
9
+ it 'delegates to the revisions array' do
10
+ expect(revisions).to receive(:[]).and_call_original
11
+ expect(subject[0]).to eq('one')
12
+ end
13
+ end
14
+
15
+ describe '#first' do
16
+ it 'delegates to the revisions array' do
17
+ expect(revisions).to receive(:first).and_call_original
18
+ expect(subject.first).to eq('one')
19
+ end
20
+ end
21
+
22
+ describe '#last' do
23
+ it 'delegates to the revisions array' do
24
+ expect(revisions).to receive(:last).and_call_original
25
+ expect(subject.last).to eq('three')
26
+ end
27
+ end
28
+
29
+ describe '#each' do
30
+ it 'delegates to the revisions array' do
31
+ expect(revisions).to receive(:each).and_call_original
32
+ expect(subject.each(&:to_s)).to eq(revisions)
33
+ end
34
+ end
35
+
36
+ describe '#map' do
37
+ it 'delegates to the revisions array' do
38
+ expect(revisions).to receive(:map).and_call_original
39
+ expect(subject.map(&:to_s)).to eq(revisions)
40
+ end
41
+ end
11
42
 
12
43
  describe '#initialize' do
13
44
  it 'stores the application' do
@@ -3,22 +3,39 @@ require 'spec_helper'
3
3
  describe EmberCliDeployRedis::Revision do
4
4
  let(:application) { double('application', name: 'app_name') }
5
5
 
6
- describe '.latest_from_redis' do
7
- let(:latest_revision_name) { 'latest_revision' }
8
- let(:do_the_thing) { described_class.latest_from_redis(application) }
6
+ describe '.active_from_redis' do
7
+ let(:active_revision_name) { 'active_revision' }
8
+ let(:do_the_thing) { described_class.active_from_redis(application) }
9
9
  before do
10
- allow(described_class).to receive(:latest_revision_from_redis)
11
- .and_return(latest_revision_name)
10
+ allow(described_class).to receive(:active_revision_from_redis)
11
+ .and_return(active_revision_name)
12
12
  end
13
- it 'gets the latest_revision_from_redis and calls Revision.new with it' do
14
- expect(described_class).to receive(:new).with(application, latest_revision_name)
15
- expect(described_class).to receive(:latest_revision_from_redis).with(application)
13
+ it 'gets the active_revision_from_redis and calls Revision.new with it' do
14
+ expect(described_class).to receive(:new).with(application, active_revision_name)
15
+ expect(described_class).to receive(:active_revision_from_redis).with(application)
16
16
  do_the_thing
17
17
  end
18
18
  end
19
19
 
20
- describe '.latest_revision_from_redis' do
21
- subject { described_class.latest_revision_from_redis(application) }
20
+ describe '#activate!' do
21
+ subject { described_class.new(application, 'new_revision') }
22
+ let(:do_the_thing) { subject.activate! }
23
+ let(:application) { EmberCliDeployRedis::Application.new('application_name') }
24
+ it 'makes the revision active' do
25
+ do_the_thing
26
+ expect(application.active_revision).to eq(subject)
27
+ end
28
+ it 'leaves the other revision in existence' do
29
+ described_class.new(application, 'old_revision').activate!
30
+ do_the_thing
31
+ old_revision = application.revision_by_name('old_revision')
32
+ expect(old_revision).to be_kind_of(EmberCliDeployRedis::Revision)
33
+ expect(old_revision).to_not be_active
34
+ end
35
+ end
36
+
37
+ describe '.active_revision_from_redis' do
38
+ subject { described_class.active_revision_from_redis(application) }
22
39
  let(:redis_key) { 'revision_list' }
23
40
  let(:most_recent_revision) { 'recent' }
24
41
  let(:oldest_revision) { 'oldest' }
@@ -41,8 +58,8 @@ describe EmberCliDeployRedis::Revision do
41
58
  end
42
59
  end
43
60
  context 'with no deployed revisions' do
44
- it 'raises an error' do
45
- expect { subject }.to raise_error
61
+ it 'returns nil' do
62
+ expect(subject).to be_nil
46
63
  end
47
64
  end
48
65
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+ require 'ember_cli_deploy_redis/web_helpers'
3
+
4
+ describe EmberCliDeployRedis::WebHelpers do
5
+ let(:described_class) {
6
+ Class.new do
7
+ include EmberCliDeployRedis::WebHelpers
8
+ end
9
+ }
10
+ before do
11
+ allow(subject).to receive(:request).and_return(request)
12
+ allow(subject).to receive(:settings).and_return(settings)
13
+ end
14
+ let(:request) { double('request', env: request_env) }
15
+ let(:request_env) { {} }
16
+ let(:settings) { double('request', locales: settings_locales) }
17
+ let(:settings_locales) { ['web/locales'] }
18
+
19
+ describe '#locale' do
20
+ context 'without an Accept-Language header' do
21
+ it 'uses the default locale' do
22
+ expect(subject.locale).to eq('en')
23
+ end
24
+ end
25
+ context 'with an Accept-Language header' do
26
+ let(:request_env) { { 'HTTP_ACCEPT_LANGUAGE' => accept_language } }
27
+
28
+ context 'starting with fr' do
29
+ let(:accept_language) { 'fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2' }
30
+ it 'returns the correct locale' do
31
+ pending "We have not localized for French."
32
+ expect(subject.locale).to eq('fr')
33
+ end
34
+ end
35
+ context 'starting with zh-cn' do
36
+ let(:accept_language) { 'zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2' }
37
+ it 'returns the correct locale' do
38
+ pending "We have not localized for Chinese."
39
+ expect(subject.locale).to eq('zh-cn')
40
+ end
41
+ end
42
+ context 'starting with nb' do
43
+ let(:accept_language) { 'nb-NO,nb;q=0.2' }
44
+ it 'returns the correct locale' do
45
+ pending "We have not localized for Norwegian."
46
+ expect(subject.locale).to eq('nb')
47
+ end
48
+ end
49
+ context "for a language we don't have (cause it doesn't exist)" do
50
+ let(:accept_language) { 'zz,zz;q=0.2' }
51
+ it 'defaults to en' do
52
+ expect(subject.locale).to eq('en')
53
+ end
54
+ end
55
+ context 'starting with en' do
56
+ let(:accept_language) { 'en-us; *' }
57
+ it 'returns the correct locale' do
58
+ expect(subject.locale).to eq('en')
59
+ end
60
+ end
61
+ context 'containing no guidance' do
62
+ let(:accept_language) { '*' }
63
+ it 'defaults to en' do
64
+ expect(subject.locale).to eq('en')
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'ember_cli_deploy_redis/web'
3
+ require 'rack/test'
4
+ require 'rspec-html-matchers'
5
+ # require 'tilt/erubis'
6
+
7
+ describe EmberCliDeployRedis::Web do
8
+ include Rack::Test::Methods
9
+ include RSpecHtmlMatchers
10
+
11
+ def app
12
+ described_class
13
+ end
14
+
15
+ let(:application1) { EmberCliDeployRedis::Application.new('application1') }
16
+ let(:app1_revision_a) { EmberCliDeployRedis::Revision.new(application1, 'app1_revision_a') }
17
+ let(:app1_revision_b) { EmberCliDeployRedis::Revision.new(application1, 'app1_revision_b') }
18
+ let(:application2) { EmberCliDeployRedis::Application.new('application2') }
19
+ let(:app2_revision_a) { EmberCliDeployRedis::Revision.new(application2, 'app2_revision_a') }
20
+ let(:app2_revision_b) { EmberCliDeployRedis::Revision.new(application2, 'app2_revision_b') }
21
+
22
+ describe 'GET /' do
23
+ let(:the_request) { get '/' }
24
+ before do
25
+ EmberCliDeployRedis.configure do |config|
26
+ config.web_application_names = %w(application1 application2)
27
+ end
28
+ app1_revision_b.activate!
29
+ app1_revision_a.activate!
30
+ app2_revision_b.activate!
31
+ app2_revision_a.activate!
32
+ app2_revision_b.activate!
33
+ end
34
+
35
+ it 'responds with Success' do
36
+ the_request
37
+ expect(last_response).to be_ok
38
+ end
39
+ it 'includes a row for each application' do
40
+ the_request
41
+ expect(last_response.body).to have_tag('tr') do
42
+ with_tag 'td.col-application a', href: '/applications/application1', text: 'application1'
43
+ with_tag 'td.col-current-revision', text: /app1_revision_a/
44
+ end
45
+ expect(last_response.body).to have_tag('tr') do
46
+ with_tag 'td.col-application a', href: '/applications/application2', text: 'application2'
47
+ with_tag 'td.col-current-revision', text: /app2_revision_b/
48
+ end
49
+ end
50
+ end
51
+
52
+ describe 'GET /applications/:app_name' do
53
+ let(:the_request) { get "/applications/application1" }
54
+
55
+ before do
56
+ app1_revision_b.activate!
57
+ app1_revision_a.activate!
58
+ app1_revision_b.activate!
59
+ end
60
+
61
+ it 'responds with Success' do
62
+ the_request
63
+ expect(last_response).to be_ok
64
+ end
65
+ it 'includes a row for each revision' do
66
+ the_request
67
+ expect(last_response.body).to have_tag('tr') do
68
+ with_tag 'td.col-revision', text: /app1_revision_b/
69
+ end
70
+ expect(last_response.body).to have_tag('tr') do
71
+ with_tag 'td.col-revision', text: /app1_revision_a/
72
+ end
73
+ expect(last_response.body).to have_tag('tr') do
74
+ with_tag 'td.col-revision', text: /app1_revision_b/
75
+ end
76
+ end
77
+ it 'shows the correct revisions as Active' do
78
+ the_request
79
+ expect(last_response.body).to have_tag('tr.revision-app1_revision_b') do
80
+ with_tag 'td.col-status', text: /\A\s*Active\s*\z/
81
+ end
82
+ end
83
+ it 'does not show the inactive revisions as Active' do
84
+ the_request
85
+ expect(last_response.body).to have_tag('tr.revision-app1_revision_a') do
86
+ without_tag 'td.col-status', text: /\A\s*Active\s*\z/
87
+ end
88
+ end
89
+ it 'has a Make Active button on non-active revisions' do
90
+ the_request
91
+ expect(last_response.body).to have_tag(
92
+ 'tr.revision-app1_revision_a td.col-status form',
93
+ method: 'post',
94
+ action: '/applications/application1/activate/app1_revision_a',
95
+ ) do
96
+ with_tag 'input', value: /Make Active/i
97
+ end
98
+ end
99
+ it 'does not have a Make Active button on active revisions' do
100
+ the_request
101
+ expect(last_response.body).to have_tag('tr.revision-app1_revision_b') do
102
+ without_tag 'td.col-status form'
103
+ end
104
+ end
105
+ context 'without a configured revision_specifier_query_param' do
106
+ it 'does not have a Test link for any revision' do
107
+ the_request
108
+ expect(last_response.body).to_not have_tag('td.col-status a', text: /test this revision/i)
109
+ end
110
+ end
111
+ context 'with a configured revision_specifier_query_param' do
112
+ before do
113
+ EmberCliDeployRedis.configure do |config|
114
+ config.revision_specifier_query_param = '_specified_revision'
115
+ end
116
+ end
117
+ it 'has a Test link for each non-active revision' do
118
+ the_request
119
+ expect(last_response.body).to have_tag(
120
+ 'tr.revision-app1_revision_a td.col-revision a',
121
+ text: /test this revision/i,
122
+ href: '/?_specified_revision[application1]=app1_revision_a',
123
+ )
124
+ end
125
+ it 'does not have a Test link for active revisions' do
126
+ the_request
127
+ expect(last_response.body).to have_tag('tr.revision-app1_revision_b') do
128
+ without_tag 'td.col-status a', text: /test this revision/i
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ describe 'POST /applications/:app_name/activate/:revision_name' do
135
+ let(:the_request) { post "/applications/application1/activate/app1_revision_a" }
136
+
137
+ before do
138
+ app1_revision_a.activate!
139
+ app1_revision_b.activate!
140
+ end
141
+
142
+ it 'redirects to the application page' do
143
+ the_request
144
+ expect(last_response).to be_redirect
145
+ follow_redirect!
146
+ expect(last_request.url).to match %r(/applications/application1$)
147
+ end
148
+ it 'makes the revision active' do
149
+ the_request
150
+ expect(application1.active_revision).to eq(app1_revision_a)
151
+ end
152
+ it 'executes the configured on_revision_activated callback' do
153
+ callback_was_called = false
154
+ EmberCliDeployRedis.configure do |config|
155
+ config.on_revision_activated do |revision|
156
+ callback_was_called = true
157
+ expect(revision).to eq(app1_revision_a)
158
+ end
159
+ end
160
+ the_request
161
+ expect(callback_was_called).to be_truthy
162
+ end
163
+ end
164
+ end