diff options
| -rw-r--r-- | app/controllers/events_controller.rb | 4 | ||||
| -rw-r--r-- | app/helpers/nodes_helper.rb | 14 | ||||
| -rw-r--r-- | app/views/nodes/show.html.erb | 4 | ||||
| -rw-r--r-- | test/controllers/events_controller_test.rb | 167 | ||||
| -rw-r--r-- | test/controllers/nodes_controller_test.rb | 33 | ||||
| -rw-r--r-- | test/models/concerns/rrule_humanizer_test.rb | 15 | ||||
| -rw-r--r-- | test/models/helpers/content_helper_test.rb | 4 | ||||
| -rw-r--r-- | test/models/helpers/nodes_helper_test.rb | 21 |
8 files changed, 219 insertions, 43 deletions
diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 9bed5dd..b98a38e 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb | |||
| @@ -37,6 +37,10 @@ class EventsController < ApplicationController | |||
| 37 | tag_list: params[:tag_list] | 37 | tag_list: params[:tag_list] |
| 38 | ) | 38 | ) |
| 39 | 39 | ||
| 40 | if params[:tag_list].present? && params[:auto_tag_source].present? | ||
| 41 | flash.now[:notice] = "Tag '#{params[:tag_list]}' was pre-filled because this page is tagged '#{params[:auto_tag_source]}'. You can remove it below." | ||
| 42 | end | ||
| 43 | |||
| 40 | respond_to do |format| | 44 | respond_to do |format| |
| 41 | format.html # new.html.erb | 45 | format.html # new.html.erb |
| 42 | format.xml { render :xml => @event } | 46 | format.xml { render :xml => @event } |
diff --git a/app/helpers/nodes_helper.rb b/app/helpers/nodes_helper.rb index 329bcc5..093bfc6 100644 --- a/app/helpers/nodes_helper.rb +++ b/app/helpers/nodes_helper.rb | |||
| @@ -44,6 +44,20 @@ module NodesHelper | |||
| 44 | ]) | 44 | ]) |
| 45 | end | 45 | end |
| 46 | 46 | ||
| 47 | DEFAULT_EVENT_TAG_BY_PAGE_TAG = { | ||
| 48 | 'erfa-detail' => 'open-day', | ||
| 49 | 'chaostreff-detail' => 'open-day' | ||
| 50 | }.freeze | ||
| 51 | |||
| 52 | def default_event_tag_mapping(page) | ||
| 53 | page_tags = page.tag_list | ||
| 54 | DEFAULT_EVENT_TAG_BY_PAGE_TAG.find { |page_tag, _| page_tags.include?(page_tag) } | ||
| 55 | end | ||
| 56 | |||
| 57 | def default_event_tag_list(page) | ||
| 58 | default_event_tag_mapping(page)&.last | ||
| 59 | end | ||
| 60 | |||
| 47 | def event_schedule_text(event) | 61 | def event_schedule_text(event) |
| 48 | if event.rrule.present? | 62 | if event.rrule.present? |
| 49 | recurrence = event.humanize_rrule(I18n.locale) | 63 | recurrence = event.humanize_rrule(I18n.locale) |
diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb index 2ce3853..c533a55 100644 --- a/app/views/nodes/show.html.erb +++ b/app/views/nodes/show.html.erb | |||
| @@ -42,7 +42,6 @@ | |||
| 42 | <td class="description">Tagged with:</td> | 42 | <td class="description">Tagged with:</td> |
| 43 | <td><%= @page.tag_list %></td> | 43 | <td><%= @page.tag_list %></td> |
| 44 | </tr> | 44 | </tr> |
| 45 | <% if @node.events.any? %> | ||
| 46 | <tr> | 45 | <tr> |
| 47 | <td class="description">Events</td> | 46 | <td class="description">Events</td> |
| 48 | <td> | 47 | <td> |
| @@ -55,9 +54,10 @@ | |||
| 55 | </li> | 54 | </li> |
| 56 | <% end %> | 55 | <% end %> |
| 57 | </ul> | 56 | </ul> |
| 57 | <% mapping = default_event_tag_mapping(@page) %> | ||
| 58 | <%= link_to 'add event', new_event_path(node_id: @node.id, tag_list: mapping&.last, auto_tag_source: mapping&.first, return_to: request.path) %> | ||
| 58 | </td> | 59 | </td> |
| 59 | </tr> | 60 | </tr> |
| 60 | <% end %> | ||
| 61 | <tr> | 61 | <tr> |
| 62 | <td class="description"><strong>Title</strong></td> | 62 | <td class="description"><strong>Title</strong></td> |
| 63 | <td><%= sanitize( @page.title ) %></td> | 63 | <td><%= sanitize( @page.title ) %></td> |
diff --git a/test/controllers/events_controller_test.rb b/test/controllers/events_controller_test.rb index 14e534e..9371ca7 100644 --- a/test/controllers/events_controller_test.rb +++ b/test/controllers/events_controller_test.rb | |||
| @@ -1,45 +1,130 @@ | |||
| 1 | require 'test_helper' | 1 | require 'test_helper' |
| 2 | 2 | ||
| 3 | class EventsControllerTest < ActionController::TestCase | 3 | class EventsControllerTest < ActionController::TestCase |
| 4 | # test "should get index" do | 4 | |
| 5 | # get :index | 5 | test "should get index" do |
| 6 | # assert_response :success | 6 | login_as :quentin |
| 7 | # assert_not_nil assigns(:events) | 7 | get :index |
| 8 | # end | 8 | assert_response :success |
| 9 | # | 9 | assert_not_nil assigns(:events) |
| 10 | # test "should get new" do | 10 | end |
| 11 | # get :new | 11 | |
| 12 | # assert_response :success | 12 | test "should get new" do |
| 13 | # end | 13 | login_as :quentin |
| 14 | # | 14 | get :new |
| 15 | # test "should create event" do | 15 | assert_response :success |
| 16 | # assert_difference('Event.count') do | 16 | end |
| 17 | # post :create, params: { :event => { } } | 17 | |
| 18 | # end | 18 | test "new pre-fills tag_list and explains it via flash when auto_tag_source is given" do |
| 19 | # | 19 | login_as :quentin |
| 20 | # assert_redirected_to event_path(assigns(:event)) | 20 | node = create_node_with_published_page |
| 21 | # end | 21 | |
| 22 | # | 22 | get :new, params: { node_id: node.id, tag_list: "open-day", auto_tag_source: "erfa-detail" } |
| 23 | # test "should show event" do | 23 | |
| 24 | # get :show, params: { :id => events(:one).to_param } | 24 | assert_response :success |
| 25 | # assert_response :success | 25 | assert_equal "open-day", assigns(:event).tag_list.to_s |
| 26 | # end | 26 | assert_match "open-day", flash[:notice] |
| 27 | # | 27 | assert_match "erfa-detail", flash[:notice] |
| 28 | # test "should get edit" do | 28 | end |
| 29 | # get :edit, params: { :id => events(:one).to_param } | 29 | |
| 30 | # assert_response :success | 30 | test "new does not flash without an auto_tag_source" do |
| 31 | # end | 31 | login_as :quentin |
| 32 | # | 32 | |
| 33 | # test "should update event" do | 33 | get :new, params: { tag_list: "open-day" } |
| 34 | # put :update, params: { :id => events(:one).to_param, :event => { } } | 34 | |
| 35 | # assert_redirected_to event_path(assigns(:event)) | 35 | assert_response :success |
| 36 | # end | 36 | assert_nil flash[:notice] |
| 37 | # | 37 | end |
| 38 | # test "should destroy event" do | 38 | |
| 39 | # assert_difference('Event.count', -1) do | 39 | test "new with no params renders a blank, unflashed form" do |
| 40 | # delete :destroy, params: { :id => events(:one).to_param } | 40 | login_as :quentin |
| 41 | # end | 41 | |
| 42 | # | 42 | get :new |
| 43 | # assert_redirected_to events_path | 43 | |
| 44 | # end | 44 | assert_response :success |
| 45 | assert_nil assigns(:event).tag_list.presence | ||
| 46 | assert_nil flash[:notice] | ||
| 47 | end | ||
| 48 | |||
| 49 | test "should show event" do | ||
| 50 | login_as :quentin | ||
| 51 | node = create_node_with_published_page | ||
| 52 | event = Event.create!(node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour) | ||
| 53 | |||
| 54 | get :show, params: { id: event.id } | ||
| 55 | assert_response :success | ||
| 56 | end | ||
| 57 | |||
| 58 | test "should get edit" do | ||
| 59 | login_as :quentin | ||
| 60 | node = create_node_with_published_page | ||
| 61 | event = Event.create!(node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour) | ||
| 62 | |||
| 63 | get :edit, params: { id: event.id } | ||
| 64 | assert_response :success | ||
| 65 | end | ||
| 66 | |||
| 67 | test "should create event attached to a node" do | ||
| 68 | login_as :quentin | ||
| 69 | node = create_node_with_published_page | ||
| 70 | |||
| 71 | assert_difference('Event.count') do | ||
| 72 | post :create, params: { | ||
| 73 | event: { | ||
| 74 | node_id: node.id, | ||
| 75 | start_time: Time.now, | ||
| 76 | end_time: Time.now + 1.hour, | ||
| 77 | tag_list: "open-day" | ||
| 78 | } | ||
| 79 | } | ||
| 80 | end | ||
| 81 | |||
| 82 | assert_redirected_to edit_node_path(node) | ||
| 83 | assert_equal 'Event was successfully created.', flash[:notice] | ||
| 84 | end | ||
| 85 | |||
| 86 | test "should not create an event without a title or a node_id" do | ||
| 87 | login_as :quentin | ||
| 88 | |||
| 89 | assert_no_difference('Event.count') do | ||
| 90 | post :create, params: { event: { start_time: Time.now, end_time: Time.now + 1.hour } } | ||
| 91 | end | ||
| 92 | |||
| 93 | assert_response :success # re-renders :new, not a redirect | ||
| 94 | end | ||
| 95 | |||
| 96 | test "should honour return_to on create" do | ||
| 97 | login_as :quentin | ||
| 98 | node = create_node_with_published_page | ||
| 99 | |||
| 100 | post :create, params: { | ||
| 101 | event: { node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour }, | ||
| 102 | return_to: node_path(node) | ||
| 103 | } | ||
| 104 | |||
| 105 | assert_redirected_to node_path(node) | ||
| 106 | end | ||
| 107 | |||
| 108 | test "should update event" do | ||
| 109 | login_as :quentin | ||
| 110 | node = create_node_with_published_page | ||
| 111 | event = Event.create!(node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour) | ||
| 112 | |||
| 113 | put :update, params: { id: event.id, event: { title: "Updated title" } } | ||
| 114 | |||
| 115 | assert_redirected_to events_path | ||
| 116 | assert_equal "Updated title", event.reload.title | ||
| 117 | end | ||
| 118 | |||
| 119 | test "should destroy event" do | ||
| 120 | login_as :quentin | ||
| 121 | node = create_node_with_published_page | ||
| 122 | event = Event.create!(node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour) | ||
| 123 | |||
| 124 | assert_difference('Event.count', -1) do | ||
| 125 | delete :destroy, params: { id: event.id } | ||
| 126 | end | ||
| 127 | |||
| 128 | assert_redirected_to events_url | ||
| 129 | end | ||
| 45 | end | 130 | end |
diff --git a/test/controllers/nodes_controller_test.rb b/test/controllers/nodes_controller_test.rb index 53799f1..f14e27c 100644 --- a/test/controllers/nodes_controller_test.rb +++ b/test/controllers/nodes_controller_test.rb | |||
| @@ -379,4 +379,37 @@ class NodesControllerTest < ActionController::TestCase | |||
| 379 | get :index | 379 | get :index |
| 380 | end | 380 | end |
| 381 | 381 | ||
| 382 | test "show renders events row and add-link for zero-event chapter node" do | ||
| 383 | login_as :quentin | ||
| 384 | node = create_node_with_published_page | ||
| 385 | node.head.tag_list = "erfa-detail" | ||
| 386 | node.head.save! | ||
| 387 | |||
| 388 | get :show, params: { id: node.id } | ||
| 389 | assert_response :success | ||
| 390 | assert_select "a", text: "add event" | ||
| 391 | assert_select "a[href*='tag_list=open-day']" | ||
| 392 | assert_select "a[href*='auto_tag_source=erfa-detail']" | ||
| 393 | end | ||
| 394 | |||
| 395 | test "show renders events row without a tag default for untagged node" do | ||
| 396 | login_as :quentin | ||
| 397 | node = create_node_with_published_page | ||
| 398 | |||
| 399 | get :show, params: { id: node.id } | ||
| 400 | assert_response :success | ||
| 401 | assert_select "a", text: "add event" | ||
| 402 | assert_select "a[href*='tag_list=']", count: 0 | ||
| 403 | end | ||
| 404 | |||
| 405 | test "show never renders a destroy link for events" do | ||
| 406 | login_as :quentin | ||
| 407 | node = create_node_with_published_page | ||
| 408 | Event.create!(node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour) | ||
| 409 | |||
| 410 | get :show, params: { id: node.id } | ||
| 411 | assert_response :success | ||
| 412 | assert_select "form.button_to.destructive", count: 0 | ||
| 413 | end | ||
| 414 | |||
| 382 | end | 415 | end |
diff --git a/test/models/concerns/rrule_humanizer_test.rb b/test/models/concerns/rrule_humanizer_test.rb index 500dbc7..279ff73 100644 --- a/test/models/concerns/rrule_humanizer_test.rb +++ b/test/models/concerns/rrule_humanizer_test.rb | |||
| @@ -81,4 +81,19 @@ class RruleHumanizerTest < ActiveSupport::TestCase | |||
| 81 | test "falls back to english for unknown locale" do | 81 | test "falls back to english for unknown locale" do |
| 82 | assert_equal "Every Tuesday", humanize("FREQ=WEEKLY;BYDAY=TU", :fr) | 82 | assert_equal "Every Tuesday", humanize("FREQ=WEEKLY;BYDAY=TU", :fr) |
| 83 | end | 83 | end |
| 84 | |||
| 85 | test "wday_abbr returns the correct German abbreviation for each day" do | ||
| 86 | monday = Time.parse("2026-07-06") # confirmed Monday | ||
| 87 | assert_equal "Mo", RruleHumanizer.wday_abbr(monday, :de) | ||
| 88 | assert_equal "Di", RruleHumanizer.wday_abbr(monday + 1.day, :de) | ||
| 89 | assert_equal "Mi", RruleHumanizer.wday_abbr(monday + 2.days, :de) | ||
| 90 | assert_equal "Do", RruleHumanizer.wday_abbr(monday + 3.days, :de) | ||
| 91 | assert_equal "Fr", RruleHumanizer.wday_abbr(monday + 4.days, :de) | ||
| 92 | assert_equal "Sa", RruleHumanizer.wday_abbr(monday + 5.days, :de) | ||
| 93 | assert_equal "So", RruleHumanizer.wday_abbr(monday + 6.days, :de) | ||
| 94 | end | ||
| 95 | |||
| 96 | test "wday_abbr falls back to :de for an unrecognized locale" do | ||
| 97 | assert_equal "Mo", RruleHumanizer.wday_abbr(Time.parse("2026-07-06"), :fr) | ||
| 98 | end | ||
| 84 | end | 99 | end |
diff --git a/test/models/helpers/content_helper_test.rb b/test/models/helpers/content_helper_test.rb index 2da82d7..a7ed478 100644 --- a/test/models/helpers/content_helper_test.rb +++ b/test/models/helpers/content_helper_test.rb | |||
| @@ -1,4 +1,8 @@ | |||
| 1 | require 'test_helper' | 1 | require 'test_helper' |
| 2 | 2 | ||
| 3 | class ContentHelperTest < ActionView::TestCase | 3 | class ContentHelperTest < ActionView::TestCase |
| 4 | test "weekday_abbr delegates through the current I18n locale" do | ||
| 5 | I18n.locale = :de | ||
| 6 | assert_equal "Mo", weekday_abbr(Time.parse("2026-07-06")) | ||
| 7 | end | ||
| 4 | end | 8 | end |
diff --git a/test/models/helpers/nodes_helper_test.rb b/test/models/helpers/nodes_helper_test.rb index 13011de..5d91a88 100644 --- a/test/models/helpers/nodes_helper_test.rb +++ b/test/models/helpers/nodes_helper_test.rb | |||
| @@ -1,4 +1,25 @@ | |||
| 1 | require 'test_helper' | 1 | require 'test_helper' |
| 2 | 2 | ||
| 3 | class NodesHelperTest < ActionView::TestCase | 3 | class NodesHelperTest < ActionView::TestCase |
| 4 | FakePage = Struct.new(:tag_list) | ||
| 5 | |||
| 6 | test "default_event_tag_mapping matches erfa-detail" do | ||
| 7 | page = FakePage.new(["erfa-detail"]) | ||
| 8 | assert_equal ["erfa-detail", "open-day"], default_event_tag_mapping(page) | ||
| 9 | end | ||
| 10 | |||
| 11 | test "default_event_tag_mapping matches chaostreff-detail" do | ||
| 12 | page = FakePage.new(["chaostreff-detail"]) | ||
| 13 | assert_equal ["chaostreff-detail", "open-day"], default_event_tag_mapping(page) | ||
| 14 | end | ||
| 15 | |||
| 16 | test "default_event_tag_mapping returns nil for unrelated tags" do | ||
| 17 | page = FakePage.new(["update"]) | ||
| 18 | assert_nil default_event_tag_mapping(page) | ||
| 19 | end | ||
| 20 | |||
| 21 | test "default_event_tag_list is nil without a matching tag" do | ||
| 22 | page = FakePage.new([]) | ||
| 23 | assert_nil default_event_tag_list(page) | ||
| 24 | end | ||
| 4 | end | 25 | end |
