locomotivecms_steam 1.3.0.rc2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -5
  3. data/Gemfile.lock +84 -82
  4. data/config/locales/de.yml +7 -5
  5. data/config/locales/el.yml +154 -0
  6. data/config/locales/en.yml +6 -1
  7. data/config/locales/es.yml +7 -1
  8. data/config/locales/et.yml +4 -0
  9. data/config/locales/fr.yml +6 -1
  10. data/config/locales/it.yml +7 -1
  11. data/config/locales/nb.yml +5 -1
  12. data/config/locales/nl.yml +8 -0
  13. data/config/locales/pl.yml +8 -0
  14. data/config/locales/pt-BR.yml +6 -0
  15. data/config/locales/ru.yml +9 -1
  16. data/lib/locomotive/steam/adapters/filesystem/sanitizers/content_entry.rb +1 -1
  17. data/lib/locomotive/steam/decorators/template_decorator.rb +1 -1
  18. data/lib/locomotive/steam/entities/content_entry.rb +4 -0
  19. data/lib/locomotive/steam/entities/content_type.rb +4 -0
  20. data/lib/locomotive/steam/entities/site.rb +2 -1
  21. data/lib/locomotive/steam/liquid/drops/content_entry.rb +1 -1
  22. data/lib/locomotive/steam/liquid/drops/site.rb +1 -1
  23. data/lib/locomotive/steam/middlewares/auth.rb +29 -3
  24. data/lib/locomotive/steam/models/concerns/validation.rb +7 -8
  25. data/lib/locomotive/steam/models/i18n_field.rb +4 -2
  26. data/lib/locomotive/steam/repositories/content_entry_repository.rb +9 -1
  27. data/lib/locomotive/steam/services.rb +1 -1
  28. data/lib/locomotive/steam/services/asset_host_service.rb +21 -17
  29. data/lib/locomotive/steam/services/auth_service.rb +93 -9
  30. data/lib/locomotive/steam/services/content_entry_service.rb +4 -1
  31. data/lib/locomotive/steam/version.rb +1 -1
  32. data/locomotivecms_steam.gemspec +10 -10
  33. data/spec/fixtures/default/app/content_types/accounts.yml +2 -1
  34. data/spec/fixtures/default/app/content_types/songs.yml +2 -2
  35. data/spec/fixtures/default/app/views/pages/account/sign_up.liquid +52 -0
  36. data/spec/fixtures/default/config/translations.yml +4 -0
  37. data/spec/fixtures/default/data/accounts.yml +1 -1
  38. data/spec/fixtures/default/data/songs.yml +1 -0
  39. data/spec/fixtures/mongodb/locomotive_accounts.bson +0 -0
  40. data/spec/fixtures/mongodb/locomotive_accounts.metadata.json +1 -1
  41. data/spec/fixtures/mongodb/locomotive_activities.bson +0 -0
  42. data/spec/fixtures/mongodb/locomotive_activities.metadata.json +1 -1
  43. data/spec/fixtures/mongodb/locomotive_content_assets.bson +0 -0
  44. data/spec/fixtures/mongodb/locomotive_content_assets.metadata.json +1 -1
  45. data/spec/fixtures/mongodb/locomotive_content_entries.bson +0 -0
  46. data/spec/fixtures/mongodb/locomotive_content_entries.metadata.json +1 -1
  47. data/spec/fixtures/mongodb/locomotive_content_types.bson +0 -0
  48. data/spec/fixtures/mongodb/locomotive_content_types.metadata.json +1 -1
  49. data/spec/fixtures/mongodb/locomotive_pages.bson +0 -0
  50. data/spec/fixtures/mongodb/locomotive_pages.metadata.json +1 -1
  51. data/spec/fixtures/mongodb/locomotive_sites.bson +0 -0
  52. data/spec/fixtures/mongodb/locomotive_sites.metadata.json +1 -1
  53. data/spec/fixtures/mongodb/locomotive_snippets.bson +0 -0
  54. data/spec/fixtures/mongodb/locomotive_snippets.metadata.json +1 -1
  55. data/spec/fixtures/mongodb/locomotive_theme_assets.bson +0 -0
  56. data/spec/fixtures/mongodb/locomotive_theme_assets.metadata.json +1 -1
  57. data/spec/fixtures/mongodb/locomotive_translations.bson +0 -0
  58. data/spec/fixtures/mongodb/locomotive_translations.metadata.json +1 -1
  59. data/spec/integration/repositories/content_entry_repository_spec.rb +1 -1
  60. data/spec/integration/repositories/page_repository_spec.rb +2 -2
  61. data/spec/integration/repositories/theme_asset_repository_spec.rb +1 -1
  62. data/spec/integration/repositories/translation_repository_spec.rb +1 -1
  63. data/spec/integration/server/assets_spec.rb +1 -1
  64. data/spec/integration/server/auth_spec.rb +70 -0
  65. data/spec/integration/services/content_entry_service_spec.rb +1 -1
  66. data/spec/support/helpers.rb +1 -1
  67. data/spec/unit/adapters/filesystem/yaml_loaders/content_entry_spec.rb +1 -1
  68. data/spec/unit/adapters/filesystem/yaml_loaders/page_spec.rb +7 -7
  69. data/spec/unit/adapters/filesystem/yaml_loaders/translation_spec.rb +1 -1
  70. data/spec/unit/entities/content_entry_spec.rb +9 -0
  71. data/spec/unit/entities/content_type_spec.rb +7 -0
  72. data/spec/unit/entities/site_spec.rb +15 -0
  73. data/spec/unit/liquid/drops/content_entry_spec.rb +41 -2
  74. data/spec/unit/liquid/drops/site_spec.rb +2 -1
  75. data/spec/unit/liquid/filters/html_spec.rb +58 -1
  76. data/spec/unit/models/i18n_field_spec.rb +8 -0
  77. data/spec/unit/repositories/content_entry_repository_spec.rb +13 -0
  78. data/spec/unit/services/asset_host_service_spec.rb +27 -3
  79. data/spec/unit/services/auth_service_spec.rb +134 -8
  80. data/spec/unit/services/content_entry_service_spec.rb +1 -1
  81. metadata +27 -24
@@ -6,26 +6,50 @@ module Locomotive
6
6
  MIN_PASSWORD_LENGTH = 6
7
7
  RESET_TOKEN_LIFETIME = 1 * 3600 # 6 hours in seconds
8
8
 
9
- attr_accessor_initialize :entries, :email_service
9
+ attr_accessor_initialize :site, :entries, :email_service
10
10
 
11
11
  def find_authenticated_resource(type, id)
12
12
  entries.find(type, id)
13
13
  end
14
14
 
15
- def sign_in(options)
15
+ def sign_up(options, context, request = nil)
16
+ entry = entries.create(options.type, options.entry) do |_entry|
17
+ _entry.extend(ContentEntryAuth)
18
+ _entry[:_password_field] = options.password_field.to_sym
19
+ end
20
+
21
+ if entry.errors.empty?
22
+ notify(:signed_up, entry, request)
23
+ context[options.type.singularize] = entry
24
+ send_welcome_email(options, context)
25
+ end
26
+
27
+ [entry.errors.empty? ? :entry_created : :invalid_entry, entry]
28
+ end
29
+
30
+ def sign_in(options, request)
16
31
  entry = entries.all(options.type, options.id_field => options.id).first
17
32
 
18
- if entry
33
+ if entry && entry.send(options.password_field)
19
34
  hashed_password = entry[:"#{options.password_field}_hash"]
20
35
  password = ::BCrypt::Engine.hash_secret(options.password, entry.send(options.password_field).try(:salt))
21
36
  same_password = secure_compare(password, hashed_password)
22
37
 
23
- return [:signed_in, entry] if same_password
38
+ if same_password
39
+ notify(:signed_in, entry, request)
40
+ return [:signed_in, entry]
41
+ end
24
42
  end
25
43
 
26
44
  :wrong_credentials
27
45
  end
28
46
 
47
+ def sign_out(entry, request)
48
+ notify(:signed_out, entry, request)
49
+
50
+ :signed_out
51
+ end
52
+
29
53
  # options is an instance of the AuthOptions class
30
54
  def forgot_password(options, context)
31
55
  entry = entries.all(options.type, options.id_field => options.id).first
@@ -73,17 +97,31 @@ module Locomotive
73
97
 
74
98
  private
75
99
 
100
+ def send_welcome_email(options, context)
101
+ return if options.disable_email
102
+
103
+ send_email options, context, <<-EMAIL
104
+ Hi,
105
+ You've been successfully registered.
106
+ Thanks!
107
+ EMAIL
108
+ end
109
+
76
110
  def send_reset_password_instructions(options, context)
111
+ send_email options, context, <<-EMAIL
112
+ Hi,
113
+ To reset your password please follow the link below: #{context['reset_password_url']}.
114
+ Thanks!
115
+ EMAIL
116
+ end
117
+
118
+ def send_email(options, context, default_body)
77
119
  email_options = { from: options.from, to: options.id, subject: options.subject, smtp: options.smtp }
78
120
 
79
121
  if options.email_handle
80
122
  email_options[:page_handle] = options.email_handle
81
123
  else
82
- email_options[:body] = <<-EMAIL
83
- Hi,
84
- To reset your password please follow the link below: #{context['reset_password_url']}.
85
- Thanks!
86
- EMAIL
124
+ email_options[:body] = default_body
87
125
  end
88
126
 
89
127
  email_service.send_email(email_options, context)
@@ -99,6 +137,52 @@ EMAIL
99
137
  res == 0
100
138
  end
101
139
 
140
+ def notify(action, entry, request)
141
+ ActiveSupport::Notifications.instrument("steam.auth.#{action}",
142
+ site: site,
143
+ entry: entry,
144
+ locale: entries.locale,
145
+ request: request
146
+ )
147
+ end
148
+
149
+ # Module inject to the content entry to enable
150
+ # related authentication methods.
151
+ #
152
+ module ContentEntryAuth
153
+
154
+ def valid?
155
+ super
156
+
157
+ name = self[:_password_field]
158
+ password = self[name]
159
+ confirmation = self["#{name}_confirmation"]
160
+
161
+ if password.to_s.size < Locomotive::Steam::AuthService::MIN_PASSWORD_LENGTH
162
+ self.errors.add(name, :too_short, count: Locomotive::Steam::AuthService::MIN_PASSWORD_LENGTH)
163
+ end
164
+
165
+ if !password.blank? && password != confirmation
166
+ self.errors.add("#{name}_confirmation", :confirmation, attribute: self._label_of(name))
167
+ end
168
+
169
+ set_password(password) if self.errors.empty?
170
+
171
+ self.errors.empty?
172
+ end
173
+
174
+ private
175
+
176
+ def set_password(password)
177
+ self[:"#{self[:_password_field]}_hash"] = BCrypt::Password.create(password)
178
+
179
+ name = self.attributes.delete(:_password_field)
180
+
181
+ self.attributes.delete_if { |_name| _name == name || _name == "#{name}_confirmation" }
182
+ end
183
+
184
+ end
185
+
102
186
  end
103
187
 
104
188
  end
@@ -28,6 +28,9 @@ module Locomotive
28
28
  def create(type_slug, attributes, as_json = false)
29
29
  with_repository(type_slug) do |_repository|
30
30
  entry = _repository.build(clean_attributes(attributes))
31
+
32
+ yield(entry) if block_given?
33
+
31
34
  decorated_entry = i18n_decorate { entry }
32
35
 
33
36
  if validate(_repository, decorated_entry)
@@ -130,7 +133,7 @@ module Locomotive
130
133
  # fields marked as unique
131
134
  content_type_repository.look_for_unique_fields(entry.content_type).each do |name, _|
132
135
  if _repository.exists?(name => entry.send(name))
133
- entry.errors.add(name, :unique)
136
+ entry.errors.add(name, :taken)
134
137
  end
135
138
  end
136
139
 
@@ -3,6 +3,6 @@
3
3
  # 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
4
4
  module Locomotive
5
5
  module Steam
6
- VERSION = '1.3.0.rc2'
6
+ VERSION = '1.3.0'
7
7
  end
8
8
  end
@@ -18,35 +18,35 @@ Gem::Specification.new do |spec|
18
18
  spec.add_development_dependency 'bundler', '~> 1.7'
19
19
  spec.add_development_dependency 'rake', '~> 10.4.2'
20
20
 
21
- spec.add_development_dependency 'mongo', '~> 2.4.1'
22
- spec.add_development_dependency 'origin', '~> 2.3.0'
21
+ spec.add_development_dependency 'mongo', '~> 2.4.3'
22
+ spec.add_development_dependency 'origin', '~> 2.3.1'
23
23
 
24
- spec.add_dependency 'nokogiri', '~> 1.7.0.1'
25
- spec.add_dependency 'sanitize', '~> 4.4.0'
24
+ spec.add_dependency 'nokogiri', '~> 1.8.1'
25
+ spec.add_dependency 'sanitize', '~> 4.5.0'
26
26
  spec.add_dependency 'morphine', '~> 0.1.1'
27
- spec.add_dependency 'httparty', '~> 0.14.0'
27
+ spec.add_dependency 'httparty', '~> 0.15.6'
28
28
  spec.add_dependency 'chronic', '~> 0.10.2'
29
29
  spec.add_dependency 'bcrypt', '~> 3.1.11'
30
30
 
31
31
  spec.add_dependency 'rack-rewrite', '~> 1.5.1'
32
32
  spec.add_dependency 'rack-cache', '~> 1.7.0'
33
33
  spec.add_dependency 'rack_csrf', '~> 2.6.0'
34
- spec.add_dependency 'dragonfly', '~> 1.1.1'
34
+ spec.add_dependency 'dragonfly', '~> 1.1.4'
35
35
  spec.add_dependency 'moneta', '~> 1.0.0'
36
36
 
37
37
  spec.add_dependency 'sprockets', '~> 3.7.1'
38
- spec.add_dependency 'sass', '~> 3.4.23'
39
- spec.add_dependency 'uglifier', '~> 3.1.6'
38
+ spec.add_dependency 'sass', '~> 3.4.25'
39
+ spec.add_dependency 'uglifier', '~> 4.1.3'
40
40
  spec.add_dependency 'coffee-script', '~> 2.4.1'
41
41
  spec.add_dependency 'compass', '~> 1.0.3'
42
42
  spec.add_dependency 'autoprefixer-rails', '~> 6.7.2'
43
43
 
44
- spec.add_dependency 'kramdown', '~> 1.13.2'
44
+ spec.add_dependency 'kramdown', '~> 1.16.2'
45
45
  spec.add_dependency 'RedCloth', '~> 4.3.2'
46
46
  spec.add_dependency 'mimetype-fu', '~> 0.1.2'
47
47
  spec.add_dependency 'mime-types', '~> 3.1.0'
48
48
  spec.add_dependency 'duktape', '~> 1.6.1.0'
49
- spec.add_dependency 'pony', '~> 1.11'
49
+ spec.add_dependency 'pony', '~> 1.12'
50
50
 
51
51
  spec.add_dependency 'locomotivecms-solid', '~> 4.0.1'
52
52
  spec.add_dependency 'locomotivecms_common', '~> 0.2.0'
@@ -47,7 +47,8 @@ fields:
47
47
  - email: # The lowercase, underscored name of the field
48
48
  label: Email # Human readable name of the field
49
49
  type: email
50
- required: false
50
+ required: true
51
+ unique: true
51
52
  hint: Explanatory text displayed in the back office
52
53
  localized: false
53
54
 
@@ -14,8 +14,8 @@ fields:
14
14
  - cover:
15
15
  label: Cover
16
16
  type: file
17
- required: true
18
- # localized: true # required when pushing the site with Wagon
17
+ required: false
18
+ #localized: true # required when pushing the site with Wagon
19
19
  - short_description:
20
20
  type: text
21
21
  text_formatting: html
@@ -0,0 +1,52 @@
1
+ ---
2
+ title: Sign up
3
+ listed: false
4
+ published: true
5
+ handle: sign_up
6
+ ---
7
+ {% extends 'index' %}
8
+
9
+ {% block content %}
10
+
11
+ <h1>Sign up</h1>
12
+
13
+ {% if current_account %}
14
+ <div class="alert alert-warning">
15
+ You're already authenticated!
16
+ </div>
17
+ {% else %}
18
+
19
+ <form action="{% path_to 'sign_up' %}" method="POST">
20
+ <input type="hidden" name="auth_action" value="sign_up" />
21
+ <input type="hidden" name="auth_content_type" value="accounts" />
22
+ <input type="hidden" name="auth_id_field" value="email" />
23
+ <input type="hidden" name="auth_password_field" value="password" />
24
+ <input type="hidden" name="auth_callback" value="{% path_to sign_in %}" />
25
+
26
+ <div class="form-group">
27
+ <label for="auth-name">Your name</label>
28
+ <input type="text" name="auth_entry[name]" class="form-control" id="auth-name" placeholder="Name">
29
+ </div>
30
+ <div class="form-group">
31
+ <label for="auth-email">Your E-mail</label>
32
+ <input type="email" name="auth_entry[email]" class="form-control" id="auth-email" placeholder="Email">
33
+ </div>
34
+ <div class="form-group">
35
+ <label for="auth-password">Password</label>
36
+ {% if auth_entry.errors.password.size > 0 %}
37
+ <span class="inline-error">{{ auth_entry.errors.password.first }}</span>
38
+ {% endif %}
39
+ <input type="password" name="auth_entry[password]" class="form-control" id="auth-password" placeholder="Password">
40
+ </div>
41
+ <div class="form-group">
42
+ <label for="auth-password">Password confirmation</label>
43
+ {% if auth_entry.errors.password_confirmation.size > 0 %}
44
+ <span class="inline-error">{{ auth_entry.errors.password_confirmation.first }}</span>
45
+ {% endif %}
46
+ <input type="password" name="auth_entry[password_confirmation]" class="form-control" id="auth-password" placeholder="Password confirmation">
47
+ </div>
48
+ <button type="submit" class="btn btn-default">Create account</button>
49
+ </form>
50
+ {% endif %}
51
+
52
+ {% endblock %}
@@ -25,3 +25,7 @@ auth_invalid_token:
25
25
  auth_password_too_short:
26
26
  en: "Your password is too short"
27
27
  fr: "Votre mot de passe est trop court"
28
+
29
+ auth_password_different_from_confirmation:
30
+ en: "Your password doesn't match the confirmation"
31
+ fr: "Votre mot de passe ne correspond à la confirmation"
@@ -3,7 +3,7 @@
3
3
  password: 'easyone'
4
4
 
5
5
  - "Jane":
6
- email: 'john@doe.net'
6
+ email: 'jane@doe.net'
7
7
  password: 'anotherone'
8
8
  _auth_reset_token: '420000000000000'
9
9
  _auth_reset_sent_at: '2020-01-01T15:00:00.000Z'
@@ -11,6 +11,7 @@
11
11
  cover:
12
12
  en: /samples/asset_collections/cover.jpg
13
13
  fr: /samples/photo_2.jpg
14
+ nb: /samples/photo_2.jpg
14
15
  band: pearl-jam
15
16
  - "Song #3":
16
17
  duration: "6:28"
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_accounts"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_accounts"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_activities"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_activities"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_content_assets"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_content_assets"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_content_entries"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_content_entries"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_content_types"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_content_types"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_pages"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_pages"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_sites"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_sites"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_snippets"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_snippets"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_theme_assets"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_theme_assets"}]}
@@ -1 +1 @@
1
- {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_dev.locomotive_translations"}]}
1
+ {"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"locomotive_engine_wagon_dev.locomotive_translations"}]}
@@ -116,7 +116,7 @@ describe Locomotive::Steam::ContentEntryRepository do
116
116
 
117
117
  let(:site_id) { mongodb_site_id }
118
118
  let(:adapter) { Locomotive::Steam::MongoDBAdapter.new(database: 'steam_test', hosts: ['127.0.0.1:27017']) }
119
- let(:entry_id) { BSON::ObjectId.from_string('5829ffa087f6435971756881') }
119
+ let(:entry_id) { BSON::ObjectId.from_string('5943b4dd87f6430cf23b814d') }
120
120
 
121
121
  end
122
122
 
@@ -14,7 +14,7 @@ describe Locomotive::Steam::PageRepository do
14
14
  describe '#all' do
15
15
  let(:conditions) { {} }
16
16
  subject { repository.all(conditions) }
17
- it { expect(subject.size).to eq 33 }
17
+ it { expect(subject.size).to eq 34 }
18
18
 
19
19
  context 'with conditions' do
20
20
  let(:conditions) { { fullpath: 'index', 'slug.ne' => '404' } }
@@ -34,7 +34,7 @@ describe Locomotive::Steam::PageRepository do
34
34
 
35
35
  describe '#only_handle_and_fullpath' do
36
36
  subject { repository.only_handle_and_fullpath }
37
- it { expect(subject.size).to eq 8 }
37
+ it { expect(subject.size).to eq 9 }
38
38
  end
39
39
 
40
40
  describe '#by_fullpath' do
@@ -26,7 +26,7 @@ describe Locomotive::Steam::ThemeAssetRepository do
26
26
  describe '#checksums' do
27
27
  subject { repository.checksums }
28
28
  it { expect(subject.size).to eq 16 }
29
- it { expect(subject['stylesheets/application.css']).to eq 'f431407c21db339b7759c2d7ded2553f' }
29
+ it { expect(subject['stylesheets/application.css']).to eq 'f06835e254f0d1b8363aae754525c723' }
30
30
  end
31
31
 
32
32
  end
@@ -13,7 +13,7 @@ describe Locomotive::Steam::TranslationRepository do
13
13
 
14
14
  describe '#all' do
15
15
  subject { repository.all }
16
- it { expect(subject.size).to eq 7 }
16
+ it { expect(subject.size).to eq 8 }
17
17
  end
18
18
 
19
19
  describe '#by_key' do
@@ -21,7 +21,7 @@ describe Locomotive::Steam::Server do
21
21
  subject { get '/all'; last_response.body }
22
22
 
23
23
  it { is_expected.to include('<link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />') }
24
- it { is_expected.to include('<script src="/javascripts/application.js" type=\'text/javascript\'></script>') }
24
+ it { is_expected.to include("<script src='/javascripts/application.js' type=\'text/javascript\'></script>") }
25
25
  it { is_expected.to include('<link rel="alternate" type="application/atom+xml" title="A title" href="/foo/bar" />') }
26
26
 
27
27
  end
@@ -8,6 +8,76 @@ describe 'Authentication' do
8
8
  run_server
9
9
  end
10
10
 
11
+ describe 'sign up action' do
12
+
13
+ it 'renders the form' do
14
+ get '/account/sign-up'
15
+ expect(last_response.body).to include '/account/sign-up'
16
+ end
17
+
18
+ describe 'press the sign up button' do
19
+
20
+ let(:params) { {
21
+ auth_action: 'sign_up',
22
+ auth_content_type: 'accounts',
23
+ auth_id_field: 'email',
24
+ auth_password_field: 'password',
25
+ auth_callback: '/account/me',
26
+ auth_entry: {
27
+ name: 'Chris Cornell',
28
+ email: 'chris@soundgarden.band',
29
+ password: 'easyone',
30
+ password_confirmation: 'easyone'
31
+ }
32
+ } }
33
+
34
+ it 'redirects to the callback' do
35
+ sign_up(params)
36
+ expect(last_response.status).to eq 301
37
+ expect(last_response.location).to eq '/account/me'
38
+ end
39
+
40
+ it 'displays the profile page as described in the params' do
41
+ params[:auth_entry][:email] = 'chris.cornell@soundgarden.band'
42
+ sign_up(params, true)
43
+ expect(last_response.body).to include "My name is Chris Cornell and I'm logged in!"
44
+ end
45
+
46
+ context 'wrong parameters' do
47
+
48
+ let(:params) { {
49
+ auth_action: 'sign_up',
50
+ auth_content_type: 'accounts',
51
+ auth_id_field: 'email',
52
+ auth_password_field: 'password',
53
+ auth_callback: '/account/me',
54
+ auth_entry: {
55
+ name: 'Chris Cornell',
56
+ email: 'chris@soundgarden.band',
57
+ password: 'easyone',
58
+ password_confirmation: 'easyone2'
59
+ }
60
+ } }
61
+
62
+ it 'renders the sign up page with an error message' do
63
+ sign_up(params)
64
+ expect(last_response.status).to eq 200
65
+ expect(last_response.body).to include '/account/sign-up'
66
+ expect(last_response.body).to include "doesn't match password"
67
+ end
68
+
69
+ end
70
+
71
+ def sign_up(params, follow_redirect = false)
72
+ post '/account/sign-up', params
73
+ follow_redirect! if follow_redirect
74
+ last_response
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+
11
81
  describe 'sign in action' do
12
82
 
13
83
  it 'renders the form' do