diff --git a/app/assets/stylesheets/admin/budgets_wizard/headings/group_switcher.scss b/app/assets/stylesheets/admin/budgets_wizard/headings/group_switcher.scss new file mode 100644 index 000000000..e0c4109f3 --- /dev/null +++ b/app/assets/stylesheets/admin/budgets_wizard/headings/group_switcher.scss @@ -0,0 +1,50 @@ +.budget-group-switcher { + margin-bottom: $line-height; + + p { + margin-bottom: 0; + } + + > .menu > li { + + > button { + align-items: center; + border: $admin-border; + border-radius: $button-radius; + display: inline-flex; + padding: rem-calc(11) rem-calc(16); + + &:active { + color: inherit; + } + + &::after { + @include css-triangle($dropdownmenu-arrow-size, currentcolor, down); + margin-left: 0.2em; + } + } + } + + .menu.is-dropdown-submenu { + margin: 0; + min-width: 100%; + padding: 0; + + li { + margin-bottom: 0; + } + + a { + cursor: default; + padding: rem-calc(11) rem-calc(16); + width: 100%; + + &:focus, + &:hover { + @include brand-background; + text-decoration: none; + outline: none; + } + } + } +} diff --git a/app/components/admin/budget_groups/groups_component.html.erb b/app/components/admin/budget_groups/groups_component.html.erb index 00bcc18fc..2b8f1d596 100644 --- a/app/components/admin/budget_groups/groups_component.html.erb +++ b/app/components/admin/budget_groups/groups_component.html.erb @@ -18,7 +18,7 @@ <%= render Admin::TableActionsComponent.new(group) do |actions| %> <%= actions.link_to t("admin.budget_groups.headings_manage"), - admin_budget_group_headings_path(budget, group), + headings_path(actions, group), class: "headings-link" %> <% end %> diff --git a/app/components/admin/budget_groups/groups_component.rb b/app/components/admin/budget_groups/groups_component.rb index 87012734d..51bf60649 100644 --- a/app/components/admin/budget_groups/groups_component.rb +++ b/app/components/admin/budget_groups/groups_component.rb @@ -10,4 +10,8 @@ class Admin::BudgetGroups::GroupsComponent < ApplicationComponent def budget @budget ||= groups.first.budget end + + def headings_path(table_actions_component, group) + send("#{table_actions_component.namespace}_budget_group_headings_path", group.budget, group) + end end diff --git a/app/components/admin/budgets_wizard/creation_step_component.html.erb b/app/components/admin/budgets_wizard/creation_step_component.html.erb new file mode 100644 index 000000000..b6ecad267 --- /dev/null +++ b/app/components/admin/budgets_wizard/creation_step_component.html.erb @@ -0,0 +1,19 @@ +
+ + + <%= content %> + + + + <% if next_step_path %> + <%= link_to t("admin.budgets_wizard.#{i18n_namespace}.continue"), + next_step_path, + class: "next-step" %> + <% else %> +

+ <%= t("admin.budgets_wizard.#{i18n_namespace}.continue") %> +

+ <% end %> +
diff --git a/app/components/admin/budgets_wizard/creation_step_component.rb b/app/components/admin/budgets_wizard/creation_step_component.rb new file mode 100644 index 000000000..2bd220146 --- /dev/null +++ b/app/components/admin/budgets_wizard/creation_step_component.rb @@ -0,0 +1,22 @@ +class Admin::BudgetsWizard::CreationStepComponent < ApplicationComponent + attr_reader :record, :next_step_path + + def initialize(record, next_step_path) + @record = record + @next_step_path = next_step_path + end + + private + + def show_form? + record.errors.any? + end + + def i18n_namespace + i18n_namespace_with_budget.gsub("budget_", "") + end + + def i18n_namespace_with_budget + record.class.table_name + end +end diff --git a/app/components/admin/budgets_wizard/creation_timeline_component.rb b/app/components/admin/budgets_wizard/creation_timeline_component.rb index 6db8d61e2..a4f4ed24f 100644 --- a/app/components/admin/budgets_wizard/creation_timeline_component.rb +++ b/app/components/admin/budgets_wizard/creation_timeline_component.rb @@ -8,6 +8,6 @@ class Admin::BudgetsWizard::CreationTimelineComponent < ApplicationComponent private def steps - %w[budget groups] + %w[budget groups headings] end end diff --git a/app/components/admin/budgets_wizard/groups/creation_step_component.html.erb b/app/components/admin/budgets_wizard/groups/creation_step_component.html.erb index a4254e09e..9f1c1ab33 100644 --- a/app/components/admin/budgets_wizard/groups/creation_step_component.html.erb +++ b/app/components/admin/budgets_wizard/groups/creation_step_component.html.erb @@ -1,19 +1,3 @@ -
- - +<%= render Admin::BudgetsWizard::CreationStepComponent.new(group, next_step_path) do %> <%= render "/admin/budget_groups/form", group: group, path: form_path, action: "create" %> - - - - <% if next_step_path %> - <%= link_to t("admin.budgets_wizard.groups.continue"), - next_step_path, - class: "next-step" %> - <% else %> -

- <%= t("admin.budgets_wizard.groups.continue") %> -

- <% end %> -
+<% end %> diff --git a/app/components/admin/budgets_wizard/groups/creation_step_component.rb b/app/components/admin/budgets_wizard/groups/creation_step_component.rb index 00a6cb2d3..8a5e3bfa9 100644 --- a/app/components/admin/budgets_wizard/groups/creation_step_component.rb +++ b/app/components/admin/budgets_wizard/groups/creation_step_component.rb @@ -12,16 +12,12 @@ class Admin::BudgetsWizard::Groups::CreationStepComponent < ApplicationComponent group.budget end - def show_form? - group.errors.any? - end - def form_path admin_budgets_wizard_budget_groups_path(budget) end def next_step_path - admin_budget_group_headings_path(budget, next_step_group) if next_step_enabled? + admin_budgets_wizard_budget_group_headings_path(budget, next_step_group) if next_step_enabled? end def next_step_enabled? diff --git a/app/components/admin/budgets_wizard/headings/creation_step_component.html.erb b/app/components/admin/budgets_wizard/headings/creation_step_component.html.erb new file mode 100644 index 000000000..a8ca3d7b4 --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/creation_step_component.html.erb @@ -0,0 +1,3 @@ +<%= render Admin::BudgetsWizard::CreationStepComponent.new(heading, next_step_path) do %> + <%= render "/admin/budget_headings/form", heading: heading, path: form_path, action: "create" %> +<% end %> diff --git a/app/components/admin/budgets_wizard/headings/creation_step_component.rb b/app/components/admin/budgets_wizard/headings/creation_step_component.rb new file mode 100644 index 000000000..8758c6bbc --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/creation_step_component.rb @@ -0,0 +1,25 @@ +class Admin::BudgetsWizard::Headings::CreationStepComponent < ApplicationComponent + attr_reader :heading + + def initialize(heading) + @heading = heading + end + + private + + def budget + heading.budget + end + + def form_path + admin_budgets_wizard_budget_group_headings_path(heading.group.budget, heading.group) + end + + def next_step_path + admin_budget_path(budget) if next_step_enabled? + end + + def next_step_enabled? + budget.headings.any? + end +end diff --git a/app/components/admin/budgets_wizard/headings/edit_component.html.erb b/app/components/admin/budgets_wizard/headings/edit_component.html.erb new file mode 100644 index 000000000..5a269b582 --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/edit_component.html.erb @@ -0,0 +1,7 @@ +<%= back_link_to admin_budgets_wizard_budget_group_headings_path(budget, group) %> + +<%= header %> + +<%= render Admin::BudgetsWizard::CreationTimelineComponent.new("headings") %> + +<%= render "/admin/budget_headings/form", heading: heading, path: form_path, action: "submit" %> diff --git a/app/components/admin/budgets_wizard/headings/edit_component.rb b/app/components/admin/budgets_wizard/headings/edit_component.rb new file mode 100644 index 000000000..ee6250b23 --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/edit_component.rb @@ -0,0 +1,26 @@ +class Admin::BudgetsWizard::Headings::EditComponent < ApplicationComponent + include Header + attr_reader :heading + + def initialize(heading) + @heading = heading + end + + def budget + heading.budget + end + + def group + heading.group + end + + def title + heading.name + end + + private + + def form_path + admin_budgets_wizard_budget_group_heading_path(budget, group, heading) + end +end diff --git a/app/components/admin/budgets_wizard/headings/group_switcher_component.html.erb b/app/components/admin/budgets_wizard/headings/group_switcher_component.html.erb new file mode 100644 index 000000000..4fe2ba830 --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/group_switcher_component.html.erb @@ -0,0 +1,21 @@ +
+ <% if other_groups.one? %> +

+ <%= t("admin.budget_headings.group_switcher.currently_showing", group: group.name) %> + <%= link_to t("admin.budget_headings.group_switcher.the_other_group", group: other_groups.first.name), + headings_path(other_groups.first) %> +

+ <% else %> +

<%= t("admin.budget_headings.group_switcher.currently_showing", group: group.name) %>

+ + <% end %> +
diff --git a/app/components/admin/budgets_wizard/headings/group_switcher_component.rb b/app/components/admin/budgets_wizard/headings/group_switcher_component.rb new file mode 100644 index 000000000..b6e490ad9 --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/group_switcher_component.rb @@ -0,0 +1,25 @@ +class Admin::BudgetsWizard::Headings::GroupSwitcherComponent < ApplicationComponent + attr_reader :group + + def initialize(group) + @group = group + end + + def render? + other_groups.any? + end + + private + + def budget + group.budget + end + + def other_groups + @other_groups ||= budget.groups.sort_by_name - [group] + end + + def headings_path(group) + admin_budgets_wizard_budget_group_headings_path(budget, group) + end +end diff --git a/app/components/admin/budgets_wizard/headings/index_component.html.erb b/app/components/admin/budgets_wizard/headings/index_component.html.erb new file mode 100644 index 000000000..21e0d538d --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/index_component.html.erb @@ -0,0 +1,10 @@ +<%= back_link_to admin_budgets_wizard_budget_groups_path(budget), t("admin.budget_headings.index.back") %> + +<%= header %> + +<%= render Admin::Budgets::HelpComponent.new("budget_headings") %> +<%= render Admin::BudgetsWizard::CreationTimelineComponent.new("headings") %> + +<%= render Admin::BudgetsWizard::Headings::GroupSwitcherComponent.new(group) %> +<%= render Admin::BudgetHeadings::HeadingsComponent.new(headings) %> +<%= render Admin::BudgetsWizard::Headings::CreationStepComponent.new(new_heading) %> diff --git a/app/components/admin/budgets_wizard/headings/index_component.rb b/app/components/admin/budgets_wizard/headings/index_component.rb new file mode 100644 index 000000000..76aa584a9 --- /dev/null +++ b/app/components/admin/budgets_wizard/headings/index_component.rb @@ -0,0 +1,21 @@ +class Admin::BudgetsWizard::Headings::IndexComponent < ApplicationComponent + include Header + attr_reader :headings, :new_heading + + def initialize(headings, new_heading) + @headings = headings + @new_heading = new_heading + end + + def budget + group.budget + end + + def group + new_heading.group + end + + def title + t("admin.budget_headings.index.title", budget: budget.name, group: group.name) + end +end diff --git a/app/controllers/admin/budget_headings_controller.rb b/app/controllers/admin/budget_headings_controller.rb index 6c0f43174..366641a8a 100644 --- a/app/controllers/admin/budget_headings_controller.rb +++ b/app/controllers/admin/budget_headings_controller.rb @@ -1,69 +1,20 @@ class Admin::BudgetHeadingsController < Admin::BaseController - include Translatable - include FeatureFlags - feature_flag :budgets - - before_action :load_budget - before_action :load_group - before_action :load_heading, only: [:edit, :update, :destroy] + include Admin::BudgetHeadingsActions def index - @headings = @group.headings.order(:id) end def new @heading = @group.headings.new end - def edit - end - - def create - @heading = @group.headings.new(budget_heading_params) - if @heading.save - redirect_to headings_index, notice: t("admin.budget_headings.create.notice") - else - render :new - end - end - - def update - if @heading.update(budget_heading_params) - redirect_to headings_index, notice: t("admin.budget_headings.update.notice") - else - render :edit - end - end - - def destroy - if @heading.can_be_deleted? - @heading.destroy! - redirect_to headings_index, notice: t("admin.budget_headings.destroy.success_notice") - else - redirect_to headings_index, alert: t("admin.budget_headings.destroy.unable_notice") - end - end - private - def load_budget - @budget = Budget.find_by_slug_or_id! params[:budget_id] - end - - def load_group - @group = @budget.groups.find_by_slug_or_id! params[:group_id] - end - - def load_heading - @heading = @group.headings.find_by_slug_or_id! params[:id] - end - def headings_index admin_budget_group_headings_path(@budget, @group) end - def budget_heading_params - valid_attributes = [:price, :population, :allow_custom_content, :latitude, :longitude, :max_ballot_lines] - params.require(:budget_heading).permit(*valid_attributes, translation_params(Budget::Heading)) + def new_action + :new end end diff --git a/app/controllers/admin/budgets_wizard/headings_controller.rb b/app/controllers/admin/budgets_wizard/headings_controller.rb new file mode 100644 index 000000000..5eb78e5d3 --- /dev/null +++ b/app/controllers/admin/budgets_wizard/headings_controller.rb @@ -0,0 +1,19 @@ +class Admin::BudgetsWizard::HeadingsController < Admin::BaseController + include Admin::BudgetHeadingsActions + + before_action :load_headings, only: [:index, :create] + + def index + @heading = @group.headings.new + end + + private + + def headings_index + admin_budgets_wizard_budget_group_headings_path(@budget, @group) + end + + def new_action + :index + end +end diff --git a/app/controllers/concerns/admin/budget_headings_actions.rb b/app/controllers/concerns/admin/budget_headings_actions.rb new file mode 100644 index 000000000..4bc125288 --- /dev/null +++ b/app/controllers/concerns/admin/budget_headings_actions.rb @@ -0,0 +1,66 @@ +module Admin::BudgetHeadingsActions + extend ActiveSupport::Concern + + included do + include Translatable + include FeatureFlags + feature_flag :budgets + + before_action :load_budget + before_action :load_group + before_action :load_headings, only: :index + before_action :load_heading, only: [:edit, :update, :destroy] + end + + def edit + end + + def create + @heading = @group.headings.new(budget_heading_params) + if @heading.save + redirect_to headings_index, notice: t("admin.budget_headings.create.notice") + else + render new_action + end + end + + def update + if @heading.update(budget_heading_params) + redirect_to headings_index, notice: t("admin.budget_headings.update.notice") + else + render :edit + end + end + + def destroy + if @heading.can_be_deleted? + @heading.destroy! + redirect_to headings_index, notice: t("admin.budget_headings.destroy.success_notice") + else + redirect_to headings_index, alert: t("admin.budget_headings.destroy.unable_notice") + end + end + + private + + def load_budget + @budget = Budget.find_by_slug_or_id! params[:budget_id] + end + + def load_group + @group = @budget.groups.find_by_slug_or_id! params[:group_id] + end + + def load_headings + @headings = @group.headings.order(:id) + end + + def load_heading + @heading = @group.headings.find_by_slug_or_id! params[:id] + end + + def budget_heading_params + valid_attributes = [:price, :population, :allow_custom_content, :latitude, :longitude, :max_ballot_lines] + params.require(:budget_heading).permit(*valid_attributes, translation_params(Budget::Heading)) + end +end diff --git a/app/views/admin/budgets_wizard/headings/edit.html.erb b/app/views/admin/budgets_wizard/headings/edit.html.erb new file mode 100644 index 000000000..63deb1260 --- /dev/null +++ b/app/views/admin/budgets_wizard/headings/edit.html.erb @@ -0,0 +1 @@ +<%= render Admin::BudgetsWizard::Headings::EditComponent.new(@heading) %> diff --git a/app/views/admin/budgets_wizard/headings/index.html.erb b/app/views/admin/budgets_wizard/headings/index.html.erb new file mode 100644 index 000000000..ed647b65a --- /dev/null +++ b/app/views/admin/budgets_wizard/headings/index.html.erb @@ -0,0 +1 @@ +<%= render Admin::BudgetsWizard::Headings::IndexComponent.new(@headings, @heading) %> diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index e2d8ee8e8..5fee91c88 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -148,6 +148,7 @@ ignore_unused: - "admin.budgets.index.filter*" - "admin.budgets.edit.(administrators|valuators).*" - "admin.budget_groups.index.*.help_block" + - "admin.budget_headings.index.*.help_block" - "admin.budget_investments.index.filter*" - "admin.organizations.index.filter*" - "admin.hidden_users.index.filter*" diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index ec67b8e09..427faae50 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -177,9 +177,14 @@ en: create: "Create new heading" edit: "Edit heading" submit: "Save heading" + group_switcher: + currently_showing: "Showing headings from the %{group} group." + different_group: "Manage headings from a different group" + the_other_group: "Manage headings from the %{group} group." index: back: "Go back to groups" help: "Headings are meant to divide the money of the participatory budget. Here you can add headings for this group and assign the amount of money that will be used for each heading." + new_button: "Add new heading" title: "%{budget} / %{group} headings" budget_phases: edit: @@ -290,10 +295,13 @@ en: creation_timeline: budget: Budget groups: Groups + headings: Headings budgets: continue: "Continue to groups" groups: continue: "Continue to headings" + headings: + continue: "Continue to phases" milestones: index: table_id: "ID" diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 7feb7440f..b6b2d06d5 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -177,9 +177,14 @@ es: create: "Crear nueva partida" edit: "Editar partida" submit: "Guardar partida" + group_switcher: + currently_showing: "Mostrando las partidas del grupo: %{group}" + different_group: "Ir a partidas de otro grupo" + the_other_group: "Ir a partidas del grupo %{group}." index: back: "Volver a grupos" help: "Las partidas sirven para dividir el dinero del presupuesto participativo. Aquí puedes ir añadiendo partidas para cada grupo y establecer la cantidad de dinero que se gastará en cada partida." + new_button: "Añadir una partida nueva" title: "Partidas de %{budget} / %{group}" budget_phases: edit: @@ -290,10 +295,13 @@ es: creation_timeline: budget: Presupuesto groups: Grupos + headings: Partidas budgets: continue: "Continuar a grupos" groups: continue: "Continuar a partidas" + headings: + continue: "Continuar a fases" milestones: index: table_id: "ID" diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 846bb8635..bb28dfa0f 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -74,7 +74,9 @@ namespace :admin do namespace :budgets_wizard do resources :budgets, only: [:create, :new] do - resources :groups, only: [:index, :create, :edit, :update, :destroy] + resources :groups, only: [:index, :create, :edit, :update, :destroy] do + resources :headings, only: [:index, :create, :edit, :update, :destroy] + end end end diff --git a/spec/components/admin/budgets_wizard/headings/group_switcher_component_spec.rb b/spec/components/admin/budgets_wizard/headings/group_switcher_component_spec.rb new file mode 100644 index 000000000..140db350d --- /dev/null +++ b/spec/components/admin/budgets_wizard/headings/group_switcher_component_spec.rb @@ -0,0 +1,41 @@ +require "rails_helper" + +describe Admin::BudgetsWizard::Headings::GroupSwitcherComponent, type: :component do + it "is not rendered for budgets with one group" do + group = create(:budget_group, budget: create(:budget)) + + render_inline Admin::BudgetsWizard::Headings::GroupSwitcherComponent.new(group) + + expect(page.text).to be_empty + expect(page).not_to have_css ".budget-group-switcher" + end + + it "renders a link to switch group for budgets with two groups" do + budget = create(:budget) + group = create(:budget_group, budget: budget, name: "Parks") + create(:budget_group, budget: budget, name: "Recreation") + + render_inline Admin::BudgetsWizard::Headings::GroupSwitcherComponent.new(group) + + expect(page).to have_content "Showing headings from the Parks group" + expect(page).to have_link "Manage headings from the Recreation group." + expect(page).not_to have_css "ul" + end + + it "renders a menu to switch group for budgets with more than two groups" do + budget = create(:budget) + group = create(:budget_group, budget: budget, name: "Parks") + create(:budget_group, budget: budget, name: "Recreation") + create(:budget_group, budget: budget, name: "Entertainment") + + render_inline Admin::BudgetsWizard::Headings::GroupSwitcherComponent.new(group) + + expect(page).to have_content "Showing headings from the Parks group" + expect(page).to have_button "Manage headings from a different group" + + within "button + ul" do + expect(page).to have_link "Recreation" + expect(page).to have_link "Entertainment" + end + end +end diff --git a/spec/system/admin/budgets_wizard/headings_spec.rb b/spec/system/admin/budgets_wizard/headings_spec.rb new file mode 100644 index 000000000..d3823347e --- /dev/null +++ b/spec/system/admin/budgets_wizard/headings_spec.rb @@ -0,0 +1,148 @@ +require "rails_helper" + +describe "Budgets wizard, headings step", :admin do + let(:budget) { create(:budget, :drafting) } + let(:group) { create(:budget_group, budget: budget, name: "Default group") } + + describe "Index" do + scenario "back to a previous step" do + visit admin_budgets_wizard_budget_group_headings_path(budget, group) + + within "#side_menu" do + expect(page).to have_css ".is-active", exact_text: "Participatory budgets" + end + + click_link "Go back to groups" + + expect(page).to have_css "tr", text: "Default group" + expect(page).to have_css ".creation-timeline" + end + + scenario "change to another group" do + economy = create(:budget_group, budget: budget, name: "Economy") + health = create(:budget_group, budget: budget, name: "Health") + create(:budget_group, budget: budget, name: "Technology") + + create(:budget_heading, group: economy, name: "Banking") + create(:budget_heading, group: health, name: "Hospitals") + + visit admin_budgets_wizard_budget_group_headings_path(budget, economy) + + within(".heading") do + expect(page).to have_content "Banking" + expect(page).not_to have_content "Hospitals" + end + + expect(page).not_to have_link "Health" + + click_button "Manage headings from a different group" + click_link "Health" + + within(".heading") do + expect(page).to have_content "Hospitals" + expect(page).not_to have_content "Banking" + end + expect(page).to have_css ".creation-timeline" + end + end + + describe "New" do + scenario "cancel creating a heading" do + visit admin_budgets_wizard_budget_group_headings_path(budget, group) + + expect(page).not_to have_field "Heading name" + expect(page).not_to have_button "Cancel" + expect(page).to have_content "Continue to phases" + + click_button "Add new heading" + + expect(page).to have_field "Heading name" + expect(page).not_to have_button "Add new heading" + expect(page).not_to have_content "Continue to phases" + + click_button "Cancel" + + expect(page).to have_button "Add new heading" + expect(page).not_to have_field "Heading name" + expect(page).not_to have_button "Cancel" + expect(page).to have_content "Continue to phases" + end + + scenario "submit the form with errors" do + visit admin_budgets_wizard_budget_group_headings_path(budget, group) + click_button "Add new heading" + + click_button "Create new heading" + + expect(page).not_to have_content "Heading created successfully!" + expect(page).to have_css(".is-invalid-label", text: "Heading name") + expect(page).to have_content "can't be blank" + expect(page).to have_button "Create new heading" + expect(page).to have_button "Cancel" + expect(page).not_to have_button "Add new heading" + expect(page).not_to have_content "Continue to phases" + end + end + + describe "Edit" do + scenario "update heading" do + create(:budget_heading, group: group, name: "Heading wiht a typo") + + visit admin_budgets_wizard_budget_group_headings_path(budget, group) + + expect(page).to have_css ".creation-timeline" + + within("tr", text: "Heading wiht a typo") { click_link "Edit" } + fill_in "Heading name", with: "Heading without typos" + click_button "Save heading" + + expect(page).to have_content "Heading updated successfully" + expect(page).to have_css ".creation-timeline" + expect(page).to have_css "td", exact_text: "Heading without typos" + end + + scenario "submit the form with errors and then without errors" do + heading = create(:budget_heading, group: group, name: "Heading wiht a typo") + + visit edit_admin_budgets_wizard_budget_group_heading_path(budget, group, heading) + fill_in "Heading name", with: "" + click_button "Save heading" + + expect(page).to have_css "#error_explanation" + expect(page).to have_css ".creation-timeline" + + fill_in "Heading name", with: "Heading without typos" + click_button "Save heading" + + expect(page).to have_content "Heading updated successfully" + expect(page).to have_css ".creation-timeline" + expect(page).to have_css "td", exact_text: "Heading without typos" + end + end + + describe "Destroy" do + scenario "delete a heading without investments" do + create(:budget_heading, group: group, name: "Delete me!") + + visit admin_budgets_wizard_budget_group_headings_path(budget, group) + within("tr", text: "Delete me!") { accept_confirm { click_link "Delete" } } + + expect(page).to have_content "Heading deleted successfully" + expect(page).not_to have_content "Delete me!" + expect(page).to have_css ".creation-timeline" + end + + scenario "try to delete a heading with investments" do + heading = create(:budget_heading, group: group, name: "Don't delete me!") + create(:budget_investment, heading: heading) + + visit admin_budgets_wizard_budget_group_headings_path(budget, group) + + within("tr", text: "Don't delete me!") { accept_confirm { click_link "Delete" } } + + expect(page).to have_content "You cannot delete a Heading that has associated investments" + expect(page).to have_content "Don't delete me!" + expect(page).to have_css ".creation-timeline" + end + end +end