Receber por email
← Voltar para o catálogo

spree-testing

Test Spree applications and extensions with RSpec — `spree_dev_tools` gem (v5.2+) for factories and helpers, FactoryBot patterns (prefer `build` over `create`), Capybara feature specs, controller/request specs, testing decorators and subscribers, dummy app for extension testing, system specs for the Hotwire admin, and CI patterns. Use when writing Spree tests, setting up CI, or refactoring slow sp

34estrelas
Atualizado há 5 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add OrcaQubits/agentic-commerce-skills-plugins

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/spree-testing/svg)](https://www.skillteca.com.br/skills/spree-testing)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Spree Testing

Before writing code

Fetch live docs:

  1. Fetch https://spreecommerce.org/docs/developer/tutorial/testing for the canonical testing tutorial.
  2. Check the spree_dev_tools gem on RubyGems and GitHub for the current factory inventory and helpers.
  3. Inspect the Spree gem's own spec/ directory for the latest test patterns.
  4. Cross-reference Rails 7+ testing docs for current request/system spec patterns.
  5. For RSpec, FactoryBot, Capybara — check current gem versions vs your Spree's Gemfile.lock.

Conceptual Architecture

The Testing Stack

| Tool | Purpose | |------|---------| | RSpec | Test framework | | FactoryBot | Test data factories | | Capybara | Feature/system specs (browser-driven) | | spree_dev_tools (v5.2+) | Spree-specific factories, shared examples, helpers | | Selenium / Cuprite | Headless browser for system specs | | Sidekiq Testing | Background job assertions | | VCR / WebMock | Stub external APIs |

spree_dev_tools (v5.2+)

Formally introduced in v5.2 as a separate gem (was previously bundled). Provides:

  • Pre-built factories for every Spree model (Spree::Order, Spree::Product, Spree::User, etc.)
  • Shared examples for common test patterns
  • Helpers for creating realistic test scenarios (create_order_with_two_items, etc.)
  • Engine spec setup for extension testing
# Gemfile
group :development, :test do
  gem 'spree_dev_tools'
end

Spec Types

| Type | What it tests | |------|---------------| | Model spec | A model's methods, validations, associations | | Request spec | HTTP request → response, including auth | | Controller spec | (Legacy — Rails 5+ prefers request specs) | | Feature spec | User behavior via Capybara | | System spec | Like feature but with full Rails 5.1+ integration | | Job spec | Background job logic | | Mailer spec | Email content | | Subscriber spec | Event subscriber assertions |

build vs create

# Slow — hits the database
let(:product) { create(:product) }

# Fast — in-memory only
let(:product) { build(:product) }

# Stub — fastest, no validation
let(:product) { build_stubbed(:product) }

Use build when you only need the object to call methods. Reach for create only when you need persistence (find_by, foreign keys, callbacks that hit the DB).

Common Factories

create(:product)                     # basic product
create(:product, name: 'Foo')        # with overrides
create(:product_in_stock)            # has stock
create(:order_with_line_items, line_items_count: 3)
create(:order_ready_to_complete)
create(:completed_order_with_pending_payment)
create(:user_with_addresses)
create(:admin_user)                   # has admin role

Verify the actual factory names against the spree_dev_tools source.

Testing a Decorator

# spec/models/spree/product_decorator_spec.rb
require 'rails_helper'

RSpec.describe Spree::Product, type: :model do
  describe 'editor_pick scope' do
    let!(:pick) { create(:product, editor_pick: true) }
    let!(:other) { create(:product, editor_pick: false) }

    it 'returns only editor-picked products' do
      expect(Spree::Product.editor_picks).to contain_exactly(pick)
    end
  end

  describe '#display_name' do
    let(:product) { build(:product, seo_title: 'Premium Tee', name: 'Tee') }

    it 'prefers seo_title' do
      expect(product.display_name).to eq('Premium Tee')
    end
  end
end

Testing a Subscriber

# spec/subscribers/order_completed_subscriber_spec.rb
require 'rails_helper'

RSpec.describe OrderCompletedSubscriber do
  let(:order) { create(:order, state: 'complete') }

  it 'enqueues an accounting sync' do
    expect {
      Spree::Bus.publish('order.completed', order: order, user: order.user)
    }.to have_enqueued_job(AccountingSyncJob).with(order_id: order.id)
  end
end

Testing a Service / Dependency Override

RSpec.describe MyApp::CartAddItemService do
  let(:order)   { create(:order) }
  let(:variant) { create(:variant) }

  it 'adds an item with extra metadata' do
    service = described_class.new
    result = service.call(order: order, variant: variant, quantity: 1, options: { source: 'app' })

    expect(result).to be_a(Spree::LineItem)
    expect(result.metafields.find_by(key: 'source').value).to eq('app')
  end
end

Feature/System Specs (Hotwire-aware)

Spree v5 admin uses Hotwire/Turbo. System specs need a JS driver:

# spec/system/admin/products_spec.rb
require 'rails_helper'

RSpec.describe 'Admin products', type: :system do
  let(:admin) { create(:admin_user) }
  before { sign_in admin; driven_by(:cuprite) }   # or :selenium_chrome_headless

  it 'creates a product' do
    visit spree.admin_products_path
    click_on 'New Product'
    fill_in 'Name', with: 'Test Product'
    fill_in 'Price', with: '19.99'
    click_on 'Create'
    expect(page).to have_content('Test Product')
  end
end

Testing API v3 Endpoints

RSpec.describe 'Store API v3 products', type: :request do
  let(:store) { create(:store) }
  let(:api_key) { create(:publishable_api_key, store: store).key }
  let!(:product) { create(:product, stores: [store]) }

  it 'lists products' do
    get '/api/v3/store/products', headers: { 'Authorization' => "Bearer #{api_key}" }
    expect(response).to have_http_status(:ok)
    body = JSON.parse(response.body)
    expect(body['data'].first['id']).to start_with('prod_')
    expect(body['data'].first['name']).to eq(product.name)
  end
end

(Verify the factory name :publishable_api_key in current spree_dev_tools.)

Testing With Sidekiq

# config/initializers/sidekiq.rb in test env auto-uses InlineTesting
require 'sidekiq/testing'
Sidekiq::Testing.fake!   # default for specs

RSpec.describe 'webhook delivery' do
  it 'enqueues a delivery job on order.completed' do
    order = create(:order, state: 'complete')
    expect {
      Spree::Bus.publish('order.completed', order: order)
    }.to change(Spree::WebhookDeliveryJob.jobs, :size).by(1)
  end
end

(Verify the job class name in the current Webhooks 2.0 implementation.)

Testing an Extension's Engine

Extensions test against a dummy Rails app:

cd spree_my_extension
bundle exec rake test_app  # generates spec/dummy
bundle exec rspec

The test_app rake task (verify it exists in current scaffolding) creates spec/dummy mounting Spree + your extension. Specs run against it.

Mocking External APIs

# spec/requests/stripe_webhook_spec.rb
RSpec.describe 'Stripe webhook', type: :request do
  it 'processes payment_intent.succeeded' do
    stub_request(:get, %r{api\.stripe\.com/v1/payment_intents})
      .to_return(body: { id: 'pi_…', status: 'succeeded' }.to_json)
    # ...
  end
end

WebMock is the standard; VCR is heavier-handed (records real responses to replay).

Implementation Guidance

Spec Suite Setup

# spec/rails_helper.rb
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rspec/rails'
require 'capybara/rspec'
require 'sidekiq/testing'

Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f }

RSpec.configure do |config|
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!

  config.include FactoryBot::Syntax::Methods
  config.include Spree::TestingSupport::AuthorizationHelpers, type: :controller
  config.include Spree::TestingSupport::ControllerRequests, type: :controller
  config.include Spree::TestingSupport::Capybara, type: :feature
end

(Verify the exact testing-support modules — they evolve.)

Speed Strategies

  1. Prefer build and build_stubbed over create
  2. Don't load full Rails for unit-y specs when possible
  3. Parallel test execution — parallel_tests gem with N processes
  4. Skip image processing in tests — `Spree::Config.imag
Compartilhar X LinkedIn