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
@@ -1,6 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Article < Upgrow::Model
4
- attribute :title
5
- attribute :body
6
4
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Comment < Upgrow::Model
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class User < Upgrow::Model
4
+ end
@@ -2,4 +2,6 @@
2
2
 
3
3
  class ArticleRecord < ApplicationRecord
4
4
  self.table_name = 'articles'
5
+ has_many :comment_records, foreign_key: :article_id, dependent: :destroy
6
+ belongs_to :user_record, foreign_key: :user_id
5
7
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CommentRecord < ApplicationRecord
4
+ self.table_name = 'comments'
5
+ belongs_to :user_record, foreign_key: :user_id
6
+ belongs_to :article_record, foreign_key: :article_id
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ class UserRecord < ApplicationRecord
3
+ self.table_name = 'users'
4
+
5
+ has_secure_password
6
+
7
+ has_many :article_records, foreign_key: :user_id, dependent: :destroy
8
+ has_many :comment_records, foreign_key: :user_id, dependent: :destroy
9
+ end
@@ -1,4 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ArticleRepository < Upgrow::Repository
4
+ def all
5
+ base.all.includes(:user_record).map do |record|
6
+ user = to_model(User, record.user_record.attributes)
7
+ to_model(record.attributes.merge(user: user))
8
+ end
9
+ end
10
+
11
+ def find_with_comments(id)
12
+ record = ArticleRecord.find(id)
13
+
14
+ comment_records = record.comment_records.includes(:user_record)
15
+
16
+ comments = comment_records.map do |comment_record|
17
+ user = to_model(User, comment_record.user_record.attributes)
18
+ to_model(Comment, comment_record.attributes.merge(user: user))
19
+ end
20
+
21
+ user = to_model(User, record.user_record.attributes)
22
+
23
+ to_model(record.attributes.merge(comments: comments, user: user))
24
+ end
25
+
26
+ def find_for_user(id, user:)
27
+ record = base.find_by(id: id, user_id: user.id)
28
+ to_model(record.attributes) if record
29
+ end
4
30
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ class CommentRepository < Upgrow::Repository
3
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UserRepository < Upgrow::Repository
4
+ def find_for_authentication(input)
5
+ record = UserRecord.find_by(email: input.email)
6
+ to_model(record.attributes) if record&.authenticate(input.password)
7
+ end
8
+
9
+ def find_from_context(id)
10
+ UserRecord.find_by(id: id)
11
+ end
12
+ end
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.routes.draw do
4
- resources :articles
4
+ resources :articles do
5
+ resources :comments, only: [:new, :create, :destroy]
6
+ end
7
+
8
+ resource :session, only: [:new, :create, :destroy]
9
+ resource :user, only: [:new, :create]
5
10
 
6
11
  root 'articles#index'
7
12
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ class CreateComments < ActiveRecord::Migration[6.1]
3
+ def change
4
+ create_table(:comments) do |t|
5
+ t.references(:article, null: false, foreign_key: true)
6
+ t.string(:author, null: false)
7
+ t.text(:body, null: false)
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ class CreateUsers < ActiveRecord::Migration[6.1]
3
+ def change
4
+ create_table(:users) do |t|
5
+ t.string(:email, null: false)
6
+ t.string(:password_digest, null: false)
7
+
8
+ t.timestamps
9
+
10
+ t.index(:email, unique: true)
11
+ end
12
+
13
+ change_table(:articles) do |t|
14
+ t.references(:user, null: false, foreign_key: true)
15
+ end
16
+
17
+ change_table(:comments) do |t|
18
+ t.remove(:author, type: :string, null: false)
19
+ t.references(:user, null: false, foreign_key: true)
20
+ end
21
+ end
22
+ end
@@ -10,13 +10,36 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2021_02_19_211631) do
13
+ ActiveRecord::Schema.define(version: 2021_04_09_164927) do
14
14
 
15
15
  create_table "articles", force: :cascade do |t|
16
16
  t.string "title", null: false
17
17
  t.text "body", null: false
18
18
  t.datetime "created_at", precision: 6, null: false
19
19
  t.datetime "updated_at", precision: 6, null: false
20
+ t.integer "user_id", null: false
21
+ t.index ["user_id"], name: "index_articles_on_user_id"
20
22
  end
21
23
 
24
+ create_table "comments", force: :cascade do |t|
25
+ t.integer "article_id", null: false
26
+ t.text "body", null: false
27
+ t.datetime "created_at", precision: 6, null: false
28
+ t.datetime "updated_at", precision: 6, null: false
29
+ t.integer "user_id", null: false
30
+ t.index ["article_id"], name: "index_comments_on_article_id"
31
+ t.index ["user_id"], name: "index_comments_on_user_id"
32
+ end
33
+
34
+ create_table "users", force: :cascade do |t|
35
+ t.string "email", null: false
36
+ t.string "password_digest", null: false
37
+ t.datetime "created_at", precision: 6, null: false
38
+ t.datetime "updated_at", precision: 6, null: false
39
+ t.index ["email"], name: "index_users_on_email", unique: true
40
+ end
41
+
42
+ add_foreign_key "articles", "users"
43
+ add_foreign_key "comments", "articles"
44
+ add_foreign_key "comments", "users"
22
45
  end
@@ -3,15 +3,28 @@
3
3
  require 'application_system_test_case'
4
4
 
5
5
  class ArticlesTest < ApplicationSystemTestCase
6
- test 'a message is shown when there are no Articles' do
6
+ setup do
7
7
  visit root_path
8
- assert_title 'Articles'
9
- assert_text 'There are no Articles just yet.'
8
+ end
9
+
10
+ test 'a guest User cannot see the new Article link' do
11
+ assert_no_link 'New Article'
12
+ end
13
+
14
+ test 'a guest User cannot see the new Article page' do
15
+ visit new_article_path
16
+ assert_title 'Sign In'
17
+ end
18
+
19
+ test 'signed in User can see the new Article link' do
20
+ sign_in
21
+ assert_link 'New Article'
10
22
  end
11
23
 
12
24
  test 'Article can be created' do
13
- visit root_path
14
- click_on 'New Article'
25
+ sign_in
26
+
27
+ click_link 'New Article'
15
28
  assert_title 'New Article'
16
29
 
17
30
  fill_in 'Title', with: 'My title'
@@ -20,11 +33,13 @@ class ArticlesTest < ApplicationSystemTestCase
20
33
 
21
34
  assert_text 'Article was successfully created.'
22
35
  assert_title 'My title'
36
+ assert_text 'Author: existing@example.com'
23
37
  assert_text 'My long body'
24
38
  end
25
39
 
26
40
  test 'validation errors are shown' do
27
- visit root_path
41
+ sign_in
42
+
28
43
  click_on 'New Article'
29
44
  click_on 'Create'
30
45
 
@@ -34,8 +49,9 @@ class ArticlesTest < ApplicationSystemTestCase
34
49
  end
35
50
 
36
51
  test 'previously entered data is shown' do
37
- visit root_path
38
- click_on 'New Article'
52
+ sign_in
53
+
54
+ click_link 'New Article'
39
55
  fill_in 'Body', with: 'Short'
40
56
  click_on 'Create'
41
57
 
@@ -44,29 +60,31 @@ class ArticlesTest < ApplicationSystemTestCase
44
60
  end
45
61
 
46
62
  test 'new Article is listed in the index page' do
47
- visit root_path
48
- click_on 'New Article'
63
+ sign_in
64
+
65
+ click_link 'New Article'
49
66
  fill_in 'Title', with: 'My title'
50
67
  fill_in 'Body', with: 'My long body'
51
68
  click_on 'Create'
52
- click_on 'Back'
53
69
 
70
+ visit root_path
54
71
  assert_link 'My title'
72
+ assert_text 'Author: existing@example.com'
55
73
  assert_text 'My long body'
56
74
  end
57
75
 
58
76
  test 'Article can be edited' do
59
- visit root_path
60
- click_on 'New Article'
61
- fill_in 'Title', with: 'My title'
62
- fill_in 'Body', with: 'My long body'
63
- click_on 'Create'
77
+ sign_in
78
+
79
+ click_link 'Lorem Barnak'
64
80
  click_on 'Edit'
65
81
 
66
82
  assert_title 'Edit Article'
67
83
 
68
- assert_field 'Title', with: 'My title'
69
- assert_field 'Body', with: 'My long body'
84
+ assert_field 'Title', with: 'Lorem Barnak'
85
+ assert_field 'Body', with: 'Cimonaque de sacristi de colon de câlique de '\
86
+ "batèche de p'tit Jésus de charogne de marde de patente à gosse de " \
87
+ "sainte-viarge de bout d'crisse de cibouleau de bâtard."
70
88
 
71
89
  fill_in 'Title', with: 'Edited title'
72
90
  fill_in 'Body', with: 'Edited body'
@@ -74,15 +92,14 @@ class ArticlesTest < ApplicationSystemTestCase
74
92
 
75
93
  assert_text 'Article was successfully updated.'
76
94
  assert_title 'Edited title'
95
+ assert_text 'Author: existing@example.com'
77
96
  assert_text 'Edited body'
78
97
  end
79
98
 
80
99
  test 'validation errors are shown when editing Article' do
81
- visit root_path
82
- click_on 'New Article'
83
- fill_in 'Title', with: 'My title'
84
- fill_in 'Body', with: 'My long body'
85
- click_on 'Create'
100
+ sign_in
101
+
102
+ click_on 'Lorem Barnak'
86
103
  click_on 'Edit'
87
104
 
88
105
  fill_in 'Title', with: ''
@@ -95,15 +112,56 @@ class ArticlesTest < ApplicationSystemTestCase
95
112
  assert_field 'Body', with: 'Short'
96
113
  end
97
114
 
115
+ test 'guest User cannot see the edit link' do
116
+ click_link 'Lorem Barnak'
117
+ assert_no_link 'Edit'
118
+ end
119
+
120
+ test 'guest User cannot access the edit page directly' do
121
+ click_link 'Lorem Barnak'
122
+
123
+ visit current_path + '/edit'
124
+
125
+ assert_title 'Sign In'
126
+ end
127
+
128
+ test 'User who is not the author of the Article cannot see its edit link' do
129
+ sign_in
130
+
131
+ click_on 'The Hobbit'
132
+ assert_no_link 'Edit'
133
+ end
134
+
135
+ test 'User who is not the author of the Article cannot access the edit page directly' do
136
+ sign_in
137
+
138
+ click_link 'The Hobbit'
139
+
140
+ visit current_path + '/edit'
141
+
142
+ assert_title 'Sign In'
143
+ end
144
+
98
145
  test 'Article can be deleted' do
99
- visit root_path
100
- click_on 'New Article'
101
- fill_in 'Title', with: 'My title'
102
- fill_in 'Body', with: 'My long body'
103
- click_on 'Create'
146
+ sign_in
147
+
148
+ click_on 'Lorem Barnak'
104
149
  click_on 'Destroy'
105
150
 
151
+ assert_title 'Articles'
106
152
  assert_text 'Article was successfully destroyed'
107
- assert_text 'There are no Articles just yet.'
153
+ assert_no_link 'Lorem Barnak'
154
+ end
155
+
156
+ test 'guest User cannot see the delete button' do
157
+ click_on 'Lorem Barnak'
158
+ assert_no_button 'Destroy'
159
+ end
160
+
161
+ test 'User who is not the author of the Article cannot see its delete link' do
162
+ sign_in
163
+
164
+ click_on 'The Hobbit'
165
+ assert_no_button 'Destroy'
108
166
  end
109
167
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'application_system_test_case'
4
+
5
+ class CommentsTest < ApplicationSystemTestCase
6
+ setup do
7
+ visit root_path
8
+ end
9
+
10
+ test 'a message is shown when there are no Comments' do
11
+ click_on 'Lorem Barnak'
12
+ assert_text 'There are no Comments just yet.'
13
+ end
14
+
15
+ test 'guest can see existing Comment' do
16
+ click_on 'The Hobbit'
17
+ assert_text 'existing@example.com says:'
18
+ assert_text 'I hate everything about this article.'
19
+ end
20
+
21
+ test 'Comment can be created' do
22
+ sign_in
23
+ click_on 'The Hobbit'
24
+
25
+ click_on 'Create Comment'
26
+ fill_in 'Body', with: 'My long comment'
27
+ click_on 'Create'
28
+
29
+ assert_title 'The Hobbit'
30
+ assert_text 'existing@example.com says:'
31
+ assert_text 'My long comment'
32
+ end
33
+
34
+ test 'validation errors are shown' do
35
+ sign_in
36
+ click_on 'The Hobbit'
37
+
38
+ click_on 'Create Comment'
39
+ fill_in 'Body', with: 'Short'
40
+ click_on 'Create'
41
+
42
+ assert_title 'New Comment'
43
+ assert_field 'Body', with: 'Short'
44
+ assert_text 'Body is too short (minimum is 10 characters)'
45
+ end
46
+
47
+ test 'guest cannot see the Create Comment link' do
48
+ click_on 'The Hobbit'
49
+ assert_no_link 'Create Comment'
50
+ end
51
+
52
+ test 'Comment can be deleted' do
53
+ sign_in
54
+ click_on 'The Hobbit'
55
+
56
+ within('.comments') do
57
+ click_on 'Delete'
58
+ end
59
+
60
+ assert_title 'The Hobbit'
61
+ assert_text 'Comment was successfully destroyed'
62
+ assert_text 'There are no Comments just yet.'
63
+ end
64
+
65
+ test 'guest cannot see the delete button' do
66
+ click_on 'The Hobbit'
67
+
68
+ within('.comments') do
69
+ assert_no_button 'Delete'
70
+ end
71
+ end
72
+
73
+ test 'User who is not the author of the comment cannot see the delete button' do
74
+ sign_in(email: 'jrr_tolkien@example.com', password: 'abc345')
75
+ click_on 'The Hobbit'
76
+
77
+ within('.comments') do
78
+ assert_no_button 'Delete'
79
+ end
80
+ end
81
+ end