Files
growstuff/spec/requests/gardens_json_spec.rb
T
Brenda WallaceandClaude Sonnet 5 86deb55d53 Let garden cards edit a garden as JSON
GET /gardens/:slug/edit.json gives the form's values and choices, and
PATCH /gardens/:slug.json returns the garden's refreshed card, or the
validation errors as 422, without queueing a flash message.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 17:42:26 +12:00

93 lines
3.6 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
# GET /gardens/:slug/edit.json and PATCH /gardens/:slug.json are for our own React
# garden cards only: session cookie and CSRF token, same origin.
describe 'Editing a garden as JSON' do
include Devise::Test::IntegrationHelpers
let(:member) { create(:london_member) }
let!(:garden) { create(:garden, owner: member, name: 'Orchard', description: 'Apples', area: 12, area_unit: 'square metre') }
let(:json_headers) { { 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' } }
def update_garden(attributes, target: garden)
patch "/gardens/#{target.slug}.json", params: { garden: attributes }.to_json, headers: json_headers
end
context 'when signed in' do
before { sign_in member }
it 'gives the current values and the choices for the selects' do
type = create(:garden_type, name: 'Allotment')
garden.update!(garden_type: type)
get "/gardens/#{garden.slug}/edit.json", headers: { 'ACCEPT' => 'application/json' }
expect(response).to have_http_status(:ok)
body = response.parsed_body
expect(body['garden']).to include('url' => "/gardens/#{garden.slug}", 'name' => 'Orchard', 'description' => 'Apples',
'area' => '12.0', 'area_unit' => 'square metre', 'garden_type_id' => type.id, 'active' => true)
expect(body['area_units']).to include('label' => 'hectares', 'value' => 'hectare')
expect(body['garden_types']).to include('id' => type.id, 'name' => 'Allotment')
expect(body).to include('member_has_location' => true, 'settings_url' => '/members/edit')
end
it "shows the member's location for a garden that has none of its own" do
garden.update_columns(location: nil)
get "/gardens/#{garden.slug}/edit.json", headers: { 'ACCEPT' => 'application/json' }
expect(response.parsed_body.dig('garden', 'location')).to eq 'Greenwich, UK'
end
it "saves the changes and returns the garden's refreshed card" do
update_garden({ name: 'Back orchard', description: 'Apples and pears' })
expect(response).to have_http_status(:ok)
expect(garden.reload).to have_attributes(name: 'Back orchard', description: 'Apples and pears')
expect(response.parsed_body['garden']).to include('id' => garden.id, 'name' => 'Back orchard', 'active' => true)
end
it 'does not queue a flash message for the next page' do
update_garden({ name: 'Back orchard' })
get root_path
expect(response.body).not_to include(I18n.t('gardens.updated'))
end
it 'marks the garden inactive, finishing its plantings, and says so in the card' do
planting = create(:planting, garden: garden, owner: member)
update_garden({ active: false })
expect(response.parsed_body['garden']).to include('active' => false)
expect(garden.reload.active).to be false
expect(planting.reload.finished).to be true
end
it 'returns validation errors as 422 and keeps the old values' do
update_garden({ name: '' })
expect(response).to have_http_status(:unprocessable_entity)
expect(response.parsed_body['errors']).to have_key('name')
expect(garden.reload.name).to eq 'Orchard'
end
it "refuses someone else's garden" do
someone_elses = create(:garden)
update_garden({ name: 'Mine now' }, target: someone_elses)
expect(response).to have_http_status(:forbidden)
expect(someone_elses.reload.name).not_to eq 'Mine now'
end
end
it 'asks a visitor who is not signed in to sign in' do
update_garden({ name: 'Nope' })
expect(response).to have_http_status(:unauthorized)
end
end