upgrow 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -12
  3. data/Rakefile +8 -4
  4. data/lib/upgrow.rb +13 -2
  5. data/lib/upgrow/action.rb +54 -0
  6. data/lib/upgrow/active_record_adapter.rb +73 -0
  7. data/lib/upgrow/basic_repository.rb +45 -0
  8. data/lib/upgrow/immutable_object.rb +57 -0
  9. data/lib/upgrow/immutable_struct.rb +40 -0
  10. data/lib/upgrow/input.rb +47 -0
  11. data/lib/upgrow/model.rb +35 -0
  12. data/lib/upgrow/repository.rb +12 -0
  13. data/lib/upgrow/result.rb +94 -0
  14. data/test/application_system_test_case.rb +13 -0
  15. data/test/dummy/app/actions/create_article_action.rb +13 -0
  16. data/test/dummy/app/actions/delete_article_action.rb +7 -0
  17. data/test/dummy/app/actions/edit_article_action.rb +10 -0
  18. data/test/dummy/app/actions/list_articles_action.rb +8 -0
  19. data/test/dummy/app/actions/show_article_action.rb +10 -0
  20. data/test/dummy/app/actions/update_article_action.rb +13 -0
  21. data/test/dummy/app/channels/application_cable/channel.rb +5 -0
  22. data/test/dummy/app/channels/application_cable/connection.rb +5 -0
  23. data/test/dummy/app/controllers/application_controller.rb +3 -0
  24. data/test/dummy/app/controllers/articles_controller.rb +64 -0
  25. data/test/dummy/app/helpers/application_helper.rb +102 -0
  26. data/test/dummy/app/inputs/article_input.rb +8 -0
  27. data/test/dummy/app/jobs/application_job.rb +9 -0
  28. data/test/dummy/app/mailers/application_mailer.rb +5 -0
  29. data/test/dummy/app/models/article.rb +6 -0
  30. data/test/dummy/app/records/application_record.rb +5 -0
  31. data/test/dummy/app/records/article_record.rb +5 -0
  32. data/test/dummy/app/repositories/article_repository.rb +4 -0
  33. data/test/dummy/config/application.rb +23 -0
  34. data/test/dummy/config/boot.rb +6 -0
  35. data/test/dummy/config/environment.rb +6 -0
  36. data/test/dummy/config/environments/development.rb +79 -0
  37. data/test/dummy/config/environments/production.rb +133 -0
  38. data/test/dummy/config/environments/test.rb +61 -0
  39. data/test/dummy/config/initializers/application_controller_renderer.rb +9 -0
  40. data/test/dummy/config/initializers/assets.rb +13 -0
  41. data/test/dummy/config/initializers/backtrace_silencers.rb +12 -0
  42. data/test/dummy/config/initializers/content_security_policy.rb +31 -0
  43. data/test/dummy/config/initializers/cookies_serializer.rb +6 -0
  44. data/test/dummy/config/initializers/filter_parameter_logging.rb +7 -0
  45. data/test/dummy/config/initializers/inflections.rb +17 -0
  46. data/test/dummy/config/initializers/mime_types.rb +5 -0
  47. data/test/dummy/config/initializers/permissions_policy.rb +12 -0
  48. data/test/dummy/config/initializers/wrap_parameters.rb +16 -0
  49. data/test/dummy/config/puma.rb +44 -0
  50. data/test/dummy/config/routes.rb +7 -0
  51. data/test/dummy/db/migrate/20210219211631_create_articles.rb +11 -0
  52. data/test/dummy/db/schema.rb +22 -0
  53. data/test/rails_helper.rb +21 -0
  54. data/test/system/articles_test.rb +109 -0
  55. data/test/test_helper.rb +3 -3
  56. data/test/upgrow/action_test.rb +25 -0
  57. data/test/upgrow/active_record_adapter_test.rb +94 -0
  58. data/test/upgrow/basic_repository_test.rb +73 -0
  59. data/test/upgrow/documentation_test.rb +12 -0
  60. data/test/upgrow/immutable_object_test.rb +60 -0
  61. data/test/upgrow/immutable_struct_test.rb +49 -0
  62. data/test/upgrow/input_test.rb +65 -0
  63. data/test/upgrow/model_test.rb +27 -0
  64. data/test/upgrow/result_test.rb +95 -0
  65. metadata +128 -7
  66. data/test/documentation_test.rb +0 -10
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # Be sure to restart your server when you modify this file.
3
+
4
+ # Add new mime types for use in respond_to blocks:
5
+ # Mime::Type.register "text/richtext", :rtf
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # Define an application-wide HTTP permissions policy. For further
3
+ # information see https://developers.google.com/web/updates/2018/06/feature-policy
4
+ #
5
+ # Rails.application.config.permissions_policy do |f|
6
+ # f.camera :none
7
+ # f.gyroscope :none
8
+ # f.microphone :none
9
+ # f.usb :none
10
+ # f.fullscreen :self
11
+ # f.payment :self, "https://secure.example.com"
12
+ # end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ # Be sure to restart your server when you modify this file.
3
+
4
+ # This file contains settings for ActionController::ParamsWrapper which
5
+ # is enabled by default.
6
+
7
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to
8
+ # an empty array.
9
+ ActiveSupport.on_load(:action_controller) do
10
+ wrap_parameters format: [:json]
11
+ end
12
+
13
+ # To enable root element in JSON for ActiveRecord objects.
14
+ # ActiveSupport.on_load(:active_record) do
15
+ # self.include_root_in_json = true
16
+ # end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ # Puma can serve each request in a thread from an internal thread pool.
3
+ # The `threads` method setting takes two numbers: a minimum and maximum.
4
+ # Any libraries that use thread pools should be configured to match
5
+ # the maximum value specified for Puma. Default is set to 5 threads for minimum
6
+ # and maximum; this matches the default thread size of Active Record.
7
+ #
8
+ max_threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }
9
+ min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
10
+ threads min_threads_count, max_threads_count
11
+
12
+ # Specifies the `worker_timeout` threshold that Puma will use to wait before
13
+ # terminating a worker in development environments.
14
+ #
15
+ worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development'
16
+
17
+ # Specifies the `port` that Puma will listen on to receive requests.
18
+ #
19
+ port ENV.fetch('PORT') { 3000 }
20
+
21
+ # Specifies the `environment` that Puma will run in.
22
+ #
23
+ environment ENV.fetch('RAILS_ENV') { 'development' }
24
+
25
+ # Specifies the `pidfile` that Puma will use.
26
+ pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }
27
+
28
+ # Specifies the number of `workers` to boot in clustered mode.
29
+ # Workers are forked web server processes. If using threads and workers together
30
+ # the concurrency of the application would be max `threads` * `workers`.
31
+ # Workers do not work on JRuby or Windows (both of which do not support
32
+ # processes).
33
+ #
34
+ # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
35
+
36
+ # Use the `preload_app!` method when specifying a `workers` number.
37
+ # This directive tells Puma to first boot the application and load code
38
+ # before forking the application. This takes advantage of Copy On Write
39
+ # process behavior so workers use less memory.
40
+ #
41
+ # preload_app!
42
+
43
+ # Allow puma to be restarted by `rails restart` command.
44
+ plugin :tmp_restart
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ resources :articles
5
+
6
+ root 'articles#index'
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ class CreateArticles < ActiveRecord::Migration[6.1]
3
+ def change
4
+ create_table(:articles) do |t|
5
+ t.string(:title, null: false)
6
+ t.text(:body, null: false)
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 2021_02_19_211631) do
14
+
15
+ create_table "articles", force: :cascade do |t|
16
+ t.string "title", null: false
17
+ t.text "body", null: false
18
+ t.datetime "created_at", precision: 6, null: false
19
+ t.datetime "updated_at", precision: 6, null: false
20
+ end
21
+
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RAILS_ENV'] = 'test'
4
+
5
+ require_relative '../test/dummy/config/environment'
6
+ ActiveRecord::Migrator.migrations_paths = [File.expand_path(
7
+ '../test/dummy/db/migrate', __dir__
8
+ )]
9
+ require 'rails/test_help'
10
+
11
+ # Load fixtures from the engine
12
+ if ActiveSupport::TestCase.respond_to?(:fixture_path=)
13
+ ActiveSupport::TestCase.fixture_path = File.expand_path('fixtures', __dir__)
14
+ ActionDispatch::IntegrationTest.fixture_path =
15
+ ActiveSupport::TestCase.fixture_path
16
+ ActiveSupport::TestCase.file_fixture_path =
17
+ ActiveSupport::TestCase.fixture_path + '/files'
18
+ ActiveSupport::TestCase.fixtures(:all)
19
+ end
20
+
21
+ Warning[:deprecated] = true
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'application_system_test_case'
4
+
5
+ class ArticlesTest < ApplicationSystemTestCase
6
+ test 'a message is shown when there are no Articles' do
7
+ visit root_path
8
+ assert_title 'Articles'
9
+ assert_text 'There are no Articles just yet.'
10
+ end
11
+
12
+ test 'Article can be created' do
13
+ visit root_path
14
+ click_on 'New Article'
15
+ assert_title 'New Article'
16
+
17
+ fill_in 'Title', with: 'My title'
18
+ fill_in 'Body', with: 'My long body'
19
+ click_on 'Create'
20
+
21
+ assert_text 'Article was successfully created.'
22
+ assert_title 'My title'
23
+ assert_text 'My long body'
24
+ end
25
+
26
+ test 'validation errors are shown' do
27
+ visit root_path
28
+ click_on 'New Article'
29
+ click_on 'Create'
30
+
31
+ assert_text "Title can't be blank"
32
+ assert_text "Body can't be blank"
33
+ assert_text 'Body is too short (minimum is 10 characters)'
34
+ end
35
+
36
+ test 'previously entered data is shown' do
37
+ visit root_path
38
+ click_on 'New Article'
39
+ fill_in 'Body', with: 'Short'
40
+ click_on 'Create'
41
+
42
+ assert_text 'Body is too short (minimum is 10 characters)'
43
+ assert_field 'Body', with: 'Short'
44
+ end
45
+
46
+ test 'new Article is listed in the index page' do
47
+ visit root_path
48
+ click_on 'New Article'
49
+ fill_in 'Title', with: 'My title'
50
+ fill_in 'Body', with: 'My long body'
51
+ click_on 'Create'
52
+ click_on 'Back'
53
+
54
+ assert_link 'My title'
55
+ assert_text 'My long body'
56
+ end
57
+
58
+ 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'
64
+ click_on 'Edit'
65
+
66
+ assert_title 'Edit Article'
67
+
68
+ assert_field 'Title', with: 'My title'
69
+ assert_field 'Body', with: 'My long body'
70
+
71
+ fill_in 'Title', with: 'Edited title'
72
+ fill_in 'Body', with: 'Edited body'
73
+ click_on 'Update'
74
+
75
+ assert_text 'Article was successfully updated.'
76
+ assert_title 'Edited title'
77
+ assert_text 'Edited body'
78
+ end
79
+
80
+ 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'
86
+ click_on 'Edit'
87
+
88
+ fill_in 'Title', with: ''
89
+ fill_in 'Body', with: 'Short'
90
+ click_on 'Update'
91
+
92
+ assert_text "Title can't be blank"
93
+ assert_text 'Body is too short (minimum is 10 characters)'
94
+ assert_field 'Title', with: ''
95
+ assert_field 'Body', with: 'Short'
96
+ end
97
+
98
+ 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'
104
+ click_on 'Destroy'
105
+
106
+ assert_text 'Article was successfully destroyed'
107
+ assert_text 'There are no Articles just yet.'
108
+ end
109
+ end
data/test/test_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'minitest/autorun'
4
- require 'active_support'
5
- require 'active_support/test_case'
6
-
4
+ require 'pry-byebug'
7
5
  require 'upgrow'
6
+
7
+ Warning[:deprecated] = true
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class ActionTest < ActiveSupport::TestCase
7
+ test '.result_class is an empty Result by default' do
8
+ assert_equal([:errors], Action.result_class.members)
9
+ end
10
+
11
+ test '.result sets the members in the Action Result class' do
12
+ result_class = Action.result_class
13
+
14
+ Action.result(:user, :data)
15
+
16
+ assert_equal([:user, :data, :errors], Action.result_class.members)
17
+
18
+ Action.result_class = result_class
19
+ end
20
+
21
+ test '#result returns the Result class from the Action class' do
22
+ assert_equal Action.result_class, Action.new.result
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class ActiveRecordAdapterTest < ActiveSupport::TestCase
7
+ class User < Model
8
+ attribute :name
9
+ end
10
+
11
+ class UserInput < Input
12
+ attribute :name
13
+ end
14
+
15
+ class UserRepository < BasicRepository
16
+ include ActiveRecordAdapter
17
+ end
18
+
19
+ class UserRecord; end
20
+
21
+ setup do
22
+ freeze_time
23
+ @base = Minitest::Mock.new
24
+ @repository = UserRepository.new(base: @base)
25
+ @record = Minitest::Mock.new
26
+ @record_attributes = {
27
+ name: 'volmer', id: 1, created_at: Time.now, updated_at: Time.now
28
+ }
29
+ @record.expect(:attributes, @record_attributes)
30
+ end
31
+
32
+ test '.new sets base to the Active Record Base class according to the Repository name by default' do
33
+ repository = UserRepository.new
34
+ assert_equal UserRecord, repository.base
35
+ end
36
+
37
+ test '#all returns all Records as Models' do
38
+ @base.expect(:all, [@record])
39
+
40
+ all = @repository.all
41
+
42
+ assert all.one?
43
+
44
+ assert_equal 1, all.first.id
45
+ assert_equal 'volmer', all.first.name
46
+ assert_equal Time.now, all.first.created_at
47
+ assert_equal Time.now, all.first.updated_at
48
+ end
49
+
50
+ test '#find retrieves the Model for the given ID' do
51
+ @base.expect(:find, @record, [1])
52
+
53
+ model = @repository.find(1)
54
+
55
+ assert_equal 1, model.id
56
+ assert_equal 'volmer', model.name
57
+ assert_equal Time.now, model.created_at
58
+ assert_equal Time.now, model.updated_at
59
+ end
60
+
61
+ test '#create creates a new Record with the given attributes' do
62
+ input = UserInput.new(name: 'volmer')
63
+
64
+ @base.expect(:create!, @record, [{ name: 'volmer' }])
65
+
66
+ model = @repository.create(input)
67
+
68
+ assert_equal 1, model.id
69
+ assert_equal 'volmer', model.name
70
+ assert_equal Time.now, model.created_at
71
+ assert_equal Time.now, model.updated_at
72
+ end
73
+
74
+ test '#update changes the existing Record attributes' do
75
+ input = UserInput.new(name: 'rafael')
76
+
77
+ @base.expect(:update, @record, [1, { name: 'rafael' }])
78
+ @record_attributes[:name] = 'rafael'
79
+
80
+ model = @repository.update(1, input)
81
+
82
+ assert_equal 1, model.id
83
+ assert_equal 'rafael', model.name
84
+ assert_equal Time.now, model.created_at
85
+ assert_equal Time.now, model.updated_at
86
+ end
87
+
88
+ test '#delete deletes the Record with the given ID' do
89
+ @base.expect(:destroy, true, [1])
90
+
91
+ @repository.delete(1)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module Upgrow
6
+ class BasicRepositoryTest < ActiveSupport::TestCase
7
+ class User < Model; end
8
+
9
+ class UserRepository < BasicRepository; end
10
+
11
+ class NoModelRepository < BasicRepository; end
12
+
13
+ setup do
14
+ freeze_time
15
+
16
+ @repository = UserRepository.new
17
+ end
18
+
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)
21
+
22
+ assert_equal :my_base, repository.base
23
+ assert_equal User, repository.model_class
24
+ end
25
+
26
+ test '.new sets the base to nil by default' do
27
+ assert_nil @repository.base
28
+ end
29
+
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
32
+ end
33
+
34
+ test '.new raises a Name Error if the Model class is undefined' do
35
+ error = assert_raises(NameError) do
36
+ NoModelRepository.new(base: :my_base)
37
+ end
38
+
39
+ assert_includes(
40
+ error.message,
41
+ 'uninitialized constant Upgrow::BasicRepositoryTest::NoModel'
42
+ )
43
+ end
44
+
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
+ )
49
+
50
+ assert_equal 1, model.id
51
+ assert_equal Time.now, model.created_at
52
+ assert_equal Time.now, model.updated_at
53
+ end
54
+
55
+ test '.to_model accepts a Hash of Symbols' do
56
+ args = { id: 1, created_at: Time.now, updated_at: Time.now }
57
+ model = @repository.to_model(args)
58
+
59
+ assert_equal 1, model.id
60
+ assert_equal Time.now, model.created_at
61
+ assert_equal Time.now, model.updated_at
62
+ end
63
+
64
+ test '.to_model accepts a Hash of Strings' do
65
+ args = { 'id' => 1, 'created_at' => Time.now, 'updated_at' => Time.now }
66
+ model = @repository.to_model(args)
67
+
68
+ assert_equal 1, model.id
69
+ assert_equal Time.now, model.created_at
70
+ assert_equal Time.now, model.updated_at
71
+ end
72
+ end
73
+ end