ardb 0.26.0 → 0.27.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 (43) hide show
  1. data/ardb.gemspec +1 -0
  2. data/bin/ardb +1 -1
  3. data/lib/ardb.rb +1 -1
  4. data/lib/ardb/adapter/base.rb +73 -66
  5. data/lib/ardb/adapter/sqlite.rb +1 -1
  6. data/lib/ardb/adapter_spy.rb +18 -5
  7. data/lib/ardb/cli.rb +239 -76
  8. data/lib/ardb/clirb.rb +58 -0
  9. data/lib/ardb/default_order_by.rb +59 -0
  10. data/lib/ardb/has_slug.rb +7 -6
  11. data/lib/ardb/migration.rb +42 -0
  12. data/lib/ardb/migration_helpers.rb +56 -53
  13. data/lib/ardb/record_spy.rb +5 -5
  14. data/lib/ardb/relation_spy.rb +13 -2
  15. data/lib/ardb/root_path.rb +7 -4
  16. data/lib/ardb/test_helpers.rb +56 -42
  17. data/lib/ardb/use_db_default.rb +8 -7
  18. data/lib/ardb/version.rb +1 -1
  19. data/test/support/factory.rb +5 -0
  20. data/test/unit/adapter/base_tests.rb +22 -5
  21. data/test/unit/adapter/mysql_tests.rb +1 -1
  22. data/test/unit/adapter/sqlite_tests.rb +2 -2
  23. data/test/unit/adapter_spy_tests.rb +19 -6
  24. data/test/unit/cli_tests.rb +610 -0
  25. data/test/unit/default_order_by_tests.rb +122 -0
  26. data/test/unit/has_slug_tests.rb +5 -0
  27. data/test/unit/migration_tests.rb +88 -0
  28. data/test/unit/record_spy_tests.rb +6 -0
  29. data/test/unit/test_helpers_tests.rb +26 -3
  30. data/test/unit/use_db_default_tests.rb +5 -0
  31. metadata +31 -25
  32. data/lib/ardb/runner.rb +0 -50
  33. data/lib/ardb/runner/connect_command.rb +0 -20
  34. data/lib/ardb/runner/create_command.rb +0 -25
  35. data/lib/ardb/runner/drop_command.rb +0 -25
  36. data/lib/ardb/runner/generate_command.rb +0 -64
  37. data/lib/ardb/runner/migrate_command.rb +0 -28
  38. data/test/unit/runner/connect_command_tests.rb +0 -17
  39. data/test/unit/runner/create_command_tests.rb +0 -67
  40. data/test/unit/runner/drop_command_tests.rb +0 -68
  41. data/test/unit/runner/generate_command_tests.rb +0 -46
  42. data/test/unit/runner/migrate_command_tests.rb +0 -96
  43. data/test/unit/runner_tests.rb +0 -69
@@ -1,17 +1,18 @@
1
+ require 'much-plugin'
2
+
1
3
  module Ardb
2
4
 
3
5
  module UseDbDefault
6
+ include MuchPlugin
4
7
 
5
- def self.included(klass)
6
- klass.class_eval do
7
- extend ClassMethods
8
- include InstanceMethods
8
+ plugin_included do
9
+ extend ClassMethods
10
+ include InstanceMethods
9
11
 
10
- @ardb_use_db_default_attrs = []
12
+ @ardb_use_db_default_attrs = []
11
13
 
12
- around_create :ardb_allow_db_to_default_attrs
14
+ around_create :ardb_allow_db_to_default_attrs
13
15
 
14
- end
15
16
  end
16
17
 
17
18
  module ClassMethods
@@ -1,3 +1,3 @@
1
1
  module Ardb
2
- VERSION = "0.26.0"
2
+ VERSION = "0.27.0"
3
3
  end
@@ -3,4 +3,9 @@ require 'assert/factory'
3
3
  module Factory
4
4
  extend Assert::Factory
5
5
 
6
+ def self.migration_id
7
+ # identifiers need to be plural b/c af activesupport's pluralize
8
+ "#{Factory.string}_things"
9
+ end
10
+
6
11
  end
@@ -13,7 +13,7 @@ class Ardb::Adapter::Base
13
13
  should have_readers :config_settings, :database
14
14
  should have_readers :ruby_schema_path, :sql_schema_path
15
15
  should have_imeths :foreign_key_add_sql, :foreign_key_drop_sql
16
- should have_imeths :create_db, :drop_db, :migrate_db
16
+ should have_imeths :create_db, :drop_db, :connect_db, :migrate_db
17
17
  should have_imeths :load_schema, :load_ruby_schema, :load_sql_schema
18
18
  should have_imeths :dump_schema, :dump_ruby_schema, :dump_sql_schema
19
19
 
@@ -51,6 +51,23 @@ class Ardb::Adapter::Base
51
51
 
52
52
  end
53
53
 
54
+ class ConnectDbTests < UnitTests
55
+ desc "`connect_db`"
56
+ setup do
57
+ @ar_base_conn_called = false
58
+ Assert.stub(ActiveRecord::Base, :connection) do |*args|
59
+ @ar_base_conn_called = true
60
+ end
61
+
62
+ @adapter.connect_db
63
+ end
64
+
65
+ should "call activerecord base's connection method" do
66
+ assert_true @ar_base_conn_called
67
+ end
68
+
69
+ end
70
+
54
71
  class MigrateDbTests < UnitTests
55
72
  desc "`migrate_db`"
56
73
  setup do
@@ -65,22 +82,22 @@ class Ardb::Adapter::Base
65
82
  @adapter.migrate_db
66
83
  end
67
84
 
68
- should "add the Ardb MigrationHelper Recorder to the ActiveRecord Command Recorder" do
85
+ should "add the ardb migration helper recorder to activerecord's command recorder" do
69
86
  exp = Ardb::MigrationHelpers::RecorderMixin
70
87
  assert_includes exp, ActiveRecord::Migration::CommandRecorder
71
88
  end
72
89
 
73
- should "set the ActiveRecord Migrator's migrations path" do
90
+ should "set the activerecord migrator's migrations path" do
74
91
  exp = Ardb.config.migrations_path
75
92
  assert_equal exp, ActiveRecord::Migrator.migrations_path
76
93
  end
77
94
 
78
- should "set the ActiveRecord Migration's verbose" do
95
+ should "set the activerecord migration's verbose attr" do
79
96
  exp = ENV["MIGRATE_QUIET"].nil?
80
97
  assert_equal exp, ActiveRecord::Migration.verbose
81
98
  end
82
99
 
83
- should "call the ActiveRecord Migrator's migrate" do
100
+ should "call the activerecord migrator's migrate method" do
84
101
  version = ENV.key?("MIGRATE_VERSION") ? ENV["MIGRATE_VERSION"].to_i : nil
85
102
  exp = [Ardb.config.migrations_path, version]
86
103
  assert_equal exp, @migrator_called_with
@@ -8,7 +8,7 @@ class Ardb::Adapter::Mysql
8
8
  setup do
9
9
  @adapter = Ardb::Adapter::Mysql.new
10
10
  end
11
- subject { @adapter }
11
+ subject{ @adapter }
12
12
 
13
13
  should "know its foreign key add sql" do
14
14
  exp_add_sql = "ALTER TABLE :from_table"\
@@ -8,14 +8,14 @@ class Ardb::Adapter::Sqlite
8
8
  setup do
9
9
  @adapter = Ardb::Adapter::Sqlite.new
10
10
  end
11
- subject { @adapter }
11
+ subject{ @adapter }
12
12
 
13
13
  should have_imeths :db_file_path, :validate!
14
14
 
15
15
  should "complain if the db file already exists" do
16
16
  FileUtils.mkdir_p(File.dirname(subject.db_file_path))
17
17
  FileUtils.touch(subject.db_file_path)
18
- assert_raises(Ardb::Runner::CmdError) { subject.validate! }
18
+ assert_raises(RuntimeError){ subject.validate! }
19
19
  FileUtils.rm(subject.db_file_path)
20
20
  end
21
21
 
@@ -1,11 +1,9 @@
1
1
  require 'assert'
2
2
  require 'ardb/adapter_spy'
3
3
 
4
- module Ardb::AdapterSpy
4
+ require 'much-plugin'
5
5
 
6
- class MyAdapter
7
- include Ardb::AdapterSpy
8
- end
6
+ module Ardb::AdapterSpy
9
7
 
10
8
  class UnitTests < Assert::Context
11
9
  desc "Ardb::AdapterSpy"
@@ -17,15 +15,20 @@ module Ardb::AdapterSpy
17
15
  should have_accessors :drop_tables_called_count
18
16
  should have_accessors :dump_schema_called_count, :load_schema_called_count
19
17
  should have_accessors :drop_db_called_count, :create_db_called_count
20
- should have_accessors :migrate_db_called_count
18
+ should have_accessors :connect_db_called_count, :migrate_db_called_count
21
19
  should have_imeths :drop_tables_called?, :drop_tables
22
20
  should have_imeths :dump_schema_called?, :dump_schema
23
21
  should have_imeths :load_schema_called?, :load_schema
24
22
  should have_imeths :drop_db_called?, :drop_db
25
23
  should have_imeths :create_db_called?, :create_db
24
+ should have_imeths :connect_db_called?, :connect_db
26
25
  should have_imeths :migrate_db_called?, :migrate_db
27
26
 
28
- should "included the record spy instance methods" do
27
+ should "use much-plugin" do
28
+ assert_includes MuchPlugin, Ardb::AdapterSpy
29
+ end
30
+
31
+ should "included the adapter spy instance methods" do
29
32
  assert_includes Ardb::AdapterSpy::InstanceMethods, subject.class
30
33
  end
31
34
 
@@ -35,6 +38,7 @@ module Ardb::AdapterSpy
35
38
  assert_equal 0, subject.load_schema_called_count
36
39
  assert_equal 0, subject.drop_db_called_count
37
40
  assert_equal 0, subject.create_db_called_count
41
+ assert_equal 0, subject.connect_db_called_count
38
42
  assert_equal 0, subject.migrate_db_called_count
39
43
  end
40
44
 
@@ -68,6 +72,11 @@ module Ardb::AdapterSpy
68
72
  subject.migrate_db
69
73
  assert_equal 1, subject.migrate_db_called_count
70
74
  assert_equal true, subject.migrate_db_called?
75
+
76
+ assert_equal false, subject.connect_db_called?
77
+ subject.connect_db
78
+ assert_equal 1, subject.connect_db_called_count
79
+ assert_equal true, subject.connect_db_called?
71
80
  end
72
81
 
73
82
  end
@@ -90,4 +99,8 @@ module Ardb::AdapterSpy
90
99
 
91
100
  end
92
101
 
102
+ class MyAdapter
103
+ include Ardb::AdapterSpy
104
+ end
105
+
93
106
  end
@@ -0,0 +1,610 @@
1
+ require 'assert'
2
+ require 'ardb/cli'
3
+
4
+ require 'ardb/adapter_spy'
5
+ require 'ardb/migration'
6
+
7
+ class Ardb::CLI
8
+
9
+ class UnitTests < Assert::Context
10
+ desc "Ardb::CLI"
11
+ setup do
12
+ @kernel_spy = KernelSpy.new
13
+ @stdout = IOSpy.new
14
+ @stderr = IOSpy.new
15
+
16
+ @cli_class = Ardb::CLI
17
+ end
18
+ subject{ @cli_class }
19
+
20
+ should have_imeths :run
21
+
22
+ should "build and run an instance of itself using `run`" do
23
+ cli_spy = CLISpy.new
24
+ Assert.stub(subject, :new).with{ cli_spy }
25
+
26
+ args = [Factory.string]
27
+ subject.run(args)
28
+ assert_equal args, cli_spy.run_called_with
29
+ end
30
+
31
+ should "know its commands" do
32
+ assert_equal 5, COMMANDS.size
33
+
34
+ assert_instance_of InvalidCommand, COMMANDS[Factory.string]
35
+
36
+ assert_equal ConnectCommand, COMMANDS['connect']
37
+ assert_equal CreateCommand, COMMANDS['create']
38
+ assert_equal DropCommand, COMMANDS['drop']
39
+ assert_equal MigrateCommand, COMMANDS['migrate']
40
+ assert_equal GenerateMigrationCommand, COMMANDS['generate-migration']
41
+ end
42
+
43
+ end
44
+
45
+ class InitTests < UnitTests
46
+ desc "when init"
47
+ setup do
48
+ @cli = @cli_class.new(@kernel_spy, @stdout, @stderr)
49
+ end
50
+ subject{ @cli }
51
+
52
+ should have_imeths :run
53
+
54
+ end
55
+
56
+ class RunSetupTests < InitTests
57
+ setup do
58
+ @command_name = Factory.string
59
+ @argv = [@command_name, Factory.string]
60
+
61
+ @command_class = Class.new
62
+ COMMANDS[@command_name] = @command_class
63
+
64
+ @command_spy = CommandSpy.new
65
+ Assert.stub(@command_class, :new).with(@argv){ @command_spy }
66
+
67
+ @ardb_init_called_with = nil
68
+ Assert.stub(Ardb, :init){ |*args| @ardb_init_called_with = args }
69
+
70
+ @invalid_command = InvalidCommand.new(@command_name)
71
+ end
72
+ teardown do
73
+ COMMANDS.delete(@command_name)
74
+ end
75
+
76
+ end
77
+
78
+ class RunTests < RunSetupTests
79
+ desc "and run"
80
+ setup do
81
+ @cli.run(@argv)
82
+ end
83
+
84
+ should "push the pwd onto the load path" do
85
+ assert_includes Dir.pwd, $LOAD_PATH
86
+ end
87
+
88
+ should "init Ardb without establishing a connection" do
89
+ assert_equal [false], @ardb_init_called_with
90
+ end
91
+
92
+ should "have run the command" do
93
+ assert_true @command_spy.run_called
94
+ end
95
+
96
+ should "have successfully exited" do
97
+ assert_equal 0, @kernel_spy.exit_status
98
+ end
99
+
100
+ end
101
+
102
+ class RunWithNoArgsTests < RunSetupTests
103
+ desc "and run with no args"
104
+ setup do
105
+ @cli.run([])
106
+ end
107
+
108
+ should "output the invalid command's help" do
109
+ assert_equal @invalid_command.help, @stdout.read
110
+ assert_empty @stderr.read
111
+ end
112
+
113
+ should "have successfully exited" do
114
+ assert_equal 0, @kernel_spy.exit_status
115
+ end
116
+
117
+ end
118
+
119
+ class RunWithInvalidCommandTests < RunSetupTests
120
+ desc "and run with an invalid command"
121
+ setup do
122
+ @name = Factory.string
123
+ @argv.unshift(@name)
124
+ @cli.run(@argv)
125
+ end
126
+
127
+ should "output that it is invalid and output the invalid command's help" do
128
+ exp = "'#{@name}' is not a command.\n\n"
129
+ assert_equal exp, @stderr.read
130
+ assert_equal @invalid_command.help, @stdout.read
131
+ end
132
+
133
+ should "have unsuccessfully exited" do
134
+ assert_equal 1, @kernel_spy.exit_status
135
+ end
136
+
137
+ end
138
+
139
+ class RunWithCommandExitErrorTests < RunSetupTests
140
+ desc "and run with a command that error exits"
141
+ setup do
142
+ Assert.stub(@command_spy, :run){ raise CommandExitError }
143
+ @cli.run(@argv)
144
+ end
145
+
146
+ should "have unsuccessfully exited with no stderr output" do
147
+ assert_equal 1, @kernel_spy.exit_status
148
+ assert_empty @stderr.read
149
+ end
150
+
151
+ end
152
+
153
+ class RunWithHelpTests < RunSetupTests
154
+ desc "and run with the help switch"
155
+ setup do
156
+ @cli.run([ '--help' ])
157
+ end
158
+
159
+ should "output the invalid command's help" do
160
+ assert_equal @invalid_command.help, @stdout.read
161
+ assert_empty @stderr.read
162
+ end
163
+
164
+ should "have successfully exited" do
165
+ assert_equal 0, @kernel_spy.exit_status
166
+ end
167
+
168
+ end
169
+
170
+ class RunWithVersionTests < RunSetupTests
171
+ desc "and run with the version switch"
172
+ setup do
173
+ @cli.run([ '--version' ])
174
+ end
175
+
176
+ should "output its version" do
177
+ assert_equal "#{Ardb::VERSION}\n", @stdout.read
178
+ assert_empty @stderr.read
179
+ end
180
+
181
+ should "have successfully exited" do
182
+ assert_equal 0, @kernel_spy.exit_status
183
+ end
184
+
185
+ end
186
+
187
+ class RunWithErrorTests < RunSetupTests
188
+ setup do
189
+ @exception = RuntimeError.new(Factory.string)
190
+ Assert.stub(@command_class, :new).with(@argv){ raise @exception }
191
+ @cli.run(@argv)
192
+ end
193
+
194
+ should "have output an error message" do
195
+ exp = "#{@exception.class}: #{@exception.message}\n" \
196
+ "#{@exception.backtrace.join("\n")}\n"
197
+ assert_equal exp, @stderr.read
198
+ assert_empty @stdout.read
199
+ end
200
+
201
+ should "have unsuccessfully exited" do
202
+ assert_equal 1, @kernel_spy.exit_status
203
+ end
204
+
205
+ end
206
+
207
+ class InvalidCommandTests < UnitTests
208
+ desc "InvalidCommand"
209
+ setup do
210
+ @name = Factory.string
211
+ @command_class = InvalidCommand
212
+ @cmd = @command_class.new(@name)
213
+ end
214
+ subject{ @cmd }
215
+
216
+ should have_readers :name, :argv, :clirb
217
+ should have_imeths :new, :run, :help
218
+
219
+ should "know its attrs" do
220
+ assert_equal @name, subject.name
221
+ assert_equal [], subject.argv
222
+
223
+ assert_instance_of Ardb::CLIRB, subject.clirb
224
+ end
225
+
226
+ should "set its argv and return itself using `new`" do
227
+ args = [Factory.string, Factory.string]
228
+ result = subject.new(args)
229
+ assert_same subject, result
230
+ assert_equal [@name, args].flatten, subject.argv
231
+ end
232
+
233
+ should "parse its argv on run`" do
234
+ assert_raises(Ardb::CLIRB::HelpExit){ subject.new(['--help']).run }
235
+ assert_raises(Ardb::CLIRB::VersionExit){ subject.new(['--version']).run }
236
+ end
237
+
238
+ should "raise a help exit if its argv is empty" do
239
+ cmd = @command_class.new([nil, ''].choice)
240
+ assert_raises(Ardb::CLIRB::HelpExit){ cmd.new([]).run }
241
+ end
242
+
243
+ should "raise an invalid command error when run" do
244
+ assert_raises(InvalidCommandError){ subject.new([Factory.string]).run }
245
+ end
246
+
247
+ should "know its help" do
248
+ exp = "Usage: ardb [COMMAND] [options]\n\n" \
249
+ "Commands: #{COMMANDS.keys.sort.join(', ')}\n" \
250
+ "Options: #{subject.clirb}"
251
+ assert_equal exp, subject.help
252
+ end
253
+
254
+ end
255
+
256
+ class ConnectCommandTests < UnitTests
257
+ desc "ConnectCommand"
258
+ setup do
259
+ @adapter_spy = Class.new{ include Ardb::AdapterSpy }.new
260
+ Assert.stub(Ardb::Adapter, Ardb.config.db.adapter.to_sym){ @adapter_spy }
261
+
262
+ @ardb_init_called = false
263
+ Assert.stub(Ardb, :init){ @ardb_init_called = true }
264
+
265
+ @command_class = ConnectCommand
266
+ @cmd = @command_class.new([], @stdout, @stderr)
267
+ end
268
+ subject{ @cmd }
269
+
270
+ should have_readers :clirb
271
+
272
+ should "know its CLI.RB" do
273
+ assert_instance_of Ardb::CLIRB, subject.clirb
274
+ end
275
+
276
+ should "know its help" do
277
+ exp = "Usage: ardb connect [options]\n\n" \
278
+ "Options: #{subject.clirb}"
279
+ assert_equal exp, subject.help
280
+ end
281
+
282
+ should "parse its args, init ardb and connect to the db on run" do
283
+ subject.run
284
+
285
+ assert_equal [], subject.clirb.args
286
+
287
+ assert_true @ardb_init_called
288
+ assert_true @adapter_spy.connect_db_called?
289
+
290
+ exp = "connected to #{Ardb.config.db.adapter} db `#{Ardb.config.db.database}`\n"
291
+ assert_equal exp, @stdout.read
292
+ end
293
+
294
+ should "output any errors and raise an exit error on run" do
295
+ err = StandardError.new(Factory.string)
296
+ err.set_backtrace(Factory.integer(3).times.map{ Factory.path })
297
+ Assert.stub(Ardb, :init){ raise err }
298
+
299
+ assert_raises(CommandExitError){ subject.run }
300
+ err_output = @stderr.read
301
+
302
+ assert_includes err.to_s, err_output
303
+ assert_includes err.backtrace.join("\n"), err_output
304
+
305
+ exp = "error connecting to #{Ardb.config.db.database.inspect} database " \
306
+ "with #{Ardb.config.db_settings.inspect}"
307
+ assert_includes exp, err_output
308
+ end
309
+
310
+ end
311
+
312
+ class CreateCommandTests < UnitTests
313
+ desc "CreateCommand"
314
+ setup do
315
+ @adapter_spy = Class.new{ include Ardb::AdapterSpy }.new
316
+ Assert.stub(Ardb::Adapter, Ardb.config.db.adapter.to_sym){ @adapter_spy }
317
+
318
+ @command_class = CreateCommand
319
+ @cmd = @command_class.new([], @stdout, @stderr)
320
+ end
321
+ subject{ @cmd }
322
+
323
+ should have_readers :clirb
324
+
325
+ should "know its CLI.RB" do
326
+ assert_instance_of Ardb::CLIRB, subject.clirb
327
+ end
328
+
329
+ should "know its help" do
330
+ exp = "Usage: ardb create [options]\n\n" \
331
+ "Options: #{subject.clirb}"
332
+ assert_equal exp, subject.help
333
+ end
334
+
335
+ should "parse its args and create the db on run" do
336
+ subject.run
337
+
338
+ assert_equal [], subject.clirb.args
339
+ assert_true @adapter_spy.create_db_called?
340
+
341
+ exp = "created #{Ardb.config.db.adapter} db `#{Ardb.config.db.database}`\n"
342
+ assert_equal exp, @stdout.read
343
+ end
344
+
345
+ should "output any errors and raise an exit error on run" do
346
+ err = StandardError.new(Factory.string)
347
+ Assert.stub(@adapter_spy, :create_db){ raise err }
348
+
349
+ assert_raises(CommandExitError){ subject.run }
350
+ err_output = @stderr.read
351
+
352
+ assert_includes err.to_s, err_output
353
+ exp = "error creating #{Ardb.config.db.database.inspect} database"
354
+ assert_includes exp, err_output
355
+ end
356
+
357
+ end
358
+
359
+ class DropCommandTests < UnitTests
360
+ desc "DropCommand"
361
+ setup do
362
+ @adapter_spy = Class.new{ include Ardb::AdapterSpy }.new
363
+ Assert.stub(Ardb::Adapter, Ardb.config.db.adapter.to_sym){ @adapter_spy }
364
+
365
+ @command_class = DropCommand
366
+ @cmd = @command_class.new([], @stdout, @stderr)
367
+ end
368
+ subject{ @cmd }
369
+
370
+ should have_readers :clirb
371
+
372
+ should "know its CLI.RB" do
373
+ assert_instance_of Ardb::CLIRB, subject.clirb
374
+ end
375
+
376
+ should "know its help" do
377
+ exp = "Usage: ardb drop [options]\n\n" \
378
+ "Options: #{subject.clirb}"
379
+ assert_equal exp, subject.help
380
+ end
381
+
382
+ should "parse its args and drop the db on run" do
383
+ subject.run
384
+
385
+ assert_equal [], subject.clirb.args
386
+ assert_true @adapter_spy.drop_db_called?
387
+
388
+ exp = "dropped #{Ardb.config.db.adapter} db `#{Ardb.config.db.database}`\n"
389
+ assert_equal exp, @stdout.read
390
+ end
391
+
392
+ should "output any errors and raise an exit error on run" do
393
+ err = StandardError.new(Factory.string)
394
+ Assert.stub(@adapter_spy, :drop_db){ raise err }
395
+
396
+ assert_raises(CommandExitError){ subject.run }
397
+ err_output = @stderr.read
398
+
399
+ assert_includes err.to_s, err_output
400
+ exp = "error dropping #{Ardb.config.db.database.inspect} database"
401
+ assert_includes exp, err_output
402
+ end
403
+
404
+ end
405
+
406
+ class MigrateCommandTests < UnitTests
407
+ desc "MigrateCommand"
408
+ setup do
409
+ @adapter_spy = Class.new{ include Ardb::AdapterSpy }.new
410
+ Assert.stub(Ardb::Adapter, Ardb.config.db.adapter.to_sym){ @adapter_spy }
411
+
412
+ @ardb_init_called = false
413
+ Assert.stub(Ardb, :init){ @ardb_init_called = true }
414
+
415
+ @command_class = MigrateCommand
416
+ @cmd = @command_class.new([], @stdout, @stderr)
417
+ end
418
+ subject{ @cmd }
419
+
420
+ should have_readers :clirb
421
+
422
+ should "know its CLI.RB" do
423
+ assert_instance_of Ardb::CLIRB, subject.clirb
424
+ end
425
+
426
+ should "know its help" do
427
+ exp = "Usage: ardb migrate [options]\n\n" \
428
+ "Options: #{subject.clirb}"
429
+ assert_equal exp, subject.help
430
+ end
431
+
432
+ should "parse its args, init ardb and migrate the db, dump schema on run" do
433
+ subject.run
434
+
435
+ assert_equal [], subject.clirb.args
436
+
437
+ assert_true @ardb_init_called
438
+ assert_true @adapter_spy.migrate_db_called?
439
+ assert_true @adapter_spy.dump_schema_called?
440
+ end
441
+
442
+ should "init ardb and only migrate on run with no schema dump env var set" do
443
+ current_no_schema = ENV['ARDB_MIGRATE_NO_SCHEMA']
444
+ ENV['ARDB_MIGRATE_NO_SCHEMA'] = 'yes'
445
+ subject.run
446
+ ENV['ARDB_MIGRATE_NO_SCHEMA'] = current_no_schema
447
+
448
+ assert_true @ardb_init_called
449
+ assert_true @adapter_spy.migrate_db_called?
450
+ assert_false @adapter_spy.dump_schema_called?
451
+ end
452
+
453
+ should "output any errors and raise an exit error on run" do
454
+ err = StandardError.new(Factory.string)
455
+ err.set_backtrace(Factory.integer(3).times.map{ Factory.path })
456
+ Assert.stub(Ardb, :init){ raise err }
457
+
458
+ assert_raises(CommandExitError){ subject.run }
459
+ err_output = @stderr.read
460
+
461
+ assert_includes err.to_s, err_output
462
+ assert_includes err.backtrace.join("\n"), err_output
463
+
464
+ exp = "error migrating #{Ardb.config.db.database.inspect} database"
465
+ assert_includes exp, err_output
466
+ end
467
+
468
+ end
469
+
470
+ class GenerateMigrationCommandTests < UnitTests
471
+ desc "GenerateMigrationCommand"
472
+ setup do
473
+ @migration_spy = nil
474
+ @migration_class = Ardb::Migration
475
+ Assert.stub(@migration_class, :new) do |*args|
476
+ @migration_spy = MigrationSpy.new(*args)
477
+ end
478
+
479
+ @command_class = GenerateMigrationCommand
480
+ @identifier = Factory.migration_id
481
+ @cmd = @command_class.new([@identifier], @stdout, @stderr)
482
+ end
483
+ subject{ @cmd }
484
+
485
+ should have_readers :clirb
486
+
487
+ should "know its CLI.RB" do
488
+ assert_instance_of Ardb::CLIRB, subject.clirb
489
+ end
490
+
491
+ should "know its help" do
492
+ exp = "Usage: ardb generate-migration [options] MIGRATION-NAME\n\n" \
493
+ "Options: #{subject.clirb}"
494
+ assert_equal exp, subject.help
495
+ end
496
+
497
+ should "parse its args and save a migration for the identifier on run" do
498
+ subject.run
499
+
500
+ assert_equal [@identifier], subject.clirb.args
501
+ assert_equal @identifier, @migration_spy.identifier
502
+ assert_true @migration_spy.save_called
503
+
504
+ exp = "generated #{@migration_spy.file_path}\n"
505
+ assert_equal exp, @stdout.read
506
+ end
507
+
508
+ should "re-raise a specific argument error on migration 'no identifer' errors" do
509
+ Assert.stub(@migration_class, :new) { raise Ardb::Migration::NoIdentifierError }
510
+ err = nil
511
+ begin
512
+ cmd = @command_class.new([])
513
+ cmd.run
514
+ rescue ArgumentError => err
515
+ end
516
+
517
+ assert_not_nil err
518
+ exp = "MIGRATION-NAME must be provided"
519
+ assert_equal exp, err.message
520
+ assert_not_empty err.backtrace
521
+ end
522
+
523
+ should "output any errors and raise an exit error on run" do
524
+ err = StandardError.new(Factory.string)
525
+ err.set_backtrace(Factory.integer(3).times.map{ Factory.path })
526
+ Assert.stub(@migration_class, :new){ raise err }
527
+
528
+ assert_raises(CommandExitError){ subject.run }
529
+ err_output = @stderr.read
530
+
531
+ assert_includes err.to_s, err_output
532
+ assert_includes err.backtrace.join("\n"), err_output
533
+
534
+ exp = "error generating migration"
535
+ assert_includes exp, err_output
536
+ end
537
+
538
+ end
539
+
540
+ class CLISpy
541
+ attr_reader :run_called_with
542
+
543
+ def initialize
544
+ @run_called_with = nil
545
+ end
546
+
547
+ def run(args)
548
+ @run_called_with = args
549
+ end
550
+ end
551
+
552
+ class CommandSpy
553
+ attr_reader :run_called
554
+
555
+ def initialize
556
+ @run_called = false
557
+ end
558
+
559
+ def run
560
+ @run_called = true
561
+ end
562
+
563
+ def help
564
+ Factory.text
565
+ end
566
+ end
567
+
568
+ class KernelSpy
569
+ attr_reader :exit_status
570
+
571
+ def initialize
572
+ @exit_status = nil
573
+ end
574
+
575
+ def exit(code)
576
+ @exit_status ||= code
577
+ end
578
+ end
579
+
580
+ class IOSpy
581
+ def initialize
582
+ @io = StringIO.new
583
+ end
584
+
585
+ def puts(message)
586
+ @io.puts message
587
+ end
588
+
589
+ def read
590
+ @io.rewind
591
+ @io.read
592
+ end
593
+ end
594
+
595
+ class MigrationSpy
596
+ attr_reader :identifier, :file_path, :save_called
597
+
598
+ def initialize(*args)
599
+ @identifier = args.first
600
+ @file_path = Factory.path
601
+ @save_called = false
602
+ end
603
+
604
+ def save!
605
+ @save_called = true
606
+ self
607
+ end
608
+ end
609
+
610
+ end