panda-core 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/panda/core/testing/rails_helper.rb +3 -4
- data/lib/panda/core/testing/support/authentication_helpers.rb +58 -0
- data/lib/panda/core/testing/support/authentication_test_helpers.rb +260 -0
- data/lib/panda/core/testing/support/generator_spec_helper.rb +97 -0
- data/lib/panda/core/testing/support/html_helpers.rb +11 -0
- data/lib/panda/core/testing/support/omniauth_setup.rb +17 -0
- data/lib/panda/core/testing/support/service_stubs.rb +40 -0
- data/lib/panda/core/testing/support/setup.rb +11 -0
- data/lib/panda/core/version.rb +1 -1
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: abf323ca5beed58dcb17cd7f39ed76028413524b20e40cd2de8d9c5d21b97fff
|
|
4
|
+
data.tar.gz: 992d91647d9cd2567b7d818beb2f7a2d173fb16edf8f78f222a576a1e6b9534f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 42f8a466d633d31ee8e77650c0afcd9f768ef7990df74b185d3722e614a623f176944a610bee1ca4eee60f33edba812eda96b0b25f5e9466773c1f1920bd1213
|
|
7
|
+
data.tar.gz: a0f9ec858050df85d6a9cac0a04dc179673ad5438d8bd6c9deeb1ee0d52c5a1d0f5c2e0af9784cc717fcd59a987efd79f9ecc55d3d2456ba842d5056acff363b
|
|
@@ -29,10 +29,9 @@ Shoulda::Matchers.configure do |config|
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# Load all support files from panda-core
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
32
|
+
# Files are now in lib/panda/core/testing/support/ to be included in the published gem
|
|
33
|
+
support_path = File.expand_path("../support", __FILE__)
|
|
34
|
+
Dir[File.join(support_path, "**/*.rb")].sort.each { |f| require f }
|
|
36
35
|
|
|
37
36
|
RSpec.configure do |config|
|
|
38
37
|
# Include panda-core route helpers by default
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Panda
|
|
4
|
+
module Core
|
|
5
|
+
module AuthenticationHelpers
|
|
6
|
+
# Create test users with fixed IDs for consistent fixture references
|
|
7
|
+
def create_admin_user
|
|
8
|
+
Panda::Core::User.find_or_create_by!(id: "8f481fcb-d9c8-55d7-ba17-5ea5d9ed8b7a") do |user|
|
|
9
|
+
user.email = "admin@test.example.com"
|
|
10
|
+
user.firstname = "Admin"
|
|
11
|
+
user.lastname = "User"
|
|
12
|
+
user.admin = true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create_regular_user
|
|
17
|
+
Panda::Core::User.find_or_create_by!(id: "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d") do |user|
|
|
18
|
+
user.email = "user@test.example.com"
|
|
19
|
+
user.firstname = "Regular"
|
|
20
|
+
user.lastname = "User"
|
|
21
|
+
user.admin = false
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# For request specs - set session directly
|
|
26
|
+
def sign_in_as(user)
|
|
27
|
+
session[:user_id] = user.id
|
|
28
|
+
Panda::Core::Current.user = user
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# For system specs - use test session endpoint if available
|
|
32
|
+
def login_as_admin
|
|
33
|
+
admin_user = create_admin_user
|
|
34
|
+
if defined?(Panda::CMS)
|
|
35
|
+
# CMS provides test session endpoint
|
|
36
|
+
post "/admin/test_sessions", params: {user_id: admin_user.id}
|
|
37
|
+
else
|
|
38
|
+
# Fall back to direct session setting
|
|
39
|
+
sign_in_as(admin_user)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def login_as_regular_user
|
|
44
|
+
regular_user = create_regular_user
|
|
45
|
+
if defined?(Panda::CMS)
|
|
46
|
+
post "/admin/test_sessions", params: {user_id: regular_user.id}
|
|
47
|
+
else
|
|
48
|
+
sign_in_as(regular_user)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
RSpec.configure do |config|
|
|
56
|
+
# Include authentication helpers for all spec types (model, request, system, component, etc.)
|
|
57
|
+
config.include Panda::Core::AuthenticationHelpers
|
|
58
|
+
end
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Comprehensive authentication test helpers for Panda Core and consuming gems
|
|
4
|
+
# This module provides helpers for:
|
|
5
|
+
# - Creating test users with fixed IDs
|
|
6
|
+
# - OAuth mocking and configuration
|
|
7
|
+
# - Test session management
|
|
8
|
+
# - Request and system test authentication
|
|
9
|
+
|
|
10
|
+
module Panda
|
|
11
|
+
module Core
|
|
12
|
+
module AuthenticationTestHelpers
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# USER CREATION HELPERS
|
|
15
|
+
# ============================================================================
|
|
16
|
+
|
|
17
|
+
# Create an admin user with fixed ID for consistent fixture references
|
|
18
|
+
def create_admin_user(attributes = {})
|
|
19
|
+
ensure_columns_loaded
|
|
20
|
+
admin_id = "8f481fcb-d9c8-55d7-ba17-5ea5d9ed8b7a"
|
|
21
|
+
Panda::Core::User.find_or_create_by!(id: admin_id) do |user|
|
|
22
|
+
user.email = attributes[:email] || "admin@example.com"
|
|
23
|
+
user.firstname = attributes[:firstname] || "Admin" if user.respond_to?(:firstname=)
|
|
24
|
+
user.lastname = attributes[:lastname] || "User" if user.respond_to?(:lastname=)
|
|
25
|
+
user.name = attributes[:name] || "Admin User" if user.respond_to?(:name=) && !user.respond_to?(:firstname=)
|
|
26
|
+
user.image_url = attributes[:image_url] || default_image_url if user.respond_to?(:image_url=)
|
|
27
|
+
# Use is_admin for the actual column, but support both for compatibility
|
|
28
|
+
if user.respond_to?(:is_admin=)
|
|
29
|
+
user.is_admin = attributes.fetch(:admin, true)
|
|
30
|
+
elsif user.respond_to?(:admin=)
|
|
31
|
+
user.admin = attributes.fetch(:admin, true)
|
|
32
|
+
end
|
|
33
|
+
# Only set OAuth fields if they exist on the model
|
|
34
|
+
user.uid = attributes[:uid] || "admin_oauth_uid_123" if user.respond_to?(:uid=)
|
|
35
|
+
user.provider = attributes[:provider] || "google_oauth2" if user.respond_to?(:provider=)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Create a regular user with fixed ID for consistent fixture references
|
|
40
|
+
def create_regular_user(attributes = {})
|
|
41
|
+
ensure_columns_loaded
|
|
42
|
+
regular_id = "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d"
|
|
43
|
+
Panda::Core::User.find_or_create_by!(id: regular_id) do |user|
|
|
44
|
+
user.email = attributes[:email] || "user@example.com"
|
|
45
|
+
user.firstname = attributes[:firstname] || "Regular" if user.respond_to?(:firstname=)
|
|
46
|
+
user.lastname = attributes[:lastname] || "User" if user.respond_to?(:lastname=)
|
|
47
|
+
user.name = attributes[:name] || "Regular User" if user.respond_to?(:name=) && !user.respond_to?(:firstname=)
|
|
48
|
+
user.image_url = attributes[:image_url] || default_image_url(dark: true) if user.respond_to?(:image_url=)
|
|
49
|
+
# Use is_admin for the actual column, but support both for compatibility
|
|
50
|
+
if user.respond_to?(:is_admin=)
|
|
51
|
+
user.is_admin = attributes.fetch(:admin, false)
|
|
52
|
+
elsif user.respond_to?(:admin=)
|
|
53
|
+
user.admin = attributes.fetch(:admin, false)
|
|
54
|
+
end
|
|
55
|
+
# Only set OAuth fields if they exist on the model
|
|
56
|
+
user.uid = attributes[:uid] || "user_oauth_uid_456" if user.respond_to?(:uid=)
|
|
57
|
+
user.provider = attributes[:provider] || "google_oauth2" if user.respond_to?(:provider=)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Backwards compatibility with fixture access patterns
|
|
62
|
+
def admin_user
|
|
63
|
+
ensure_columns_loaded
|
|
64
|
+
@admin_user ||= Panda::Core::User.find_by(email: "admin@example.com") || create_admin_user
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def regular_user
|
|
68
|
+
ensure_columns_loaded
|
|
69
|
+
@regular_user ||= Panda::Core::User.find_by(email: "user@example.com") || create_regular_user
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# ============================================================================
|
|
73
|
+
# OMNIAUTH HELPERS
|
|
74
|
+
# ============================================================================
|
|
75
|
+
|
|
76
|
+
def clear_omniauth_config
|
|
77
|
+
OmniAuth.config.mock_auth.clear
|
|
78
|
+
Rails.application.env_config.delete("omniauth.auth") if defined?(Rails.application)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def mock_oauth_for_user(user, provider: :google_oauth2)
|
|
82
|
+
clear_omniauth_config
|
|
83
|
+
OmniAuth.config.test_mode = true
|
|
84
|
+
OmniAuth.config.mock_auth[provider] = OmniAuth::AuthHash.new({
|
|
85
|
+
provider: provider.to_s,
|
|
86
|
+
uid: (user.respond_to?(:uid) ? user.uid : nil) || user.id,
|
|
87
|
+
info: {
|
|
88
|
+
email: user.email,
|
|
89
|
+
name: user.name,
|
|
90
|
+
image: user.respond_to?(:image_url) ? user.image_url : nil
|
|
91
|
+
},
|
|
92
|
+
credentials: {
|
|
93
|
+
token: "mock_token_#{user.id}",
|
|
94
|
+
expires_at: Time.now + 1.week
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# ============================================================================
|
|
100
|
+
# REQUEST SPEC HELPERS (Direct Session Manipulation)
|
|
101
|
+
# ============================================================================
|
|
102
|
+
|
|
103
|
+
# For request specs - set session directly (fast, no HTTP requests)
|
|
104
|
+
def sign_in_as(user)
|
|
105
|
+
# This works in request specs where we have direct access to the session
|
|
106
|
+
begin
|
|
107
|
+
if respond_to?(:session)
|
|
108
|
+
session[:user_id] = user.id
|
|
109
|
+
end
|
|
110
|
+
rescue NoMethodError
|
|
111
|
+
# Session method doesn't exist in this context (e.g., system specs)
|
|
112
|
+
end
|
|
113
|
+
Panda::Core::Current.user = user
|
|
114
|
+
user
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# ============================================================================
|
|
118
|
+
# SYSTEM SPEC HELPERS (HTTP-based Authentication)
|
|
119
|
+
# ============================================================================
|
|
120
|
+
|
|
121
|
+
# For system specs - use test session endpoint (works across processes)
|
|
122
|
+
# This uses the TestSessionsController which is only available in test environment
|
|
123
|
+
#
|
|
124
|
+
# NOTE: Due to Cuprite's redirect handling, we visit the target path directly
|
|
125
|
+
# after setting up the session via the test endpoint. Flash messages won't be
|
|
126
|
+
# available in system tests due to cross-process timing. Use request specs
|
|
127
|
+
# to test flash messages (see authentication_request_spec.rb).
|
|
128
|
+
def login_with_test_endpoint(user, return_to: nil, expect_success: true)
|
|
129
|
+
return_path = return_to || determine_default_redirect_path
|
|
130
|
+
|
|
131
|
+
# Visit the test login endpoint (sets session via Redis)
|
|
132
|
+
# Note: Capybara/Cuprite may not follow the redirect properly, so we
|
|
133
|
+
# manually navigate to the expected destination
|
|
134
|
+
visit "/admin/test_login/#{user.id}?return_to=#{return_path}"
|
|
135
|
+
|
|
136
|
+
# Wait briefly for session to be set
|
|
137
|
+
sleep 0.2
|
|
138
|
+
|
|
139
|
+
# Manually visit the destination since Cuprite doesn't reliably follow redirects
|
|
140
|
+
if expect_success
|
|
141
|
+
visit return_path
|
|
142
|
+
# Wait for page to load
|
|
143
|
+
sleep 0.2
|
|
144
|
+
|
|
145
|
+
# Verify we're on the expected path
|
|
146
|
+
expect(page).to have_current_path(return_path, wait: 2)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Convenience method: Login with Google OAuth provider (using test endpoint)
|
|
151
|
+
def login_with_google(user, expect_success: true)
|
|
152
|
+
login_with_test_endpoint(user, return_to: determine_default_redirect_path, expect_success: expect_success)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Convenience method: Login with GitHub OAuth provider (using test endpoint)
|
|
156
|
+
def login_with_github(user, expect_success: true)
|
|
157
|
+
login_with_test_endpoint(user, return_to: determine_default_redirect_path, expect_success: expect_success)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Convenience method: Login with Microsoft OAuth provider (using test endpoint)
|
|
161
|
+
def login_with_microsoft(user, expect_success: true)
|
|
162
|
+
login_with_test_endpoint(user, return_to: determine_default_redirect_path, expect_success: expect_success)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# High-level helper: Login as admin (creates user if needed)
|
|
166
|
+
def login_as_admin(attributes = {})
|
|
167
|
+
user = create_admin_user(attributes)
|
|
168
|
+
if respond_to?(:visit)
|
|
169
|
+
# System spec - use test endpoint
|
|
170
|
+
login_with_test_endpoint(user, expect_success: true)
|
|
171
|
+
else
|
|
172
|
+
# Request spec - use direct session
|
|
173
|
+
sign_in_as(user)
|
|
174
|
+
end
|
|
175
|
+
user
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# High-level helper: Login as regular user (creates user if needed)
|
|
179
|
+
def login_as_user(attributes = {})
|
|
180
|
+
user = create_regular_user(attributes)
|
|
181
|
+
if respond_to?(:visit)
|
|
182
|
+
# System spec - regular users get redirected to login
|
|
183
|
+
login_with_test_endpoint(user, expect_success: false)
|
|
184
|
+
else
|
|
185
|
+
# Request spec - use direct session
|
|
186
|
+
sign_in_as(user)
|
|
187
|
+
end
|
|
188
|
+
user
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Manual OAuth login (slower, but tests actual OAuth flow)
|
|
192
|
+
# Use this when you need to test the OAuth callback handler itself
|
|
193
|
+
def manual_login_with_oauth(user, provider: :google_oauth2)
|
|
194
|
+
mock_oauth_for_user(user, provider: provider)
|
|
195
|
+
|
|
196
|
+
visit admin_login_path
|
|
197
|
+
expect(page).to have_css("#button-sign-in-#{provider}")
|
|
198
|
+
find("#button-sign-in-#{provider}").click
|
|
199
|
+
|
|
200
|
+
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[provider]
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# ============================================================================
|
|
204
|
+
# PRIVATE HELPER METHODS
|
|
205
|
+
# ============================================================================
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
def ensure_columns_loaded
|
|
210
|
+
return if @columns_loaded
|
|
211
|
+
Panda::Core::User.connection.schema_cache.clear!
|
|
212
|
+
Panda::Core::User.reset_column_information
|
|
213
|
+
@columns_loaded = true
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def default_image_url(dark: false)
|
|
217
|
+
color = dark ? "%23999" : "%23ccc"
|
|
218
|
+
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Crect width='100' height='100' fill='#{color}'/%3E%3C/svg%3E"
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def determine_default_redirect_path
|
|
222
|
+
# Check if we're in a CMS context
|
|
223
|
+
if defined?(Panda::CMS)
|
|
224
|
+
"/admin/cms"
|
|
225
|
+
else
|
|
226
|
+
"/admin"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def admin_login_path
|
|
231
|
+
if defined?(panda_core)
|
|
232
|
+
panda_core.admin_login_path
|
|
233
|
+
else
|
|
234
|
+
"/admin/login"
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def admin_root_path
|
|
239
|
+
if defined?(panda_core)
|
|
240
|
+
panda_core.admin_root_path
|
|
241
|
+
else
|
|
242
|
+
"/admin"
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Configure RSpec to include these helpers in appropriate test types
|
|
250
|
+
RSpec.configure do |config|
|
|
251
|
+
config.include Panda::Core::AuthenticationTestHelpers, type: :request
|
|
252
|
+
config.include Panda::Core::AuthenticationTestHelpers, type: :system
|
|
253
|
+
config.include Panda::Core::AuthenticationTestHelpers, type: :controller
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Configure OmniAuth for testing
|
|
257
|
+
OmniAuth.config.test_mode = true
|
|
258
|
+
OmniAuth.config.on_failure = proc { |env|
|
|
259
|
+
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
|
|
260
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require "rails/generators"
|
|
2
|
+
|
|
3
|
+
module GeneratorSpecHelper
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
before(:each) do
|
|
8
|
+
prepare_destination
|
|
9
|
+
@original_stdout = $stdout
|
|
10
|
+
$stdout = File.new(File::NULL, "w")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
after(:each) do
|
|
14
|
+
FileUtils.rm_rf(destination_root)
|
|
15
|
+
$stdout = @original_stdout
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def destination_root
|
|
20
|
+
@destination_root ||= File.expand_path("../../tmp/generators", __dir__)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def prepare_destination
|
|
24
|
+
FileUtils.rm_rf(destination_root)
|
|
25
|
+
FileUtils.mkdir_p(destination_root)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def run_generator(args = [])
|
|
29
|
+
args = Array(args)
|
|
30
|
+
# Use the generator namespace instead of class name
|
|
31
|
+
generator_name = described_class.namespace
|
|
32
|
+
Rails::Generators.invoke(generator_name, args, destination_root: destination_root)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def generator
|
|
36
|
+
@generator ||= described_class.new([], destination_root: destination_root)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def file_exists?(path)
|
|
40
|
+
File.exist?(File.join(destination_root, path))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def read_file(path)
|
|
44
|
+
File.read(File.join(destination_root, path))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def capture(stream)
|
|
50
|
+
stream = stream.to_s
|
|
51
|
+
captured_stream = StringIO.new
|
|
52
|
+
|
|
53
|
+
# Map stream names to their global variables to avoid eval
|
|
54
|
+
streams = {
|
|
55
|
+
"stdout" => $stdout,
|
|
56
|
+
"stderr" => $stderr,
|
|
57
|
+
"stdin" => $stdin
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
original_stream = streams[stream]
|
|
61
|
+
case stream
|
|
62
|
+
when "stdout"
|
|
63
|
+
$stdout = captured_stream
|
|
64
|
+
when "stderr"
|
|
65
|
+
$stderr = captured_stream
|
|
66
|
+
when "stdin"
|
|
67
|
+
$stdin = captured_stream
|
|
68
|
+
else
|
|
69
|
+
raise ArgumentError, "Unsupported stream: #{stream}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
yield
|
|
73
|
+
captured_stream.string
|
|
74
|
+
ensure
|
|
75
|
+
case stream
|
|
76
|
+
when "stdout"
|
|
77
|
+
$stdout = original_stream
|
|
78
|
+
when "stderr"
|
|
79
|
+
$stderr = original_stream
|
|
80
|
+
when "stdin"
|
|
81
|
+
$stdin = original_stream
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
RSpec.configure do |config|
|
|
87
|
+
config.include GeneratorSpecHelper, type: :generator
|
|
88
|
+
|
|
89
|
+
# Ensure generator tests have a clean environment
|
|
90
|
+
config.before(:each, type: :generator) do
|
|
91
|
+
prepare_destination
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
config.after(:each, type: :generator) do
|
|
95
|
+
FileUtils.rm_rf(destination_root) if defined?(destination_root)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Configure authentication providers for tests
|
|
4
|
+
RSpec.configure do |config|
|
|
5
|
+
config.before(:each, type: :controller) do
|
|
6
|
+
# Set up test authentication providers
|
|
7
|
+
Panda::Core.configure do |core_config|
|
|
8
|
+
core_config.authentication_providers = {
|
|
9
|
+
google_oauth2: {
|
|
10
|
+
client_id: "test_client_id",
|
|
11
|
+
client_secret: "test_client_secret",
|
|
12
|
+
options: {}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "tempfile"
|
|
4
|
+
require "base64"
|
|
5
|
+
|
|
6
|
+
# Stub services that make external HTTP requests to prevent them in tests
|
|
7
|
+
RSpec.configure do |config|
|
|
8
|
+
config.before(:each) do
|
|
9
|
+
# Stub URI.open to prevent external HTTP requests when downloading avatars
|
|
10
|
+
# This affects AttachAvatarService which downloads avatars from OAuth providers
|
|
11
|
+
# Tests that specifically need real HTTP requests can override this stub
|
|
12
|
+
allow(URI).to receive(:open).and_wrap_original do |original_method, *args, **kwargs, &block|
|
|
13
|
+
url = args[0]
|
|
14
|
+
|
|
15
|
+
# Only stub avatar downloads from OAuth providers and test URLs
|
|
16
|
+
if /googleusercontent\.com|githubusercontent\.com|graph\.microsoft\.com|example\.com/.match?(url.to_s)
|
|
17
|
+
# Use the actual test fixture file instead of creating a fake file
|
|
18
|
+
# This ensures compatibility with Active Storage
|
|
19
|
+
fixture_path = Panda::Core::Engine.root.join("spec", "fixtures", "files", "test_image.jpg")
|
|
20
|
+
downloaded_file = File.open(fixture_path, "rb")
|
|
21
|
+
|
|
22
|
+
# Add methods that AttachAvatarService expects
|
|
23
|
+
downloaded_file.define_singleton_method(:content_type) { "image/jpeg" }
|
|
24
|
+
downloaded_file.define_singleton_method(:size) { File.size(fixture_path) }
|
|
25
|
+
|
|
26
|
+
# Call the block with our file if a block is given
|
|
27
|
+
if block_given?
|
|
28
|
+
result = block.call(downloaded_file)
|
|
29
|
+
downloaded_file.close unless downloaded_file.closed?
|
|
30
|
+
result
|
|
31
|
+
else
|
|
32
|
+
downloaded_file
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
# For other URLs, use the original method
|
|
36
|
+
original_method.call(*args, **kwargs, &block)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/panda/core/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: panda-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Otaina Limited
|
|
@@ -471,6 +471,13 @@ files:
|
|
|
471
471
|
- lib/panda/core/sluggable.rb
|
|
472
472
|
- lib/panda/core/subscribers/authentication_subscriber.rb
|
|
473
473
|
- lib/panda/core/testing/rails_helper.rb
|
|
474
|
+
- lib/panda/core/testing/support/authentication_helpers.rb
|
|
475
|
+
- lib/panda/core/testing/support/authentication_test_helpers.rb
|
|
476
|
+
- lib/panda/core/testing/support/generator_spec_helper.rb
|
|
477
|
+
- lib/panda/core/testing/support/html_helpers.rb
|
|
478
|
+
- lib/panda/core/testing/support/omniauth_setup.rb
|
|
479
|
+
- lib/panda/core/testing/support/service_stubs.rb
|
|
480
|
+
- lib/panda/core/testing/support/setup.rb
|
|
474
481
|
- lib/panda/core/version.rb
|
|
475
482
|
- lib/tasks/assets.rake
|
|
476
483
|
- lib/tasks/panda/core/migrations.rake
|