voyage 1.44.0.9 → 1.44.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34805db52fd3603e41eb324e307c4c5fca0e05af
4
- data.tar.gz: 62e934b8eb5fae05b49f229c0795888d41fa1c96
3
+ metadata.gz: d2d85038fd4f02fe75a941bfbeb66bfb7c1ae2fc
4
+ data.tar.gz: 00f7aa3152f0e7ec2bc036420d0f96a87926690b
5
5
  SHA512:
6
- metadata.gz: a41c3764da14b591fd920a1c44c59bd7576351ad6b967120609d930f3975c5498db0d671f99c060420bf9f762c43b588ece957abf6752559d486eb1f53946585
7
- data.tar.gz: 0ab410d991d66a534598e5b285f986f4301bc273ef24b8c6793babb308f1af6886c70bbc9f2ce9b58883c1b511504db09997bb37fef7a71a2236a78bc70f9688
6
+ metadata.gz: 60ea2891a535d8abc0f216f5801f3cadbf37a97541b1fb5deaa2b9dae70d390d919e6fafe930b22145b9f6b6253881b72c4f85ee81aadf51920439187a413357
7
+ data.tar.gz: 3309b6cefdefdc3696329becf3c23960fdd590f0ffd046f3122ca806ddf91db4e91c65f6c5c34752f61ab44da5f4250ab264494ab474c06636f21db52bc1c3e8
@@ -86,6 +86,11 @@ module Suspenders
86
86
  def install_devise
87
87
  if @@accept_defaults || agree?('Would you like to install Devise? (Y/n)')
88
88
  @@use_devise = true
89
+
90
+ if @@accept_defaults || agree?('Would you like to install Devise token authentication? (Y/n)')
91
+ devise_token_auth = true
92
+ end
93
+
89
94
  bundle_command 'exec rails generate devise:install'
90
95
 
91
96
  if @@accept_defaults || agree?("Would you like to add first_name and last_name to the devise model? (Y/n)")
@@ -112,7 +117,7 @@ module Suspenders
112
117
  end
113
118
 
114
119
  customize_devise_views if adding_first_and_last_name
115
- customize_application_controller_for_devise(adding_first_and_last_name)
120
+ customize_application_controller_for_devise(adding_first_and_last_name, devise_token_auth)
116
121
  add_devise_registrations_controller
117
122
  customize_resource_controller_for_devise(adding_first_and_last_name)
118
123
  add_admin_views_for_devise_resource(adding_first_and_last_name)
@@ -124,6 +129,7 @@ module Suspenders
124
129
  customize_user_factory(adding_first_and_last_name)
125
130
  generate_seeder_templates(using_devise: true)
126
131
  customize_user_spec
132
+ add_token_auth
127
133
  else
128
134
  generate_seeder_templates(using_devise: false)
129
135
  end
@@ -149,7 +155,7 @@ module Suspenders
149
155
  end
150
156
  end
151
157
 
152
- def customize_application_controller_for_devise(adding_first_and_last_name)
158
+ def customize_application_controller_for_devise(adding_first_and_last_name, devise_token_auth)
153
159
  inject_into_file 'app/controllers/application_controller.rb', before: "class ApplicationController < ActionController::Base" do <<-RUBY.gsub(/^ {8}/, '')
154
160
  # rubocop:disable Metrics/ClassLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/LineLength
155
161
  RUBY
@@ -159,6 +165,7 @@ module Suspenders
159
165
 
160
166
  check_authorization unless: :devise_or_pages_controller?
161
167
  impersonates :user
168
+ #{'acts_as_token_authentication_handler_for User' if devise_token_auth}
162
169
 
163
170
  before_action :configure_permitted_parameters, if: :devise_controller?
164
171
  before_action :authenticate_user!, unless: -> { is_a?(HighVoltage::PagesController) }
@@ -316,6 +323,7 @@ module Suspenders
316
323
  end
317
324
 
318
325
  template '../templates/admin_users_controller.rb', 'app/controllers/admin/users_controller.rb'
326
+ template '../templates/admin_controller.rb', 'app/controllers/admin/admin_controller.rb'
319
327
  end
320
328
 
321
329
  def authorize_devise_resource_for_index_action
@@ -508,11 +516,45 @@ module Suspenders
508
516
  expect(user.tester?).to eq(false)
509
517
  end
510
518
  end
519
+
520
+ context 'new user creation' do
521
+ it 'ensures uniqueness of the uuid' do
522
+ allow(User).to receive(:exists?).and_return(true, false)
523
+
524
+ expect do
525
+ create(:user)
526
+ end.to change { User.count }.by(1)
527
+
528
+ expect(User).to have_received(:exists?).exactly(2).times
529
+ end
530
+ end
511
531
  RUBY
512
532
 
513
533
  replace_in_file 'spec/models/user_spec.rb', find, replace
514
534
  end
515
535
 
536
+ def add_token_auth
537
+ inject_into_file 'app/models/user.rb', after: "class User < ApplicationRecord" do <<-'RUBY'.gsub(/^ {6}/, '')
538
+
539
+ acts_as_token_authenticatable
540
+ RUBY
541
+ end
542
+
543
+ generate 'migration add_authentication_token_to_users "authentication_token:string{30}:uniq"'
544
+
545
+ # specs
546
+ template '../templates/specs/features/user_impersonation_spec.rb', 'spec/features/user_impersonation_spec.rb', force: true
547
+ template '../templates/specs/features/user_list_spec.rb', 'spec/features/user_list_spec.rb', force: true
548
+ template '../templates/specs/features/user_signup_spec.rb', 'spec/features/user_signup_spec.rb', force: true
549
+ template '../templates/specs/requests/user_api_spec.rb', 'spec/requests/user_api_spec.rb', force: true
550
+ template '../templates/specs/support/api/schemas/user.json', 'spec/support/api/schemas/user.json', force: true
551
+ template '../templates/config_initializers_ams.rb', 'config/initializers/ams.rb', force: true
552
+ template '../templates/specs/support/matchers/api_schema_matcher.rb', 'spec/support/matchers/api_schema_matcher.rb', force: true
553
+ template '../templates/specs/mailers/application_mailer_spec.rb.erb', 'spec/mailers/application_mailer_spec.rb', force: true
554
+ template '../templates/specs/support/features/session_helpers.rb', 'spec/support/features/session_helpers.rb', force: true
555
+ template '../templates/specs/support/request_spec_helper.rb', 'spec/support/request_spec_helper.rb', force: true
556
+ end
557
+
516
558
  def customize_application_js
517
559
  template '../templates/application.js', 'app/assets/javascripts/application.js', force: true
518
560
 
@@ -712,6 +754,20 @@ module Suspenders
712
754
  template '../templates/favicon.ico', 'app/assets/images/favicon.ico', force: true
713
755
  end
714
756
 
757
+ def customize_application_mailer
758
+ template '../templates/application_mailer.rb.erb', 'app/mailers/application_mailer.rb', force: true
759
+ end
760
+
761
+ def add_specs
762
+ inject_into_file 'app/jobs/application_job.rb', before: "class ApplicationJob < ActiveJob::Base" do <<-RUBY.gsub(/^ {8}/, '')
763
+ # :nocov:
764
+ RUBY
765
+ end
766
+
767
+ template '../templates/specs/controllers/admin/users_controller_spec.rb', 'spec/controllers/admin/users_controller_spec.rb', force: true
768
+ template '../templates/specs/controllers/application_controller_spec.rb', 'spec/controllers/application_controller_spec.rb', force: true
769
+ end
770
+
715
771
  # Do this last
716
772
  def rake_db_setup
717
773
  rake 'db:migrate'
@@ -750,6 +806,7 @@ module Suspenders
750
806
  .zenflow-log
751
807
  errors.err
752
808
  .ctags
809
+ .cadre/coverage.vim
753
810
  RUBY
754
811
  end
755
812
  end
@@ -43,6 +43,8 @@ module Suspenders
43
43
  invoke :add_auto_annotate_models_rake_task
44
44
  invoke :update_delayed_job_migration_rails_5_1_specify_4_2
45
45
  invoke :add_favicon
46
+ invoke :customize_application_mailer
47
+ invoke :add_specs
46
48
 
47
49
 
48
50
  # Do these last
@@ -137,6 +139,14 @@ module Suspenders
137
139
  build :add_favicon
138
140
  end
139
141
 
142
+ def customize_application_mailer
143
+ build :customize_application_mailer
144
+ end
145
+
146
+ def add_specs
147
+ build :add_specs
148
+ end
149
+
140
150
  def spin_up_webpacker
141
151
  build :spin_up_webpacker
142
152
  end
@@ -41,8 +41,10 @@ gem 'canard', git: 'https://github.com/jondkinney/canard.git', branch: 'feature/
41
41
  gem 'cancancan' # authorization library
42
42
  gem 'devise'
43
43
  gem 'pretender' # impersonate users as an admin
44
+ gem 'simple_token_authentication', '~> 1.0' # adds token authentication to Devise
44
45
 
45
46
  # Database Tweaks
47
+ gem 'active_model_serializers', '~> 0.10.0'
46
48
  gem 'dynamic_form' # for custom messages without the database column
47
49
  gem 'friendly_id' # slugs in the url auto-generated
48
50
  gem 'nested_form_fields' # Dynamically add and remove nested has_many association fields in a Ruby on Rails form
@@ -80,7 +82,6 @@ group :development do
80
82
  gem 'fix-db-schema-conflicts' # when working with multiple developers schema order of columns is standardized.
81
83
  gem 'meta_request' # for chrome rails console plugin found here: https://chrome.google.com/webstore/detail/railspanel/gjpfobpafnhjhbajcjgccbbdofdckggg?hl=en-US
82
84
  gem 'rails-erd' # auto gen ERD Diagram of models in the app on rake db:migrate
83
- gem 'redcarpet' # used to render the readme inside a static welcome page from the high_voltage gem
84
85
  gem 'zenflow', git: 'https://github.com/zencoder/zenflow.git'
85
86
  end
86
87
 
@@ -89,16 +90,16 @@ group :development, :test do
89
90
  gem "bullet"
90
91
  gem "bundler-audit", ">= 0.5.0", require: false
91
92
  gem "dotenv-rails"
92
- gem "factory_girl_rails"
93
+ <%# gem "factory_girl_rails" %>
93
94
  <%# gem "pry-byebug" %>
94
95
  <%# gem "pry-rails" %>
95
96
  gem "rspec-rails", "~> 3.5"
96
97
 
97
98
  # Customizations
98
- gem 'faker' # provides auto generated names for factories, can be customized
99
99
  gem 'letter_opener' # auto-open emails when they're sent
100
100
  gem 'rubocop'
101
101
  gem 'rubocop-rspec', require: false
102
+ gem 'redcarpet' # used to render the readme inside a static welcome page from the high_voltage gem
102
103
  end
103
104
 
104
105
  group :development, :staging do
@@ -118,10 +119,17 @@ group :test do
118
119
  # Customizations
119
120
  gem 'cadre' # highlights code coverage in vim
120
121
  gem 'capybara' # DSL for finding elements on a page during integration testing
122
+ gem 'json-schema' # Allows testing API responses against JSON schema
121
123
  gem 'poltergeist' # Headless browser, used in integration tests
124
+ gem 'rspec_junit_formatter' # Creates JUnit style XML for use in CircleCI
122
125
  gem 'selenium-webdriver' # `brew install chromedriver`, used for acceptance tests in an actual browser.
123
126
  end
124
127
 
128
+ group :development, :test, :staging do
129
+ gem 'factory_girl_rails'
130
+ gem 'faker' # provides auto generated names for factories, can be customized
131
+ end
132
+
125
133
  group :staging, :production do
126
134
  gem "rack-timeout"
127
135
  end
@@ -0,0 +1,13 @@
1
+ module Admin
2
+ class AdminController < ApplicationController
3
+ before_action :require_admin!
4
+ skip_authorization_check
5
+
6
+ private
7
+
8
+ def require_admin!
9
+ txt = 'You must be an admin to perform that action'
10
+ redirect_to root_path, alert: txt unless current_user.admin?
11
+ end
12
+ end
13
+ end
@@ -1,10 +1,12 @@
1
1
  module Admin
2
- class UsersController < ApplicationController
3
- before_action :require_admin!, except: [:stop_impersonating]
4
- skip_authorization_check
2
+ class UsersController < AdminController
3
+ skip_before_action :require_admin!, only: [:stop_impersonating]
4
+ respond_to :html, :json
5
5
 
6
6
  def index
7
7
  @users = User.all
8
+
9
+ respond_with(@users)
8
10
  end
9
11
 
10
12
  def impersonate
@@ -22,11 +24,6 @@ module Admin
22
24
 
23
25
  private
24
26
 
25
- def require_admin!
26
- txt = 'You must be an admin to perform that action'
27
- redirect_to root_path, notice: txt unless current_user.admin?
28
- end
29
-
30
27
  def track_impersonation(user, status)
31
28
  analytics_track(
32
29
  true_user,
@@ -0,0 +1,11 @@
1
+ class ApplicationMailer < ActionMailer::Base
2
+ default from: "no-reply@<%= app_name %>.com",
3
+ return_path: "contact@<%= app_name %>.com"
4
+
5
+ layout 'mailer'
6
+
7
+ def email(to_address, subject, body)
8
+ options = { to: to_address, subject: subject, body: body }
9
+ mail options
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ ActiveModelSerializers.config.adapter = :json_api
@@ -7,11 +7,7 @@ module DeviseCustomizations
7
7
  protected
8
8
 
9
9
  def after_sign_up_path_for(resource)
10
- if user_signed_in?
11
- analytics_alias_user_path(resource)
12
- else
13
- new_user_session_path(resource)
14
- end
10
+ analytics_alias_user_path(resource)
15
11
  end
16
12
  end
17
13
  end
@@ -37,8 +37,9 @@ RSpec.configure do |config|
37
37
 
38
38
  config.use_transactional_fixtures = false
39
39
 
40
- config.include Devise::TestHelpers, type: :controller
41
- config.include ControllerHelpers, type: :controller
40
+ config.include Devise::Test::ControllerHelpers, type: :controller
41
+ config.include RequestSpecHelper, type: :request
42
+ config.include Features::SessionHelpers, type: :feature
42
43
  # config.include Paperclip::Shoulda::Matchers
43
44
 
44
45
  Capybara.javascript_driver = :poltergeist
@@ -15,6 +15,19 @@ RSpec/FilePath:
15
15
  RSpec/LeadingSubject:
16
16
  Enabled: false
17
17
 
18
+ Metrics/BlockLength:
19
+ Exclude:
20
+ - 'spec/**/*'
21
+
22
+ RSpec/NestedGroups:
23
+ Max: 6
24
+
25
+ RSpec/MultipleExpectations:
26
+ Max: 2
27
+
28
+ RSpec/ExampleLength:
29
+ Max: 15
30
+
18
31
  Rails:
19
32
  Enabled: true
20
33
 
@@ -39,6 +52,7 @@ AllCops:
39
52
  - 'config/initializers/wrap_parameters.rb'
40
53
  - 'bin/**/*'
41
54
  - 'Rakefile'
55
+ - 'node_modules/**/*'
42
56
  Include:
43
57
  - 'Gemfile'
44
58
  - '.simplecov'
@@ -1,4 +1,4 @@
1
- if ENV['COVERAGE'].match?(/\Atrue\z/i)
1
+ if ENV['COVERAGE'] && ENV['COVERAGE'].match?(/\Atrue\z/i)
2
2
  require 'cadre/simplecov'
3
3
 
4
4
  SimpleCov.start do
@@ -9,6 +9,7 @@ if ENV['COVERAGE'].match?(/\Atrue\z/i)
9
9
  add_group 'Helpers', 'app/helpers'
10
10
  add_group 'Mailers', 'app/mailers'
11
11
  add_group 'Models', 'app/models'
12
+ add_group 'Abilities', 'app/abilities'
12
13
  add_group 'Serializers', 'app/serializers'
13
14
  add_group 'Services', 'app/services'
14
15
  add_group 'Workers', 'app/workers'
@@ -19,6 +20,10 @@ if ENV['COVERAGE'].match?(/\Atrue\z/i)
19
20
  add_group 'Ignored Code' do |src_file|
20
21
  File.readlines(src_file.filename).grep(/:nocov:/).any?
21
22
  end
23
+
24
+ add_filter 'app/channels'
25
+ add_filter 'lib/tasks'
26
+ add_filter 'lib/seeder'
22
27
  end
23
28
 
24
29
  SimpleCov.formatters = [
@@ -0,0 +1,69 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Admin::UsersController, type: :request do
4
+ let(:admin_user) { create(:user, :admin) }
5
+ let(:user) { create(:user) }
6
+
7
+ describe '#index' do
8
+ context 'authenticated' do
9
+ context 'admin' do
10
+ it 'loads all users in the browser' do
11
+ sign_in(admin_user)
12
+ get admin_users_path
13
+ expect(response).to be_success
14
+ end
15
+
16
+ it 'lists all users as json' do
17
+ token_header_params = {
18
+ 'X-User-Email': admin_user.email,
19
+ 'X-User-Token': admin_user.authentication_token,
20
+ }
21
+
22
+ get admin_users_url, headers: token_header_params, as: :json
23
+
24
+ expect(response.content_type).to eq('application/json')
25
+ expect(response).to have_http_status(:success)
26
+ end
27
+ end
28
+
29
+ context 'user' do
30
+ it 'redirects with an alert that you need to be an admin' do
31
+ sign_in(user)
32
+ get admin_users_path
33
+ expect(response).to be_redirect
34
+
35
+ txt = 'You must be an admin to perform that action'
36
+ expect(flash[:alert]).to eq(txt)
37
+ end
38
+ end
39
+ end
40
+
41
+ context 'NOT authenticated' do
42
+ it 'redirects to sign in page with an alert' do
43
+ get admin_users_path
44
+ expect(response).to be_redirect
45
+
46
+ txt = 'You need to sign in or sign up before continuing.'
47
+ expect(flash[:alert]).to eq(txt)
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#impersonate' do
53
+ it 'changes the current user from admin to the specified user' do
54
+ sign_in(admin_user)
55
+ get impersonate_admin_user_path(user)
56
+ expect(controller.current_user).to eq(user)
57
+ end
58
+ end
59
+
60
+ describe '#stop_impersonating' do
61
+ it 'returns the current_user to the admin user' do
62
+ sign_in(admin_user)
63
+ get impersonate_admin_user_path(user)
64
+ expect(controller.current_user).to eq(user)
65
+ get stop_impersonating_admin_users_path
66
+ expect(controller.current_user).to eq(admin_user)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,81 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe ApplicationController, type: :controller do
4
+ let(:user) { create(:user) }
5
+ let(:admin_user) { create(:user, :admin) }
6
+
7
+ controller do
8
+ skip_authorization_check only: :show
9
+
10
+ def index
11
+ raise CanCan::AccessDenied
12
+ end
13
+
14
+ def show
15
+ render body: 'show called'
16
+ end
17
+ end
18
+
19
+ context 'errors' do
20
+ it 'rescues from cancan errors and redirects' do
21
+ sign_in(user)
22
+ get :index
23
+ expect(response).to be_redirect
24
+ end
25
+ end
26
+
27
+ context 'analytics' do
28
+ before do
29
+ allow(user).to receive(:tester?).and_return(false)
30
+ allow(Analytics).to receive(:track)
31
+ end
32
+
33
+ it 'tracks with some global defaults' do
34
+ controller.analytics_track(user, 'Signed In', page_name: 'Page')
35
+ expect(Analytics).to have_received(:track)
36
+ end
37
+
38
+ it 'trys to pull roles on a non-user object' do
39
+ allow(user).to receive(:roles).and_return(StandardError.new('bazinga'))
40
+ controller.analytics_track(user, 'Signed In', page_name: 'Page')
41
+ expect(Analytics).to have_received(:track)
42
+ end
43
+ end
44
+
45
+ context 'variants' do
46
+ it 'allows iPad variants' do
47
+ request.env['HTTP_USER_AGENT'] = 'iPad'
48
+ sign_in(user)
49
+ get :show, params: { id: 'anyid' }
50
+ expect(request.variant).to include(:tablet)
51
+ end
52
+
53
+ it 'allows iPhone variants' do
54
+ request.env['HTTP_USER_AGENT'] = 'iPhone'
55
+ sign_in(user)
56
+ get :show, params: { id: 'anyid' }
57
+ expect(request.variant).to include(:phone)
58
+ end
59
+
60
+ it 'allows Android phone variants' do
61
+ request.env['HTTP_USER_AGENT'] = 'Android mobile'
62
+ sign_in(user)
63
+ get :show, params: { id: 'anyid' }
64
+ expect(request.variant).to include(:phone)
65
+ end
66
+
67
+ it 'allows Android tablet variants' do
68
+ request.env['HTTP_USER_AGENT'] = 'Android'
69
+ sign_in(user)
70
+ get :show, params: { id: 'anyid' }
71
+ expect(request.variant).to include(:tablet)
72
+ end
73
+
74
+ it 'allows Windows phone variants' do
75
+ request.env['HTTP_USER_AGENT'] = 'Windows Phone'
76
+ sign_in(user)
77
+ get :show, params: { id: 'anyid' }
78
+ expect(request.variant).to include(:phone)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,38 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'Impersonate user' do
4
+ given(:admin_user) { create(:user, :admin) }
5
+ given(:regular_user) { create(:user) }
6
+
7
+ scenario 'With admin privileges' do
8
+ sign_in(admin_user.email, admin_user.password)
9
+
10
+ visit impersonate_admin_user_path(id: regular_user.id)
11
+
12
+ expect(page).to have_content('Stop Impersonating')
13
+ end
14
+
15
+ scenario 'With admin privileges: End Impersonation' do
16
+ sign_in(admin_user.email, admin_user.password)
17
+
18
+ visit impersonate_admin_user_path(id: regular_user.id)
19
+ visit stop_impersonating_admin_users_path
20
+
21
+ expect(page).to_not have_content('Stop Impersonating')
22
+ end
23
+
24
+ scenario 'Without admin privileges' do
25
+ sign_in(regular_user.email, regular_user.password)
26
+
27
+ visit impersonate_admin_user_path(id: admin_user.id)
28
+
29
+ expect(page).to have_content('You must be an admin to perform that action')
30
+ end
31
+
32
+ scenario 'Stop impersonating when not impersonating' do
33
+ visit stop_impersonating_admin_users_path
34
+
35
+ expect(page)
36
+ .to have_content('You need to sign in or sign up before continuing.')
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'Retrieve user list from browser' do
4
+ scenario 'without admin privileges' do
5
+ user = create(:user)
6
+
7
+ sign_in(user.email, user.password)
8
+ visit admin_users_path
9
+
10
+ expect(page).to have_content('You must be an admin to perform that action')
11
+ end
12
+
13
+ scenario 'with admin privileges' do
14
+ user = create(:user, :admin)
15
+
16
+ sign_in(user.email, user.password)
17
+ visit admin_users_path
18
+
19
+ expect(page).to have_content(user.email)
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_helper'
2
+
3
+ feature 'User signup' do
4
+ scenario 'Valid user information' do
5
+ sign_up_with('First', 'Last', 'test@example.com', 'password', 'password')
6
+ expect(page).to have_content('Welcome! You have signed up successfully.')
7
+ end
8
+
9
+ scenario 'Passwords do not match' do
10
+ sign_up_with('First', 'Last', 'test@example.com', 'password', 'password2')
11
+ expect(page).to have_content("doesn't match Password")
12
+ end
13
+
14
+ scenario 'Email is invalid' do
15
+ sign_up_with('First', 'Last', 'test2example.com', 'password', 'password')
16
+ expect(page).to have_content('is invalid')
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require 'rails_helper'
2
+
3
+ describe ApplicationMailer do
4
+ it 'sets the correct subject' do
5
+ subject = 'Test email subject'
6
+ mail = described_class.email('test@example.com',
7
+ subject, 'Test email body')
8
+
9
+ expect(mail.subject).to eq(subject)
10
+ end
11
+
12
+ it 'includes content in the body of the email' do
13
+ body = 'Test email body'
14
+ mail = described_class.email('test@example.com',
15
+ 'Test email subject', body)
16
+
17
+ expect(mail.body).to eq(body)
18
+ end
19
+
20
+ it 'sends from no-reply@<%= app_name %>.com' do
21
+ mail = described_class.email('test@example.com',
22
+ 'Test email subject', 'Test email body')
23
+
24
+ expect(mail.from).to include('no-reply@<%= app_name %>.com')
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'Retrieve user list from API', type: :request do
4
+ context 'with token authentication via query params' do
5
+ it 'returns status code 200' do
6
+ user = create(:user, :admin)
7
+
8
+ get admin_users_url(user_email: user.email,
9
+ user_token: user.authentication_token), as: :json
10
+
11
+ expect(response.status).to eq 200
12
+ end
13
+
14
+ it 'returns valid user JSON matching schema' do
15
+ user = create(:user, :admin)
16
+
17
+ get admin_users_url(user_email: user.email,
18
+ user_token: user.authentication_token), as: :json
19
+
20
+ expect(response).to match_response_schema('user')
21
+ end
22
+ end
23
+
24
+ context 'with token authentication via request headers' do
25
+ it 'returns status code 200' do
26
+ user = create(:user, :admin)
27
+ token_header_params = { 'X-User-Email': user.email,
28
+ 'X-User-Token': user.authentication_token }
29
+
30
+ get admin_users_url, headers: token_header_params, as: :json
31
+
32
+ expect(response.status).to eq 200
33
+ end
34
+ it 'returns value user JSON matching schema' do
35
+ user = create(:user, :admin)
36
+ token_header_params = { 'X-User-Email': user.email,
37
+ 'X-User-Token': user.authentication_token }
38
+
39
+ get admin_users_url, headers: token_header_params, as: :json
40
+
41
+ expect(response).to match_response_schema('user')
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "Users schema based on JSON API",
4
+ "type": "object",
5
+ "required": [
6
+ "data"
7
+ ],
8
+ "data": {
9
+ "description": "List of user resources.",
10
+ "type": "array",
11
+ "items": {
12
+ "type": "object",
13
+ "required": [
14
+ "type",
15
+ "id"
16
+ ],
17
+ "properties": {
18
+ "type": {
19
+ "type": "string"
20
+ },
21
+ "id": {
22
+ "type": "integer"
23
+ },
24
+ "attributes": {
25
+ "required": [
26
+ "first-name",
27
+ "last-name",
28
+ "email",
29
+ "authentication-token"
30
+ ],
31
+ "properties": {
32
+ "first-name": {
33
+ "type": "string"
34
+ },
35
+ "last-name": {
36
+ "type": "string"
37
+ },
38
+ "email": {
39
+ "type": "string"
40
+ },
41
+ "authentication-token": {
42
+ "type": "string"
43
+ },
44
+ "created-at": {
45
+ "type": "string",
46
+ "format": "date-time"
47
+ },
48
+ "updated-at": {
49
+ "type": "string",
50
+ "format": "date-time"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ },
56
+ "uniqueItems": true
57
+ }
58
+ }
@@ -0,0 +1,27 @@
1
+ module Features
2
+ module SessionHelpers
3
+ def sign_in(email, password)
4
+ visit sign_in_path
5
+ within '.form-inputs' do
6
+ fill_in 'user_email', with: email
7
+ fill_in 'user_password', with: password
8
+ end
9
+
10
+ click_button 'Log in'
11
+ end
12
+
13
+ def sign_up_with(first, last, email, password, password_confirmation)
14
+ visit new_user_registration_path
15
+ within '.form-inputs' do
16
+ fill_in 'First name', with: first
17
+ fill_in 'Last name', with: last
18
+
19
+ fill_in 'Email', with: email
20
+ fill_in 'user_password', with: password
21
+ fill_in 'user_password_confirmation', with: password_confirmation
22
+ end
23
+
24
+ click_button 'Sign up'
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ RSpec::Matchers.define :match_response_schema do |schema|
2
+ match do |response|
3
+ schema_directory = "#{Dir.pwd}/spec/support/api/schemas"
4
+ schema_path = "#{schema_directory}/#{schema}.json"
5
+ JSON::Validator.validate!(schema_path, response.body, strict: true)
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module RequestSpecHelper
2
+ include Warden::Test::Helpers
3
+
4
+ def self.included(base)
5
+ base.before(:each) { Warden.test_mode! }
6
+ base.after(:each) { Warden.test_reset! }
7
+ end
8
+
9
+ def sign_in(resource)
10
+ login_as(resource, scope: warden_scope(resource))
11
+ end
12
+
13
+ def sign_out(resource)
14
+ logout(warden_scope(resource))
15
+ end
16
+
17
+ private
18
+
19
+ def warden_scope(resource)
20
+ resource.class.name.underscore.to_sym
21
+ end
22
+ end
@@ -5,5 +5,5 @@ module Voyage
5
5
  .read("#{File.dirname(__FILE__)}/../../.ruby-version")
6
6
  .strip
7
7
  .freeze
8
- VERSION = '1.44.0.9'.freeze
8
+ VERSION = '1.44.0.10'.freeze
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: voyage
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.44.0.9
4
+ version: 1.44.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoughtbot, headway
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-02 00:00:00.000000000 Z
11
+ date: 2017-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bitters
@@ -109,13 +109,16 @@ files:
109
109
  - lib/voyage/templates/Gemfile.erb
110
110
  - lib/voyage/templates/README.md.erb
111
111
  - lib/voyage/templates/about.html.erb
112
+ - lib/voyage/templates/admin_controller.rb
112
113
  - lib/voyage/templates/admin_users_controller.rb
113
114
  - lib/voyage/templates/analytics_alias.html.erb.erb
114
115
  - lib/voyage/templates/analytics_identify.html.erb.erb
115
116
  - lib/voyage/templates/analytics_ruby_initializer.rb
116
117
  - lib/voyage/templates/application.js
118
+ - lib/voyage/templates/application_mailer.rb.erb
117
119
  - lib/voyage/templates/auto_annotate_models.rake
118
120
  - lib/voyage/templates/config_dj_rails5_patches.rb
121
+ - lib/voyage/templates/config_initializers_ams.rb
119
122
  - lib/voyage/templates/config_locales_en.yml.erb
120
123
  - lib/voyage/templates/controller_helpers.rb
121
124
  - lib/voyage/templates/custom_cancan_matchers.rb
@@ -126,6 +129,17 @@ files:
126
129
  - lib/voyage/templates/seeder.rb.erb
127
130
  - lib/voyage/templates/seeds.rb.erb
128
131
  - lib/voyage/templates/simplecov.rb
132
+ - lib/voyage/templates/specs/controllers/admin/users_controller_spec.rb
133
+ - lib/voyage/templates/specs/controllers/application_controller_spec.rb
134
+ - lib/voyage/templates/specs/features/user_impersonation_spec.rb
135
+ - lib/voyage/templates/specs/features/user_list_spec.rb
136
+ - lib/voyage/templates/specs/features/user_signup_spec.rb
137
+ - lib/voyage/templates/specs/mailers/application_mailer_spec.rb.erb
138
+ - lib/voyage/templates/specs/requests/user_api_spec.rb
139
+ - lib/voyage/templates/specs/support/api/schemas/user.json
140
+ - lib/voyage/templates/specs/support/features/session_helpers.rb
141
+ - lib/voyage/templates/specs/support/matchers/api_schema_matcher.rb
142
+ - lib/voyage/templates/specs/support/request_spec_helper.rb
129
143
  - lib/voyage/templates/users_index.html.erb
130
144
  - lib/voyage/templates/voyage_layout.html.erb.erb
131
145
  - lib/voyage/templates/welcome.html.erb