upgrow 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/lib/upgrow.rb +2 -8
  4. data/lib/upgrow/action.rb +66 -16
  5. data/lib/upgrow/actions.rb +31 -0
  6. data/lib/upgrow/active_record_adapter.rb +24 -15
  7. data/lib/upgrow/active_record_schema.rb +63 -0
  8. data/lib/upgrow/basic_model.rb +64 -0
  9. data/lib/upgrow/basic_repository.rb +49 -22
  10. data/lib/upgrow/error.rb +19 -0
  11. data/lib/upgrow/immutable_object.rb +26 -21
  12. data/lib/upgrow/input.rb +7 -0
  13. data/lib/upgrow/model.rb +12 -12
  14. data/lib/upgrow/model_schema.rb +31 -0
  15. data/lib/upgrow/repository.rb +3 -0
  16. data/lib/upgrow/result.rb +18 -55
  17. data/lib/upgrow/schema.rb +33 -0
  18. data/test/application_system_test_case.rb +11 -0
  19. data/test/dummy/app/actions/application_action.rb +10 -0
  20. data/test/dummy/app/actions/articles/create_action.rb +15 -0
  21. data/test/dummy/app/actions/articles/destroy_action.rb +9 -0
  22. data/test/dummy/app/actions/articles/edit_action.rb +12 -0
  23. data/test/dummy/app/actions/articles/index_action.rb +11 -0
  24. data/test/dummy/app/actions/articles/new_action.rb +8 -0
  25. data/test/dummy/app/actions/articles/show_action.rb +11 -0
  26. data/test/dummy/app/actions/articles/update_action.rb +15 -0
  27. data/test/dummy/app/actions/comments/create_action.rb +15 -0
  28. data/test/dummy/app/actions/comments/destroy_action.rb +9 -0
  29. data/test/dummy/app/actions/comments/new_action.rb +8 -0
  30. data/test/dummy/app/actions/sessions/create_action.rb +23 -0
  31. data/test/dummy/app/actions/sessions/destroy_action.rb +6 -0
  32. data/test/dummy/app/actions/sessions/new_action.rb +8 -0
  33. data/test/dummy/app/actions/user_action.rb +10 -0
  34. data/test/dummy/app/actions/users/create_action.rb +13 -0
  35. data/test/dummy/app/actions/users/new_action.rb +8 -0
  36. data/test/dummy/app/controllers/application_controller.rb +10 -0
  37. data/test/dummy/app/controllers/articles_controller.rb +32 -28
  38. data/test/dummy/app/controllers/comments_controller.rb +41 -0
  39. data/test/dummy/app/controllers/sessions_controller.rb +34 -0
  40. data/test/dummy/app/controllers/users_controller.rb +29 -0
  41. data/test/dummy/app/helpers/application_helper.rb +27 -3
  42. data/test/dummy/app/helpers/users_helper.rb +15 -0
  43. data/test/dummy/app/inputs/article_input.rb +3 -0
  44. data/test/dummy/app/inputs/comment_input.rb +11 -0
  45. data/test/dummy/app/inputs/session_input.rb +9 -0
  46. data/test/dummy/app/inputs/user_input.rb +9 -0
  47. data/test/dummy/app/models/article.rb +0 -2
  48. data/test/dummy/app/models/comment.rb +4 -0
  49. data/test/dummy/app/models/user.rb +4 -0
  50. data/test/dummy/app/records/article_record.rb +2 -0
  51. data/test/dummy/app/records/comment_record.rb +7 -0
  52. data/test/dummy/app/records/user_record.rb +9 -0
  53. data/test/dummy/app/repositories/article_repository.rb +26 -0
  54. data/test/dummy/app/repositories/comment_repository.rb +3 -0
  55. data/test/dummy/app/repositories/user_repository.rb +12 -0
  56. data/test/dummy/config/routes.rb +6 -1
  57. data/test/dummy/db/migrate/20210320140432_create_comments.rb +12 -0
  58. data/test/dummy/db/migrate/20210409164927_create_users.rb +22 -0
  59. data/test/dummy/db/schema.rb +24 -1
  60. data/test/system/articles_test.rb +87 -29
  61. data/test/system/comments_test.rb +81 -0
  62. data/test/system/guest_user_test.rb +14 -0
  63. data/test/system/sign_in_test.rb +57 -0
  64. data/test/system/sign_out_test.rb +19 -0
  65. data/test/system/sign_up_test.rb +38 -0
  66. data/test/test_helper.rb +6 -1
  67. data/test/upgrow/action_test.rb +101 -9
  68. data/test/upgrow/actions_test.rb +24 -0
  69. data/test/upgrow/active_record_adapter_test.rb +12 -17
  70. data/test/upgrow/active_record_schema_test.rb +92 -0
  71. data/test/upgrow/basic_model_test.rb +95 -0
  72. data/test/upgrow/basic_repository_test.rb +48 -27
  73. data/test/upgrow/immutable_object_test.rb +43 -7
  74. data/test/upgrow/input_test.rb +19 -1
  75. data/test/upgrow/model_schema_test.rb +44 -0
  76. data/test/upgrow/model_test.rb +48 -11
  77. data/test/upgrow/result_test.rb +19 -64
  78. data/test/upgrow/schema_test.rb +44 -0
  79. metadata +128 -50
  80. data/test/dummy/app/actions/create_article_action.rb +0 -13
  81. data/test/dummy/app/actions/delete_article_action.rb +0 -7
  82. data/test/dummy/app/actions/edit_article_action.rb +0 -10
  83. data/test/dummy/app/actions/list_articles_action.rb +0 -8
  84. data/test/dummy/app/actions/show_article_action.rb +0 -10
  85. data/test/dummy/app/actions/update_article_action.rb +0 -13
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class BasicModelTest < ActiveSupport::TestCase
7
+ class SampleModel < BasicModel
8
+ attribute :title
9
+ attribute :body
10
+
11
+ belongs_to :user
12
+ end
13
+
14
+ class SubSampleModel < SampleModel
15
+ has_many :tags
16
+ end
17
+
18
+ setup do
19
+ @original_schema = BasicModel.schema.dup
20
+ end
21
+
22
+ teardown do
23
+ BasicModel.schema = @original_schema
24
+ end
25
+
26
+ test '.schema includes ID by default' do
27
+ assert_equal [:id, :title, :body], SampleModel.schema.attribute_names
28
+ end
29
+
30
+ test '.schema does not have associations by default' do
31
+ assert_empty BasicModel.schema.association_names
32
+ end
33
+
34
+ test '.schema includes the Model associations' do
35
+ assert_equal [:user], SampleModel.schema.association_names
36
+ assert_equal [:user, :tags], SubSampleModel.schema.association_names
37
+ end
38
+
39
+ test '.has_many defines an association in the Schema' do
40
+ BasicModel.has_many(:comments)
41
+ assert_equal [:comments], BasicModel.schema.association_names
42
+ end
43
+
44
+ test '.belongs_to defines an association in the Schema' do
45
+ BasicModel.belongs_to(:author)
46
+ assert_equal [:author], BasicModel.schema.association_names
47
+ end
48
+
49
+ test '.new requires all attributes' do
50
+ error = assert_raises(KeyError) do
51
+ SampleModel.new(title: 'volmer', id: 1)
52
+ end
53
+
54
+ assert_equal 'key not found: :body', error.message
55
+ end
56
+
57
+ test '.new optionally accepts associations' do
58
+ model = SampleModel.new(
59
+ title: 'volmer',
60
+ body: 'My long body',
61
+ id: 1,
62
+ user: :my_user
63
+ )
64
+
65
+ assert_equal :my_user, model.user
66
+ end
67
+
68
+ test '#respond_to? is true for association readers' do
69
+ model = SubSampleModel.new(id: 1, title: 'volmer', body: 'hello')
70
+
71
+ assert model.respond_to?(:user)
72
+ assert model.respond_to?(:tags)
73
+ end
74
+
75
+ test 'association reader raises Association Not Loaded Error for an association that was not loaded' do
76
+ model = SampleModel.new(
77
+ title: 'volmer',
78
+ body: 'My long body',
79
+ id: 1,
80
+ )
81
+
82
+ assert_raises(Model::AssociationNotLoadedError) { model.user }
83
+ end
84
+
85
+ test 'attribute readers work when association is not loaded' do
86
+ model = SampleModel.new(
87
+ title: 'volmer',
88
+ body: 'My long body',
89
+ id: 1,
90
+ )
91
+
92
+ assert_equal 'volmer', model.title
93
+ end
94
+ end
95
+ end
@@ -4,36 +4,48 @@ require 'test_helper'
4
4
 
5
5
  module Upgrow
6
6
  class BasicRepositoryTest < ActiveSupport::TestCase
7
- class User < Model; end
7
+ class User < BasicModel; end
8
+
9
+ class Car < BasicModel
10
+ attribute :wheels
11
+ end
8
12
 
9
13
  class UserRepository < BasicRepository; end
10
14
 
11
15
  class NoModelRepository < BasicRepository; end
12
16
 
13
17
  setup do
14
- freeze_time
15
-
18
+ @original_base = UserRepository.base
19
+ @original_model_class = UserRepository.model_class
16
20
  @repository = UserRepository.new
17
21
  end
18
22
 
19
- test '.new instantiates a new Repository with a base and a Model class' do
20
- repository = UserRepository.new(base: :my_base, model_class: User)
23
+ teardown do
24
+ UserRepository.base = @original_base
25
+ UserRepository.model_class = @original_model_class
26
+ end
27
+
28
+ test '.base is nil by default' do
29
+ assert_nil UserRepository.base
30
+ end
21
31
 
22
- assert_equal :my_base, repository.base
23
- assert_equal User, repository.model_class
32
+ test '.base can be set' do
33
+ UserRepository.base = :my_base
34
+ assert_equal :my_base, UserRepository.base
24
35
  end
25
36
 
26
- test '.new sets the base to nil by default' do
27
- assert_nil @repository.base
37
+ test '.model_class is iferred based on the Repository name' do
38
+ assert_equal User, UserRepository.model_class
28
39
  end
29
40
 
30
- test '.new sets the Model class by default to a constant derived from the Repository name' do
31
- assert_equal User, @repository.model_class
41
+ test '.model_class can be set' do
42
+ UserRepository.model_class = :my_model_class
43
+ assert_equal :my_model_class, UserRepository.model_class
32
44
  end
33
45
 
34
- test '.new raises a Name Error if the Model class is undefined' do
46
+ test '.model_class raises a Name Error if the Model class is undefined' do
35
47
  error = assert_raises(NameError) do
36
- NoModelRepository.new(base: :my_base)
48
+ NoModelRepository.model_class
37
49
  end
38
50
 
39
51
  assert_includes(
@@ -42,32 +54,41 @@ module Upgrow
42
54
  )
43
55
  end
44
56
 
45
- test '.to_model returns a new Model with the given attributes as keyword arguments' do
46
- model = @repository.to_model(
47
- id: 1, created_at: Time.now, updated_at: Time.now
48
- )
57
+ test '#base is inferred from the Repository class base' do
58
+ UserRepository.base = :my_base
59
+ assert_equal :my_base, UserRepository.new.base
60
+ end
61
+
62
+ test '#model_class is inferred from the Repository class Model class' do
63
+ UserRepository.model_class = :my_model_class
64
+ assert_equal :my_model_class, UserRepository.new.model_class
65
+ end
66
+
67
+ test '#to_model returns a new Model with the given attributes as keyword arguments' do
68
+ model = @repository.to_model(id: 1)
69
+
70
+ assert_equal 1, model.id
71
+ end
72
+
73
+ test '#to_model accepts a Model class explicitly' do
74
+ model = @repository.to_model(Car, id: 1, wheels: 4)
49
75
 
50
76
  assert_equal 1, model.id
51
- assert_equal Time.now, model.created_at
52
- assert_equal Time.now, model.updated_at
77
+ assert_equal 4, model.wheels
53
78
  end
54
79
 
55
- test '.to_model accepts a Hash of Symbols' do
56
- args = { id: 1, created_at: Time.now, updated_at: Time.now }
80
+ test '#to_model accepts a Hash of Symbols' do
81
+ args = { id: 1 }
57
82
  model = @repository.to_model(args)
58
83
 
59
84
  assert_equal 1, model.id
60
- assert_equal Time.now, model.created_at
61
- assert_equal Time.now, model.updated_at
62
85
  end
63
86
 
64
- test '.to_model accepts a Hash of Strings' do
65
- args = { 'id' => 1, 'created_at' => Time.now, 'updated_at' => Time.now }
87
+ test '#to_model accepts a Hash of Strings' do
88
+ args = { 'id' => 1 }
66
89
  model = @repository.to_model(args)
67
90
 
68
91
  assert_equal 1, model.id
69
- assert_equal Time.now, model.created_at
70
- assert_equal Time.now, model.updated_at
71
92
  end
72
93
  end
73
94
  end
@@ -13,12 +13,26 @@ module Upgrow
13
13
  attribute :name
14
14
  end
15
15
 
16
- test '.attribute_names is empty by default' do
17
- assert_empty ImmutableObject.attribute_names
16
+ setup do
17
+ @original_schema = Sample.schema
18
18
  end
19
19
 
20
- test '.attribute_names returns a list of attribute names' do
21
- assert_equal [:title, :body, :name], SubSample.attribute_names
20
+ teardown do
21
+ Sample.schema = @original_schema
22
+ end
23
+
24
+ test '.schema is empty by default' do
25
+ assert_empty ImmutableObject.schema.attribute_names
26
+ end
27
+
28
+ test '.schema can be set' do
29
+ Sample.schema = :my_schema
30
+
31
+ assert_equal :my_schema, Sample.schema
32
+ end
33
+
34
+ test '.schema contains all declared attributes' do
35
+ assert_equal [:title, :body, :name], SubSample.schema.attribute_names
22
36
  end
23
37
 
24
38
  test '.new creates a frozen instance with the given attributes' do
@@ -29,7 +43,7 @@ module Upgrow
29
43
  assert sample.frozen?
30
44
  end
31
45
 
32
- test 'it does not allow members to be mutated' do
46
+ test 'it does not allow attributes to be mutated' do
33
47
  sample = Sample.new(title: 'volmer', body: 'hello')
34
48
 
35
49
  refute sample.respond_to?(:title=)
@@ -44,17 +58,39 @@ module Upgrow
44
58
  assert_equal 'Unknown attribute [:fake]', error.message
45
59
  end
46
60
 
47
- test '.new requires inherited attributes' do
61
+ test '.new allows inherited attributes' do
48
62
  sub_sample = SubSample.new(title: 'volmer', body: 'hello', name: 'rafael')
49
63
  assert_equal 'volmer', sub_sample.title
50
64
  assert_equal 'hello', sub_sample.body
51
65
  assert_equal 'rafael', sub_sample.name
52
66
  end
53
67
 
54
- test '#attributes returns the collection of attributes' do
68
+ test '.new allows omitting attributes' do
69
+ sub_sample = SubSample.new(title: 'volmer')
70
+ assert_equal 'volmer', sub_sample.title
71
+ assert_nil sub_sample.body
72
+ assert_nil sub_sample.name
73
+ end
74
+
75
+ test '#respond_to? is true for all attribute readers' do
76
+ sub_sample = SubSample.new(title: 'volmer')
77
+
78
+ assert sub_sample.respond_to?(:title)
79
+ assert sub_sample.respond_to?(:body)
80
+ assert sub_sample.respond_to?(:name)
81
+ end
82
+
83
+ test '#attributes returns the collection of frozen attributes' do
55
84
  sample = Sample.new(title: 'volmer', body: 'hello')
56
85
 
57
86
  assert_equal({ title: 'volmer', body: 'hello' }, sample.attributes)
87
+ assert sample.attributes.frozen?
88
+ end
89
+
90
+ test '#attributes returns attributes that were omitted' do
91
+ sample = Sample.new
92
+
93
+ assert_equal({ title: nil, body: nil }, sample.attributes)
58
94
  end
59
95
  end
60
96
  end
@@ -12,7 +12,7 @@ module Upgrow
12
12
  validates :title, presence: true
13
13
  end
14
14
 
15
- test '#errors is an empty Active Model Errors' do
15
+ test '#errors is empty' do
16
16
  input = Input.new
17
17
  errors = input.errors
18
18
  assert_empty errors
@@ -61,5 +61,23 @@ module Upgrow
61
61
  input = SampleInput.new
62
62
  refute_predicate input, :valid?
63
63
  end
64
+
65
+ test '#errors is empty when validation is successful' do
66
+ input = SampleInput.new(title: 'volmer')
67
+ assert_predicate input, :valid?
68
+ assert_empty input.errors
69
+ end
70
+
71
+ test '#errors is populated when validation fails' do
72
+ input = SampleInput.new
73
+ refute_predicate input, :valid?
74
+ assert_predicate input.errors, :one?
75
+
76
+ error = input.errors.first
77
+
78
+ assert_equal :title, error.attribute
79
+ assert_equal :blank, error.type
80
+ assert_equal "Title can't be blank", error.full_message
81
+ end
64
82
  end
65
83
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class ModelSchemaTest < ActiveSupport::TestCase
7
+ setup do
8
+ @schema = ModelSchema.new
9
+ end
10
+
11
+ test '#association_names is empty by default' do
12
+ assert_empty @schema.attribute_names
13
+ end
14
+
15
+ test '#association_names returns the defined associations' do
16
+ @schema.association(:user)
17
+ @schema.association(:tags)
18
+
19
+ assert_equal [:user, :tags], @schema.association_names
20
+ end
21
+
22
+ test '#association defines an association' do
23
+ @schema.association(:user)
24
+
25
+ assert_equal [:user], @schema.association_names
26
+ end
27
+
28
+ test '#association does not define the same association twice' do
29
+ @schema.association(:user)
30
+ @schema.association(:user)
31
+
32
+ assert_equal [:user], @schema.association_names
33
+ end
34
+
35
+ test '#dup creates a Schema with independent association names' do
36
+ @schema.association(:user)
37
+ new_schema = @schema.dup
38
+ new_schema.association(:tags)
39
+
40
+ assert_equal [:user], @schema.association_names
41
+ assert_equal [:user, :tags], new_schema.association_names
42
+ end
43
+ end
44
+ end
@@ -2,26 +2,63 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
+ require 'upgrow/model'
6
+
5
7
  module Upgrow
6
8
  class ModelTest < ActiveSupport::TestCase
7
9
  class SampleModel < Model
8
- attribute :title
9
- attribute :body
10
10
  end
11
11
 
12
- test '.attribute_names includes :id, :created_at, and :updated_at' do
13
- expected = [:id, :created_at, :updated_at, :title, :body]
14
- assert_equal expected, SampleModel.attribute_names
12
+ class SubSampleModel < SampleModel
13
+ end
14
+
15
+ class SampleModelWithAttribute < Model
16
+ attribute :phone
17
+ end
18
+
19
+ class SampleModelRecord
20
+ def self.attribute_names
21
+ ['id', 'name']
22
+ end
23
+ end
24
+
25
+ class SubSampleModelRecord
26
+ def self.attribute_names
27
+ ['email']
28
+ end
29
+ end
30
+
31
+ class SampleModelWithAttributeRecord
32
+ def self.attribute_names
33
+ ['id']
34
+ end
35
+ end
36
+
37
+ class OrphanedModel < Model
38
+ end
39
+
40
+ test '.schema is inferred from the Active Record with the Model name' do
41
+ assert_equal [:id, :name], SampleModel.schema.attribute_names
42
+ end
43
+
44
+ test '.schema is populated with inherited attributes' do
45
+ assert_equal [:email, :id, :name], SubSampleModel.schema.attribute_names
46
+ end
47
+
48
+ test '.schema includes explicit attributes as well as Active Record attributes' do
49
+ assert_equal [:id, :phone],
50
+ SampleModelWithAttribute.schema.attribute_names
15
51
  end
16
52
 
17
- test '.new requires all attributes' do
18
- error = assert_raises(KeyError) do
19
- SampleModel.new(
20
- title: 'volmer', id: 1, created_at: Time.now, updated_at: Time.now
21
- )
53
+ test '.new raises a Name Error if the Record class is undefined' do
54
+ error = assert_raises(NameError) do
55
+ OrphanedModel.new
22
56
  end
23
57
 
24
- assert_equal 'key not found: :body', error.message
58
+ assert_includes(
59
+ error.message,
60
+ 'uninitialized constant Upgrow::ModelTest::OrphanedModelRecord'
61
+ )
25
62
  end
26
63
  end
27
64
  end