letter_opener_web 1.3.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/brakeman-analysis.yml +46 -0
- data/.github/workflows/main.yml +34 -0
- data/.github/workflows/release-gem.yml +32 -0
- data/.gitignore +1 -0
- data/.rspec +1 -1
- data/.rubocop.yml +5 -16
- data/.rubocop_todo.yml +19 -0
- data/CHANGELOG.md +22 -1
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +33 -24
- data/app/controllers/letter_opener_web/application_controller.rb +1 -0
- data/app/controllers/letter_opener_web/letters_controller.rb +14 -7
- data/app/models/letter_opener_web/letter.rb +37 -5
- data/app/views/layouts/letter_opener_web/_javascripts.html.erb +31 -0
- data/app/views/layouts/letter_opener_web/_styles.html.erb +3 -0
- data/{vendor/assets/javascripts/letter_opener_web/favcount.js → app/views/layouts/letter_opener_web/js/_favcount.html.erb} +9 -7
- data/app/views/layouts/letter_opener_web/js/_jquery.html.erb +7 -0
- data/app/views/layouts/letter_opener_web/letters.html.erb +5 -3
- data/app/views/layouts/letter_opener_web/styles/_bootstrap.html.erb +9 -0
- data/app/views/layouts/letter_opener_web/styles/_icon.html.erb +2 -0
- data/app/views/layouts/letter_opener_web/styles/_letters.html.erb +70 -0
- data/app/views/letter_opener_web/letters/_item.html.erb +10 -0
- data/app/views/letter_opener_web/letters/index.html.erb +11 -46
- data/config/routes.rb +5 -5
- data/letter_opener_web.gemspec +19 -15
- data/lib/letter_opener_web/delivery_method.rb +1 -1
- data/lib/letter_opener_web/engine.rb +0 -10
- data/lib/letter_opener_web/version.rb +1 -1
- data/lib/letter_opener_web.rb +1 -0
- data/spec/controllers/letter_opener_web/letters_controller_spec.rb +22 -11
- data/spec/dummy/app/assets/config/manifest.js +0 -2
- data/spec/dummy/app/assets/stylesheets/application.css +0 -16
- data/spec/dummy/app/channels/application_cable/channel.rb +6 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +6 -0
- data/spec/dummy/app/controllers/application_controller.rb +0 -1
- data/spec/dummy/app/{assets/javascripts → javascript/packs}/application.js +2 -0
- data/spec/dummy/app/jobs/application_job.rb +9 -0
- data/spec/dummy/app/models/application_record.rb +5 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +4 -7
- data/spec/dummy/bin/rails +2 -4
- data/spec/dummy/bin/rake +2 -4
- data/spec/dummy/bin/setup +7 -10
- data/spec/dummy/config/application.rb +21 -7
- data/spec/dummy/config/environments/development.rb +44 -6
- data/spec/dummy/config/environments/production.rb +51 -14
- data/spec/dummy/config/environments/test.rb +30 -6
- data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -4
- data/spec/dummy/config/initializers/assets.rb +5 -5
- data/spec/dummy/config/initializers/backtrace_silencers.rb +5 -3
- data/spec/dummy/config/initializers/content_security_policy.rb +29 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +3 -1
- data/spec/dummy/config/initializers/permissions_policy.rb +12 -0
- data/spec/dummy/config/locales/en.yml +11 -1
- data/spec/dummy/config/puma.rb +18 -22
- data/spec/dummy/config/routes.rb +1 -4
- data/spec/dummy/config.ru +1 -0
- data/spec/dummy/public/404.html +6 -6
- data/spec/dummy/public/422.html +6 -6
- data/spec/dummy/public/500.html +6 -6
- data/spec/dummy/storage/.keep +0 -0
- data/spec/letter_opener_web_spec.rb +2 -2
- data/spec/models/letter_opener_web/letter_spec.rb +62 -17
- data/spec/spec_helper.rb +8 -0
- metadata +91 -54
- data/.travis.yml +0 -26
- data/app/assets/javascripts/letter_opener_web/application.js +0 -30
- data/app/assets/stylesheets/letter_opener_web/application.css.erb +0 -54
- data/bin/rails +0 -11
- data/spec/dummy/app/controllers/home_controller.rb +0 -10
- data/spec/dummy/app/mailers/contact_mailer.rb +0 -14
- data/spec/dummy/app/views/contact_mailer/new_message.html.erb +0 -21
- data/spec/dummy/app/views/contact_mailer/new_message.text.erb +0 -3
- data/spec/dummy/app/views/home/index.html.erb +0 -50
- data/spec/dummy/bin/bundle +0 -5
- data/spec/dummy/bin/update +0 -31
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
- data/spec/dummy/config/initializers/session_store.rb +0 -5
- data/spec/dummy/config/secrets.yml +0 -22
- data/spec/dummy/config/spring.rb +0 -8
- data/vendor/assets/images/letter_opener_web/blue-dot.ico +0 -0
- data/vendor/assets/images/letter_opener_web/glyphicons-halflings-white.png +0 -0
- data/vendor/assets/images/letter_opener_web/glyphicons-halflings.png +0 -0
- data/vendor/assets/javascripts/letter_opener_web/bootstrap.min.js +0 -6
- data/vendor/assets/javascripts/letter_opener_web/jquery-1.8.3.min.js +0 -2
- data/vendor/assets/javascripts/letter_opener_web/jquery_ujs.js +0 -429
- data/vendor/assets/stylesheets/letter_opener_web/bootstrap.min.css +0 -9
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# Be sure to restart your server when you modify this file.
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# ActiveSupport::Reloader.to_prepare do
|
5
|
+
# ApplicationController.renderer.defaults.merge!(
|
6
|
+
# http_host: 'example.org',
|
7
|
+
# https: false
|
8
|
+
# )
|
9
|
+
# end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
2
|
# Be sure to restart your server when you modify this file.
|
4
3
|
|
5
4
|
# Version of your assets, change this if you want to expire all your assets.
|
6
|
-
Rails.application.config.assets.version = '1.0'
|
5
|
+
# Rails.application.config.assets.version = '1.0'
|
7
6
|
|
8
|
-
# Add additional assets to the asset load path
|
7
|
+
# Add additional assets to the asset load path.
|
9
8
|
# Rails.application.config.assets.paths << Emoji.images_path
|
10
9
|
|
11
10
|
# Precompile additional assets.
|
12
|
-
# application.js, application.css, and all non-JS/CSS in app/assets
|
13
|
-
#
|
11
|
+
# application.js, application.css, and all non-JS/CSS in the app/assets
|
12
|
+
# folder are already added.
|
13
|
+
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# Be sure to restart your server when you modify this file.
|
3
4
|
|
4
5
|
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
5
|
-
# Rails.backtrace_cleaner.add_silencer { |line|
|
6
|
+
# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
|
6
7
|
|
7
|
-
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
|
8
|
-
#
|
8
|
+
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
|
9
|
+
# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
|
10
|
+
Rails.backtrace_cleaner.remove_silencers! if ENV['BACKTRACE']
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Be sure to restart your server when you modify this file.
|
3
|
+
|
4
|
+
# Define an application-wide content security policy
|
5
|
+
# For further information see the following documentation
|
6
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
7
|
+
|
8
|
+
# Rails.application.config.content_security_policy do |policy|
|
9
|
+
# policy.default_src :self, :https
|
10
|
+
# policy.font_src :self, :https, :data
|
11
|
+
# policy.img_src :self, :https, :data
|
12
|
+
# policy.object_src :none
|
13
|
+
# policy.script_src :self, :https
|
14
|
+
# policy.style_src :self, :https
|
15
|
+
|
16
|
+
# # Specify URI for violation reports
|
17
|
+
# # policy.report_uri "/csp-violation-report-endpoint"
|
18
|
+
# end
|
19
|
+
|
20
|
+
# If you are using UJS then enable automatic nonce generation
|
21
|
+
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
22
|
+
|
23
|
+
# Set the nonce only to specific directives
|
24
|
+
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
|
25
|
+
|
26
|
+
# Report CSP violations to a specified URI
|
27
|
+
# For further information see the following documentation:
|
28
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
|
29
|
+
# Rails.application.config.content_security_policy_report_only = true
|
@@ -3,4 +3,6 @@
|
|
3
3
|
# Be sure to restart your server when you modify this file.
|
4
4
|
|
5
5
|
# Configure sensitive parameters which will be filtered from the log file.
|
6
|
-
Rails.application.config.filter_parameters += [
|
6
|
+
Rails.application.config.filter_parameters += %i[
|
7
|
+
passw secret token _key crypt salt certificate otp ssn
|
8
|
+
]
|
@@ -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
|
@@ -16,8 +16,18 @@
|
|
16
16
|
#
|
17
17
|
# This would use the information in config/locales/es.yml.
|
18
18
|
#
|
19
|
+
# The following keys must be escaped otherwise they will not be retrieved by
|
20
|
+
# the default I18n backend:
|
21
|
+
#
|
22
|
+
# true, false, on, off, yes, no
|
23
|
+
#
|
24
|
+
# Instead, surround them with single quotes.
|
25
|
+
#
|
26
|
+
# en:
|
27
|
+
# 'true': 'foo'
|
28
|
+
#
|
19
29
|
# To learn more, please read the Rails Internationalization guide
|
20
|
-
# available at
|
30
|
+
# available at https://guides.rubyonrails.org/i18n.html.
|
21
31
|
|
22
32
|
en:
|
23
33
|
hello: "Hello world"
|
data/spec/dummy/config/puma.rb
CHANGED
@@ -1,24 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Puma can serve each request in a thread from an internal thread pool.
|
4
|
-
# The `threads` method setting takes two numbers a minimum and maximum.
|
4
|
+
# The `threads` method setting takes two numbers: a minimum and maximum.
|
5
5
|
# Any libraries that use thread pools should be configured to match
|
6
6
|
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
7
|
-
# and maximum
|
7
|
+
# and maximum; this matches the default thread size of Active Record.
|
8
8
|
#
|
9
|
-
|
10
|
-
|
9
|
+
max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
|
10
|
+
min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
|
11
|
+
threads min_threads_count, max_threads_count
|
11
12
|
|
12
|
-
# Specifies the `
|
13
|
+
# Specifies the `worker_timeout` threshold that Puma will use to wait before
|
14
|
+
# terminating a worker in development environments.
|
13
15
|
#
|
14
|
-
|
16
|
+
worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development'
|
17
|
+
|
18
|
+
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
19
|
+
#
|
20
|
+
port ENV.fetch('PORT', 3000)
|
15
21
|
|
16
22
|
# Specifies the `environment` that Puma will run in.
|
17
23
|
#
|
18
|
-
environment ENV.fetch('RAILS_ENV'
|
24
|
+
environment ENV.fetch('RAILS_ENV', 'development')
|
25
|
+
|
26
|
+
# Specifies the `pidfile` that Puma will use.
|
27
|
+
pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid')
|
19
28
|
|
20
29
|
# Specifies the number of `workers` to boot in clustered mode.
|
21
|
-
# Workers are forked
|
30
|
+
# Workers are forked web server processes. If using threads and workers together
|
22
31
|
# the concurrency of the application would be max `threads` * `workers`.
|
23
32
|
# Workers do not work on JRuby or Windows (both of which do not support
|
24
33
|
# processes).
|
@@ -28,22 +37,9 @@ environment ENV.fetch('RAILS_ENV') { 'development' }
|
|
28
37
|
# Use the `preload_app!` method when specifying a `workers` number.
|
29
38
|
# This directive tells Puma to first boot the application and load code
|
30
39
|
# before forking the application. This takes advantage of Copy On Write
|
31
|
-
# process behavior so workers use less memory.
|
32
|
-
# you need to make sure to reconnect any threads in the `on_worker_boot`
|
33
|
-
# block.
|
40
|
+
# process behavior so workers use less memory.
|
34
41
|
#
|
35
42
|
# preload_app!
|
36
43
|
|
37
|
-
# The code in the `on_worker_boot` will be called if you are using
|
38
|
-
# clustered mode by specifying a number of `workers`. After each worker
|
39
|
-
# process is booted this block will be run, if you are using `preload_app!`
|
40
|
-
# option you will want to use this block to reconnect to any threads
|
41
|
-
# or connections that may have been created at application boot, Ruby
|
42
|
-
# cannot share connections between processes.
|
43
|
-
#
|
44
|
-
# on_worker_boot do
|
45
|
-
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
|
46
|
-
# end
|
47
|
-
|
48
44
|
# Allow puma to be restarted by `rails restart` command.
|
49
45
|
plugin :tmp_restart
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/dummy/config.ru
CHANGED
data/spec/dummy/public/404.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>The page you were looking for doesn't exist (404)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/404.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
data/spec/dummy/public/422.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>The change you wanted was rejected (422)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/422.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
data/spec/dummy/public/500.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>We're sorry, but something went wrong (500)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/500.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
File without changes
|
@@ -1,20 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
describe LetterOpenerWeb::Letter do
|
4
|
-
let(:location) {
|
3
|
+
RSpec.describe LetterOpenerWeb::Letter do
|
4
|
+
let(:location) { Pathname.new(__dir__).join('..', '..', 'tmp').cleanpath }
|
5
5
|
|
6
6
|
def rich_text(mail_id)
|
7
|
-
|
8
|
-
Rich text for #{mail_id}
|
9
|
-
<!DOCTYPE html>
|
10
|
-
<
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
<
|
15
|
-
<
|
16
|
-
|
17
|
-
|
7
|
+
<<~MAIL
|
8
|
+
Rich text for #{mail_id}
|
9
|
+
<!DOCTYPE html>
|
10
|
+
<body>
|
11
|
+
<div id="container">
|
12
|
+
<div id="message_headers">
|
13
|
+
<dl>
|
14
|
+
<dt>From:</dt>
|
15
|
+
<dd>noreply@example.com</dd>
|
16
|
+
</dl>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<a href='a-link.html'>
|
20
|
+
<img src='an-image.jpg'>
|
21
|
+
Link text
|
22
|
+
</a>
|
23
|
+
<a href='fooo.html'>Bar</a>
|
24
|
+
<a href="example.html" class="blank"></a>
|
25
|
+
<address><a href="inside-address.html">inside address</a></address>
|
26
|
+
</div>
|
27
|
+
</body>
|
28
|
+
MAIL
|
18
29
|
end
|
19
30
|
|
20
31
|
before :each do
|
@@ -36,6 +47,28 @@ MAIL
|
|
36
47
|
FileUtils.rm_rf(location)
|
37
48
|
end
|
38
49
|
|
50
|
+
describe 'rich text headers' do
|
51
|
+
let(:id) { '1111_1111' }
|
52
|
+
subject { described_class.new(id: id).headers }
|
53
|
+
|
54
|
+
before do
|
55
|
+
FileUtils.rm_rf("#{location}/#{id}/plain.html")
|
56
|
+
end
|
57
|
+
|
58
|
+
it { is_expected.to match(%r{<dl>\s*<dt>From:</dt>\s*<dd>noreply@example\.com</dd>}m) }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'plain text headers' do
|
62
|
+
let(:id) { '1111_1111' }
|
63
|
+
subject { described_class.new(id: id).headers }
|
64
|
+
|
65
|
+
before do
|
66
|
+
FileUtils.rm_rf("#{location}/#{id}/rich.html")
|
67
|
+
end
|
68
|
+
|
69
|
+
it { is_expected.to eq('UNABLE TO PARSE HEADERS') }
|
70
|
+
end
|
71
|
+
|
39
72
|
describe 'rich text version' do
|
40
73
|
let(:id) { '1111_1111' }
|
41
74
|
subject { described_class.new(id: id).rich_text }
|
@@ -45,9 +78,10 @@ MAIL
|
|
45
78
|
it 'changes links to show up on a new window' do
|
46
79
|
link_html = [
|
47
80
|
"<a href='a-link.html' target='_blank'>",
|
48
|
-
"<img src='an-image.jpg'/>",
|
49
|
-
|
50
|
-
|
81
|
+
" <img src='an-image.jpg'/>",
|
82
|
+
' Link text',
|
83
|
+
'</a>'
|
84
|
+
].join("\n ")
|
51
85
|
|
52
86
|
expect(subject).to include(link_html)
|
53
87
|
end
|
@@ -128,13 +162,24 @@ MAIL
|
|
128
162
|
|
129
163
|
describe '#delete' do
|
130
164
|
let(:id) { '1111_1111' }
|
165
|
+
|
131
166
|
subject { described_class.new(id: id).delete }
|
132
167
|
|
133
|
-
it'removes the letter with given id' do
|
168
|
+
it 'removes the letter with given id' do
|
134
169
|
subject
|
135
170
|
directories = Dir["#{location}/*"]
|
136
171
|
expect(directories.count).to eql(1)
|
137
172
|
expect(directories.first).not_to match(id)
|
138
173
|
end
|
174
|
+
|
175
|
+
context 'when the id is outside of the letters base path' do
|
176
|
+
let(:id) { '../3333_3333' }
|
177
|
+
|
178
|
+
it 'does not remove the letter' do
|
179
|
+
expect(FileUtils).not_to receive(:rm_rf).with(location.join(id).cleanpath.to_s)
|
180
|
+
|
181
|
+
expect(subject).to be_nil
|
182
|
+
end
|
183
|
+
end
|
139
184
|
end
|
140
185
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start
|
5
|
+
|
6
|
+
if ENV.fetch('CI', '') == 'true'
|
7
|
+
require 'codecov'
|
8
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
9
|
+
end
|
10
|
+
|
3
11
|
require 'shoulda-matchers'
|
4
12
|
|
5
13
|
RSpec.configure do |config|
|