rails-queue-it 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +116 -0
  3. data/.circleci/setup-rubygems.sh +3 -0
  4. data/.editorconfig +24 -0
  5. data/.gitignore +9 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +503 -0
  8. data/.ruby-version +1 -0
  9. data/CHANGELOG.md +7 -0
  10. data/Gemfile +15 -0
  11. data/Gemfile.lock +277 -0
  12. data/Guardfile +12 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +202 -0
  15. data/Rakefile +10 -0
  16. data/app/assets/config/queue_it_manifest.js +1 -0
  17. data/app/assets/images/queue_it/.keep +0 -0
  18. data/app/assets/stylesheets/queue_it/application.css +15 -0
  19. data/app/controllers/queue_it/application_controller.rb +5 -0
  20. data/app/helpers/queue_it/application_helper.rb +4 -0
  21. data/app/jobs/queue_it/application_job.rb +4 -0
  22. data/app/mailers/queue_it/application_mailer.rb +6 -0
  23. data/app/models/concerns/queue_it/queable.rb +89 -0
  24. data/app/models/queue_it/application_record.rb +5 -0
  25. data/app/models/queue_it/node.rb +68 -0
  26. data/app/models/queue_it/queue.rb +111 -0
  27. data/app/views/layouts/queue_it/application.html.erb +15 -0
  28. data/bin/rails +25 -0
  29. data/config/routes.rb +2 -0
  30. data/db/migrate/20210723140008_create_queue_it_queues.rb +10 -0
  31. data/db/migrate/20210723140434_create_queue_it_nodes.rb +12 -0
  32. data/lib/generators/queue_it/install/USAGE +5 -0
  33. data/lib/generators/queue_it/install/install_generator.rb +19 -0
  34. data/lib/generators/queue_it/install/templates/initializer.rb +2 -0
  35. data/lib/queue_it.rb +25 -0
  36. data/lib/queue_it/engine.rb +15 -0
  37. data/lib/queue_it/example_class.rb +7 -0
  38. data/lib/queue_it/version.rb +3 -0
  39. data/lib/tasks/auto_annotate_models.rake +67 -0
  40. data/lib/tasks/queue_it_tasks.rake +4 -0
  41. data/queue_it.gemspec +38 -0
  42. data/spec/concerns/queue_it/queable_spec.rb +492 -0
  43. data/spec/dummy/Rakefile +6 -0
  44. data/spec/dummy/app/assets/config/manifest.js +3 -0
  45. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  46. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  47. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  48. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  49. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  50. data/spec/dummy/app/javascript/packs/application.js +15 -0
  51. data/spec/dummy/app/jobs/application_job.rb +7 -0
  52. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  53. data/spec/dummy/app/models/application_record.rb +3 -0
  54. data/spec/dummy/app/models/task.rb +3 -0
  55. data/spec/dummy/app/models/user.rb +2 -0
  56. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  57. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  58. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  59. data/spec/dummy/bin/rails +4 -0
  60. data/spec/dummy/bin/rake +4 -0
  61. data/spec/dummy/bin/setup +33 -0
  62. data/spec/dummy/config.ru +5 -0
  63. data/spec/dummy/config/application.rb +30 -0
  64. data/spec/dummy/config/boot.rb +5 -0
  65. data/spec/dummy/config/cable.yml +10 -0
  66. data/spec/dummy/config/database.yml +27 -0
  67. data/spec/dummy/config/environment.rb +5 -0
  68. data/spec/dummy/config/environments/development.rb +81 -0
  69. data/spec/dummy/config/environments/production.rb +112 -0
  70. data/spec/dummy/config/environments/test.rb +49 -0
  71. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  72. data/spec/dummy/config/initializers/assets.rb +12 -0
  73. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  74. data/spec/dummy/config/initializers/content_security_policy.rb +28 -0
  75. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  76. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  77. data/spec/dummy/config/initializers/inflections.rb +16 -0
  78. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  79. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  80. data/spec/dummy/config/locales/en.yml +33 -0
  81. data/spec/dummy/config/puma.rb +38 -0
  82. data/spec/dummy/config/routes.rb +3 -0
  83. data/spec/dummy/config/spring.rb +6 -0
  84. data/spec/dummy/config/storage.yml +34 -0
  85. data/spec/dummy/db/migrate/20210723142357_create_users.rb +9 -0
  86. data/spec/dummy/db/migrate/20210723172002_create_tasks.rb +9 -0
  87. data/spec/dummy/db/schema.rb +52 -0
  88. data/spec/dummy/public/404.html +67 -0
  89. data/spec/dummy/public/422.html +67 -0
  90. data/spec/dummy/public/500.html +66 -0
  91. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  92. data/spec/dummy/public/apple-touch-icon.png +0 -0
  93. data/spec/dummy/public/favicon.ico +0 -0
  94. data/spec/dummy/spec/models/task_spec.rb +7 -0
  95. data/spec/dummy/spec/models/user_spec.rb +7 -0
  96. data/spec/factories/queue_it/nodes.rb +18 -0
  97. data/spec/factories/queue_it/queues.rb +26 -0
  98. data/spec/factories/tasks.rb +11 -0
  99. data/spec/factories/users.rb +5 -0
  100. data/spec/fixtures/files/image.png +0 -0
  101. data/spec/fixtures/files/video.mp4 +0 -0
  102. data/spec/models/queue_it/node_spec.rb +43 -0
  103. data/spec/models/queue_it/queue_spec.rb +116 -0
  104. data/spec/queue_it_spec.rb +16 -0
  105. data/spec/rails_helper.rb +52 -0
  106. data/spec/spec_helper.rb +9 -0
  107. data/spec/support/test_helpers.rb +5 -0
  108. metadata +441 -0
data/lib/queue_it.rb ADDED
@@ -0,0 +1,25 @@
1
+ require "queue_it/engine"
2
+
3
+ module QueueIt
4
+ extend self
5
+
6
+ # You can add, in this module, your own configuration options as in the example below...
7
+ #
8
+ # attr_writer :my_option
9
+ #
10
+ # def my_option
11
+ # return "Default Value" unless @my_option
12
+ # @my_option
13
+ # end
14
+ #
15
+ # Then, you can customize the default behaviour (typically in a Rails initializer) like this:
16
+ #
17
+ # QueueIt.setup do |config|
18
+ # config.root_url = "Another value"
19
+ # end
20
+
21
+ def setup
22
+ yield self
23
+ require "queue_it"
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ module QueueIt
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace QueueIt
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec, fixture: false
7
+ g.fixture_replacement :factory_bot, dir: "spec/factories"
8
+ end
9
+
10
+ initializer "initialize" do
11
+ # Require here all your engine's classes.
12
+ require_relative "./example_class"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module QueueIt
2
+ class ExampleClass
3
+ def self.say_hi
4
+ "Hello Platanus developer!"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module QueueIt
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,67 @@
1
+ if Rails.env.development?
2
+ task :set_annotation_options do
3
+ # You can override any of these by setting an environment variable of the
4
+ # same name.
5
+ Annotate.set_defaults(
6
+ 'routes' => 'false',
7
+ 'position_in_routes' => 'after',
8
+ 'position_in_class' => 'after',
9
+ 'position_in_test' => 'after',
10
+ 'position_in_fixture' => 'after',
11
+ 'position_in_factory' => 'after',
12
+ 'position_in_serializer' => 'after',
13
+ 'show_foreign_keys' => 'true',
14
+ 'show_indexes' => 'true',
15
+ 'simple_indexes' => 'false',
16
+ 'model_dir' => 'app/models',
17
+ 'root_dir' => '',
18
+ 'include_version' => 'false',
19
+ 'require' => '',
20
+ 'exclude_tests' => 'true',
21
+ 'exclude_fixtures' => 'true',
22
+ 'exclude_factories' => 'true',
23
+ 'exclude_serializers' => 'true',
24
+ 'exclude_scaffolds' => 'true',
25
+ 'exclude_controllers' => 'true',
26
+ 'exclude_helpers' => 'false',
27
+ 'ignore_model_sub_dir' => 'false',
28
+ 'ignore_columns' => nil,
29
+ 'ignore_unknown_models' => 'false',
30
+ 'hide_limit_column_types' => 'integer,boolean',
31
+ 'skip_on_db_migrate' => 'false',
32
+ 'format_bare' => 'true',
33
+ 'format_rdoc' => 'false',
34
+ 'format_markdown' => 'false',
35
+ 'sort' => 'false',
36
+ 'force' => 'false',
37
+ 'trace' => 'false',
38
+ 'wrapper_open' => nil,
39
+ 'wrapper_close' => nil,
40
+ 'models' => true
41
+ )
42
+ end
43
+
44
+ Annotate.load_tasks
45
+
46
+ data_migrate_tasks = %w(
47
+ db:migrate
48
+ db:migrate:up
49
+ db:migrate:down
50
+ db:migrate:redo
51
+ db:rollback
52
+ )
53
+
54
+ data_migrate_tasks.each do |task|
55
+ Rake::Task[task].enhance do
56
+ Rake::Task[Rake.application.top_level_tasks.last].enhance do
57
+ annotation_options_task = if Rake::Task.task_defined?('app:set_annotation_options')
58
+ 'app:set_annotation_options'
59
+ else
60
+ 'set_annotation_options'
61
+ end
62
+ Rake::Task[annotation_options_task].invoke
63
+ Annotate::Migration.update_annotations
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :queue_it do
3
+ # # Task goes here
4
+ # end
data/queue_it.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem"s version:
4
+ require "queue_it/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = "rails-queue-it"
9
+ s.version = QueueIt::VERSION
10
+ s.authors = ["Platanus", "Gabriel Lyon"]
11
+ s.email = ["rubygems@platan.us", "gabriel@platan.us"]
12
+ s.homepage = "https://github.com/platanus/queue_it/master"
13
+ s.summary = ""
14
+ s.description = ""
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split($/).reject { |fn| fn.start_with? "spec" }
18
+ s.bindir = "exe"
19
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ s.test_files = Dir["spec/**/*"]
21
+
22
+ s.add_dependency "rails", ">= 6.0"
23
+ s.add_development_dependency "annotate", "~> 3.0"
24
+ s.add_development_dependency "bundler", "~> 2.2.15"
25
+ s.add_development_dependency "coveralls"
26
+ s.add_development_dependency "factory_bot_rails"
27
+ s.add_development_dependency "faker"
28
+ s.add_development_dependency "guard-rspec"
29
+ s.add_development_dependency "pg"
30
+ s.add_development_dependency "pry"
31
+ s.add_development_dependency "pry-rails"
32
+ s.add_development_dependency "rspec_junit_formatter"
33
+ s.add_development_dependency "rspec-rails"
34
+ s.add_development_dependency "rubocop", "~> 1.9"
35
+ s.add_development_dependency "rubocop-rails"
36
+ s.add_development_dependency "shoulda-matchers"
37
+ s.add_development_dependency "sqlite3"
38
+ end
@@ -0,0 +1,492 @@
1
+ describe 'Concerns::Queable' do
2
+ let(:task) { create(:task) }
3
+
4
+ describe '#find_or_create_queue!' do
5
+ before do
6
+ task.find_or_create_queue!
7
+ end
8
+
9
+ it { expect(task.queue).not_to be(nil) }
10
+ end
11
+
12
+ describe '#push_to_queue' do
13
+ context 'when queue is empty or not created' do
14
+ let(:nodable) { create(:user) }
15
+
16
+ before do
17
+ task.push_to_queue(nodable)
18
+ end
19
+
20
+ it 'expect queue to not be empty' do
21
+ expect(task.queue).not_to be(nil)
22
+ end
23
+
24
+ it 'expect head_node to be defined' do
25
+ expect(task.queue.head_node).not_to be(nil)
26
+ end
27
+
28
+ it "expect head_node to be 'head' kind" do
29
+ expect(task.queue.head_node.kind).to eq('head')
30
+ end
31
+ end
32
+
33
+ context 'when queue has one previous node' do
34
+ let(:first_nodable) { create(:user) }
35
+ let(:second_nodable) { create(:user) }
36
+ let(:in_head) { true }
37
+
38
+ before do
39
+ task.push_to_queue(first_nodable)
40
+ task.push_to_queue(second_nodable, in_head)
41
+ end
42
+
43
+ context 'when node addition is in head (in_head is true)' do
44
+ it "expects to add second_nodable as head and first_nodable to be kind 'tail'" do
45
+ expect(task.queue.head_node.kind).to eq('head')
46
+ expect(task.queue.tail_node.kind).to eq('tail')
47
+ end
48
+
49
+ it 'expects first_noable to have second_nodable as parent_node' do
50
+ expect(task.queue.nodes.find_by(kind: :head).nodable).to eq(second_nodable)
51
+ expect(task.queue.nodes.find_by(kind: :tail).nodable).to eq(first_nodable)
52
+ expect(task.queue.nodes.find_by(kind: :tail).parent_node.nodable).to eq(second_nodable)
53
+ end
54
+ end
55
+
56
+ context 'when node adition is in tail (in_head is false)' do
57
+ let(:in_head) { false }
58
+
59
+ it "expects to add second_nodable as kind 'tail' and first_nodable to still be head" do
60
+ expect(task.queue.head_node.kind).to eq('head')
61
+ expect(task.queue.tail_node.kind).to eq('tail')
62
+ end
63
+
64
+ it 'expects second_noable to have first_nodable as parent_node' do
65
+ expect(task.queue.nodes.find_by(kind: :head).nodable).to eq(first_nodable)
66
+ expect(task.queue.nodes.find_by(kind: :tail).nodable).to eq(second_nodable)
67
+ expect(task.queue.nodes.find_by(kind: :tail).parent_node.nodable).to eq(first_nodable)
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'when queue has more than one node' do
73
+ let(:first_nodable) { create(:user) }
74
+ let(:second_nodable) { create(:user) }
75
+ let(:third_nodable) { create(:user) }
76
+ let(:in_head) { true }
77
+
78
+ before do
79
+ task.push_to_queue(first_nodable)
80
+ task.push_to_queue(second_nodable, in_head)
81
+ task.push_to_queue(third_nodable, in_head)
82
+ end
83
+
84
+ context 'when node addition is in head (in_head is true)' do
85
+ it 'expects first_noable to have second_nodable as parent_node and second_nodable to\
86
+ have third_nodable as parent_node' do
87
+ expect(task.queue.nodes.find_by(kind: :head).nodable).to eq(third_nodable)
88
+ expect(task.queue.nodes.find_by(kind: :any).nodable).to eq(second_nodable)
89
+ expect(task.queue.nodes.find_by(kind: :any).parent_node.nodable).to eq(third_nodable)
90
+ expect(task.queue.nodes.find_by(kind: :tail).nodable).to eq(first_nodable)
91
+ expect(task.queue.nodes.find_by(kind: :tail).parent_node.nodable).to eq(second_nodable)
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ describe '#get_next_node_in_queue' do
98
+ context "when queue dosen't exist or is empty" do
99
+ it { expect(task.get_next_node_in_queue).to be(nil) }
100
+ end
101
+
102
+ context 'when queue has one node' do
103
+ let(:nodable) { create(:user) }
104
+
105
+ before { task.push_to_queue(nodable) }
106
+
107
+ it "expects to find head_node and do not change it's kind value" do
108
+ expect(task.get_next_node_in_queue.nodable).to eq(nodable)
109
+ expect(task.queue.nodes.find_by(kind: :head).nodable).to eq(nodable)
110
+ end
111
+ end
112
+
113
+ context 'when queue has two nodes' do
114
+ let(:first_nodable) { create(:user) }
115
+ let(:second_nodable) { create(:user) }
116
+ let(:in_head) { true }
117
+
118
+ before do
119
+ task.push_to_queue(first_nodable)
120
+ task.push_to_queue(second_nodable, in_head)
121
+ end
122
+
123
+ it "expects to return second_nodable node and to change node 'head' for 'tail' and reverse" do
124
+ expect(task.get_next_node_in_queue.nodable).to eq(second_nodable)
125
+ expect(task.queue.nodes.find_by(kind: :head).nodable).to eq(first_nodable)
126
+ expect(task.queue.nodes.find_by(kind: :tail).nodable).to eq(second_nodable)
127
+ end
128
+ end
129
+
130
+ context 'when queue is generic (has more than two nodes)' do
131
+ let(:first_nodable) { create(:user) }
132
+ let(:second_nodable) { create(:user) }
133
+ let(:third_nodable) { create(:user) }
134
+ let(:in_head) { true }
135
+
136
+ before do
137
+ task.push_to_queue(first_nodable)
138
+ task.push_to_queue(second_nodable, in_head)
139
+ task.push_to_queue(third_nodable, in_head)
140
+ end
141
+
142
+ it "expects to get third nodable and to correctly move the queue" do
143
+ expect(task.get_next_node_in_queue.nodable).to eq(third_nodable)
144
+ expect(task.queue.nodes.find_by(kind: :head).nodable).to eq(second_nodable)
145
+ expect(task.queue.nodes.find_by(kind: :any).nodable).to eq(first_nodable)
146
+ expect(task.queue.nodes.find_by(kind: :tail).nodable).to eq(third_nodable)
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '#formatted_queue' do
152
+ let(:action_to_call) { 'name' }
153
+
154
+ context "when queue dosen't exist or is empty" do
155
+ it { expect(task.formatted_queue(action_to_call)).to be(nil) }
156
+ end
157
+
158
+ context 'when queue has one node' do
159
+ let(:nodable) { create(:user) }
160
+
161
+ before { task.push_to_queue(nodable) }
162
+
163
+ it "expects to receive an array with nodable name" do
164
+ expect(task.formatted_queue(action_to_call)).to eq([nodable.name])
165
+ end
166
+ end
167
+
168
+ context 'when queue has two nodes' do
169
+ let(:first_nodable) { create(:user) }
170
+ let(:second_nodable) { create(:user) }
171
+ let(:in_head) { true }
172
+
173
+ before do
174
+ task.push_to_queue(first_nodable)
175
+ task.push_to_queue(second_nodable, in_head)
176
+ end
177
+
178
+ it "expects to receive array with second and first nodable's names" do
179
+ expect(
180
+ task.formatted_queue(action_to_call)
181
+ ).to eq([second_nodable.name, first_nodable.name])
182
+ end
183
+ end
184
+
185
+ context 'when queue is generic (has more than two nodes)' do
186
+ let(:first_nodable) { create(:user) }
187
+ let(:second_nodable) { create(:user) }
188
+ let(:third_nodable) { create(:user) }
189
+ let(:in_head) { true }
190
+
191
+ before do
192
+ task.push_to_queue(first_nodable)
193
+ task.push_to_queue(second_nodable, in_head)
194
+ task.push_to_queue(third_nodable, in_head)
195
+ end
196
+
197
+ it "expect to receive array with third, second and frist nodable's names" do
198
+ expect(
199
+ task.formatted_queue(action_to_call)
200
+ ).to eq([third_nodable.name, second_nodable.name, first_nodable.name])
201
+ end
202
+ end
203
+ end
204
+
205
+ describe '#delete_queue_nodes' do
206
+ context 'when queue is empty' do
207
+ before { task.find_or_create_queue! }
208
+
209
+ it { expect { task.delete_queue_nodes }.not_to change { task.queue.size } }
210
+ end
211
+
212
+ context 'when queue is with nodes' do
213
+ let(:nodables) { create_list(:user, 5) }
214
+
215
+ before do
216
+ nodables.each do |nodable|
217
+ task.push_to_queue(nodable)
218
+ end
219
+ end
220
+
221
+ it { expect { task.delete_queue_nodes }.to change { task.queue.size }.from(5).to(0) }
222
+ end
223
+ end
224
+
225
+ describe '#remove_from_queue' do
226
+ context "when queue dosen't exist or is empty" do
227
+ let(:nodable) { create(:user) }
228
+
229
+ it { expect(task.remove_from_queue(nodable)).to be(nil) }
230
+ end
231
+
232
+ context "when queue does not have the nodable in it" do
233
+ let(:task) { create(:task, :with_three_nodes) }
234
+ let(:nodable) { create(:user) }
235
+
236
+ it { expect(task.remove_from_queue(nodable)).to be(nil) }
237
+ end
238
+
239
+ context 'when queue has one node' do
240
+ let(:nodable) { create(:user) }
241
+
242
+ before { task.push_to_queue(nodable) }
243
+
244
+ it "expects to find and delete the nodables node" do
245
+ expect { task.remove_from_queue(nodable) }.to change { task.queue.size }.from(1).to(0)
246
+ end
247
+ end
248
+
249
+ context 'when queue has two different nodables' do
250
+ let(:first_nodable) { create(:user) }
251
+ let(:second_nodable) { create(:user) }
252
+ let(:in_head) { true }
253
+
254
+ before do
255
+ task.push_to_queue(first_nodable)
256
+ task.push_to_queue(second_nodable, in_head)
257
+ end
258
+
259
+ it "expects to delete first_nodable" do
260
+ expect do
261
+ task.remove_from_queue(first_nodable)
262
+ end.to change { task.queue.size }.from(2).to(1)
263
+ expect(task.queue.head_node.nodable).to eq(second_nodable)
264
+ end
265
+
266
+ it "expects to delete second_nodable" do
267
+ expect do
268
+ task.remove_from_queue(second_nodable)
269
+ end.to change { task.queue.size }.from(2).to(1)
270
+ expect(task.queue.head_node.nodable).to eq(first_nodable)
271
+ end
272
+
273
+ context 'when the second_nodable is added in the tail' do
274
+ let(:in_head) { false }
275
+
276
+ it "expects to delete first_nodable" do
277
+ expect do
278
+ task.remove_from_queue(first_nodable)
279
+ end.to change { task.queue.size }.from(2).to(1)
280
+ expect(task.queue.head_node.nodable).to eq(second_nodable)
281
+ end
282
+
283
+ it "expects to delete second_nodable" do
284
+ expect do
285
+ task.remove_from_queue(second_nodable)
286
+ end.to change { task.queue.size }.from(2).to(1)
287
+ expect(task.queue.head_node.nodable).to eq(first_nodable)
288
+ end
289
+ end
290
+ end
291
+
292
+ context 'when queue has two equal nodables' do
293
+ let(:nodable) { create(:user) }
294
+
295
+ before do
296
+ task.push_to_queue(nodable)
297
+ task.push_to_queue(nodable)
298
+ end
299
+
300
+ it "expects to delte both nodes from the queue" do
301
+ expect do
302
+ task.remove_from_queue(nodable)
303
+ end.to change { task.queue.size }.from(2).to(0)
304
+ end
305
+ end
306
+
307
+ context 'when queue is generic (has more than two nodes)' do
308
+ let(:first_nodable) { create(:user) }
309
+ let(:second_nodable) { create(:user) }
310
+ let(:third_nodable) { create(:user) }
311
+ let(:in_head) { true }
312
+
313
+ before do
314
+ task.push_to_queue(first_nodable)
315
+ task.push_to_queue(second_nodable, in_head)
316
+ task.push_to_queue(third_nodable, in_head)
317
+ end
318
+
319
+ it "expects to delete first_nodable's node and to have second_nodable as tail" do
320
+ expect do
321
+ task.remove_from_queue(first_nodable)
322
+ end.to change { task.queue.size }.from(3).to(2)
323
+ expect(task.queue.tail_node.nodable).to eq(second_nodable)
324
+ end
325
+
326
+ it "expects to delete second_nodable's node and to have first_nodable as tail" do
327
+ expect do
328
+ task.remove_from_queue(second_nodable)
329
+ end.to change { task.queue.size }.from(3).to(2)
330
+ expect(task.queue.tail_node.nodable).to eq(first_nodable)
331
+ end
332
+
333
+ it "expects to delete third_nodable's node and to have second_nodable as head" do
334
+ expect { task.remove_from_queue(third_nodable) }.to change { task.queue.size }.from(3).to(2)
335
+ expect(task.queue.head_node.nodable).to eq(second_nodable)
336
+ end
337
+
338
+ context 'when nodes are added in the tail' do
339
+ let(:in_head) { false }
340
+
341
+ it "expects to delete first_nodable's node and to have second_nodable as tail" do
342
+ expect do
343
+ task.remove_from_queue(first_nodable)
344
+ end.to change { task.queue.size }.from(3).to(2)
345
+ expect(task.queue.head_node.nodable).to eq(second_nodable)
346
+ end
347
+
348
+ it "expects to delete second_nodable's node and to have first_nodable as tail" do
349
+ expect do
350
+ task.remove_from_queue(second_nodable)
351
+ end.to change { task.queue.size }.from(3).to(2)
352
+ expect(task.queue.tail_node.nodable).to eq(third_nodable)
353
+ end
354
+
355
+ it "expects to delete third_nodable's node and to have second_nodable as head" do
356
+ expect do
357
+ task.remove_from_queue(third_nodable)
358
+ end.to change { task.queue.size }.from(3).to(2)
359
+ expect(task.queue.tail_node.nodable).to eq(second_nodable)
360
+ end
361
+ end
362
+ end
363
+
364
+ context 'when queue has three nodes but two nodables are the same' do
365
+ let(:first_nodable) { create(:user) }
366
+ let(:second_nodable) { create(:user) }
367
+ let(:in_head) { true }
368
+
369
+ before do
370
+ task.push_to_queue(first_nodable)
371
+ task.push_to_queue(first_nodable, in_head)
372
+ task.push_to_queue(second_nodable, in_head)
373
+ end
374
+
375
+ it "expects to delete first and second node when first_nodable is deleted" do
376
+ expect do
377
+ task.remove_from_queue(first_nodable)
378
+ end.to change { task.queue.size }.from(3).to(1)
379
+ expect(task.queue.head_node.nodable).to eq(second_nodable)
380
+ end
381
+
382
+ context 'when nodes are added in the tail' do
383
+ let(:in_head) { false }
384
+
385
+ it "expects to delete first and second node when first_nodable is deleted" do
386
+ expect do
387
+ task.remove_from_queue(first_nodable)
388
+ end.to change { task.queue.size }.from(3).to(1)
389
+ expect(task.queue.head_node.nodable).to eq(second_nodable)
390
+ end
391
+ end
392
+ end
393
+
394
+ context 'when queue has three nodes with the same nodable' do
395
+ let(:nodable) { create(:user) }
396
+ let(:in_head) { true }
397
+
398
+ before do
399
+ task.push_to_queue(nodable)
400
+ task.push_to_queue(nodable)
401
+ task.push_to_queue(nodable)
402
+ end
403
+
404
+ it "expects to delete first and second node when first_nodable is deleted" do
405
+ expect { task.remove_from_queue(nodable) }.to change { task.queue.size }.from(3).to(0)
406
+ end
407
+ end
408
+
409
+ context 'when queue has lenght 5', focus: true do
410
+ let(:first_nodable) { create(:user) }
411
+ let(:second_nodable) { create(:user) }
412
+ let(:third_nodable) { create(:user) }
413
+ let(:fourth_nodable) { create(:user) }
414
+ let(:fifth_nodable) { create(:user) }
415
+ let(:in_head) { true }
416
+
417
+ before do
418
+ task.push_to_queue(first_nodable)
419
+ task.push_to_queue(second_nodable, in_head)
420
+ task.push_to_queue(third_nodable, in_head)
421
+ task.push_to_queue(fourth_nodable, in_head)
422
+ task.push_to_queue(fifth_nodable, in_head)
423
+ end
424
+
425
+ RSpec.shared_examples "properly_removed" do
426
+ it "expects not to raise an error and to properly delete de nodable's node" do
427
+ expect { task.remove_from_queue(nodable_to_remove) }.to change {
428
+ task.queue.size
429
+ }.from(5).to(4)
430
+ end
431
+ end
432
+
433
+ context 'when removing the the head_node of the queue (fifth_nodable)' do
434
+ let(:nodable_to_remove) { fifth_nodable }
435
+
436
+ include_examples 'properly_removed'
437
+
438
+ it "expects head_node to have third_nodable as child_node" do
439
+ task.remove_from_queue(fifth_nodable)
440
+ expect(task.queue.head_node.nodable).to eq(fourth_nodable)
441
+ expect(task.queue.head_node.child_node.nodable).to eq(third_nodable)
442
+ end
443
+ end
444
+
445
+ context 'when removing the second nodable of the queue (fourth_nodable)' do
446
+ let(:nodable_to_remove) { fourth_nodable }
447
+
448
+ include_examples 'properly_removed'
449
+
450
+ it "expects head_node to have third_nodable as child_node" do
451
+ task.remove_from_queue(fourth_nodable)
452
+ expect(task.queue.head_node.child_node.nodable).to eq(third_nodable)
453
+ end
454
+ end
455
+
456
+ context 'when removing the third nodable of the queue (third_nodable)' do
457
+ let(:nodable_to_remove) { third_nodable }
458
+
459
+ include_examples 'properly_removed'
460
+
461
+ it "expects fourth_nodable to have second_nodable as child_node" do
462
+ task.remove_from_queue(third_nodable)
463
+ expect(task.queue.head_node.child_node.nodable).to eq(fourth_nodable)
464
+ expect(task.queue.head_node.child_node.child_node.nodable).to eq(second_nodable)
465
+ end
466
+ end
467
+
468
+ context 'when removing the penultimaten (second_nodable)' do
469
+ let(:nodable_to_remove) { second_nodable }
470
+
471
+ include_examples 'properly_removed'
472
+
473
+ it "expects tail_node to have third_nodable as parent_node" do
474
+ task.remove_from_queue(second_nodable)
475
+ expect(task.queue.tail_node.parent_node.nodable).to eq(third_nodable)
476
+ end
477
+ end
478
+
479
+ context 'when removing the tail_node (first_nodable)' do
480
+ let(:nodable_to_remove) { first_nodable }
481
+
482
+ include_examples 'properly_removed'
483
+
484
+ it "expects tail_node to have third_nodable as parent_node" do
485
+ task.remove_from_queue(first_nodable)
486
+ expect(task.queue.tail_node.nodable).to eq(second_nodable)
487
+ expect(task.queue.tail_node.parent_node.nodable).to eq(third_nodable)
488
+ end
489
+ end
490
+ end
491
+ end
492
+ end