Files
growstuff/spec/controllers/seeds_controller_spec.rb
a2abe79e6f Fix Translation missing en.seeds.updated (#5100)
* Fix missing en.seeds.updated translation

Add missing updated key under the seeds scope in config/locales/en.yml
and add controller test verifying flash notice on seed update.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Update SeedsController test route parameter to use slug

Seeds routes use param: :slug. Updated test parameter key from id to slug.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-10-26 19:56:13 +10:30

287 lines
9.3 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
describe SeedsController do
let(:owner) { create(:member) }
describe "GET index" do
describe "picks up owner from params" do
before do
get :index, params: { member_slug: owner.slug }
end
it { expect(assigns(:owner)).to eq(owner) }
end
describe "sorting by nearness on a crop" do
let(:crop) { create(:crop) }
let(:viewer) { create(:london_member) }
let!(:far_seed) { create(:seed, crop:, owner: create(:south_pole_member), tradable_to: 'locally') }
let!(:unlocated_seed) { create(:seed, crop:, owner: create(:member), tradable_to: 'locally') }
let!(:near_seed) { create(:seed, crop:, owner: create(:london_member), tradable_to: 'locally') }
it 'lists nearest first when signed in with a location' do
sign_in viewer
get :index, params: { crop_slug: crop.slug }
expect(assigns(:seeds).to_a).to eq([near_seed, far_seed, unlocated_seed])
end
it 'does not sort by distance when signed out' do
get :index, params: { crop_slug: crop.slug }
expect(assigns(:sort_by_distance)).to be false
end
end
end
describe 'GET index filters' do
let(:crop) { create(:crop) }
let!(:own_seed) { create(:seed, crop:, source: 'my own seed saving', tradable_to: 'locally') }
let!(:bought_seed) { create(:seed, crop:, source: 'retail outlet', tradable_to: 'locally') }
let!(:traded_seed) { create(:seed, crop:, source: 'traded from another person', tradable_to: 'locally') }
context 'when choosing my own saving' do
before { get :index, params: { from: 'own' } }
it { expect(assigns(:seeds)).to contain_exactly(own_seed) }
end
context 'when choosing bought' do
before { get :index, params: { from: 'bought' } }
it { expect(assigns(:seeds)).to contain_exactly(bought_seed) }
end
context 'when choosing traded' do
before { get :index, params: { from: 'traded' } }
it { expect(assigns(:seeds)).to contain_exactly(traded_seed) }
end
context 'when choosing heirloom only' do
let!(:heirloom_seed) { create(:seed, crop:, heirloom: 'heirloom', tradable_to: 'locally') }
before { get :index, params: { from: 'heirloom' } }
it { expect(assigns(:seeds)).to contain_exactly(heirloom_seed) }
end
context 'when choosing past sow-by' do
let!(:expired_seed) { create(:seed, crop:, plant_before: Date.new(2020, 12, 31), tradable_to: 'locally') }
before { get :index, params: { past: '1' } }
it { expect(assigns(:seeds)).to include(expired_seed) }
end
context 'when a filter is chosen' do
before { get :index, params: { from: 'own' } }
it { expect(assigns(:filtered)).to be true }
end
context 'without a filter' do
before { get :index }
it { expect(assigns(:filtered)).to be false }
end
end
describe 'GET index of one crop' do
let(:tomato) { create(:crop, name: 'tomato') }
let(:brandywine) { create(:crop, name: 'Brandywine tomato', parent: tomato) }
let!(:variety_seed) { create(:seed, crop: brandywine, tradable_to: 'locally') }
let!(:parent_seed) { create(:seed, crop: tomato, tradable_to: 'locally') }
let!(:other_seed) { create(:seed, tradable_to: 'locally') }
context 'when choosing a crop' do
before { get :index, params: { crop: tomato.slug } }
it { expect(assigns(:seeds)).to contain_exactly(variety_seed, parent_seed) }
it { expect(assigns(:search_crop)).to eq tomato }
it { expect(assigns(:seed_total)).to eq 2 }
end
context 'when the crop does not exist' do
before { get :index, params: { crop: 'not-a-crop' } }
it { expect(assigns(:seeds)).to include(variety_seed, parent_seed, other_seed) }
it { expect(assigns(:search_crop)).to be_nil }
end
context 'on a crop\'s own page' do
before { get :index, params: { crop_slug: tomato.slug, crop: brandywine.slug } }
it { expect(assigns(:search_crop)).to be_nil }
end
end
describe 'GET index as the results alone' do
render_views
let(:owner) { create(:member) }
let(:tomato) { create(:crop, name: 'tomato') }
let(:json) { response.parsed_body }
before do
create(:seed, owner:, crop: tomato)
request.headers['X-Seed-Library'] = 'results'
get :index, params: { member_slug: owner.slug, crop: tomato.slug }, format: :json
end
it { expect(response.media_type).to eq 'application/json' }
it { expect(json['tabs']).to include('In stock') }
it { expect(json['results']).to include('seed-shelf') }
it { expect(json['results']).not_to include('<html') }
it { expect(json['crop']).to eq('name' => 'tomato', 'slug' => tomato.slug) }
it { expect(response.headers['Vary']).to include('X-Seed-Library') }
end
describe 'GET index pages of whole piles' do
let(:owner) { create(:member) }
let(:crops) { %w(apple beet carrot).map { |name| create(:crop, name:) } }
before do
stub_const('SeedsController::PER_PAGE', 2)
create_list(:seed, 5, owner:, crop: crops.first)
create_list(:seed, 4, owner:, crop: crops.second)
create_list(:seed, 3, owner:, crop: crops.third)
end
context 'on the first page' do
before { get :index, params: { member_slug: owner.slug } }
it { expect(assigns(:seeds).size).to eq 9 }
it { expect(assigns(:seeds).map(&:crop).uniq).to match_array crops.first(2) }
it { expect(assigns(:piles).total_entries).to eq 3 }
end
context 'on the second page' do
before { get :index, params: { member_slug: owner.slug, page: 2 } }
it { expect(assigns(:seeds).map(&:crop).uniq).to eq [crops.third] }
it { expect(assigns(:seeds).size).to eq 3 }
end
context 'when asking for csv' do
before { get :index, params: { member_slug: owner.slug }, format: :csv }
it { expect(assigns(:piles)).to be_nil }
it { expect(assigns(:seeds).size).to eq 2 } # a page of seeds, not of piles
end
end
describe 'GET index grouped by year' do
let(:owner) { create(:member) }
before do
create(:seed, owner:, saved_at: Date.new(2021, 5, 6))
create(:seed, owner:, saved_at: nil)
get :index, params: { member_slug: owner.slug, group: 'year' }
end
it { expect(assigns(:shelves).keys).to eq [Time.zone.today.year.to_s, '2021'] }
end
describe 'GET index of everyone\'s seeds' do
let!(:shared_seed) { create(:seed, tradable_to: 'locally') }
let!(:private_seed) { create(:seed, tradable_to: 'nowhere') }
context 'with no owner' do
before { get :index }
it { expect(assigns(:seeds)).to contain_exactly(shared_seed) }
it { expect(assigns(:shared_totals)).to eq(packets: 1, gardeners: 1) }
end
context 'with an owner' do
let(:owner) { private_seed.owner }
before { get :index, params: { member_slug: owner.slug } }
it { expect(assigns(:seeds)).to contain_exactly(private_seed) }
it { expect(assigns(:shared_totals)).to be_nil }
end
context 'when asking for csv' do
before { get :index, format: :csv }
it { expect(assigns(:seeds)).to include(private_seed) }
end
end
describe 'GET index scoped to people near or followed' do
let(:viewer) { create(:london_member) }
let!(:followed_seed) { create(:seed, owner: followed, tradable_to: 'locally') }
let!(:near_seed) { create(:seed, owner: create(:london_member), tradable_to: 'locally') }
let!(:far_seed) { create(:seed, owner: create(:south_pole_member), tradable_to: 'locally') }
let(:followed) { create(:south_pole_member) }
before do
create(:follow, follower: viewer, followed:)
sign_in viewer
end
context 'when following' do
before { get :index, params: { scope: 'following' } }
it { expect(assigns(:seeds)).to contain_exactly(followed_seed) }
end
context 'when near me' do
before { get :index, params: { scope: 'near' } }
it { expect(assigns(:seeds)).to contain_exactly(near_seed) }
end
context 'when within a distance' do
before { get :index, params: { within: '50' } }
it { expect(assigns(:seeds)).to contain_exactly(near_seed) }
end
end
describe 'GET index counts' do
let(:owner) { create(:member) }
before do
create(:seed, owner:)
create(:seed, owner:, finished: true)
create(:seed, owner:, plant_before: Date.new(2020, 12, 31))
get :index, params: { member_slug: owner.slug }
end
it { expect(assigns(:in_stock_count)).to eq 2 }
it { expect(assigns(:finished_count)).to eq 1 }
it { expect(assigns(:past_count)).to eq 2 }
it { expect(assigns(:stats)).to include(packets: 2) }
end
describe 'GET new' do
before { sign_in owner }
it { expect(response).to be_successful }
context 'with parent planting' do
let!(:planting) { create(:planting, owner:) }
before do
get :new, params: { planting_slug: planting.to_param }
end
it { expect(assigns(:planting)).to eq(planting) }
end
end
describe 'PATCH update' do
let!(:seed) { create(:seed, owner:) }
before { sign_in owner }
it 'updates seed and sets flash notice' do
patch :update, params: { slug: seed.to_param, seed: { description: 'Updated seed notes' } }
expect(flash[:notice]).to eq('Seed was successfully updated.')
end
end
end