Rails 4.2使用Puffing Billy Stub第三方图片延迟响应失败
看起来你遇到的核心问题是Puffing Billy的白名单和Stub配置没生效,导致Cloudinary的图片请求要么被完全阻塞,要么Stub没触发,没法模拟慢加载场景。我来一步步帮你排查和修复:
1. 修正白名单配置(关键!)
你日志里的错误Connection to https://res.cloudinary.com:443/... not cached and new http connections are disabled,说明白名单没正确匹配请求。Puffing Billy的whitelist配置需要的是主机名,不是带协议的完整URL。把你的Billy配置里的白名单改成:
c.whitelist = ['localhost', '127.0.0.1', 'res.cloudinary.com']
去掉https://,这样Puffing Billy才会识别这个主机的请求是允许的,不会直接拦截。
2. 修复Stub的写法
你当前的Stub Proc写法有两个问题:
- 返回的键是
code,但Puffing Billy需要的是status - 没有返回实际的图片内容,浏览器无法识别图片加载完成,导致Spinner不会消失
修改Stub为:
proxy.stub("https://res.cloudinary.com/demo/image/upload/sample.jpg").and_return( Proc.new do |params, headers, body| sleep 3 # 用3秒足够测试,不用10秒节省时间 # 用本地图片Fixture返回,避免依赖外部资源 image_path = Rails.root.join('spec', 'fixtures', 'sample_image.jpg') { status: 200, body: File.read(image_path), headers: { 'Content-Type' => 'image/jpeg' } } end )
记得先在spec/fixtures/目录下放一张测试用的sample_image.jpg。
3. 优化测试逻辑,避免硬编码Sleep
硬编码sleep 15很不可靠,应该用Capybara的内置等待机制:
context "non signed in visitor", js: true, billy: true do describe "Spinner shows while waiting then disappears" do it "should show spinner during image load and hide afterwards" do proxy.stub("https://res.cloudinary.com/demo/image/upload/sample.jpg").and_return( Proc.new do |params, headers, body| sleep 3 image_path = Rails.root.join('spec', 'fixtures', 'sample_image.jpg') { status: 200, body: File.read(image_path), headers: { 'Content-Type' => 'image/jpeg' } } end ) visit actual_deal_page_path(deal) # 验证Spinner立即显示 expect(page).to have_css('div#fullPageLoadingSpinner', visible: :visible, wait: 1) # 此时图片不可见 expect(page).not_to have_css("img[src*='sample.jpg']", visible: :visible, wait: 1) # 等待图片加载完成,Spinner隐藏 expect(page).to have_css('div#fullPageLoadingSpinner', visible: :hidden, wait: 5) # 验证图片成功显示 expect(page).to have_css("img[src*='sample.jpg']", visible: :visible, wait: 5) end end end
wait: 5告诉Capybara最多等5秒,直到条件满足,比硬Sleep更稳定。
4. 暂时禁用缓存,确保Stub生效
你的配置里开启了c.cache = true和c.persist_cache = true,如果之前有缓存的Cloudinary请求,Stub可能不会触发。可以暂时把c.cache = false,或者删除缓存目录spec/support/http_cache/billy/,测试通过后再恢复缓存。
5. 确认前端图片加载逻辑正确
最后要确保你的前端JS是正确监听图片加载事件的,比如:
const spinner = document.getElementById('fullPageLoadingSpinner'); const coverImage = document.querySelector('.deal-page-bckdImgCover'); // 图片加载完成后隐藏Spinner coverImage.addEventListener('load', () => { spinner.style.visibility = 'hidden'; // 或者用你项目里的隐藏逻辑 }); // 处理图片加载失败的情况 coverImage.addEventListener('error', () => { spinner.style.visibility = 'hidden'; // 可选:显示错误提示 });
如果前端逻辑没正确绑定事件,即使图片加载了,Spinner也不会消失,这点很容易被忽略。
内容的提问来源于stack exchange,提问作者Mathieu

