upgrow 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/upgrow.rb +2 -8
- data/lib/upgrow/action.rb +66 -16
- data/lib/upgrow/actions.rb +31 -0
- data/lib/upgrow/active_record_adapter.rb +24 -15
- data/lib/upgrow/active_record_schema.rb +63 -0
- data/lib/upgrow/basic_model.rb +64 -0
- data/lib/upgrow/basic_repository.rb +49 -22
- data/lib/upgrow/error.rb +19 -0
- data/lib/upgrow/immutable_object.rb +26 -21
- data/lib/upgrow/input.rb +7 -0
- data/lib/upgrow/model.rb +12 -12
- data/lib/upgrow/model_schema.rb +31 -0
- data/lib/upgrow/repository.rb +3 -0
- data/lib/upgrow/result.rb +18 -55
- data/lib/upgrow/schema.rb +33 -0
- data/test/application_system_test_case.rb +11 -0
- data/test/dummy/app/actions/application_action.rb +10 -0
- data/test/dummy/app/actions/articles/create_action.rb +15 -0
- data/test/dummy/app/actions/articles/destroy_action.rb +9 -0
- data/test/dummy/app/actions/articles/edit_action.rb +12 -0
- data/test/dummy/app/actions/articles/index_action.rb +11 -0
- data/test/dummy/app/actions/articles/new_action.rb +8 -0
- data/test/dummy/app/actions/articles/show_action.rb +11 -0
- data/test/dummy/app/actions/articles/update_action.rb +15 -0
- data/test/dummy/app/actions/comments/create_action.rb +15 -0
- data/test/dummy/app/actions/comments/destroy_action.rb +9 -0
- data/test/dummy/app/actions/comments/new_action.rb +8 -0
- data/test/dummy/app/actions/sessions/create_action.rb +23 -0
- data/test/dummy/app/actions/sessions/destroy_action.rb +6 -0
- data/test/dummy/app/actions/sessions/new_action.rb +8 -0
- data/test/dummy/app/actions/user_action.rb +10 -0
- data/test/dummy/app/actions/users/create_action.rb +13 -0
- data/test/dummy/app/actions/users/new_action.rb +8 -0
- data/test/dummy/app/controllers/application_controller.rb +10 -0
- data/test/dummy/app/controllers/articles_controller.rb +32 -28
- data/test/dummy/app/controllers/comments_controller.rb +41 -0
- data/test/dummy/app/controllers/sessions_controller.rb +34 -0
- data/test/dummy/app/controllers/users_controller.rb +29 -0
- data/test/dummy/app/helpers/application_helper.rb +27 -3
- data/test/dummy/app/helpers/users_helper.rb +15 -0
- data/test/dummy/app/inputs/article_input.rb +3 -0
- data/test/dummy/app/inputs/comment_input.rb +11 -0
- data/test/dummy/app/inputs/session_input.rb +9 -0
- data/test/dummy/app/inputs/user_input.rb +9 -0
- data/test/dummy/app/models/article.rb +0 -2
- data/test/dummy/app/models/comment.rb +4 -0
- data/test/dummy/app/models/user.rb +4 -0
- data/test/dummy/app/records/article_record.rb +2 -0
- data/test/dummy/app/records/comment_record.rb +7 -0
- data/test/dummy/app/records/user_record.rb +9 -0
- data/test/dummy/app/repositories/article_repository.rb +26 -0
- data/test/dummy/app/repositories/comment_repository.rb +3 -0
- data/test/dummy/app/repositories/user_repository.rb +12 -0
- data/test/dummy/config/routes.rb +6 -1
- data/test/dummy/db/migrate/20210320140432_create_comments.rb +12 -0
- data/test/dummy/db/migrate/20210409164927_create_users.rb +22 -0
- data/test/dummy/db/schema.rb +24 -1
- data/test/system/articles_test.rb +87 -29
- data/test/system/comments_test.rb +81 -0
- data/test/system/guest_user_test.rb +14 -0
- data/test/system/sign_in_test.rb +57 -0
- data/test/system/sign_out_test.rb +19 -0
- data/test/system/sign_up_test.rb +38 -0
- data/test/test_helper.rb +6 -1
- data/test/upgrow/action_test.rb +101 -9
- data/test/upgrow/actions_test.rb +24 -0
- data/test/upgrow/active_record_adapter_test.rb +12 -17
- data/test/upgrow/active_record_schema_test.rb +92 -0
- data/test/upgrow/basic_model_test.rb +95 -0
- data/test/upgrow/basic_repository_test.rb +48 -27
- data/test/upgrow/immutable_object_test.rb +43 -7
- data/test/upgrow/input_test.rb +19 -1
- data/test/upgrow/model_schema_test.rb +44 -0
- data/test/upgrow/model_test.rb +48 -11
- data/test/upgrow/result_test.rb +19 -64
- data/test/upgrow/schema_test.rb +44 -0
- metadata +128 -50
- data/test/dummy/app/actions/create_article_action.rb +0 -13
- data/test/dummy/app/actions/delete_article_action.rb +0 -7
- data/test/dummy/app/actions/edit_article_action.rb +0 -10
- data/test/dummy/app/actions/list_articles_action.rb +0 -8
- data/test/dummy/app/actions/show_article_action.rb +0 -10
- data/test/dummy/app/actions/update_article_action.rb +0 -13
@@ -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,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
|
data/test/dummy/config/routes.rb
CHANGED
@@ -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
|
data/test/dummy/db/schema.rb
CHANGED
@@ -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:
|
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
|
-
|
6
|
+
setup do
|
7
7
|
visit root_path
|
8
|
-
|
9
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
48
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
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: '
|
69
|
-
assert_field 'Body', with: '
|
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
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
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
|