Skip to content

Commit 0a95ae6

Browse files
jlledomclaude
andcommitted
Add/Fix tests
Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ba09201 commit 0a95ae6

File tree

4 files changed

+218
-1
lines changed

4 files changed

+218
-1
lines changed

features/step_definitions/asset_host_steps.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,36 @@
33
Given /^the asset host is unset$/ do
44
Rails.configuration.three_scale.asset_host = nil
55
Rails.configuration.asset_host = nil
6+
7+
# Reconfigure CSP with original policy (without CDN URL)
8+
policy_config = ThreeScale::ContentSecurityPolicy::AdminPortal.policy_config
9+
Rails.application.config.content_security_policy do |policy|
10+
ThreeScale::ContentSecurityPolicy::AdminPortal.add_policy_config(policy, policy_config)
11+
Rails.application.instance_variable_get(:@app_env_config)&.[]=('action_dispatch.content_security_policy', policy)
12+
end
613
end
714

815
Given /^the asset host is set to "(.*)"$/ do |asset_host|
916
cdn_url = "#{asset_host}:#{Capybara.current_session.server.port}"
1017
Rails.configuration.three_scale.asset_host = cdn_url
1118
Rails.configuration.asset_host = cdn_url
19+
20+
# Get original policy and add CDN URL to CSP directives
21+
original_policy = ThreeScale::ContentSecurityPolicy::AdminPortal.policy_config
22+
policy_with_cdn = original_policy.deep_dup
23+
24+
# Append CDN URL to script_src, style_src, and font_src
25+
policy_with_cdn[:script_src] = (policy_with_cdn[:script_src] || []) + [cdn_url]
26+
policy_with_cdn[:style_src] = (policy_with_cdn[:style_src] || []) + [cdn_url]
27+
policy_with_cdn[:font_src] = (policy_with_cdn[:font_src] || []) + [cdn_url]
28+
29+
# Reconfigure CSP with CDN URL included
30+
# Rails set the CSP configuration just once during initialization,
31+
# This hack is needed to make it change between tests
32+
Rails.application.config.content_security_policy do |policy|
33+
ThreeScale::ContentSecurityPolicy::AdminPortal.add_policy_config(policy, policy_with_cdn)
34+
Rails.application.instance_variable_get(:@app_env_config)&.[]=('action_dispatch.content_security_policy', policy)
35+
end
1236
end
1337

1438
Then /^(?:javascript\s)?assets should be loaded from the asset host$/ do
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
class DeveloperPortal::ContentSecurityPolicyTest < ActionDispatch::IntegrationTest
6+
7+
class TestController < ApplicationController
8+
def html
9+
render html: '<html><body>Test</body></html>'.html_safe
10+
end
11+
12+
def json
13+
render json: { test: true }
14+
end
15+
16+
def not_modified
17+
head :not_modified
18+
end
19+
end
20+
21+
def with_test_routes
22+
DeveloperPortal::Engine.routes.draw do
23+
get '/test/csp/html' => 'content_security_policy_test/test#html'
24+
get '/test/csp/json' => 'content_security_policy_test/test#json'
25+
get '/test/csp/304' => 'content_security_policy_test/test#not_modified'
26+
end
27+
yield
28+
ensure
29+
Rails.application.routes_reloader.reload!
30+
end
31+
32+
def setup
33+
@provider = FactoryBot.create(:provider_account)
34+
@buyer = FactoryBot.create(:buyer_account, provider_account: @provider)
35+
host! @provider.internal_domain
36+
end
37+
38+
test 'includes configured directives from YAML' do
39+
with_test_routes do
40+
get '/test/csp/html'
41+
42+
assert_response :success
43+
csp_header = response.headers['Content-Security-Policy']
44+
45+
# Verify it contains the permissive default_src directive from developer_portal_policy
46+
assert_includes csp_header, "default-src"
47+
assert_includes csp_header, "*"
48+
assert_includes csp_header, "'unsafe-eval'"
49+
assert_includes csp_header, "'unsafe-inline'"
50+
end
51+
end
52+
53+
test 'does not apply CSP headers to non-HTML responses' do
54+
with_test_routes do
55+
get '/test/csp/json', params: { format: :json }
56+
57+
assert_response :success
58+
# JSON responses should not have CSP headers
59+
assert_nil response.headers['Content-Security-Policy']
60+
assert_nil response.headers['Content-Security-Policy-Report-Only']
61+
end
62+
end
63+
64+
test 'middleware handles 304 Not Modified responses correctly' do
65+
# The middleware has special handling for 304 responses to avoid
66+
# nonce mismatches with cached content. This test verifies the middleware
67+
# returns early for 304 responses and does not add CSP headers.
68+
69+
with_test_routes do
70+
get '/test/csp/304'
71+
72+
assert_response :not_modified
73+
# CSP middleware should not add headers to 304 responses
74+
assert_nil response.headers['Content-Security-Policy']
75+
assert_nil response.headers['Content-Security-Policy-Report-Only']
76+
end
77+
end
78+
end

test/integration/secure_headers_test.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ def setup
1515
assert_equal 'DENY', response.headers['X-Frame-Options']
1616
assert_equal 'nosniff', response.headers['X-Content-Type-Options']
1717
assert_equal '1; mode=block', response.headers['X-XSS-Protection']
18-
assert_equal "default-src * data: mediastream: blob: filesystem: ws: wss: 'unsafe-eval' 'unsafe-inline'", response.headers['Content-Security-Policy']
1918
end
2019

2120
test 'do not add non used secure headers in the response' do
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
require 'test_helper'
2+
3+
class ThreeScale::ContentSecurityPolicy::AdminPortalTest < ActiveSupport::TestCase
4+
test 'config returns Rails configuration for CSP' do
5+
config = ThreeScale::ContentSecurityPolicy::AdminPortal.config
6+
7+
assert_not_nil config
8+
assert_kind_of ActiveSupport::OrderedOptions, config
9+
end
10+
11+
test 'enabled? returns true in test environment' do
12+
assert_equal true, ThreeScale::ContentSecurityPolicy::AdminPortal.enabled?
13+
end
14+
15+
test 'policy_config returns hash of CSP directives from YAML' do
16+
policy_hash = ThreeScale::ContentSecurityPolicy::AdminPortal.policy_config
17+
18+
assert_kind_of Hash, policy_hash
19+
assert policy_hash.present?
20+
21+
# Verify it contains restrictive directives
22+
assert policy_hash.key?(:default_src)
23+
assert_includes policy_hash[:default_src], "'self'"
24+
assert policy_hash.key?(:script_src)
25+
assert_includes policy_hash[:script_src], "'self'"
26+
end
27+
28+
test 'report_only? returns false from YAML config' do
29+
assert_equal false, ThreeScale::ContentSecurityPolicy::AdminPortal.report_only?
30+
end
31+
32+
test 'policy_config returns empty hash when config.admin_portal_policy is nil' do
33+
ThreeScale::ContentSecurityPolicy::AdminPortal.config.stubs(:admin_portal_policy).returns(nil)
34+
policy_hash = ThreeScale::ContentSecurityPolicy::AdminPortal.policy_config
35+
36+
assert_equal({}, policy_hash)
37+
end
38+
end
39+
40+
class ThreeScale::ContentSecurityPolicy::DeveloperPortalTest < ActiveSupport::TestCase
41+
test 'config returns Rails configuration for CSP' do
42+
config = ThreeScale::ContentSecurityPolicy::DeveloperPortal.config
43+
44+
assert_not_nil config
45+
assert_kind_of ActiveSupport::OrderedOptions, config
46+
end
47+
48+
test 'enabled? returns true in test environment' do
49+
assert_equal true, ThreeScale::ContentSecurityPolicy::DeveloperPortal.enabled?
50+
end
51+
52+
test 'policy_config returns hash of CSP directives from YAML' do
53+
policy_hash = ThreeScale::ContentSecurityPolicy::DeveloperPortal.policy_config
54+
55+
assert_kind_of Hash, policy_hash
56+
assert policy_hash.present?
57+
58+
# Verify it contains the permissive default_src directive
59+
assert policy_hash.key?(:default_src)
60+
assert_includes policy_hash[:default_src], "*"
61+
assert_includes policy_hash[:default_src], "'unsafe-eval'"
62+
assert_includes policy_hash[:default_src], "'unsafe-inline'"
63+
end
64+
65+
test 'report_only? returns false from YAML config' do
66+
assert_equal false, ThreeScale::ContentSecurityPolicy::DeveloperPortal.report_only?
67+
end
68+
69+
test 'policy_config returns empty hash when config.developer_portal_policy is nil' do
70+
ThreeScale::ContentSecurityPolicy::DeveloperPortal.config.stubs(:developer_portal_policy).returns(nil)
71+
policy_hash = ThreeScale::ContentSecurityPolicy::DeveloperPortal.policy_config
72+
73+
assert_equal({}, policy_hash)
74+
end
75+
end
76+
77+
class ThreeScale::ContentSecurityPolicyWithoutYAMLTest < ActiveSupport::TestCase
78+
test 'AdminPortal enabled? returns false when config is missing' do
79+
empty_config = ActiveSupport::OrderedOptions.new
80+
ThreeScale::ContentSecurityPolicy::AdminPortal.stubs(:config).returns(empty_config)
81+
82+
assert_equal false, ThreeScale::ContentSecurityPolicy::AdminPortal.enabled?
83+
end
84+
85+
test 'AdminPortal policy_config returns empty hash when config is missing' do
86+
empty_config = ActiveSupport::OrderedOptions.new
87+
ThreeScale::ContentSecurityPolicy::AdminPortal.stubs(:config).returns(empty_config)
88+
89+
policy_hash = ThreeScale::ContentSecurityPolicy::AdminPortal.policy_config
90+
91+
assert_equal({}, policy_hash)
92+
end
93+
94+
test 'AdminPortal report_only? returns false when config is missing' do
95+
empty_config = ActiveSupport::OrderedOptions.new
96+
ThreeScale::ContentSecurityPolicy::AdminPortal.stubs(:config).returns(empty_config)
97+
98+
assert_equal false, ThreeScale::ContentSecurityPolicy::AdminPortal.report_only?
99+
end
100+
101+
test 'AdminPortal enabled? handles nil config values gracefully' do
102+
config = ActiveSupport::OrderedOptions.new
103+
config.enabled = nil
104+
ThreeScale::ContentSecurityPolicy::AdminPortal.stubs(:config).returns(config)
105+
106+
assert_equal false, ThreeScale::ContentSecurityPolicy::AdminPortal.enabled?
107+
end
108+
109+
test 'AdminPortal report_only? handles nil config values gracefully' do
110+
config = ActiveSupport::OrderedOptions.new
111+
config.report_only = nil
112+
ThreeScale::ContentSecurityPolicy::AdminPortal.stubs(:config).returns(config)
113+
114+
assert_equal false, ThreeScale::ContentSecurityPolicy::AdminPortal.report_only?
115+
end
116+
end

0 commit comments

Comments
 (0)