resque-scheduler-web 0.0.3 → 0.0.4

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 (25) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb +25 -3
  4. data/app/views/resque_web/plugins/resque_scheduler/delayed/_search_form.erb +1 -1
  5. data/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb +46 -41
  6. data/app/views/resque_web/plugins/resque_scheduler/delayed/jobs_klass.erb +5 -4
  7. data/app/views/resque_web/plugins/resque_scheduler/delayed/search.erb +1 -1
  8. data/lib/resque/scheduler/web/version.rb +1 -1
  9. data/spec/dummy/config/application.rb +2 -0
  10. data/spec/features/delayed/cancel_delayed_job_spec.rb +28 -0
  11. data/spec/features/delayed/clear_all_jobs_spec.rb +24 -0
  12. data/spec/features/delayed/delayed_jobs_index_page_spec.rb +10 -15
  13. data/spec/features/delayed/delayed_jobs_timestamp_page_spec.rb +40 -13
  14. data/spec/features/delayed/see_all_timestamps_for_a_class_spec.rb +55 -0
  15. data/spec/features/delayed/send_a_delayed_job_to_the_queue_spec.rb +29 -0
  16. data/spec/features/navigation_spec.rb +23 -2
  17. data/spec/features/schedules/cannot_delete_a_job_when_the_schedule_is_static.rb +14 -10
  18. data/spec/features/schedules/delete_a_job_from_the_dynamic_schedule_spec.rb +42 -31
  19. data/spec/features/schedules/requeuing_a_job_with_parameters_spec.rb +32 -16
  20. data/spec/features/schedules/requeuing_a_job_without_parameters_spec.rb +26 -22
  21. data/spec/features/schedules/scheduled_jobs_index_page_spec.rb +35 -24
  22. data/spec/spec_helper.rb +1 -0
  23. data/spec/support/shared_steps.rb +47 -0
  24. data/spec/support/test_jobs.rb +14 -0
  25. metadata +13 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cdaf732772b3cf1c129b8394190a3e3e2d991d01
4
- data.tar.gz: 932897408224f2238e1a5323c415fc26f08164b4
3
+ metadata.gz: 0e0d9ae424811136f0f35b1c596f174b5e452d56
4
+ data.tar.gz: 558a1cc70f5fb9262acc90eae0977f6e15917f88
5
5
  SHA512:
6
- metadata.gz: 9c9d83155665494ef45db59edb1ae4e61b3017ca46a17620f4ba748ec577d5c2088f944de2b3154dd27a60fc73d79a18ea6abfbbd1b3101f06a935b201b4ea6d
7
- data.tar.gz: 2cda060442328d84b6ffe8b01687bc665811e69ff0713fadf295160e889a3bd1913ecc089696828ff3778f2804b4ce3d2a8db63b10245990169c07ecb0243531
6
+ metadata.gz: 4a179c41dd6f5c3a9f8366e00adf05956006adcf0b1d9be60587b61607bf4c9da9deb435362d0903fb1ebf52c976003799b8b07f4ddd9ec9cc14ba523ce8ed80
7
+ data.tar.gz: 1a064fb3d53f6a127e95001a2284f165920a627b8b9d2d91ce69366afaa8030a252b8060e5d14e8f7b32eef300b99af7f8703f839c9a407dcf65c2ed10904fe1
data/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## 0.0.4
4
+ * More Rspec feature specs. All main functionality is now covered with
5
+ integration tests.
6
+ * Timestamps page for a job now correctly shows timestamps for jobs which
7
+ inherit from `ActiveJob::Base`.
8
+ * Timestamps page for a job shows timestamps as links.
9
+ * Some layout and styling improvements.
10
+
11
+ ## 0.0.3
12
+ * Fixed timestamps page.
13
+ * Added Rspec features to cover more functionality that was previously untested.
14
+
15
+ ## 0.0.2
16
+ * Add documentation for methods and classes.
17
+ * Clean up lots of Rubocop issues with the code style.
18
+ * Set up Travis CI.
19
+ * Add various badges to the README.
20
+ * Add runtime dependencies to prevent a bug with earlier versions of
21
+ resque-scheduler, which defined `Resque::Scheduler` as a class, rather than a
22
+ module.
23
+
24
+ ## 0.0.1
25
+ * Code ported over from the main resque-scheduler gem, extracted from the
26
+ Sinatra interface, and put into a rails engine.
27
+ * Test suite converted to use Rspec.
@@ -14,13 +14,32 @@ module ResqueWeb
14
14
  end
15
15
 
16
16
  # GET /delayed/jobs/:klass
17
- # Shows us all of the jobs of this type, with these args. Accessed by
17
+ # Shows us all of the timestamps where jobs of this type, with these
18
+ # args are currently scheduled as delayed jobs. Accessed by
18
19
  # clicking the 'All schedules' link next to a delayed job.
19
20
  def jobs_klass
20
21
  klass = Resque::Scheduler::Util.constantize(params[:klass])
21
- @args = JSON.load(URI.decode(params[:args]))
22
- @timestamps = Resque.scheduled_at(klass, *@args)
22
+ @args = params[:args] ? JSON.load(URI.decode(params[:args])) : []
23
+
24
+ # ActiveJob hack. The wrapper class does not know what queue the
25
+ # wrapped class wants to use, so we need to tell Resque Scheduler
26
+ # the queue, rather than have it use Resque's internal guessing
27
+ # mechanism.
28
+ if klass.to_s == 'ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper'
29
+ queue_name = @args.first['queue_name']
30
+ hashed_job = Resque.send :job_to_hash_with_queue, queue_name, klass, @args
31
+ search = Resque.send :encode, hashed_job
32
+ @timestamps = Resque.instance_eval do
33
+ redis.smembers("timestamps:#{search}").map do |key|
34
+ key.tr('delayed:', '').to_i
35
+ end
36
+ end
37
+ else
38
+ @timestamps = Resque.scheduled_at(klass, *@args)
39
+ end
23
40
  rescue
41
+ # Should this be a rescue? Seems to cover the case of the params
42
+ # not validating or something.
24
43
  @timestamps = []
25
44
  end
26
45
 
@@ -30,6 +49,7 @@ module ResqueWeb
30
49
  end
31
50
 
32
51
  # POST /delayed/cancel_now
52
+ # cancels a specific job based on klass, timestamp and args.
33
53
  def cancel_now
34
54
  klass = Resque::Scheduler::Util.constantize(params['klass'])
35
55
  timestamp = params['timestamp']
@@ -45,6 +65,8 @@ module ResqueWeb
45
65
  end
46
66
 
47
67
  # POST /delayed/queue_now
68
+ # Sends ALL of the delayed jobs at a particular timestamp to the queue,
69
+ # regardless of their details.
48
70
  def queue_now
49
71
  timestamp = params['timestamp'].to_i
50
72
  if timestamp > 0
@@ -1,6 +1,6 @@
1
1
  <form method="POST" action="<%= delayed_search_path %>">
2
2
  <input type='input' name='search' value="<%= params[:search] %>"/>
3
- <input type='submit' value='Search'/>
3
+ <input type='submit' value='Search' class="btn btn-default"/>
4
4
  </form>
5
5
 
6
6
 
@@ -7,53 +7,58 @@
7
7
  Server local time: <%= Time.now %>
8
8
  </p>
9
9
 
10
- <p class='sub'>
11
- <% finish = [@start + @number_to_show, @total_number_of_delayed_jobs].min %>
12
- Showing <%= @start %> to <%= finish %> of
13
- <b><%= @total_number_of_delayed_jobs %></b> timestamps
14
- </p>
10
+ <% if @timestamps.any? %>
11
+
12
+ <p class='sub'>
13
+ <% finish = [@start + @number_to_show, @total_number_of_delayed_jobs].min %>
14
+ Showing <%= @start %> to <%= finish %> of
15
+ <b><%= @total_number_of_delayed_jobs %></b> timestamps
16
+ </p>
15
17
 
16
- <table class="table table-bordered">
17
- <tr>
18
- <th></th>
19
- <th>Timestamp</th>
20
- <th>Job count</th>
21
- <th>Class</th>
22
- <th>Args</th>
23
- <th>All schedules</th>
24
- </tr>
25
- <% @timestamps.each do |timestamp| %>
26
- <tr class="delayed-job">
27
- <td>
28
- <form action="<%= queue_now_path %>" method="post">
29
- <input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
30
- <input type="submit" value="Queue now" class="btn btn-default">
31
- </form>
32
- </td>
33
- <td><a href="<%= delayed_path timestamp: timestamp %>"><%= format_time(Time.at(timestamp)) %></a></td>
34
- <td class="job-count"><%= delayed_timestamp_size = Resque.delayed_timestamp_size(timestamp) %></td>
35
- <% job = Resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
36
- <td>
37
- <% if job && delayed_timestamp_size == 1 %>
38
- <%= h(job['class']) %>
39
- <% else %>
40
- <a href="<%= timestamp_path timestamp: timestamp %>">see details</a>
41
- <% end %>
42
- </td>
43
- <td><%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %></td>
44
- <td>
45
- <% if job %>
46
- <a href="<%= delayed_job_class_path klass: job['class'], args: URI.encode(job['args'].to_json) %>">All schedules</a>
47
- <% end %>
48
- </td>
18
+ <table class="table table-bordered">
19
+ <tr>
20
+ <th></th>
21
+ <th>Timestamp</th>
22
+ <th>Job count</th>
23
+ <th>Class</th>
24
+ <th>Args</th>
25
+ <th>All schedules</th>
49
26
  </tr>
50
- <% end %>
51
- </table>
27
+ <% @timestamps.each do |timestamp| %>
28
+ <tr class="delayed-job">
29
+ <td>
30
+ <form action="<%= queue_now_path %>" method="post">
31
+ <input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
32
+ <input type="submit" value="Queue now" class="btn btn-default">
33
+ </form>
34
+ </td>
35
+ <td class="timestamp-link"><a href="<%= timestamp_path timestamp: timestamp %>"><%= format_time(Time.at(timestamp)) %></a></td>
36
+ <td class="job-count"><%= delayed_timestamp_size = Resque.delayed_timestamp_size(timestamp) %></td>
37
+ <% job = Resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
38
+ <td>
39
+ <% if job && delayed_timestamp_size == 1 %>
40
+ <%= h(job['class']) %>
41
+ <% else %>
42
+ <a href="<%= timestamp_path timestamp: timestamp %>">see details</a>
43
+ <% end %>
44
+ </td>
45
+ <td><%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %></td>
46
+ <td>
47
+ <% if job %>
48
+ <a href="<%= delayed_job_class_path klass: job['class'], args: URI.encode(job['args'].to_json) %>">All schedules</a>
49
+ <% end %>
50
+ </td>
51
+ </tr>
52
+ <% end %>
53
+ </table>
54
+ <% else %>
55
+ <h2>There are no delayed jobs</h2>
56
+ <% end %>
52
57
 
53
58
  <% if @total_number_of_delayed_jobs > 0 %>
54
59
  <br>
55
60
  <form method="POST" action="<%= clear_path %>" class='clear-delayed'>
56
- <input type='submit' name='' value='Clear Delayed Jobs' />
61
+ <input type='submit' name='' value='Clear All Delayed Jobs' class="btn btn-default"/>
57
62
  </form>
58
63
  <% end %>
59
64
 
@@ -1,14 +1,15 @@
1
- <h1>Delayed jobs scheduled for <%= params[:klass] %> (<%= @args %>)</h1>
1
+ <h1>Timestamps where delayed jobs are scheduled for class:<br> <%= params[:klass] %></h1>
2
+ <h2>With params: <%= @args %></h2>
2
3
 
3
- <table class='jobs'>
4
+ <table class='jobs table table-bordered'>
4
5
  <tr>
5
- <th>Timestamp</th>
6
+ <th><%= "Timestamp".pluralize(@timestamps.size) %></th>
6
7
  </tr>
7
8
 
8
9
  <% @timestamps.each do |t| %>
9
10
  <tr>
10
11
  <td>
11
- <%= Time.at(t) %>
12
+ <%= link_to Time.at(t), timestamp_path(timestamp: t.to_i), class: 'timestamp-link' %>
12
13
  </td>
13
14
  </tr>
14
15
  <% end %>
@@ -24,7 +24,7 @@
24
24
  <input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
25
25
  <input type="hidden" name="klass" value="<%= job['class'] %>">
26
26
  <input type="hidden" name="args" value="<%= Resque.encode job['args'] %>">
27
- <input type="submit" value="Cancel Job">
27
+ <input type="submit" value="Cancel Job" class="btn btn-default">
28
28
  </form>
29
29
  </td>
30
30
  <td class='args'><%= format_time(Time.at(job['timestamp'])) %></td>
@@ -1,7 +1,7 @@
1
1
  module Resque
2
2
  module Scheduler
3
3
  module Web
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.4'
5
5
  end
6
6
  end
7
7
  end
@@ -28,5 +28,7 @@ module Dummy
28
28
 
29
29
  # Do not swallow errors in after_commit/after_rollback callbacks.
30
30
  config.active_record.raise_in_transactional_callbacks = true
31
+
32
+ config.active_job.queue_adapter = :resque
31
33
  end
32
34
  end
@@ -0,0 +1,28 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'cancelling a delayed job' do
4
+
5
+ include SharedFunctionsForFeatures
6
+
7
+ scenario 'cancelling the job from the search page' do
8
+ given_there_is_a_delayed_job
9
+ when_i_search_for_the_delayed_job
10
+ and_i_cancel_the_job
11
+ then_i_should_be_on_the_delayed_jobs_page
12
+ and_the_job_should_not_be_present_on_the_page
13
+ end
14
+
15
+ def and_i_cancel_the_job
16
+ click_button 'Cancel'
17
+ end
18
+
19
+ def when_i_search_for_the_delayed_job
20
+ visit resque_scheduler_engine_routes.delayed_path
21
+ fill_in 'search', with: 'some'
22
+ click_button 'Search'
23
+ end
24
+
25
+ def and_the_job_should_not_be_present_on_the_page
26
+ expect(page).to_not have_content 'SomeIvarJob'
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'clearing all of the delayed jobs' do
4
+
5
+ include SharedFunctionsForFeatures
6
+
7
+ scenario 'clearing the jobs from the delayed index' do
8
+ given_there_are_two_delayed_jobs_enqueued_at_different_times
9
+ when_i_visit_the_delayed_jobs_page
10
+ and_i_click_the_clear_all_jobs_button
11
+ then_i_should_be_on_the_delayed_jobs_page
12
+ and_i_should_not_see_any_jobs_on_the_page
13
+ end
14
+
15
+ def and_i_should_not_see_any_jobs_on_the_page
16
+ expect(page).to_not have_content 'SomeIvarJob'
17
+ expect(page).to_not have_content 'JobWithoutParams'
18
+ end
19
+
20
+ def and_i_click_the_clear_all_jobs_button
21
+ click_button 'Clear All Delayed Jobs'
22
+ end
23
+
24
+ end
@@ -2,23 +2,18 @@ require 'rails_helper'
2
2
 
3
3
  feature 'seeing all the delayed jobs on the index page' do
4
4
 
5
- after do
6
- reset_the_resque_schedule
7
- end
8
-
9
- let(:some_time_in_the_future) { Time.now + 3600 }
10
- let(:some_other_time_in_the_future) { Time.now + 4600 }
5
+ include SharedFunctionsForFeatures
11
6
 
12
- # Given there is a delayed job
13
- # And another delayed job enqueued at a later time
14
- # When I visit the delayed jobs index page
15
- # Then I should see the job on the page
16
7
  scenario 'delayed jobs show up on the page when at different times' do
17
- Resque.enqueue_at(some_time_in_the_future, SomeIvarJob)
18
- Resque.enqueue_at(some_other_time_in_the_future, JobWithoutParams)
19
- visit resque_scheduler_engine_routes.delayed_path
8
+ given_there_are_two_delayed_jobs_enqueued_at_different_times
9
+ when_i_visit_the_delayed_jobs_page
10
+ then_i_should_see_the_details_of_both_jobs_on_the_page
11
+ end
12
+
13
+ def then_i_should_see_the_details_of_both_jobs_on_the_page
20
14
  expect(page).to have_content 'SomeIvarJob'
21
15
  expect(page).to have_content 'JobWithoutParams'
16
+ expect(page).to have_content some_time_in_the_future
17
+ expect(page).to have_content some_other_time_in_the_future
22
18
  end
23
-
24
- end
19
+ end
@@ -2,28 +2,55 @@ require 'rails_helper'
2
2
 
3
3
  feature 'seeing a summary of the delayed jobs for a timestamp on the index' do
4
4
 
5
- after do
6
- reset_the_resque_schedule
5
+ include SharedFunctionsForFeatures
6
+
7
+ scenario 'delayed jobs show up on the page when at the same times' do
8
+ given_there_are_two_delayed_jobs_enqueued_at_the_same_time
9
+ when_i_visit_the_delayed_jobs_page
10
+ then_i_should_see_the_delayed_jobs_on_the_page_as_summary
11
+ when_i_click_through_to_the_details_page
12
+ then_i_should_see_the_details_of_the_jobs
7
13
  end
8
14
 
9
- let(:some_time_in_the_future) { Time.now + 3600 }
10
- let(:some_other_time_in_the_future) { Time.now + 4600 }
15
+ scenario 'jobs on the delayed page all have a link to their timestamp page' do
16
+ given_there_is_a_delayed_job
17
+ when_i_visit_the_delayed_jobs_page
18
+ when_i_click_on_the_timestamp_next_to_the_job
19
+ then_i_should_be_on_the_timestamps_page
20
+ end
11
21
 
12
- # Given there is a delayed job
13
- # And another delayed job enqueued at the same time
14
- # When I visit the delayed jobs index page
15
- # Then I should see the jobs on the page as a summary
16
- # When I click through to the details page
17
- # Then I should see the details of the jobs
18
- scenario 'delayed jobs show up on the page when at the same times' do
19
- Resque.enqueue_at(some_time_in_the_future, JobWithParams, { argument: 'thingy' })
22
+ def then_i_should_be_on_the_timestamps_page
23
+ expected_path = resque_scheduler_engine_routes.timestamp_path(
24
+ timestamp: some_time_in_the_future.to_i
25
+ )
26
+ expect(current_path).to eq expected_path
27
+ end
28
+
29
+ def when_i_click_on_the_timestamp_next_to_the_job
30
+ all('.timestamp-link a').first.click
31
+ end
32
+
33
+ def given_there_are_two_delayed_jobs_enqueued_at_the_same_time
34
+ Resque.enqueue_at(some_time_in_the_future, JobWithParams, argument: 'thingy')
20
35
  Resque.enqueue_at(some_time_in_the_future, JobWithoutParams)
36
+ end
37
+
38
+ def when_i_visit_the_delayed_jobs_page
21
39
  visit resque_scheduler_engine_routes.delayed_path
40
+ end
41
+
42
+ def then_i_should_see_the_delayed_jobs_on_the_page_as_summary
22
43
  expect(page).to have_css '.job-count', text: '2'
44
+ end
45
+
46
+ def when_i_click_through_to_the_details_page
23
47
  click_link 'see details'
48
+ end
49
+
50
+ def then_i_should_see_the_details_of_the_jobs
24
51
  expect(page).to have_content 'JobWithParams'
25
52
  expect(page).to have_content '"argument"=>"thingy"'
26
53
  expect(page).to have_content 'JobWithoutParams'
54
+ expect(page).to have_content some_time_in_the_future
27
55
  end
28
-
29
56
  end
@@ -0,0 +1,55 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'seeing all of the timestamps where a class is delayed' do
4
+
5
+ include SharedFunctionsForFeatures
6
+
7
+ scenario 'viewing the timestamps page with no params' do
8
+ given_there_is_a_delayed_job
9
+ when_i_visit_the_delayed_jobs_page
10
+ and_i_click_on_the_link_to_see_all_the_timestamps_for_that_job
11
+ then_i_should_be_on_the_delayed_class_page
12
+ and_i_should_see_the_timestamp_on_the_page
13
+ end
14
+
15
+ scenario 'viewing the timestamps page with activejob' do
16
+ given_there_is_a_delayed_job_with_active_job
17
+ when_i_visit_the_delayed_jobs_page
18
+ and_i_click_on_the_link_to_see_all_the_timestamps_for_that_job
19
+ and_i_should_see_the_timestamp_on_the_page
20
+ when_i_click_on_the_timestap
21
+ then_i_should_be_on_the_timestamp_page
22
+ end
23
+
24
+ def and_i_click_on_the_link_to_see_all_the_timestamps_for_that_job
25
+ click_link 'All schedules'
26
+ end
27
+
28
+ def then_i_should_be_on_the_delayed_class_page
29
+ expect(current_path).to eq resque_scheduler_engine_routes.delayed_job_class_path klass: 'SomeIvarJob'
30
+ end
31
+
32
+ def then_i_should_be_on_the_delayed_class_page_with_params
33
+ expect(current_path).to eq resque_scheduler_engine_routes.delayed_job_class_path klass: 'JobWithParams'
34
+ end
35
+
36
+ def and_i_should_see_the_timestamp_on_the_page
37
+ expect(page).to have_content some_time_in_the_future
38
+ end
39
+
40
+ def given_there_is_a_delayed_job_with_params
41
+ Resque.enqueue_at(some_time_in_the_future, JobWithParams, argument: 'thingy')
42
+ end
43
+
44
+ def given_there_is_a_delayed_job_with_active_job
45
+ ActiveJobTest.set(wait_until: some_time_in_the_future).perform_later
46
+ end
47
+
48
+ def when_i_click_on_the_timestap
49
+ all('.timestamp-link').first.click
50
+ end
51
+
52
+ def then_i_should_be_on_the_timestamp_page
53
+ expect(current_path).to eq resque_scheduler_engine_routes.timestamp_path timestamp: some_time_in_the_future.to_i
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'Sending a delayed job to the queue for immediate execution' do
4
+
5
+ include SharedFunctionsForFeatures
6
+
7
+ let(:queue_name) { 'ivar' }
8
+ let(:job_class) { 'SomeIvarJob' }
9
+
10
+ scenario 'Pressing the queue button sends the job to the queue immediately' do
11
+ given_there_is_a_delayed_job
12
+ when_i_visit_the_delayed_jobs_page
13
+ and_i_press_the_queue_now_button
14
+ then_i_should_be_on_the_overview_page
15
+ and_i_should_see_the_job_in_the_queue
16
+ when_i_click_through_to_the_queue_page
17
+ then_i_should_see_the_details_of_the_job_on_the_page
18
+ when_i_visit_the_delayed_jobs_page
19
+ then_i_should_not_see_any_delayed_jobs
20
+ end
21
+
22
+ def and_i_press_the_queue_now_button
23
+ click_button 'Queue now'
24
+ end
25
+
26
+ def then_i_should_not_see_any_delayed_jobs
27
+ expect(page).to have_content 'There are no delayed jobs'
28
+ end
29
+ end
@@ -2,14 +2,35 @@ require 'rails_helper'
2
2
 
3
3
  feature 'the tabs added to the resque web interface work correctly' do
4
4
  scenario 'the Schedule tab works' do
5
+ when_i_visit_the_resque_web_overview_page
6
+ and_i_follow_the_schedule_link
7
+ then_i_should_be_on_the_schedules_page
8
+ end
9
+
10
+ scenario 'the Delayed tab works' do
11
+ when_i_visit_the_resque_web_overview_page
12
+ when_i_follow_the_delayed_link
13
+ then_i_should_be_on_the_delayed_page
14
+ end
15
+
16
+ def when_i_visit_the_resque_web_overview_page
5
17
  visit ResqueWeb::Engine.app.url_helpers.overview_path
18
+ end
19
+
20
+ def and_i_follow_the_schedule_link
6
21
  click_link 'Schedule'
22
+ end
23
+
24
+ def then_i_should_be_on_the_schedules_page
7
25
  expect(current_path).to eq resque_scheduler_engine_routes.schedules_path
8
26
  end
9
27
 
10
- scenario 'the Delayed tab works' do
11
- visit ResqueWeb::Engine.app.url_helpers.overview_path
28
+ def when_i_follow_the_delayed_link
12
29
  click_link 'Delayed'
30
+ end
31
+
32
+ def then_i_should_be_on_the_delayed_page
13
33
  expect(current_path).to eq resque_scheduler_engine_routes.delayed_path
14
34
  end
35
+
15
36
  end
@@ -1,12 +1,16 @@
1
1
  require 'rails_helper'
2
-
3
2
  feature 'deleting a job from the dynamic schedule' do
4
3
 
5
- def visit_scheduler_page
6
- visit resque_scheduler_engine_routes.schedules_path
4
+ include SharedFunctionsForFeatures
5
+
6
+ scenario 'the delete button is not present when the schedule is static' do
7
+ given_there_are_some_jobs_in_the_schedule
8
+ and_the_schedule_is_set_to_be_static
9
+ when_i_visit_the_scheduler_page
10
+ then_there_should_not_be_a_delete_button_for_the_job
7
11
  end
8
12
 
9
- before do
13
+ def given_there_are_some_jobs_in_the_schedule
10
14
  Resque.schedule = {
11
15
  'some_ivar_job' => {
12
16
  'cron' => '* * * * *',
@@ -24,18 +28,18 @@ feature 'deleting a job from the dynamic schedule' do
24
28
  }
25
29
  }
26
30
  }
27
- allow(Resque::Scheduler).to receive(:dynamic).and_return(false)
28
31
  Resque::Scheduler.load_schedule!
29
- visit_scheduler_page
30
32
  end
31
33
 
32
- after do
33
- reset_the_resque_schedule
34
+ def and_the_schedule_is_set_to_be_static
35
+ allow(Resque::Scheduler).to receive(:dynamic).and_return(false)
34
36
  end
35
37
 
36
- scenario 'the delete button is not present when the schedule is static' do
37
- visit resque_scheduler_engine_routes.schedules_path
38
+ def then_there_should_not_be_a_delete_button_for_the_job
38
39
  expect(page).to_not have_css '#job_some_ivar_job .delete-button'
39
40
  end
40
41
 
42
+ def when_i_visit_the_scheduler_page
43
+ visit resque_scheduler_engine_routes.schedules_path
44
+ end
41
45
  end
@@ -2,11 +2,37 @@ require 'rails_helper'
2
2
 
3
3
  feature 'deleting a job from the dynamic schedule' do
4
4
 
5
- def visit_scheduler_page
6
- visit resque_scheduler_engine_routes.schedules_path
7
- end
5
+ include SharedFunctionsForFeatures
8
6
 
9
7
  before do
8
+ given_there_are_two_jobs_in_the_scheduler
9
+ and_the_schedule_is_set_up_to_be_dyamic
10
+ when_i_visit_the_scheduler_page
11
+ end
12
+
13
+ scenario 'the job disappears from the UI' do
14
+ when_i_delete_the_job_from_the_ui
15
+ then_i_should_be_on_the_scheduler_page
16
+ and_the_job_should_not_be_present_in_the_ui
17
+ end
18
+
19
+ scenario 'the other job remains in the UI' do
20
+ when_i_delete_the_job_from_the_ui
21
+ then_i_should_be_on_the_scheduler_page
22
+ and_the_other_job_should_still_be_present_in_the_ui
23
+ end
24
+
25
+ scenario 'the job is removed from the resque backend' do
26
+ when_i_delete_the_job_from_the_ui
27
+ then_i_should_be_on_the_scheduler_page
28
+ and_the_job_should_no_longer_be_present_in_the_resque_schedule
29
+ end
30
+
31
+ def and_the_schedule_is_set_up_to_be_dyamic
32
+ allow(Resque::Scheduler).to receive(:dynamic).and_return(true)
33
+ end
34
+
35
+ def given_there_are_two_jobs_in_the_scheduler
10
36
  Resque.schedule = {
11
37
  'some_ivar_job' => {
12
38
  'cron' => '* * * * *',
@@ -24,45 +50,30 @@ feature 'deleting a job from the dynamic schedule' do
24
50
  }
25
51
  }
26
52
  }
27
- allow(Resque::Scheduler).to receive(:dynamic).and_return(true)
28
53
  Resque::Scheduler.load_schedule!
29
- visit_scheduler_page
30
54
  end
31
55
 
32
- after do
33
- reset_the_resque_schedule
56
+ def when_i_visit_the_scheduler_page
57
+ visit resque_scheduler_engine_routes.schedules_path
34
58
  end
35
59
 
36
- # Given there is a job in the scheduler
37
- # And the schedule is set up to be dynamic
38
- # When I delete the job from the UI
39
- # Then I should be on the schedule page
40
- # And the job should no longer be present
41
- scenario 'the job disappears from the UI' do
60
+ def when_i_delete_the_job_from_the_ui
42
61
  find('#job_some_ivar_job .delete-button').click
43
- expect(current_path).to eq resque_scheduler_engine_routes.schedules_path
44
- expect(page).to_not have_css '#job_some_ivar_job'
45
62
  end
46
63
 
47
- # Given there are two jobs in the scheduler
48
- # And the schedule is set up to be dynamic
49
- # When I delete the job from the UI
50
- # Then I should be on the schedule page
51
- # And the other job should still be present
52
- scenario 'the other job remains in the UI' do
53
- find('#job_some_ivar_job .delete-button').click
64
+ def then_i_should_be_on_the_scheduler_page
54
65
  expect(current_path).to eq resque_scheduler_engine_routes.schedules_path
55
- expect(page).to have_css '#job_some_other_job'
56
66
  end
57
67
 
58
- # Given there is a job in the scheduler
59
- # And the schedule is set up to be dynamic
60
- # When I delete the job from the UI
61
- # Then I should be on the schedule page
62
- # And the job should no longer be present in the Resque schedule
63
- scenario 'the job is removed from the resque backend' do
64
- find('#job_some_ivar_job .delete-button').click
65
- expect(current_path).to eq resque_scheduler_engine_routes.schedules_path
68
+ def and_the_job_should_no_longer_be_present_in_the_resque_schedule
66
69
  expect(Resque.schedule).to_not have_key 'some_ivar_job'
67
70
  end
71
+
72
+ def and_the_other_job_should_still_be_present_in_the_ui
73
+ expect(page).to have_css '#job_some_other_job'
74
+ end
75
+
76
+ def and_the_job_should_not_be_present_in_the_ui
77
+ expect(page).to_not have_css '#job_some_ivar_job'
78
+ end
68
79
  end
@@ -1,39 +1,55 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  feature 'requeuing a job that has defined params' do
4
+
5
+ include SharedFunctionsForFeatures
6
+
4
7
  before do
5
- Resque.schedule = Test::RESQUE_SCHEDULE
6
- Resque::Scheduler.load_schedule!
8
+ given_i_have_a_job_which_requires_params_in_the_schedule
7
9
  end
8
10
 
9
- after do
10
- reset_the_resque_schedule
11
+ scenario 'I am prompted to enter the params required for the requeued job' do
12
+ when_i_visit_the_schedules_page
13
+ and_i_requeue_the_job_with_new_params
14
+ then_i_should_be_on_the_overview_page
15
+ and_i_should_see_the_job_in_the_queue
16
+ when_i_click_on_the_link_to_the_queue
17
+ then_i_should_see_details_of_the_job_on_the_page
11
18
  end
12
19
 
13
- # Given I have a job which requires params in the schedule
14
- # When I press the requeue button
15
- # Then I should be presented with a form that prompts me for the params
16
- # When I enter the params and submit the form
17
- # Then I should be on the overview page
18
- # And I should see the job in the queue
19
- # When I visit the queue page
20
- # Then I should see the job on the page with the new params
21
- scenario 'I am prompted to enter the params required for the requeued job' do
22
- job_name = 'job_with_params'
23
- queue_name = 'quick'
24
- job_class = 'JobWithParams'
20
+ let(:job_name) { 'job_with_params' }
21
+ let(:queue_name) { 'quick' }
22
+ let(:job_class) { 'JobWithParams' }
25
23
 
24
+ def given_i_have_a_job_which_requires_params_in_the_schedule
25
+ Resque.schedule = Test::RESQUE_SCHEDULE
26
+ Resque::Scheduler.load_schedule!
27
+ end
28
+
29
+ def when_i_visit_the_schedules_page
26
30
  visit resque_scheduler_engine_routes.schedules_path
31
+ end
32
+
33
+ def and_i_requeue_the_job_with_new_params
27
34
  click_button "requeue_job_#{job_name}"
28
35
 
29
36
  fill_in 'log_level', with: 'info'
30
37
  click_button 'Queue now'
38
+ end
31
39
 
40
+ def then_i_should_be_on_the_overview_page
32
41
  expect(current_path).to eq ResqueWeb::Engine.app.url_helpers.overview_path
42
+ end
43
+
44
+ def and_i_should_see_the_job_in_the_queue
33
45
  expect(page).to have_content "#{queue_name} 1"
46
+ end
34
47
 
48
+ def when_i_click_on_the_link_to_the_queue
35
49
  find('.queues .queue a', text: queue_name).click
50
+ end
36
51
 
52
+ def then_i_should_see_details_of_the_job_on_the_page
37
53
  expect(page).to have_content job_class
38
54
  expect(page).to have_css 'td.args', text: /"log_level"=>"info"/
39
55
  end
@@ -1,7 +1,31 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  feature 'requeuing a job that has no params' do
4
+
5
+ include SharedFunctionsForFeatures
6
+
4
7
  before do
8
+ given_i_have_a_job_which_requires_params_in_the_schedule
9
+ end
10
+
11
+ scenario 'I am prompted to enter the params required for the requeued job' do
12
+ when_i_visit_the_schedules_page
13
+ and_i_requeue_the_job
14
+ then_i_should_be_on_the_overview_page
15
+ and_i_should_see_the_job_in_the_queue
16
+ when_i_click_through_to_the_queue_page
17
+ then_i_should_see_the_details_of_the_job_on_the_page
18
+ end
19
+
20
+ let(:queue_name) { 'quick' }
21
+ let(:job_name) { 'job_without_params' }
22
+ let(:job_class) { 'JobWithoutParams' }
23
+
24
+ def when_i_visit_the_schedules_page
25
+ visit resque_scheduler_engine_routes.schedules_path
26
+ end
27
+
28
+ def given_i_have_a_job_which_requires_params_in_the_schedule
5
29
  Resque.schedule = {
6
30
  'job_without_params' => {
7
31
  'cron' => '* * * * *',
@@ -15,29 +39,9 @@ feature 'requeuing a job that has no params' do
15
39
  Resque::Scheduler.load_schedule!
16
40
  end
17
41
 
18
- after do
19
- reset_the_resque_schedule
20
- end
21
-
22
- # Given I have a job which requires params in the schedule
23
- # When I press the requeue button
24
- # Then I should be on the overview page
25
- # And I should see the job in the queue
26
- # When I visit the queue page
27
- # Then I should see the job on the page with the new params
28
- scenario 'I am prompted to enter the params required for the requeued job' do
29
- job_name = 'job_without_params'
30
- queue_name = 'quick'
31
- job_class = 'JobWithoutParams'
32
-
33
- visit resque_scheduler_engine_routes.schedules_path
42
+ def and_i_requeue_the_job
34
43
  click_button "requeue_job_#{job_name}"
44
+ end
35
45
 
36
- expect(current_path).to eq ResqueWeb::Engine.app.url_helpers.overview_path
37
- expect(page).to have_content "#{queue_name} 1"
38
-
39
- find('.queues .queue a', text: queue_name).click
40
46
 
41
- expect(page).to have_content job_class
42
- end
43
47
  end
@@ -1,13 +1,36 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  feature 'Viewing the schedule page and interacting with it' do
4
- def visit_scheduler_page
5
- visit resque_scheduler_engine_routes.schedules_path
6
- end
4
+
5
+ include SharedFunctionsForFeatures
7
6
 
8
7
  before do
8
+ given_the_resque_scheduler_is_using_the_production_environment
9
+ and_there_are_several_jobs_in_the_schedule
10
+ when_i_visit_the_scheduler_page
11
+ end
12
+
13
+ scenario 'the page has the correct title' do
14
+ then_the_page_should_have_the_correct_title
15
+ end
16
+
17
+ scenario 'the index shows the scheduled job' do
18
+ then_the_page_should_have_the_class_name_of_the_job_in_this_env
19
+ end
20
+
21
+ scenario 'the index excludes jobs for other envs' do
22
+ then_the_page_should_not_have_the_name_of_jobs_from_other_envs
23
+ end
24
+
25
+ scenario 'the index includes job used in multiple environments' do
26
+ then_the_page_should_have_the_name_of_jobs_in_both_this_and_other_envs
27
+ end
28
+
29
+ def given_the_resque_scheduler_is_using_the_production_environment
9
30
  Resque::Scheduler.env = 'production'
31
+ end
10
32
 
33
+ def and_there_are_several_jobs_in_the_schedule
11
34
  Resque.schedule = {
12
35
  'some_ivar_job' => {
13
36
  'cron' => '* * * * *',
@@ -38,46 +61,34 @@ feature 'Viewing the schedule page and interacting with it' do
38
61
  }
39
62
  }
40
63
  Resque::Scheduler.load_schedule!
41
- visit_scheduler_page
42
64
  end
43
65
 
44
- after do
45
- reset_the_resque_schedule
66
+ def when_i_visit_the_resque_web_home_page
67
+ visit '/resque_web'
46
68
  end
47
69
 
48
- it 'Link to Schedule page in navigation works' do
49
- visit '/resque_web'
70
+ def and_i_click_the_schedule_link
50
71
  click_link 'Schedule'
51
- assert page.has_css? 'h1', 'Schedule'
52
72
  end
53
73
 
54
- it 'has the correct title' do
74
+ def then_the_page_should_have_the_correct_title
55
75
  assert page.has_css?('h1', 'Schedule')
56
76
  end
57
77
 
58
- it 'shows the scheduled job' do
78
+ def then_the_page_should_have_the_class_name_of_the_job_in_this_env
59
79
  assert page.body.include?('SomeIvarJob')
60
80
  end
61
81
 
62
- it 'excludes jobs for other envs' do
82
+ def then_the_page_should_not_have_the_name_of_jobs_from_other_envs
63
83
  refute page.body.include?('SomeFancyJob')
64
84
  end
65
85
 
66
- it 'includes job used in multiple environments' do
86
+ def then_the_page_should_have_the_name_of_jobs_in_both_this_and_other_envs
67
87
  assert page.body.include?('SomeSharedEnvJob')
68
88
  end
69
89
 
70
- it 'allows delete when dynamic' do
71
- allow(Resque::Scheduler).to receive(:dynamic).and_return(true)
72
- visit_scheduler_page
73
-
74
- assert page.body.include?('Delete')
90
+ def when_i_visit_the_scheduler_page
91
+ visit resque_scheduler_engine_routes.schedules_path
75
92
  end
76
93
 
77
- it "doesn't allow delete when static" do
78
- allow(Resque::Scheduler).to receive(:dynamic).and_return(false)
79
- visit_scheduler_page
80
-
81
- refute page.body.include?('Delete')
82
- end
83
94
  end
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ ENV['RAILS_ENV'] = 'test'
6
6
  require 'resque'
7
7
  require 'resque-scheduler'
8
8
  require_relative 'support/functions'
9
+ require_relative 'support/shared_steps'
9
10
 
10
11
 
11
12
  Resque::Scheduler.configure do |c|
@@ -0,0 +1,47 @@
1
+ module SharedFunctionsForFeatures
2
+
3
+ def self.included(base)
4
+ base.instance_eval do
5
+ let(:some_time_in_the_future) { Time.now + 3600 }
6
+ let(:some_other_time_in_the_future) { Time.now + 4600 }
7
+
8
+ after do
9
+ reset_the_resque_schedule
10
+ end
11
+ end
12
+ end
13
+
14
+ def when_i_visit_the_delayed_jobs_page
15
+ visit resque_scheduler_engine_routes.delayed_path
16
+ end
17
+
18
+ def then_i_should_be_on_the_delayed_jobs_page
19
+ expect(current_path).to eq resque_scheduler_engine_routes.delayed_path
20
+ end
21
+
22
+ def given_there_are_two_delayed_jobs_enqueued_at_different_times
23
+ Resque.enqueue_at(some_time_in_the_future, SomeIvarJob)
24
+ Resque.enqueue_at(some_other_time_in_the_future, JobWithoutParams)
25
+ end
26
+
27
+ def given_there_is_a_delayed_job
28
+ Resque.enqueue_at(some_time_in_the_future, SomeIvarJob)
29
+ end
30
+
31
+ def then_i_should_be_on_the_overview_page
32
+ expect(current_path).to eq ResqueWeb::Engine.app.url_helpers.overview_path
33
+ end
34
+
35
+ def and_i_should_see_the_job_in_the_queue
36
+ expect(page).to have_content "#{queue_name} 1"
37
+ end
38
+
39
+ def when_i_click_through_to_the_queue_page
40
+ find('.queues .queue a', text: queue_name).click
41
+ end
42
+
43
+ def then_i_should_see_the_details_of_the_job_on_the_page
44
+ expect(page).to have_content job_class
45
+ end
46
+ end
47
+
@@ -1,3 +1,5 @@
1
+ require 'active_job'
2
+
1
3
  # Allows us to test that we can find working jobs
2
4
  class OngoingJob
3
5
  def self.queue
@@ -46,6 +48,18 @@ JobWithoutParams = Class.new(JobWithParams) do
46
48
  @queue = :quick
47
49
  end
48
50
 
51
+ class ActiveJobTest < ActiveJob::Base
52
+ queue_as :test_queue
53
+
54
+ def self.queue
55
+ queue_name
56
+ end
57
+
58
+ def perform
59
+
60
+ end
61
+ end
62
+
49
63
  # Test module
50
64
  module Foo
51
65
  # Test class
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-scheduler-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Gibson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-28 00:00:00.000000000 Z
11
+ date: 2015-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: resque-web
@@ -205,6 +205,7 @@ files:
205
205
  - ".rspec"
206
206
  - ".rubocop.yml"
207
207
  - ".travis.yml"
208
+ - CHANGELOG.md
208
209
  - Gemfile
209
210
  - LICENSE.txt
210
211
  - README.md
@@ -275,8 +276,12 @@ files:
275
276
  - spec/dummy/public/422.html
276
277
  - spec/dummy/public/500.html
277
278
  - spec/dummy/public/favicon.ico
279
+ - spec/features/delayed/cancel_delayed_job_spec.rb
280
+ - spec/features/delayed/clear_all_jobs_spec.rb
278
281
  - spec/features/delayed/delayed_jobs_index_page_spec.rb
279
282
  - spec/features/delayed/delayed_jobs_timestamp_page_spec.rb
283
+ - spec/features/delayed/see_all_timestamps_for_a_class_spec.rb
284
+ - spec/features/delayed/send_a_delayed_job_to_the_queue_spec.rb
280
285
  - spec/features/navigation_spec.rb
281
286
  - spec/features/schedules/cannot_delete_a_job_when_the_schedule_is_static.rb
282
287
  - spec/features/schedules/delete_a_job_from_the_dynamic_schedule_spec.rb
@@ -290,6 +295,7 @@ files:
290
295
  - spec/spec_helper.rb
291
296
  - spec/support/functions.rb
292
297
  - spec/support/redis_instance.rb
298
+ - spec/support/shared_steps.rb
293
299
  - spec/support/test_jobs.rb
294
300
  homepage: https://github.com/mattgibson/resque-scheduler-web
295
301
  licenses:
@@ -362,8 +368,12 @@ test_files:
362
368
  - spec/dummy/public/422.html
363
369
  - spec/dummy/public/500.html
364
370
  - spec/dummy/public/favicon.ico
371
+ - spec/features/delayed/cancel_delayed_job_spec.rb
372
+ - spec/features/delayed/clear_all_jobs_spec.rb
365
373
  - spec/features/delayed/delayed_jobs_index_page_spec.rb
366
374
  - spec/features/delayed/delayed_jobs_timestamp_page_spec.rb
375
+ - spec/features/delayed/see_all_timestamps_for_a_class_spec.rb
376
+ - spec/features/delayed/send_a_delayed_job_to_the_queue_spec.rb
367
377
  - spec/features/navigation_spec.rb
368
378
  - spec/features/schedules/cannot_delete_a_job_when_the_schedule_is_static.rb
369
379
  - spec/features/schedules/delete_a_job_from_the_dynamic_schedule_spec.rb
@@ -377,4 +387,5 @@ test_files:
377
387
  - spec/spec_helper.rb
378
388
  - spec/support/functions.rb
379
389
  - spec/support/redis_instance.rb
390
+ - spec/support/shared_steps.rb
380
391
  - spec/support/test_jobs.rb