pg_rails 7.6.19 → 7.6.21.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/pg_associable/app/javascript/modal_controller.js +8 -4
  3. data/pg_associable/spec/pg_associable/helpers_spec.rb +8 -13
  4. data/pg_engine/app/components/inline_edit/inline_edit_component.html.slim +1 -1
  5. data/pg_engine/app/components/inline_edit/inline_show_component.html.slim +2 -2
  6. data/pg_engine/app/components/notifications_bell_component.rb +1 -1
  7. data/pg_engine/app/controllers/admin/accounts_controller.rb +2 -2
  8. data/pg_engine/app/controllers/admin/user_accounts_controller.rb +3 -3
  9. data/pg_engine/app/controllers/admin/users_controller.rb +4 -1
  10. data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +12 -7
  11. data/pg_engine/app/controllers/concerns/pg_engine/tenant_helper.rb +33 -0
  12. data/pg_engine/app/controllers/pg_engine/base_admin_controller.rb +0 -1
  13. data/pg_engine/app/controllers/pg_engine/base_controller.rb +18 -21
  14. data/pg_engine/app/controllers/pg_engine/base_public_controller.rb +1 -1
  15. data/pg_engine/app/controllers/pg_engine/base_users_controller.rb +5 -3
  16. data/pg_engine/app/controllers/pg_engine/devise_controller.rb +4 -1
  17. data/pg_engine/app/controllers/pg_engine/tenant_controller.rb +22 -0
  18. data/pg_engine/app/controllers/{users → tenant}/dashboard_controller.rb +2 -2
  19. data/pg_engine/app/controllers/tenant/inline_edit_controller.rb +22 -0
  20. data/pg_engine/app/controllers/tenant/user_accounts_controller.rb +56 -0
  21. data/pg_engine/app/controllers/users/accounts_controller.rb +46 -15
  22. data/pg_engine/app/controllers/users/invitations_controller.rb +78 -0
  23. data/pg_engine/app/controllers/users/notifications_controller.rb +1 -0
  24. data/pg_engine/app/controllers/users/registrations_controller.rb +3 -2
  25. data/pg_engine/app/decorators/account_decorator.rb +18 -0
  26. data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +9 -1
  27. data/pg_engine/app/decorators/user_account_decorator.rb +76 -11
  28. data/pg_engine/app/helpers/pg_engine/accounts_helper.rb +9 -0
  29. data/pg_engine/app/helpers/pg_engine/frame_helper.rb +12 -0
  30. data/pg_engine/app/lib/pg_engine/default_url_options.rb +21 -0
  31. data/pg_engine/app/lib/pg_engine/filtros_builder.rb +2 -0
  32. data/pg_engine/app/models/account.rb +28 -1
  33. data/pg_engine/app/models/concerns/pg_engine/child_record.rb +55 -0
  34. data/pg_engine/app/models/current.rb +21 -3
  35. data/pg_engine/app/models/pg_engine/base_record.rb +5 -0
  36. data/pg_engine/app/models/user.rb +51 -9
  37. data/pg_engine/app/models/user_account.rb +74 -9
  38. data/pg_engine/app/policies/account_policy.rb +35 -16
  39. data/pg_engine/app/policies/email_log_policy.rb +0 -4
  40. data/pg_engine/app/policies/email_policy.rb +0 -4
  41. data/pg_engine/app/policies/pg_engine/base_policy.rb +31 -10
  42. data/pg_engine/app/policies/user_account_policy.rb +59 -25
  43. data/pg_engine/app/policies/user_policy.rb +14 -1
  44. data/pg_engine/app/views/admin/user_accounts/_form.html.slim +1 -1
  45. data/pg_engine/app/views/admin/user_accounts/show.html.slim +15 -0
  46. data/pg_engine/app/views/admin/users/show.html.slim +0 -3
  47. data/pg_engine/app/views/pg_engine/base/index.html.slim +2 -2
  48. data/pg_engine/app/views/tenant/dashboard/dashboard.html.slim +2 -0
  49. data/pg_engine/app/views/tenant/user_accounts/_fields.html.slim +13 -0
  50. data/pg_engine/app/views/tenant/user_accounts/_form.html.slim +9 -0
  51. data/pg_engine/app/views/tenant/user_accounts/show.html.slim +20 -0
  52. data/pg_engine/app/views/users/accounts/_form.html.slim +7 -0
  53. data/pg_engine/app/views/users/accounts/show.html.slim +23 -15
  54. data/pg_engine/config/initializers/acts_as_tenant.rb +7 -2
  55. data/pg_engine/config/initializers/devise.rb +10 -0
  56. data/pg_engine/config/initializers/ransack.rb +2 -0
  57. data/pg_engine/config/locales/es.yml +60 -0
  58. data/pg_engine/config/routes.rb +21 -11
  59. data/pg_engine/config/simple_form/simple_form_bootstrap.rb +2 -2
  60. data/pg_engine/db/migrate/20241023203849_devise_invitable.rb +14 -0
  61. data/pg_engine/db/migrate/20241027225618_add_membership_status_to_user_accounts.rb +6 -0
  62. data/pg_engine/db/seeds.rb +6 -6
  63. data/pg_engine/lib/pg_engine/configuracion.rb +36 -1
  64. data/pg_engine/lib/pg_engine/navigator.rb +2 -25
  65. data/pg_engine/lib/pg_engine/utils/{check_invalid_records.rb → resource_reports.rb} +22 -3
  66. data/pg_engine/lib/pg_engine.rb +1 -0
  67. data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +3 -2
  68. data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +11 -9
  69. data/pg_engine/spec/factories/accounts.rb +8 -0
  70. data/pg_engine/spec/factories/user_accounts.rb +1 -1
  71. data/pg_engine/spec/factories/users.rb +6 -0
  72. data/pg_engine/spec/models/concerns/pg_engine/child_record_spec.rb +27 -0
  73. data/pg_engine/spec/models/user_account_spec.rb +5 -1
  74. data/pg_engine/spec/models/user_spec.rb +3 -25
  75. data/pg_engine/spec/policies/account_policy_spec.rb +19 -0
  76. data/pg_engine/spec/requests/devise/invitations_spec.rb +196 -0
  77. data/pg_engine/spec/requests/resource_spec.rb +14 -15
  78. data/pg_engine/spec/requests/users/accounts_spec.rb +117 -8
  79. data/pg_engine/spec/requests/users/base_controller_spec.rb +31 -0
  80. data/pg_engine/spec/requests/users/dashboard_spec.rb +4 -9
  81. data/pg_engine/spec/requests/users/date_jumper_spec.rb +2 -1
  82. data/pg_engine/spec/requests/users/inline_edit_spec.rb +6 -5
  83. data/pg_engine/spec/requests/users/registrations_spec.rb +2 -2
  84. data/pg_engine/spec/requests/users/user_accounts_spec.rb +54 -0
  85. data/pg_engine/spec/system/login_spec.rb +2 -2
  86. data/pg_engine/spec/system/noticed_spec.rb +0 -2
  87. data/pg_engine/spec/system/signup_spec.rb +4 -3
  88. data/pg_engine/spec/system/tenants_spec.rb +10 -9
  89. data/pg_layout/app/javascript/application.js +1 -1
  90. data/pg_layout/app/javascript/config/turbo_rails/index.js +1 -1
  91. data/pg_layout/app/lib/navbar.rb +15 -1
  92. data/pg_layout/app/views/devise/invitations/edit.html.erb +34 -0
  93. data/pg_layout/app/views/devise/invitations/new.html.erb +15 -0
  94. data/pg_layout/app/views/devise/mailer/invitation_instructions.html.erb +11 -0
  95. data/pg_layout/app/views/devise/mailer/invitation_instructions.text.erb +11 -0
  96. data/pg_layout/app/views/devise/registrations/edit.html.erb +1 -0
  97. data/pg_layout/app/views/layouts/pg_layout/base.html.slim +6 -5
  98. data/pg_layout/app/views/pg_layout/_navbar.html.erb +7 -6
  99. data/pg_layout/app/views/pg_layout/_sidebar.html.erb +2 -20
  100. data/pg_layout/app/views/pg_layout/_signed_in_links.html.slim +52 -0
  101. data/pg_layout/lib/pg_layout.rb +0 -5
  102. data/pg_rails/lib/pg_rails/pundit_matchers.rb +21 -0
  103. data/pg_rails/lib/pg_rails/tpath_support.rb +73 -0
  104. data/pg_rails/lib/pg_rails.rb +6 -0
  105. data/pg_rails/lib/version.rb +1 -1
  106. data/pg_rails/scss/pg_rails.scss +1 -1
  107. data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +1 -1
  108. data/pg_scaffold/lib/generators/pg_slim/templates/index.html.slim +1 -1
  109. metadata +44 -10
  110. data/pg_engine/app/controllers/concerns/pg_engine/require_tenant_set.rb +0 -15
  111. data/pg_engine/app/controllers/users/account_switcher_controller.rb +0 -30
  112. data/pg_engine/app/controllers/users/inline_edit_controller.rb +0 -21
  113. data/pg_engine/app/views/users/account_switcher/list.html.slim +0 -24
  114. data/pg_engine/app/views/users/dashboard/dashboard.html.slim +0 -1
  115. data/pg_engine/spec/requests/users/switcher_spec.rb +0 -84
@@ -4,11 +4,46 @@
4
4
 
5
5
  module PgEngine
6
6
  class Configuracion
7
- attr_accessor :users_controller, :global_domains, :navigators
7
+ attr_accessor :users_controller, :global_domains, :navigators, :user_profiles
8
+
9
+ # attr_accessor :profile_groups
8
10
 
9
11
  def initialize
10
12
  @global_domains = ['app.localhost.com', 'test.host', 'localhost']
11
13
  @navigators = [PgEngine::Navigator.new]
14
+ # @profile_groups = [:account]
15
+ @user_profiles = {
16
+ account__owner: 0
17
+ }
18
+ user_profiles.merge!(
19
+ user_accounts__read: 1000 + 1
20
+ )
21
+ # add_profiles(:user_accounts, 1000)
22
+ end
23
+
24
+ def add_profiles(key, base)
25
+ # profile_groups.push(key)
26
+ user_profiles.merge!(
27
+ "#{key}__read": base + 1,
28
+ "#{key}__update": base + 10,
29
+ "#{key}__create": base + 30,
30
+ "#{key}__archive": base + 50,
31
+ "#{key}__export": base + 80,
32
+ "#{key}__destroy": base + 100
33
+ )
34
+ end
35
+
36
+ def profile_groups_options
37
+ groups = user_profiles.keys.map { |v| v.to_s.split('__').first }.uniq
38
+
39
+ groups = groups.excluding('account') unless Current.namespace == :admin
40
+
41
+ groups.map do |group|
42
+ options = user_profiles.keys.select { |va| va.starts_with?(group) }.map do |va|
43
+ [va, I18n.t(va.to_s.split('__').last, scope: 'profile_member')]
44
+ end
45
+ { name: group, options: }
46
+ end
12
47
  end
13
48
  end
14
49
  end
@@ -2,40 +2,17 @@ module PgEngine
2
2
  class Navigator
3
3
  # rubocop:disable Metrics/MethodLength
4
4
  def configure(navbar)
5
- navbar.add_item('sidebar.not_signed_in', {
6
- name: 'Crear una cuenta',
7
- path: 'new_user_registration_path'
8
- })
9
- navbar.add_item('sidebar.not_signed_in', {
10
- name: 'Iniciar sesión',
11
- path: 'new_user_session_path'
12
- })
13
- navbar.add_item('sidebar.not_signed_in', {
14
- name: 'Contacto',
15
- path: 'new_public_mensaje_contacto_path'
16
- })
17
-
18
5
  # *****************************************************
19
6
 
20
7
  navbar.add_item('sidebar.signed_in', {
21
8
  name: 'Inicio',
22
- path: 'users_root_path',
9
+ path: 'tenant_root_path',
23
10
  priority: 0
24
11
  })
25
- navbar.add_item('sidebar.signed_in', {
26
- name: 'Mi perfil',
27
- path: 'edit_user_registration_path',
28
- policy: 'policy(Current.user).edit?'
29
- })
30
- navbar.add_item('sidebar.signed_in', {
31
- name: 'Cerrar sesión',
32
- path: 'destroy_user_session_path',
33
- attributes: 'data-turbo-method="delete"'
34
- })
35
12
 
36
13
  # *****************************************************
37
14
 
38
- return unless Current.user&.developer?
15
+ return unless Current.namespace == :admin
39
16
 
40
17
  navbar.add_item('sidebar.signed_in', {
41
18
  name: 'Eventos',
@@ -1,8 +1,8 @@
1
1
  # :nocov:
2
2
  module PgEngine
3
3
  module Utils
4
- class CheckInvalidRecords
5
- def run
4
+ class ResourceReports
5
+ def check_invalid_records
6
6
  invalids = []
7
7
  classes.each do |klass|
8
8
  klass.find_each do |record|
@@ -19,6 +19,26 @@ module PgEngine
19
19
  end
20
20
  end
21
21
 
22
+ def report(klass)
23
+ if klass.respond_to?(:discarded)
24
+ <<~STRING
25
+ #{klass}.unscoped.count: #{klass.unscoped.count}
26
+ #{klass}.unscoped.kept.count: #{klass.unscoped.kept.count}
27
+ #{klass}.unscoped.unkept.count: #{klass.unscoped.unkept.count}
28
+ #{klass}.unscoped.discarded.count: #{klass.unscoped.discarded.count}
29
+ #{klass}.unscoped.undiscarded.count: #{klass.unscoped.undiscarded.count}
30
+ STRING
31
+ else
32
+ <<~STRING
33
+ #{klass}.unscoped.count: #{klass.unscoped.count}
34
+ STRING
35
+ end
36
+ end
37
+
38
+ def report_all
39
+ classes.map { |klass| report(klass).to_s }.join("\n")
40
+ end
41
+
22
42
  def classes
23
43
  all = ActiveRecord::Base.descendants.select { |m| m.table_name.present? }
24
44
  all - ignored_classes
@@ -28,7 +48,6 @@ module PgEngine
28
48
  [
29
49
  ActionText::Record,
30
50
  ActionMailbox::Record,
31
- ActiveAdmin::Comment,
32
51
  ActiveStorage::Record,
33
52
  PgEngine::BaseRecord,
34
53
  Audited::Audit,
@@ -26,6 +26,7 @@ require 'rainbow'
26
26
  require 'simple_form'
27
27
  require 'devise'
28
28
  require 'devise-i18n'
29
+ require 'devise_invitable'
29
30
  require 'rails-i18n'
30
31
  require 'slim-rails'
31
32
  require 'enumerize'
@@ -45,6 +45,7 @@ RSpec.describe Admin::AccountsController do
45
45
  let(:user) { create :user, :developer }
46
46
 
47
47
  before do
48
+ create :user, :owner
48
49
  sign_in user if user.present?
49
50
  end
50
51
 
@@ -60,7 +61,7 @@ RSpec.describe Admin::AccountsController do
60
61
  get :index, params: {}
61
62
  end
62
63
 
63
- let!(:account) { create :account }
64
+ let!(:account) { create :account, :with_owner }
64
65
 
65
66
  it 'returns a success response' do
66
67
  subject
@@ -99,7 +100,7 @@ RSpec.describe Admin::AccountsController do
99
100
 
100
101
  describe 'GET #show' do
101
102
  it 'returns a success response' do
102
- account = create(:account)
103
+ account = create(:account, :with_owner)
103
104
  get :show, params: { id: account.to_param }
104
105
  expect(response).to be_successful
105
106
  end
@@ -29,7 +29,12 @@ require 'rails_helper'
29
29
 
30
30
  RSpec.describe Admin::UserAccountsController do
31
31
  render_views
32
- let!(:user) { create :user }
32
+ let!(:user) do
33
+ create :user
34
+ end
35
+ let(:user_account) do
36
+ create :user_account, user:, account:
37
+ end
33
38
 
34
39
  let!(:account) { ActsAsTenant.current_tenant }
35
40
 
@@ -64,7 +69,9 @@ RSpec.describe Admin::UserAccountsController do
64
69
  get :index, params: {}
65
70
  end
66
71
 
67
- before { create :user_account }
72
+ before do
73
+ create :user
74
+ end
68
75
 
69
76
  it 'returns a success response' do
70
77
  subject
@@ -94,7 +101,6 @@ RSpec.describe Admin::UserAccountsController do
94
101
 
95
102
  describe 'GET #show' do
96
103
  it 'returns a success response' do
97
- user_account = create(:user_account)
98
104
  get :show, params: { id: user_account.to_param }
99
105
  expect(response).to be_successful
100
106
  end
@@ -109,7 +115,6 @@ RSpec.describe Admin::UserAccountsController do
109
115
 
110
116
  describe 'GET #edit' do
111
117
  it 'returns a success response' do
112
- user_account = create(:user_account)
113
118
  get :edit, params: { id: user_account.to_param }
114
119
  expect(response).to be_successful
115
120
  end
@@ -149,7 +154,6 @@ RSpec.describe Admin::UserAccountsController do
149
154
  end
150
155
 
151
156
  it 'redirects to the user_account' do
152
- user_account = create(:user_account)
153
157
  put :update, params: { id: user_account.to_param, user_account: valid_attributes }
154
158
 
155
159
  expect(response).to redirect_to([:admin, UserAccount.last])
@@ -158,13 +162,11 @@ RSpec.describe Admin::UserAccountsController do
158
162
 
159
163
  context 'with invalid params' do
160
164
  it 'returns a unprocessable_entity response' do
161
- user_account = create(:user_account)
162
165
  put :update, params: { id: user_account.to_param, user_account: invalid_attributes }
163
166
  expect(response).to have_http_status(:unprocessable_entity)
164
167
  end
165
168
 
166
169
  it 'renders the edit template' do
167
- user_account = create(:user_account)
168
170
  put :update, params: { id: user_account.to_param, user_account: invalid_attributes }
169
171
  expect(response).to render_template(:edit)
170
172
  end
@@ -177,11 +179,11 @@ RSpec.describe Admin::UserAccountsController do
177
179
  delete :destroy, params: { id: user_account.to_param, land_on: }
178
180
  end
179
181
 
180
- let!(:user_account) { create :user_account }
181
182
  let(:land_on) { nil }
182
183
 
183
184
  it 'destroys the requested user_account' do
184
- expect { subject }.to change(UserAccount, :count).by(-1)
185
+ user_account
186
+ expect { subject }.to change(UserAccount.unscoped, :count).by(-1)
185
187
  end
186
188
 
187
189
  it 'envía el pg-event' do
@@ -6,5 +6,13 @@ FactoryBot.define do
6
6
  factory :account do
7
7
  plan { Account.plan.values.sample }
8
8
  nombre { Faker::Lorem.sentence }
9
+
10
+ trait :with_owner do
11
+ after(:create) do |model|
12
+ ActsAsTenant.with_tenant(model) do
13
+ create :user, :owner
14
+ end
15
+ end
16
+ end
9
17
  end
10
18
  end
@@ -6,7 +6,7 @@ FactoryBot.define do
6
6
  factory :user_account do
7
7
  association :user
8
8
  association :account
9
- profiles { [UserAccount.profiles.values.sample] }
9
+ profiles { [] }
10
10
 
11
11
  trait :user_existente do
12
12
  user { nil }
@@ -68,5 +68,11 @@ FactoryBot.define do
68
68
  trait :developer do
69
69
  developer { true }
70
70
  end
71
+
72
+ trait :owner do
73
+ user_accounts do
74
+ [build(:user_account, account: ActsAsTenant.current_tenant, profiles: [:account__owner])]
75
+ end
76
+ end
71
77
  end
72
78
  end
@@ -0,0 +1,27 @@
1
+ require 'rails_helper'
2
+
3
+ describe PgEngine::ChildRecord do
4
+ describe '#parent_accessor' do
5
+ it 'the values are independent from each class' do
6
+ model_class = Class.new(PgEngine::BaseRecord)
7
+ another_model_class = Class.new(PgEngine::BaseRecord)
8
+ model_class.include described_class
9
+ another_model_class.include described_class
10
+ model_class.parent_accessor = :one
11
+ another_model_class.parent_accessor = :two
12
+ expect(model_class.parent_accessor).to be :one
13
+ expect(another_model_class.parent_accessor).to be :two
14
+ expect { described_class.parent_accessor }.to raise_error(NoMethodError)
15
+ end
16
+ end
17
+
18
+ describe '#parent?' do
19
+ it do
20
+ expect(create(:cosa)).to be_parent
21
+ end
22
+
23
+ it do
24
+ expect(create(:categoria_de_cosa)).not_to be_parent
25
+ end
26
+ end
27
+ end
@@ -8,6 +8,10 @@ RSpec.describe UserAccount do
8
8
  let(:user_account) { create(:user_account) }
9
9
 
10
10
  it 'se persiste' do
11
- expect(user_account).to be_persisted
11
+ ActsAsTenant.without_tenant do
12
+ expect(user_account).to be_persisted
13
+ expect(User.count).to eq 1
14
+ expect(described_class.count).to eq 1
15
+ end
12
16
  end
13
17
  end
@@ -5,10 +5,12 @@
5
5
  require 'rails_helper'
6
6
 
7
7
  RSpec.describe User do
8
- let(:user) { create(:user) }
8
+ let(:user) { create(:user, :owner) }
9
9
 
10
10
  it 'se persiste' do
11
11
  expect(user).to be_persisted
12
+ expect(UserAccount.unscoped.count).to eq 1
13
+ expect(UserAccount.first.profiles).to include(:account__owner)
12
14
  end
13
15
 
14
16
  it do
@@ -21,28 +23,4 @@ RSpec.describe User do
21
23
  expect(results).to eq [user]
22
24
  end
23
25
  end
24
-
25
- describe 'default scope' do
26
- before do
27
- ActsAsTenant.current_tenant = nil
28
- ActsAsTenant.test_tenant = nil
29
- Current.reset
30
- end
31
-
32
- it 'scopes according to tenant' do
33
- account = create(:account)
34
- other_account = create(:account)
35
- usr1 = usr2 = usr3 = usr4 = nil
36
- ActsAsTenant.with_tenant(other_account) do
37
- usr3 = create(:user)
38
- usr4 = create(:user)
39
- end
40
- ActsAsTenant.with_tenant(account) do
41
- usr1 = create(:user)
42
- usr2 = create(:user)
43
- expect(described_class.all).to contain_exactly(usr1, usr2)
44
- end
45
- expect(described_class.all).to contain_exactly(usr1, usr2, usr3, usr4)
46
- end
47
- end
48
26
  end
@@ -0,0 +1,19 @@
1
+ require 'rails_helper'
2
+
3
+ describe AccountPolicy do
4
+ subject do
5
+ described_class.new(user, account)
6
+ end
7
+
8
+ let(:account) { ActsAsTenant.current_tenant }
9
+ let(:user) { create :user, account: }
10
+
11
+ it do
12
+ expect(subject).to permit(:show)
13
+ end
14
+
15
+ it do
16
+ user.user_accounts.first.update(membership_status: :disabled)
17
+ expect(subject).to permit(:show)
18
+ end
19
+ end
@@ -0,0 +1,196 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec::Matchers.define_negated_matcher :not_change, :change
4
+
5
+ describe 'invite users to the platform and to an account' do
6
+ let(:account) { ActsAsTenant.current_tenant }
7
+
8
+ describe 'send an invitation to the platform', :tpath_req do
9
+ let(:logged_user) { create :user, :owner }
10
+
11
+ before do
12
+ sign_in logged_user
13
+ end
14
+
15
+ describe 'new' do
16
+ it 'shows the form' do
17
+ get '/users/invitation/new'
18
+ expect(response).to have_http_status(:ok)
19
+ expect(response.body).to have_text('Agregar usuario')
20
+ end
21
+ end
22
+
23
+ describe 'create' do
24
+ subject do
25
+ post '/users/invitation', params:
26
+ end
27
+
28
+ let(:email) { Faker::Internet.email }
29
+ let(:params) do
30
+ {
31
+ user: {
32
+ email:,
33
+ user_accounts_attributes: [{
34
+ profiles: ['cosas__read']
35
+ }]
36
+ }
37
+ }
38
+ end
39
+
40
+ it 'creates the User and the UserAccount' do
41
+ expect { subject }.to change(User.unscoped, :count).by(1).and(change(UserAccount.unscoped, :count).by(1))
42
+ expect(UserAccount.last.profiles).to contain_exactly('cosas__read')
43
+ end
44
+
45
+ context 'when the user exists but not the user account' do
46
+ let!(:other_user) do
47
+ ActsAsTenant.without_tenant do
48
+ create :user
49
+ end
50
+ end
51
+ let(:email) { other_user.email }
52
+
53
+ it 'creates the UserAccount but not the User' do
54
+ expect { subject }.to not_change(User.unscoped, :count).and(change(UserAccount.unscoped, :count).by(1))
55
+ end
56
+ end
57
+
58
+ context 'when the user exists but is discarded' do
59
+ let!(:other_user) do
60
+ ActsAsTenant.without_tenant do
61
+ create :user, discarded_at: Time.current
62
+ end
63
+ end
64
+ let(:email) { other_user.email }
65
+
66
+ it 'doesnt create any' do
67
+ expect { subject }.to not_change(User.unscoped, :count).and(not_change(UserAccount.unscoped, :count))
68
+ expect(response).to have_http_status(:unprocessable_entity)
69
+ end
70
+ end
71
+
72
+ context 'when the user belongs to the account' do
73
+ let(:email) { logged_user.email }
74
+
75
+ it 'doesnt create any' do
76
+ expect { subject }.to not_change(User.unscoped, :count).and(not_change(UserAccount.unscoped, :count))
77
+ expect(response).to have_http_status(:unprocessable_entity)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ describe 'accept an invitation to the platform and to the account' do
84
+ subject do
85
+ put '/users/invitation', params: {
86
+ user: {
87
+ nombre: Faker::Name.first_name,
88
+ apellido: Faker::Name.last_name,
89
+ password: 'asd12345',
90
+ password_confirmation: 'asd12345',
91
+ accept_terms: '1',
92
+ invitation_token: user.raw_invitation_token
93
+ }
94
+ }
95
+ end
96
+
97
+ let(:user) do
98
+ User.invite!({ email: Faker::Internet.email, user_accounts_attributes: [{ profiles: [] }] })
99
+ end
100
+
101
+ it do
102
+ expect(user.user_accounts.length).to eq 1
103
+ user_account = user.user_accounts.first
104
+ expect(user_account.invitation_status).to eq 'ist_invited'
105
+ expect { subject }.to change { user.reload.invitation_accepted_at }.to(be_present)
106
+ put "/u/espacios/#{account.to_param}/update_invitation", params: { accept: 1 }
107
+ expect(user_account.reload.invitation_status).to eq 'ist_accepted'
108
+ end
109
+ end
110
+
111
+ describe 'update an invitation' do
112
+ let(:logged_user) { create :user, account: }
113
+ let(:user_account) do
114
+ logged_user.user_accounts.first
115
+ end
116
+
117
+ before do
118
+ sign_in logged_user
119
+ user_account.update(membership_status:, invitation_status: :ist_invited)
120
+ end
121
+
122
+ context 'when accepting an invite' do
123
+ subject do
124
+ put "/u/espacios/#{account.to_param}/update_invitation", params: { accept: 1 }
125
+ end
126
+
127
+ let(:membership_status) { :ms_active }
128
+
129
+ it do
130
+ expect { subject }.to change { user_account.reload.invitation_status }.to('ist_accepted')
131
+ end
132
+
133
+ pending 'and doesnt belong to the account'
134
+ end
135
+
136
+ context 'when rejecting an invite' do
137
+ subject do
138
+ put "/u/espacios/#{account.to_param}/update_invitation", params: { reject: 1 }
139
+ end
140
+
141
+ let(:membership_status) { :ms_active }
142
+
143
+ it do
144
+ expect { subject }.to change { user_account.reload.invitation_status }.to('ist_rejected')
145
+ end
146
+ end
147
+
148
+ context 'when signing off the account' do
149
+ subject do
150
+ put "/u/espacios/#{account.to_param}/update_invitation", params: { sign_off: 1 }
151
+ end
152
+
153
+ let(:membership_status) { %i[ms_active ms_disabled].sample }
154
+
155
+ it do
156
+ expect { subject }.to change { user_account.reload.invitation_status }.to('ist_signed_off')
157
+ end
158
+ end
159
+ end
160
+
161
+ describe 'remove an invitation', :tpath_req do
162
+ subject do
163
+ delete "/u/t/user_accounts/#{user_account.to_param}"
164
+ end
165
+
166
+ let(:logged_user) { create :user, :owner }
167
+ let(:user_account) do
168
+ user.user_accounts.first
169
+ end
170
+ let!(:user) do
171
+ User.invite!({ email: Faker::Internet.email, user_accounts_attributes: [{ profiles: [] }] })
172
+ end
173
+
174
+ before do
175
+ sign_in logged_user
176
+ end
177
+
178
+ context 'when the user is confirmed' do
179
+ before do
180
+ user.nombre = Faker::Name.first_name
181
+ user.apellido = Faker::Name.last_name
182
+ user.accept_invitation!
183
+ end
184
+
185
+ it 'removes the UserAccount but not the User' do
186
+ expect { subject }.to change { UserAccount.unscoped.count }.by(-1).and(not_change(User.unscoped, :count))
187
+ end
188
+ end
189
+
190
+ context 'when the user is not confirmed' do
191
+ it 'removes both the UserAccount and the User' do
192
+ expect { subject }.to change { UserAccount.unscoped.count }.by(-1).and(change(User.unscoped, :count).by(-1))
193
+ end
194
+ end
195
+ end
196
+ end
@@ -1,7 +1,7 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe 'Resources' do
4
- let(:user) { create :user }
3
+ describe 'Resources', :tpath_req do
4
+ let(:user) { create :user, :owner }
5
5
  let(:cosa) { create :cosa }
6
6
 
7
7
  before do
@@ -10,34 +10,33 @@ describe 'Resources' do
10
10
 
11
11
  describe 'action links' do
12
12
  it 'shows the archive link' do
13
- get '/u/cosas/' + cosa.to_param
13
+ get '/u/t/cosas/' + cosa.to_param
14
14
  expect(response).to have_http_status(:ok)
15
- regex = %r{<a data-turbo-method="post" .* href="/u/cosas/[\d]+/archive">}
16
- expect(response.body).to match regex
15
+ expect(response.body).to have_css('span[title="Archivar"] a')
17
16
  end
18
17
 
19
18
  it 'shows the unarchive link' do
20
19
  cosa.update(discarded_at: Time.current)
21
- get '/u/cosas/' + cosa.to_param
22
- expect(response.body).to have_link(href: %r{/u/cosas/[\d]+/restore})
20
+ get '/u/t/cosas/' + cosa.to_param
21
+ expect(response.body).to have_link(href: %r{/u/t/.*/cosas/[\d]+/restore})
23
22
  end
24
23
  end
25
24
 
26
25
  describe 'set breadcrumbs for all actions' do
27
26
  it 'when flat archived index' do
28
- get '/u/cosas/archived'
29
- expect(response.body).to have_css('.breadcrumb a[href="/u/cosas"]')
27
+ get '/u/t/cosas/archived'
28
+ expect(response.body).to have_css('.breadcrumb a[href*="/cosas"]')
30
29
  end
31
30
 
32
31
  it 'when nested archived index' do
33
- get "/u/categoria_de_cosas/#{cosa.categoria_de_cosa.to_param}/cosas/archived"
32
+ get "/u/t/categoria_de_cosas/#{cosa.categoria_de_cosa.to_param}/cosas/archived"
34
33
  expect(response.body).to \
35
- have_css ".breadcrumb a[href=\"/u/categoria_de_cosas/#{cosa.categoria_de_cosa.to_param}/cosas\"]"
34
+ have_css ".breadcrumb a[href*=\"/categoria_de_cosas/#{cosa.categoria_de_cosa.to_param}/cosas\"]"
36
35
  end
37
36
  end
38
37
 
39
38
  describe '#archive' do
40
- let(:url) { "/u/cosas/#{cosa.to_param}/archive" }
39
+ let(:url) { "/u/t/cosas/#{cosa.to_param}/archive" }
41
40
 
42
41
  it 'when accepts turbo stream' do
43
42
  headers = { 'ACCEPT' => 'text/vnd.turbo-stream.html' }
@@ -47,7 +46,7 @@ describe 'Resources' do
47
46
 
48
47
  it 'when accepts only html' do
49
48
  expect { post url }.to change { cosa.reload.discarded_at }.to(be_present)
50
- expect(response).to redirect_to([:users, cosa])
49
+ expect(response).to redirect_to([:tenant, cosa])
51
50
  end
52
51
 
53
52
  context 'when fails' do
@@ -64,7 +63,7 @@ describe 'Resources' do
64
63
 
65
64
  it 'when accepts only html' do
66
65
  post url
67
- expect(response).to redirect_to([:users, cosa])
66
+ expect(response).to redirect_to([:tenant, cosa])
68
67
  expect(flash[:alert]).to eq 'Hubo un error al intentar actualizar el coso'
69
68
  end
70
69
  end
@@ -72,7 +71,7 @@ describe 'Resources' do
72
71
 
73
72
  describe '#restore' do
74
73
  subject do
75
- post "/u/cosas/#{cosa.to_param}/restore"
74
+ post "/u/t/cosas/#{cosa.to_param}/restore"
76
75
  end
77
76
 
78
77
  let(:cosa) { create :cosa, discarded_at: Time.zone.now }