Before running tests, ensure the test database is set up:
1
Start Docker services
make local
2
Setup test database
RAILS_ENV=test bin/rails db:setup
3
Export JavaScript constants
RAILS_ENV=test bin/rails js:export
The js:export command generates JavaScript constants for the test environment. Without this, tests may try to navigate to the development domain and encounter 502 errors.
Don’t use “should” in test descriptions. Be descriptive about the behavior being tested.
it "displays the user's balance" do expect(page).to have_text("Balance $100")endit "redirects to login when not authenticated" do visit dashboard_path expect(current_path).to eq(login_path)end
RSpec.describe "Dashboard", js: true, type: :system do let(:seller) { create(:named_seller) } before do login_as seller end it "displays correct values and headings for stats" do visit dashboard_path within "main" do expect(page).to have_text("Balance $100", normalize_ws: true) expect(page).to have_text("Last 7 days $50", normalize_ws: true) expect(page).to have_text("Last 28 days $150", normalize_ws: true) end endend
VCR records HTTP requests and replays them in tests:
RSpec.describe PayPalService do it "processes payment" do VCR.use_cassette("paypal/successful_payment") do result = PayPalService.process_payment(amount: 100) expect(result).to be_success end endend
Scope VCR cassettes to specific test files. Sharing cassettes across tests causes collisions where tests read incorrect cached responses.
RSpec.describe ProcessOrderJob do it "enqueues the job" do expect { ProcessOrderJob.perform_async(order.id) }.to change { ProcessOrderJob.jobs.size }.by(1) end it "processes the order" do ProcessOrderJob.new.perform(order.id) expect(order.reload.status).to eq("processed") endend
Avoid to_not have_enqueued_sidekiq_job or not_to have_enqueued_sidekiq_job because they’re prone to false positives. Make assertions on SidekiqWorkerName.jobs.size instead.
RSpec.describe "Products API" do describe "GET /api/v2/products" do it "returns successful response" do get "/api/v2/products" expect(response).to have_http_status(:ok) end it "returns products array" do create(:product) get "/api/v2/products" expect(json_response["products"]).to be_an(Array) end endend