1use opentalk_roomserver_types::{
5 breakout::{BREAKOUT_MODULE_ID, event::BreakoutEvent},
6 core::{CORE_MODULE_ID, CoreEvent},
7 error::{ERROR_MODULE_ID, SignalingError},
8};
9use opentalk_roomserver_types_automod::{AUTOMOD_MODULE_ID, event::AutomodEvent};
10use opentalk_roomserver_types_chat::{CHAT_MODULE_ID, event::ChatEvent};
11use opentalk_roomserver_types_echo::{ECHO_MODULE_ID, event::EchoEvent};
12use opentalk_roomserver_types_legal_vote::{LEGAL_VOTE_MODULE_ID, event::LegalVoteEvent};
13use opentalk_roomserver_types_meeting_notes::{MEETING_NOTES_MODULE_ID, MeetingNotesEvent};
14use opentalk_roomserver_types_meeting_report::{
15 MEETING_REPORT_MODULE_ID, event::MeetingReportEvent,
16};
17use opentalk_roomserver_types_moderation::{MODERATION_MODULE_ID, event::ModerationEvent};
18use opentalk_roomserver_types_polls::{POLLS_MODULE_ID, event::PollsEvent};
19use opentalk_roomserver_types_raise_hands::{RAISE_HANDS_MODULE_ID, event::RaiseHandsEvent};
20use opentalk_roomserver_types_recording::{RECORDING_MODULE_ID, event::RecordingEvent};
21use opentalk_roomserver_types_subroom_audio::{SUBROOM_AUDIO_MODULE_ID, event::SubroomAudioEvent};
22use opentalk_roomserver_types_timer::{TIMER_MODULE_ID, TimerEvent};
23use opentalk_roomserver_types_training_participation_report::{
24 TRAINING_PARTICIPATION_REPORT_MODULE_ID, TrainingParticipationReportEvent,
25};
26use opentalk_roomserver_types_transcription::{TRANSCRIPTION_MODULE_ID, event::TranscriptionEvent};
27use opentalk_roomserver_types_whiteboard::{WHITEBOARD_MODULE_ID, WhiteboardEvent};
28use opentalk_types_common::{modules::ModuleId, time::Timestamp};
29use serde::{Deserialize, Serialize};
30pub use {
32 opentalk_roomserver_types_e2ee::{E2EE_MODULE_ID, E2eeEvent},
33 opentalk_roomserver_types_excalidraw::{EXCALIDRAW_MODULE_ID, ExcalidrawEvent},
34 opentalk_roomserver_types_livekit::{
35 Credentials, LIVEKIT_MODULE_ID, LiveKitError, LiveKitEvent, LiveKitState,
36 },
37 opentalk_roomserver_types_reaction::{REACTION_MODULE_ID, ReactionEvent},
38 opentalk_roomserver_types_shared_folder::{
39 event::SharedFolder,
40 {SHARED_FOLDER_MODULE_ID, event::SharedFolderEvent},
41 },
42};
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct SignalingEvent {
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub transaction_id: Option<u64>,
48 timestamp: Timestamp,
49 #[serde(flatten)]
50 pub payload: SignalingModuleEvent,
51}
52
53impl SignalingEvent {
54 pub fn namespace(&self) -> ModuleId {
55 self.payload.namespace()
56 }
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60#[serde(tag = "namespace", content = "payload", rename_all = "snake_case")]
61pub enum SignalingModuleEvent {
62 Error(SignalingError),
63 Automod(AutomodEvent),
64 Core(CoreEvent),
65 Breakout(BreakoutEvent),
66 Echo(EchoEvent),
67 Chat(ChatEvent),
68
69 #[serde(rename = "livekit")]
70 LiveKit(LiveKitEvent),
71
72 E2ee(E2eeEvent),
73
74 Timer(TimerEvent),
75 Polls(PollsEvent),
76 SharedFolder(SharedFolderEvent),
77 MeetingReport(MeetingReportEvent),
78 Moderation(ModerationEvent),
79 RaiseHands(RaiseHandsEvent),
80 SubroomAudio(SubroomAudioEvent),
81 MeetingNotes(MeetingNotesEvent),
82 Whiteboard(WhiteboardEvent),
83 Excalidraw(ExcalidrawEvent),
84 LegalVote(LegalVoteEvent),
85 TrainingParticipationReport(TrainingParticipationReportEvent),
86 Recording(RecordingEvent),
87 Transcription(TranscriptionEvent),
88 Reaction(ReactionEvent),
89}
90
91impl SignalingModuleEvent {
92 pub fn namespace(&self) -> ModuleId {
93 match self {
94 Self::Error(..) => ERROR_MODULE_ID,
95 Self::Automod(..) => AUTOMOD_MODULE_ID,
96 Self::Core(..) => CORE_MODULE_ID,
97 Self::Breakout(..) => BREAKOUT_MODULE_ID,
98 Self::Echo(..) => ECHO_MODULE_ID,
99 Self::Chat(..) => CHAT_MODULE_ID,
100 Self::LiveKit(..) => LIVEKIT_MODULE_ID,
101 Self::E2ee(..) => E2EE_MODULE_ID,
102 Self::Timer(..) => TIMER_MODULE_ID,
103 Self::Polls(..) => POLLS_MODULE_ID,
104 Self::SharedFolder(..) => SHARED_FOLDER_MODULE_ID,
105 Self::MeetingReport(..) => MEETING_REPORT_MODULE_ID,
106 Self::Moderation(..) => MODERATION_MODULE_ID,
107 Self::RaiseHands(..) => RAISE_HANDS_MODULE_ID,
108 Self::SubroomAudio(..) => SUBROOM_AUDIO_MODULE_ID,
109 Self::MeetingNotes(..) => MEETING_NOTES_MODULE_ID,
110 Self::Whiteboard(..) => WHITEBOARD_MODULE_ID,
111 Self::Excalidraw(..) => EXCALIDRAW_MODULE_ID,
112 Self::LegalVote(..) => LEGAL_VOTE_MODULE_ID,
113 Self::TrainingParticipationReport(..) => TRAINING_PARTICIPATION_REPORT_MODULE_ID,
114 Self::Recording(..) => RECORDING_MODULE_ID,
115 Self::Transcription(..) => TRANSCRIPTION_MODULE_ID,
116 Self::Reaction(..) => REACTION_MODULE_ID,
117 }
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use std::collections::{BTreeMap, BTreeSet};
124
125 use insta::assert_snapshot;
126 use opentalk_roomserver_types::{
127 breakout::event::BreakoutEvent, connection_id::ConnectionId, core::CoreEvent,
128 error::SignalingError,
129 };
130 use opentalk_roomserver_types_automod::event::{AutomodEvent, StoppedReason};
131 use opentalk_roomserver_types_chat::event::ChatEvent;
132 use opentalk_roomserver_types_echo::event::EchoEvent;
133 use opentalk_roomserver_types_excalidraw::ExcalidrawEvent;
134 use opentalk_roomserver_types_legal_vote::{
135 LegalVoteEvent,
136 token::Token,
137 vote::{LegalVoteId, VoteOption},
138 };
139 use opentalk_roomserver_types_livekit::LiveKitEvent;
140 use opentalk_roomserver_types_meeting_notes::MeetingNotesEvent;
141 use opentalk_roomserver_types_meeting_report::event::MeetingReportEvent;
142 use opentalk_roomserver_types_moderation::event::ModerationEvent;
143 use opentalk_roomserver_types_polls::{
144 ChoiceId, PollId,
145 command::{Choices, Vote},
146 event::PollsEvent,
147 };
148 use opentalk_roomserver_types_raise_hands::event::RaiseHandsEvent;
149 use opentalk_roomserver_types_reaction::ReactionEvent;
150 use opentalk_roomserver_types_subroom_audio::{
151 WhisperId,
152 event::SubroomAudioEvent,
153 state::{WhisperGroup, WhisperState},
154 };
155 use opentalk_roomserver_types_timer::TimerEvent;
156 use opentalk_roomserver_types_training_participation_report::TrainingParticipationReportEvent;
157 use opentalk_roomserver_types_transcription::{
158 event::TranscriptionEvent, state::TranscriptionStatus,
159 };
160 use opentalk_roomserver_types_whiteboard::WhiteboardEvent;
161 use opentalk_types_common::{assets::AssetId, modules::ModuleId, time::Timestamp};
162 use opentalk_types_signaling::ParticipantId;
163 use serde::Deserialize;
164 use url::Url;
165
166 use super::SignalingModuleEvent;
167 use crate::api::event::SignalingEvent;
168
169 #[derive(Debug, Clone, Deserialize)]
170 pub struct NamespaceOnly {
171 pub namespace: ModuleId,
172 }
173
174 #[test]
175 fn serialize_event_error_internal() {
176 let event = SignalingEvent {
177 transaction_id: None,
178 timestamp: Timestamp::unix_epoch(),
179 payload: SignalingModuleEvent::Error(SignalingError::Internal),
180 };
181 let raw = serde_json::to_string_pretty(&event).unwrap();
182
183 assert_snapshot!(raw, @r#"
184 {
185 "timestamp": "1970-01-01T00:00:00Z",
186 "namespace": "error",
187 "payload": {
188 "error": "internal"
189 }
190 }
191 "#);
192
193 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
195 assert_eq!(namespace_only.namespace, event.namespace());
196 }
197
198 #[test]
199 fn serialize_event_error_unknown_namespace() {
200 let event = SignalingEvent {
201 transaction_id: None,
202 timestamp: Timestamp::unix_epoch(),
203 payload: SignalingModuleEvent::Error(SignalingError::UnknownNamespace {
204 invalid_namespace: "foo".into(),
205 }),
206 };
207 let raw = serde_json::to_string_pretty(&event).unwrap();
208
209 assert_snapshot!(raw, @r#"
210 {
211 "timestamp": "1970-01-01T00:00:00Z",
212 "namespace": "error",
213 "payload": {
214 "error": "unknown_namespace",
215 "invalid_namespace": "foo"
216 }
217 }
218 "#);
219
220 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
222 assert_eq!(namespace_only.namespace, event.namespace());
223 }
224
225 #[test]
226 fn serialize_event_automod() {
227 let event = SignalingEvent {
228 transaction_id: None,
229 timestamp: Timestamp::unix_epoch(),
230 payload: SignalingModuleEvent::Automod(AutomodEvent::Stopped(
231 StoppedReason::SessionFinished,
232 )),
233 };
234 let raw = serde_json::to_string_pretty(&event).unwrap();
235
236 assert_snapshot!(raw, @r#"
237 {
238 "timestamp": "1970-01-01T00:00:00Z",
239 "namespace": "automod",
240 "payload": {
241 "message": "stopped",
242 "reason": "session_finished"
243 }
244 }
245 "#);
246 }
247
248 #[test]
249 fn serialize_event_core() {
250 let event = SignalingEvent {
251 transaction_id: None,
252 timestamp: Timestamp::unix_epoch(),
253 payload: SignalingModuleEvent::Core(CoreEvent::ParticipantConnected {
254 participant_id: ParticipantId::from_u128(0x01),
255 connection_id: ConnectionId::from_u128(0x02),
256 peer_data: Default::default(),
257 }),
258 };
259 let raw = serde_json::to_string_pretty(&event).unwrap();
260
261 assert_snapshot!(raw, @r#"
262 {
263 "timestamp": "1970-01-01T00:00:00Z",
264 "namespace": "core",
265 "payload": {
266 "message": "participant_connected",
267 "participant_id": "00000000-0000-0000-0000-000000000001",
268 "connection_id": "00000000-0000-0000-0000-000000000002"
269 }
270 }
271 "#);
272
273 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
275 assert_eq!(namespace_only.namespace, event.namespace());
276 }
277
278 #[test]
279 fn serialize_event_breakout() {
280 let event = SignalingEvent {
281 transaction_id: None,
282 timestamp: Timestamp::unix_epoch(),
283 payload: SignalingModuleEvent::Breakout(BreakoutEvent::Closed),
284 };
285 let raw = serde_json::to_string_pretty(&event).unwrap();
286
287 assert_snapshot!(raw, @r#"
288 {
289 "timestamp": "1970-01-01T00:00:00Z",
290 "namespace": "breakout",
291 "payload": {
292 "message": "closed"
293 }
294 }
295 "#);
296
297 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
299 assert_eq!(namespace_only.namespace, event.namespace());
300 }
301
302 #[test]
303 fn serialize_event_chat() {
304 let event = SignalingEvent {
305 transaction_id: None,
306 timestamp: Timestamp::unix_epoch(),
307 payload: SignalingModuleEvent::Chat(ChatEvent::ChatDisabled {
308 issued_by: ParticipantId::from_u128(0x01),
309 }),
310 };
311 let raw = serde_json::to_string_pretty(&event).unwrap();
312
313 assert_snapshot!(raw, @r#"
314 {
315 "timestamp": "1970-01-01T00:00:00Z",
316 "namespace": "chat",
317 "payload": {
318 "message": "chat_disabled",
319 "issued_by": "00000000-0000-0000-0000-000000000001"
320 }
321 }
322 "#);
323
324 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
326 assert_eq!(namespace_only.namespace, event.namespace());
327 }
328
329 #[test]
330 fn serialize_event_echo() {
331 let event = SignalingEvent {
332 transaction_id: None,
333 timestamp: Timestamp::unix_epoch(),
334 payload: SignalingModuleEvent::Echo(EchoEvent::Pong),
335 };
336 let raw = serde_json::to_string_pretty(&event).unwrap();
337
338 assert_snapshot!(raw, @r#"
339 {
340 "timestamp": "1970-01-01T00:00:00Z",
341 "namespace": "echo",
342 "payload": {
343 "message": "pong"
344 }
345 }
346 "#);
347
348 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
350 assert_eq!(namespace_only.namespace, event.namespace());
351 }
352
353 #[test]
354 fn serialize_event_livekit() {
355 let event = SignalingEvent {
356 transaction_id: None,
357 timestamp: Timestamp::unix_epoch(),
358 payload: SignalingModuleEvent::LiveKit(LiveKitEvent::ScreenSharePermissionsUpdated {
359 grant: false,
360 participants: BTreeSet::new(),
361 }),
362 };
363 let raw = serde_json::to_string_pretty(&event).unwrap();
364
365 assert_snapshot!(raw, @r#"
366 {
367 "timestamp": "1970-01-01T00:00:00Z",
368 "namespace": "livekit",
369 "payload": {
370 "message": "screen_share_permissions_updated",
371 "grant": false,
372 "participants": []
373 }
374 }
375 "#);
376
377 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
379 assert_eq!(namespace_only.namespace, event.namespace());
380 }
381
382 #[test]
383 fn serialize_event_timer() {
384 let event = SignalingEvent {
385 transaction_id: None,
386 timestamp: Timestamp::unix_epoch(),
387 payload: SignalingModuleEvent::Timer(TimerEvent::UpdatedReadyStatus {
388 participant_id: ParticipantId::nil(),
389 status: true,
390 }),
391 };
392 let raw = serde_json::to_string_pretty(&event).unwrap();
393
394 assert_snapshot!(raw, @r#"
395 {
396 "timestamp": "1970-01-01T00:00:00Z",
397 "namespace": "timer",
398 "payload": {
399 "message": "updated_ready_status",
400 "participant_id": "00000000-0000-0000-0000-000000000000",
401 "status": true
402 }
403 }
404 "#);
405
406 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
408 assert_eq!(namespace_only.namespace, event.namespace());
409 }
410
411 #[test]
412 fn serialize_event_polls() {
413 let event = SignalingEvent {
414 transaction_id: None,
415 timestamp: Timestamp::unix_epoch(),
416 payload: SignalingModuleEvent::Polls(PollsEvent::Voted(Vote {
417 poll_id: PollId::nil(),
418 choices: Choices::Single {
419 choice_id: ChoiceId::from_u32(0),
420 },
421 })),
422 };
423 let raw = serde_json::to_string_pretty(&event).unwrap();
424
425 assert_snapshot!(raw, @r#"
426 {
427 "timestamp": "1970-01-01T00:00:00Z",
428 "namespace": "polls",
429 "payload": {
430 "message": "voted",
431 "poll_id": "00000000-0000-0000-0000-000000000000",
432 "choice_id": 0
433 }
434 }
435 "#);
436
437 let namespace_only: NamespaceOnly = serde_json::from_str(&raw).unwrap();
439 assert_eq!(namespace_only.namespace, event.namespace());
440 }
441
442 #[test]
443 fn serialize_event_meeting_report() {
444 let event = SignalingEvent {
445 transaction_id: None,
446 timestamp: Timestamp::unix_epoch(),
447 payload: SignalingModuleEvent::MeetingReport(MeetingReportEvent::PdfAsset {
448 filename: "name".into(),
449 asset_id: AssetId::nil(),
450 }),
451 };
452 let raw = serde_json::to_string_pretty(&event).unwrap();
453
454 assert_snapshot!(raw, @r#"
455 {
456 "timestamp": "1970-01-01T00:00:00Z",
457 "namespace": "meeting_report",
458 "payload": {
459 "message": "pdf_asset",
460 "filename": "name",
461 "asset_id": "00000000-0000-0000-0000-000000000000"
462 }
463 }
464 "#);
465 }
466
467 #[test]
468 fn serialize_event_moderation() {
469 let event = SignalingEvent {
470 transaction_id: None,
471 timestamp: Timestamp::unix_epoch(),
472 payload: SignalingModuleEvent::Moderation(ModerationEvent::Accepted),
473 };
474 let raw = serde_json::to_string_pretty(&event).unwrap();
475
476 assert_snapshot!(raw, @r#"
477 {
478 "timestamp": "1970-01-01T00:00:00Z",
479 "namespace": "moderation",
480 "payload": {
481 "message": "accepted"
482 }
483 }
484 "#);
485 }
486
487 #[test]
488 fn serialize_event_raise_hands() {
489 let event = SignalingEvent {
490 transaction_id: None,
491 timestamp: Timestamp::unix_epoch(),
492 payload: SignalingModuleEvent::RaiseHands(RaiseHandsEvent::HandRaised {
493 participant: ParticipantId::nil(),
494 }),
495 };
496 let raw = serde_json::to_string_pretty(&event).unwrap();
497
498 assert_snapshot!(raw, @r#"
499 {
500 "timestamp": "1970-01-01T00:00:00Z",
501 "namespace": "raise_hands",
502 "payload": {
503 "message": "hand_raised",
504 "participant": "00000000-0000-0000-0000-000000000000"
505 }
506 }
507 "#);
508 }
509
510 #[test]
511 fn serialize_event_subroom_audio() {
512 let group = WhisperGroup {
513 whisper_id: WhisperId::nil(),
514 participants: BTreeMap::from([
515 (ParticipantId::from_u128(0), WhisperState::Creator),
516 (ParticipantId::from_u128(1), WhisperState::Invited),
517 ]),
518 };
519
520 let event = SignalingEvent {
521 transaction_id: None,
522 timestamp: Timestamp::unix_epoch(),
523 payload: SignalingModuleEvent::SubroomAudio(SubroomAudioEvent::WhisperGroupCreated {
524 token: "<jwt-token>".into(),
525 group: group.into(),
526 }),
527 };
528 let raw = serde_json::to_string_pretty(&event).unwrap();
529
530 assert_snapshot!(raw, @r#"
531 {
532 "timestamp": "1970-01-01T00:00:00Z",
533 "namespace": "subroom_audio",
534 "payload": {
535 "message": "whisper_group_created",
536 "token": "<jwt-token>",
537 "whisper_id": "00000000-0000-0000-0000-000000000000",
538 "participants": [
539 {
540 "participant_id": "00000000-0000-0000-0000-000000000000",
541 "state": "creator"
542 },
543 {
544 "participant_id": "00000000-0000-0000-0000-000000000001",
545 "state": "invited"
546 }
547 ]
548 }
549 }
550 "#);
551 }
552
553 #[test]
554 fn serialize_event_meeting_notes() {
555 let event = SignalingEvent {
556 transaction_id: None,
557 timestamp: Timestamp::unix_epoch(),
558 payload: SignalingModuleEvent::MeetingNotes(MeetingNotesEvent::AccessChanged {
559 readers: Vec::new(),
560 writers: Vec::new(),
561 }),
562 };
563 let raw = serde_json::to_string_pretty(&event).unwrap();
564
565 assert_snapshot!(raw, @r#"
566 {
567 "timestamp": "1970-01-01T00:00:00Z",
568 "namespace": "meeting_notes",
569 "payload": {
570 "message": "access_changed",
571 "readers": [],
572 "writers": []
573 }
574 }
575 "#);
576 }
577
578 #[test]
579 fn serialize_event_whiteboard() {
580 let event = SignalingEvent {
581 transaction_id: None,
582 timestamp: Timestamp::unix_epoch(),
583 payload: SignalingModuleEvent::Whiteboard(WhiteboardEvent::Initialized {
584 url: Url::parse("https://example.com").unwrap(),
585 }),
586 };
587 let raw = serde_json::to_string_pretty(&event).unwrap();
588
589 assert_snapshot!(raw, @r#"
590 {
591 "timestamp": "1970-01-01T00:00:00Z",
592 "namespace": "whiteboard",
593 "payload": {
594 "message": "initialized",
595 "url": "https://example.com/"
596 }
597 }
598 "#);
599 }
600
601 #[test]
602 fn serialize_event_excalidraw() {
603 let event = SignalingEvent {
604 transaction_id: None,
605 timestamp: Timestamp::unix_epoch(),
606 payload: SignalingModuleEvent::Excalidraw(ExcalidrawEvent::Followed {
607 participant_id: ParticipantId::nil(),
608 }),
609 };
610 let raw = serde_json::to_string_pretty(&event).unwrap();
611
612 assert_snapshot!(raw, @r#"
613 {
614 "timestamp": "1970-01-01T00:00:00Z",
615 "namespace": "excalidraw",
616 "payload": {
617 "message": "followed",
618 "participant_id": "00000000-0000-0000-0000-000000000000"
619 }
620 }
621 "#);
622 }
623
624 #[test]
625 fn serialize_event_legal_vote() {
626 let event = SignalingEvent {
627 transaction_id: None,
628 timestamp: Timestamp::unix_epoch(),
629 payload: SignalingModuleEvent::LegalVote(LegalVoteEvent::Voted {
630 legal_vote_id: LegalVoteId::from_u128(1),
631 vote_option: VoteOption::Yes,
632 issuer: ParticipantId::from_u128(2),
633 consumed_token: Token::new(3),
634 }),
635 };
636 let raw = serde_json::to_string_pretty(&event).unwrap();
637
638 assert_snapshot!(raw, @r#"
639 {
640 "timestamp": "1970-01-01T00:00:00Z",
641 "namespace": "legal_vote",
642 "payload": {
643 "message": "voted",
644 "legal_vote_id": "00000000-0000-0000-0000-000000000001",
645 "vote_option": "yes",
646 "issuer": "00000000-0000-0000-0000-000000000002",
647 "consumed_token": "11111111114"
648 }
649 }
650 "#);
651 }
652
653 #[test]
654 fn serialize_training_participation_report() {
655 let event = SignalingEvent {
656 transaction_id: None,
657 timestamp: Timestamp::unix_epoch(),
658 payload: SignalingModuleEvent::TrainingParticipationReport(
659 TrainingParticipationReportEvent::PresenceConfirmationLogged,
660 ),
661 };
662 let raw = serde_json::to_string_pretty(&event).unwrap();
663
664 assert_snapshot!(raw, @r#"
665 {
666 "timestamp": "1970-01-01T00:00:00Z",
667 "namespace": "training_participation_report",
668 "payload": {
669 "message": "presence_confirmation_logged"
670 }
671 }
672 "#);
673 }
674
675 #[test]
676 fn serialize_event_transcription() {
677 let event = SignalingEvent {
678 transaction_id: None,
679 timestamp: Timestamp::unix_epoch(),
680 payload: SignalingModuleEvent::Transcription(TranscriptionEvent::StateUpdated {
681 status: TranscriptionStatus::Running,
682 }),
683 };
684
685 let raw = serde_json::to_string_pretty(&event).unwrap();
686
687 assert_snapshot!(raw, @r#"
688 {
689 "timestamp": "1970-01-01T00:00:00Z",
690 "namespace": "transcription",
691 "payload": {
692 "message": "state_updated",
693 "status": "running"
694 }
695 }
696 "#);
697 }
698
699 #[test]
700 fn serialize_event_reaction() {
701 let event = SignalingEvent {
702 transaction_id: None,
703 timestamp: Timestamp::unix_epoch(),
704 payload: SignalingModuleEvent::Reaction(ReactionEvent::Reacted {
705 participant_id: ParticipantId::nil(),
706 reaction: opentalk_roomserver_types_reaction::Reaction::ThumbsUp,
707 }),
708 };
709
710 let raw = serde_json::to_string_pretty(&event).unwrap();
711
712 assert_snapshot!(raw, @r#"
713 {
714 "timestamp": "1970-01-01T00:00:00Z",
715 "namespace": "reaction",
716 "payload": {
717 "message": "reacted",
718 "participant_id": "00000000-0000-0000-0000-000000000000",
719 "reaction": "thumbs_up"
720 }
721 }
722 "#);
723 }
724}