From 27a4054dce842e21cd9e2b01b0d49fed9e6668ad Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Thu, 19 Feb 2026 09:12:10 -0700 Subject: [PATCH 01/12] Add wiki_page_published/unpublished live event methods Co-Authored-By: Claude Sonnet 4.6 --- lib/canvas/live_events.rb | 14 ++++++++++++++ spec/lib/canvas/live_events_spec.rb | 30 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/lib/canvas/live_events.rb b/lib/canvas/live_events.rb index b3c4c6592bdca..50811690e2921 100644 --- a/lib/canvas/live_events.rb +++ b/lib/canvas/live_events.rb @@ -630,6 +630,20 @@ def self.wiki_page_deleted(page) }) end + def self.wiki_page_published(page) + post_event_stringified("wiki_page_published", { + wiki_page_id: page.global_id, + title: LiveEvents.truncate(page.title) + }) + end + + def self.wiki_page_unpublished(page) + post_event_stringified("wiki_page_unpublished", { + wiki_page_id: page.global_id, + title: LiveEvents.truncate(page.title) + }) + end + def self.attachment_created(attachment) post_event_stringified("attachment_created", get_attachment_data(attachment)) end diff --git a/spec/lib/canvas/live_events_spec.rb b/spec/lib/canvas/live_events_spec.rb index be5205990fa9b..46e5afe78a5a9 100644 --- a/spec/lib/canvas/live_events_spec.rb +++ b/spec/lib/canvas/live_events_spec.rb @@ -331,6 +331,36 @@ def wiki_page_updated end end + describe ".wiki_page_published" do + before do + course_with_teacher + @page = @course.wiki_pages.create(title: "a page", body: "some body", workflow_state: "unpublished") + end + + it "posts a wiki_page_published event with the page id and title" do + expect_event("wiki_page_published", { + wiki_page_id: @page.global_id.to_s, + title: "a page" + }) + Canvas::LiveEvents.wiki_page_published(@page) + end + end + + describe ".wiki_page_unpublished" do + before do + course_with_teacher + @page = @course.wiki_pages.create(title: "a page", body: "some body") + end + + it "posts a wiki_page_unpublished event with the page id and title" do + expect_event("wiki_page_unpublished", { + wiki_page_id: @page.global_id.to_s, + title: "a page" + }) + Canvas::LiveEvents.wiki_page_unpublished(@page) + end + end + describe ".conversation_forwarded" do before do @user1 = user_model From 2df06d379453fd8d283cc30a05fb9fe996141236 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Thu, 19 Feb 2026 09:19:18 -0700 Subject: [PATCH 02/12] Trigger live events on wiki page publish/unpublish Wire up workflow_state change detection in the after_update observer callback so publishing or unpublishing a wiki page fires the appropriate wiki_page_published/wiki_page_unpublished events. Co-Authored-By: Claude Sonnet 4.6 --- lib/canvas/live_events_callbacks.rb | 9 +++++++++ spec/observers/live_events_observer_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index e531b773edbbc..de640ae585e2c 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -135,6 +135,15 @@ def self.after_update(obj, changes) changes["title"]&.first, changes["body"]&.first) end + if changes["workflow_state"] + _old_state, new_state = changes["workflow_state"] + case new_state + when "active" + Canvas::LiveEvents.wiki_page_published(obj) + when "unpublished" + Canvas::LiveEvents.wiki_page_unpublished(obj) + end + end when Assignment Canvas::LiveEvents.assignment_updated(obj) when AssignmentGroup diff --git a/spec/observers/live_events_observer_spec.rb b/spec/observers/live_events_observer_spec.rb index e69696ba42858..4d54278144572 100644 --- a/spec/observers/live_events_observer_spec.rb +++ b/spec/observers/live_events_observer_spec.rb @@ -106,6 +106,26 @@ expect(Canvas::LiveEvents).to receive(:wiki_page_deleted).once @page.destroy_permanently! end + + it "posts published event when page is published" do + wiki_page_model(workflow_state: "unpublished") + expect(Canvas::LiveEvents).to receive(:wiki_page_published).once + @page.publish! + end + + it "posts unpublished event when page is unpublished" do + wiki_page_model + expect(Canvas::LiveEvents).to receive(:wiki_page_unpublished).once + @page.unpublish! + end + + it "does not post published/unpublished event when only title changes" do + wiki_page_model + expect(Canvas::LiveEvents).not_to receive(:wiki_page_published) + expect(Canvas::LiveEvents).not_to receive(:wiki_page_unpublished) + @page.title = "new title" + @page.save + end end describe "attachment" do From 29e1765149d29879b56896c165365828d39049ba Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Fri, 20 Feb 2026 17:01:47 -0700 Subject: [PATCH 03/12] Removed wiki_page_published and wiki_page_unpublished methods. When wiki page workflow_state is detected, wiki_page_updated is called instead. --- lib/canvas/live_events.rb | 14 -------------- lib/canvas/live_events_callbacks.rb | 7 +------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/lib/canvas/live_events.rb b/lib/canvas/live_events.rb index 50811690e2921..b3c4c6592bdca 100644 --- a/lib/canvas/live_events.rb +++ b/lib/canvas/live_events.rb @@ -630,20 +630,6 @@ def self.wiki_page_deleted(page) }) end - def self.wiki_page_published(page) - post_event_stringified("wiki_page_published", { - wiki_page_id: page.global_id, - title: LiveEvents.truncate(page.title) - }) - end - - def self.wiki_page_unpublished(page) - post_event_stringified("wiki_page_unpublished", { - wiki_page_id: page.global_id, - title: LiveEvents.truncate(page.title) - }) - end - def self.attachment_created(attachment) post_event_stringified("attachment_created", get_attachment_data(attachment)) end diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index de640ae585e2c..54fc7833e3c6a 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -136,12 +136,7 @@ def self.after_update(obj, changes) changes["body"]&.first) end if changes["workflow_state"] - _old_state, new_state = changes["workflow_state"] - case new_state - when "active" - Canvas::LiveEvents.wiki_page_published(obj) - when "unpublished" - Canvas::LiveEvents.wiki_page_unpublished(obj) + Canvas::LiveEvents.wiki_page_updated(obj) end end when Assignment From 51b9b144366ef59fd12b1a5d518b5d4f820a52f8 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Fri, 20 Feb 2026 17:07:57 -0700 Subject: [PATCH 04/12] Updated wiki_page_update call with appropriate parameters. Removed stray 'end' in conditional statement. --- lib/canvas/live_events_callbacks.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index 54fc7833e3c6a..ddb3aca414013 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -136,8 +136,9 @@ def self.after_update(obj, changes) changes["body"]&.first) end if changes["workflow_state"] - Canvas::LiveEvents.wiki_page_updated(obj) - end + Canvas::LiveEvents.wiki_page_updated(obj, + changes["title"]&.first, + changes["body"]&.first) end when Assignment Canvas::LiveEvents.assignment_updated(obj) From c8655f0d40e7545071b9567c497f77844d6e9de5 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Fri, 20 Feb 2026 17:13:57 -0700 Subject: [PATCH 05/12] Replaced changes to title and body parameters with nil for when calling wiki_page_updated due to workflow state change (publish/unpublish) as these values do not change. --- lib/canvas/live_events_callbacks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index ddb3aca414013..b808f12ee3166 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -137,8 +137,8 @@ def self.after_update(obj, changes) end if changes["workflow_state"] Canvas::LiveEvents.wiki_page_updated(obj, - changes["title"]&.first, - changes["body"]&.first) + nil, + nil end when Assignment Canvas::LiveEvents.assignment_updated(obj) From 653c642714831569acfb6ffd96def94ae5d511db Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Fri, 20 Feb 2026 17:16:36 -0700 Subject: [PATCH 06/12] Add missing ')' --- lib/canvas/live_events_callbacks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index b808f12ee3166..91ebf51382fbb 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -138,7 +138,7 @@ def self.after_update(obj, changes) if changes["workflow_state"] Canvas::LiveEvents.wiki_page_updated(obj, nil, - nil + nil) end when Assignment Canvas::LiveEvents.assignment_updated(obj) From a3312bc20887d30e41f2f320a6a4bfa26bb3c943 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Fri, 20 Feb 2026 17:18:19 -0700 Subject: [PATCH 07/12] Fixed minor indentation issue so style is consistent. --- lib/canvas/live_events_callbacks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index 91ebf51382fbb..2647517281e2e 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -136,7 +136,7 @@ def self.after_update(obj, changes) changes["body"]&.first) end if changes["workflow_state"] - Canvas::LiveEvents.wiki_page_updated(obj, + Canvas::LiveEvents.wiki_page_updated(obj, nil, nil) end From 72d00ee80ab444f4bd3e44929e9caaf962644ac7 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Thu, 26 Feb 2026 15:10:53 -0700 Subject: [PATCH 08/12] Updated tests for publishing/unpublishing wiki page. --- spec/lib/canvas/live_events_spec.rb | 30 --------------------- spec/observers/live_events_observer_spec.rb | 13 +++++---- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/spec/lib/canvas/live_events_spec.rb b/spec/lib/canvas/live_events_spec.rb index 46e5afe78a5a9..be5205990fa9b 100644 --- a/spec/lib/canvas/live_events_spec.rb +++ b/spec/lib/canvas/live_events_spec.rb @@ -331,36 +331,6 @@ def wiki_page_updated end end - describe ".wiki_page_published" do - before do - course_with_teacher - @page = @course.wiki_pages.create(title: "a page", body: "some body", workflow_state: "unpublished") - end - - it "posts a wiki_page_published event with the page id and title" do - expect_event("wiki_page_published", { - wiki_page_id: @page.global_id.to_s, - title: "a page" - }) - Canvas::LiveEvents.wiki_page_published(@page) - end - end - - describe ".wiki_page_unpublished" do - before do - course_with_teacher - @page = @course.wiki_pages.create(title: "a page", body: "some body") - end - - it "posts a wiki_page_unpublished event with the page id and title" do - expect_event("wiki_page_unpublished", { - wiki_page_id: @page.global_id.to_s, - title: "a page" - }) - Canvas::LiveEvents.wiki_page_unpublished(@page) - end - end - describe ".conversation_forwarded" do before do @user1 = user_model diff --git a/spec/observers/live_events_observer_spec.rb b/spec/observers/live_events_observer_spec.rb index 4d54278144572..008a7cfb7273e 100644 --- a/spec/observers/live_events_observer_spec.rb +++ b/spec/observers/live_events_observer_spec.rb @@ -107,22 +107,21 @@ @page.destroy_permanently! end - it "posts published event when page is published" do + it "posts update event when page is published" do wiki_page_model(workflow_state: "unpublished") - expect(Canvas::LiveEvents).to receive(:wiki_page_published).once + expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil).once @page.publish! end - it "posts unpublished event when page is unpublished" do + it "posts update event when page is unpublished" do wiki_page_model - expect(Canvas::LiveEvents).to receive(:wiki_page_unpublished).once + expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil).once @page.unpublish! end - it "does not post published/unpublished event when only title changes" do + it "does not post workflow_state update event when only title changes" do wiki_page_model - expect(Canvas::LiveEvents).not_to receive(:wiki_page_published) - expect(Canvas::LiveEvents).not_to receive(:wiki_page_unpublished) + expect(Canvas::LiveEvents).not_to receive(:wiki_page_updated).with(anything, nil, nil) @page.title = "new title" @page.save end From 27ae538408aa23011af7c01e1f6667d4d9c7aba7 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Wed, 4 Mar 2026 15:41:08 -0700 Subject: [PATCH 09/12] Formatted Canvas::LiveEvents.wiki_page_updated function so arguments are on the same line. --- lib/canvas/live_events_callbacks.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index 2647517281e2e..d02bdea835a00 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -136,9 +136,7 @@ def self.after_update(obj, changes) changes["body"]&.first) end if changes["workflow_state"] - Canvas::LiveEvents.wiki_page_updated(obj, - nil, - nil) + Canvas::LiveEvents.wiki_page_updated(obj, nil, nil) end when Assignment Canvas::LiveEvents.assignment_updated(obj) From 269ba0b04e98681130a8097cfd864db73e12c3a3 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Wed, 4 Mar 2026 15:51:47 -0700 Subject: [PATCH 10/12] Removed incorrectly written test. --- spec/observers/live_events_observer_spec.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/spec/observers/live_events_observer_spec.rb b/spec/observers/live_events_observer_spec.rb index 008a7cfb7273e..031b0cb40f886 100644 --- a/spec/observers/live_events_observer_spec.rb +++ b/spec/observers/live_events_observer_spec.rb @@ -118,13 +118,6 @@ expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil).once @page.unpublish! end - - it "does not post workflow_state update event when only title changes" do - wiki_page_model - expect(Canvas::LiveEvents).not_to receive(:wiki_page_updated).with(anything, nil, nil) - @page.title = "new title" - @page.save - end end describe "attachment" do From 455aa9536e8c1d8aae0bdabc1502f843d6c86fbf Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Wed, 4 Mar 2026 16:57:29 -0700 Subject: [PATCH 11/12] Merged wiki page title/body and workflow_state conditions. --- lib/canvas/live_events_callbacks.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index d02bdea835a00..3171d3459d841 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -130,14 +130,11 @@ def self.after_update(obj, changes) when GroupMembership Canvas::LiveEvents.group_membership_updated(obj) when WikiPage - if changes["title"] || changes["body"] + if changes["title"] || changes["body"] || changes["workflow_state"] Canvas::LiveEvents.wiki_page_updated(obj, changes["title"]&.first, changes["body"]&.first) end - if changes["workflow_state"] - Canvas::LiveEvents.wiki_page_updated(obj, nil, nil) - end when Assignment Canvas::LiveEvents.assignment_updated(obj) when AssignmentGroup From 2c03cb3d29ed675ce4203cb5523dc2cd089fcdc4 Mon Sep 17 00:00:00 2001 From: Bradan Schwanke Date: Thu, 12 Mar 2026 11:49:49 -0600 Subject: [PATCH 12/12] Updated code so that workflow_state is included in the body when triggering a live event. Updated tests to reflect this change. --- lib/canvas/live_events.rb | 9 ++++-- lib/canvas/live_events_callbacks.rb | 3 +- spec/lib/canvas/live_events_spec.rb | 32 +++++++++++++++++---- spec/observers/live_events_observer_spec.rb | 8 +++--- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/lib/canvas/live_events.rb b/lib/canvas/live_events.rb index b3c4c6592bdca..e94c5a946c032 100644 --- a/lib/canvas/live_events.rb +++ b/lib/canvas/live_events.rb @@ -605,11 +605,12 @@ def self.wiki_page_created(page) }) end - def self.wiki_page_updated(page, old_title, old_body) + def self.wiki_page_updated(page, old_title, old_body, old_workflow_state) payload = { wiki_page_id: page.global_id, title: LiveEvents.truncate(page.title), - body: LiveEvents.truncate(page.body) + body: LiveEvents.truncate(page.body), + workflow_state: page.workflow_state, } if old_title @@ -620,6 +621,10 @@ def self.wiki_page_updated(page, old_title, old_body) payload[:old_body] = LiveEvents.truncate(old_body) end + if old_workflow_state + payload[:old_workflow_state] = old_workflow_state + end + post_event_stringified("wiki_page_updated", payload) end diff --git a/lib/canvas/live_events_callbacks.rb b/lib/canvas/live_events_callbacks.rb index 3171d3459d841..f9765b64d6e80 100644 --- a/lib/canvas/live_events_callbacks.rb +++ b/lib/canvas/live_events_callbacks.rb @@ -133,7 +133,8 @@ def self.after_update(obj, changes) if changes["title"] || changes["body"] || changes["workflow_state"] Canvas::LiveEvents.wiki_page_updated(obj, changes["title"]&.first, - changes["body"]&.first) + changes["body"]&.first, + changes["workflow_state"]&.first) end when Assignment Canvas::LiveEvents.assignment_updated(obj) diff --git a/spec/lib/canvas/live_events_spec.rb b/spec/lib/canvas/live_events_spec.rb index be5205990fa9b..fe0e19c5df1d2 100644 --- a/spec/lib/canvas/live_events_spec.rb +++ b/spec/lib/canvas/live_events_spec.rb @@ -290,15 +290,21 @@ def body @page = @course.wiki_pages.create(title: "old title", body: "old body") end - def wiki_page_updated - Canvas::LiveEvents.wiki_page_updated(@page, @page.title_changed? ? @page.title_was : nil, @page.body_changed? ? @page.body_was : nil) + def wiki_page_updated(old_workflow_state: nil) + Canvas::LiveEvents.wiki_page_updated( + @page, + @page.title_changed? ? @page.title_was : nil, + @page.body_changed? ? @page.body_was : nil, + old_workflow_state + ) end - it "does not set old_title or old_body if they don't change" do + it "does not set old_title, old_body, or old_workflow_state if they don't change" do expect_event("wiki_page_updated", { wiki_page_id: @page.global_id.to_s, title: "old title", - body: "old body" + body: "old body", + workflow_state: @page.workflow_state }) wiki_page_updated @@ -311,7 +317,8 @@ def wiki_page_updated wiki_page_id: @page.global_id.to_s, title: "new title", old_title: "old title", - body: "old body" + body: "old body", + workflow_state: @page.workflow_state }) wiki_page_updated @@ -324,11 +331,24 @@ def wiki_page_updated wiki_page_id: @page.global_id.to_s, title: "old title", body: "new body", - old_body: "old body" + old_body: "old body", + workflow_state: @page.workflow_state }) wiki_page_updated end + + it "sets old_workflow_state if the workflow_state changed" do + expect_event("wiki_page_updated", { + wiki_page_id: @page.global_id.to_s, + title: "old title", + body: "old body", + workflow_state: @page.workflow_state, + old_workflow_state: "unpublished" + }) + + wiki_page_updated(old_workflow_state: "unpublished") + end end describe ".conversation_forwarded" do diff --git a/spec/observers/live_events_observer_spec.rb b/spec/observers/live_events_observer_spec.rb index 031b0cb40f886..fc24651496421 100644 --- a/spec/observers/live_events_observer_spec.rb +++ b/spec/observers/live_events_observer_spec.rb @@ -77,14 +77,14 @@ it "posts update events for title" do wiki_page_model(title: "old title") - expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, "old title", nil) + expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, "old title", nil, nil) @page.title = "new title" @page.save end it "posts update events for body" do wiki_page_model(body: "old body") - expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, "old body") + expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, "old body", nil) @page.body = "new body" @page.save end @@ -109,13 +109,13 @@ it "posts update event when page is published" do wiki_page_model(workflow_state: "unpublished") - expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil).once + expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil, "unpublished").once @page.publish! end it "posts update event when page is unpublished" do wiki_page_model - expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil).once + expect(Canvas::LiveEvents).to receive(:wiki_page_updated).with(@page, nil, nil, "active").once @page.unpublish! end end