rails-queue-it 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 (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