From 306730742c6501c432ada34e5dd9cb5c0dbfed74 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 13 Mar 2026 09:11:07 +0100
Subject: [PATCH 01/18] Improve not found error handling
# Conflicts:
# lang/en/app.php
---
app/Exceptions/Handler.php | 18 ++++++
lang/en/app.php | 1 +
.../components/SettingsRolesDeleteButton.vue | 7 ++-
.../SettingsServerPoolsDeleteButton.vue | 12 +++-
.../SettingsServersDeleteButton.vue | 7 ++-
.../components/SettingsUsersDeleteButton.vue | 7 ++-
.../SettingsUsersResetPasswordButton.vue | 6 ++
resources/js/services/Api.js | 26 ++++++++
resources/js/views/AdminRolesIndex.vue | 1 +
resources/js/views/AdminRolesView.vue | 1 +
resources/js/views/AdminRoomTypesView.vue | 1 +
resources/js/views/AdminServerPoolsIndex.vue | 1 +
resources/js/views/AdminServerPoolsView.vue | 1 +
resources/js/views/AdminServersIndex.vue | 1 +
resources/js/views/AdminServersView.vue | 9 +++
resources/js/views/AdminUsersIndex.vue | 2 +
resources/js/views/AdminUsersView.vue | 2 +
.../e2e/AdminRolesIndexRoleActions.cy.js | 48 +++++++++++++-
.../e2e/AdminRolesViewRoleActions.cy.js | 30 +++++++++
.../AdminRoomTypesIndexRoomTypeActions.cy.js | 12 ++--
.../AdminRoomTypesViewRoomTypeActions.cy.js | 31 ++++++++++
...minServerPoolsIndexServerPoolActions.cy.js | 53 +++++++++++++++-
...dminServerPoolsViewServerPoolActions.cy.js | 29 +++++++++
.../e2e/AdminServersIndexServerActions.cy.js | 50 ++++++++++++++-
.../e2e/AdminServersViewServerActions.cy.js | 31 ++++++++++
.../e2e/AdminUsersIndexUserActions.cy.js | 48 +++++++++++++-
.../e2e/AdminUsersViewUserActions.cy.js | 62 +++++++++++++++++++
27 files changed, 482 insertions(+), 15 deletions(-)
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index f258bdf18..18321caff 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -2,12 +2,14 @@
namespace App\Exceptions;
+use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Foundation\ViteException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Psr\Log\LogLevel;
use Spatie\LaravelIgnition\Exceptions\ViewException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
class Handler extends ExceptionHandler
@@ -75,5 +77,21 @@ public function register(): void
return null;
});
+
+ $this->renderable(function (NotFoundHttpException $e, Request $request) {
+ if ($request->expectsJson()) {
+ $modelNotFoundException = $e->getPrevious() instanceof ModelNotFoundException ? $e->getPrevious() : null;
+
+ if ($modelNotFoundException) {
+ $json = [
+ 'message' => 'model_not_found',
+ 'model' => class_basename($modelNotFoundException->getModel()),
+ 'ids' => $modelNotFoundException->getIds(),
+ ];
+
+ return response()->json($json, 404);
+ }
+ }
+ });
}
}
diff --git a/lang/en/app.php b/lang/en/app.php
index cb8232260..880ca7f9c 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -64,6 +64,7 @@
'flash' => [
'client_error' => 'An unknown error occurred in the application!',
'guests_only' => 'The request can only be made by guests!',
+ 'model_not_found' => ':model with id :ids was not found!',
'server_error' => [
'empty_message' => 'An error occurred on the server during request!',
'error_code' => 'Error code: :statusCode',
diff --git a/resources/js/components/SettingsRolesDeleteButton.vue b/resources/js/components/SettingsRolesDeleteButton.vue
index 61f2a9e1d..76a6afa7a 100644
--- a/resources/js/components/SettingsRolesDeleteButton.vue
+++ b/resources/js/components/SettingsRolesDeleteButton.vue
@@ -46,6 +46,7 @@
diff --git a/resources/js/components/RoomFavoriteButton.vue b/resources/js/components/RoomFavoriteButton.vue
index 0e64e9ef8..1cd422a2f 100644
--- a/resources/js/components/RoomFavoriteButton.vue
+++ b/resources/js/components/RoomFavoriteButton.vue
@@ -33,6 +33,10 @@ const props = defineProps({
type: Boolean,
default: true,
},
+ redirectOnRoomModelNotFound: {
+ type: Boolean,
+ default: false,
+ },
});
const isLoading = ref(false);
@@ -57,6 +61,7 @@ function toggleFavorite() {
.catch((error) => {
api.error(error, {
redirectOnUnauthenticated: props.redirectOnUnauthenticated,
+ redirectOnRoomModelNotFound: props.redirectOnRoomModelNotFound,
});
})
.finally(() => {
diff --git a/resources/js/components/RoomHeader.vue b/resources/js/components/RoomHeader.vue
index 4f1ea5735..e0a87fb68 100644
--- a/resources/js/components/RoomHeader.vue
+++ b/resources/js/components/RoomHeader.vue
@@ -33,6 +33,7 @@
v-if="!hideFavorites && authStore.isAuthenticated"
:room="props.room"
:redirect-on-unauthenticated="false"
+ :redirect-on-room-model-not-found="true"
@favorites-changed="emit('reload')"
/>
{
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabDescription.vue b/resources/js/components/RoomTabDescription.vue
index bb0eeef14..583b8e113 100644
--- a/resources/js/components/RoomTabDescription.vue
+++ b/resources/js/components/RoomTabDescription.vue
@@ -229,7 +229,10 @@ function save() {
editorOpen.value = false;
}
// Handle other errors
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
// Disable saving indicator
diff --git a/resources/js/components/RoomTabFiles.vue b/resources/js/components/RoomTabFiles.vue
index e00bf354a..8fc21ff94 100644
--- a/resources/js/components/RoomTabFiles.vue
+++ b/resources/js/components/RoomTabFiles.vue
@@ -425,7 +425,10 @@ function loadData(page = null) {
return emit("invalidRoomAuthToken");
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
paginator.revertFirst();
loadingError.value = true;
})
diff --git a/resources/js/components/RoomTabFilesDeleteButton.vue b/resources/js/components/RoomTabFilesDeleteButton.vue
index 184663335..b933ea9e1 100644
--- a/resources/js/components/RoomTabFilesDeleteButton.vue
+++ b/resources/js/components/RoomTabFilesDeleteButton.vue
@@ -101,14 +101,20 @@ function deleteFile() {
// deleting failed
if (error.response) {
// file not found
- if (error.response.status === env.HTTP_NOT_FOUND) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model !== "Room"
+ ) {
toast.error(t("rooms.flash.file_gone"));
emit("notFound");
modalVisible.value = false;
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabFilesEditButton.vue b/resources/js/components/RoomTabFilesEditButton.vue
index 25362cdb5..a4c6bc3d5 100644
--- a/resources/js/components/RoomTabFilesEditButton.vue
+++ b/resources/js/components/RoomTabFilesEditButton.vue
@@ -195,7 +195,10 @@ function save() {
// editing failed
if (error.response) {
// file not found
- if (error.response.status === env.HTTP_NOT_FOUND) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model !== "Room"
+ ) {
toast.error(t("rooms.flash.file_gone"));
emit("notFound");
modalVisible.value = false;
@@ -207,7 +210,10 @@ function save() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabFilesUploadButton.vue b/resources/js/components/RoomTabFilesUploadButton.vue
index c65a8018d..599e76fa4 100644
--- a/resources/js/components/RoomTabFilesUploadButton.vue
+++ b/resources/js/components/RoomTabFilesUploadButton.vue
@@ -265,7 +265,10 @@ function uploadFile(file) {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
});
}
diff --git a/resources/js/components/RoomTabHistory.vue b/resources/js/components/RoomTabHistory.vue
index c4efa78e0..c0a6424f0 100644
--- a/resources/js/components/RoomTabHistory.vue
+++ b/resources/js/components/RoomTabHistory.vue
@@ -298,7 +298,10 @@ function loadData(page = null) {
})
.catch((error) => {
paginator.revertFirst();
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabMembers.vue b/resources/js/components/RoomTabMembers.vue
index 184c344b0..031521eec 100644
--- a/resources/js/components/RoomTabMembers.vue
+++ b/resources/js/components/RoomTabMembers.vue
@@ -377,7 +377,10 @@ function loadData(page = null) {
})
.catch((error) => {
paginator.revertFirst();
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabMembersAddSingleModal.vue b/resources/js/components/RoomTabMembersAddSingleModal.vue
index 1ef150ca7..d99ccc778 100644
--- a/resources/js/components/RoomTabMembersAddSingleModal.vue
+++ b/resources/js/components/RoomTabMembersAddSingleModal.vue
@@ -192,7 +192,10 @@ function asyncFind(query) {
})
.catch((error) => {
tooManyResults.value = false;
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingSearch.value = false;
diff --git a/resources/js/components/RoomTabMembersBulkDeleteButton.vue b/resources/js/components/RoomTabMembersBulkDeleteButton.vue
index 077b18b1a..f3dd54e1e 100644
--- a/resources/js/components/RoomTabMembersBulkDeleteButton.vue
+++ b/resources/js/components/RoomTabMembersBulkDeleteButton.vue
@@ -130,7 +130,10 @@ function deleteMembers() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersBulkEditButton.vue b/resources/js/components/RoomTabMembersBulkEditButton.vue
index 273951c3c..1f13795f8 100644
--- a/resources/js/components/RoomTabMembersBulkEditButton.vue
+++ b/resources/js/components/RoomTabMembersBulkEditButton.vue
@@ -168,7 +168,10 @@ function save() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersBulkImportModal.vue b/resources/js/components/RoomTabMembersBulkImportModal.vue
index aeb8a9983..546f1a5af 100644
--- a/resources/js/components/RoomTabMembersBulkImportModal.vue
+++ b/resources/js/components/RoomTabMembersBulkImportModal.vue
@@ -341,7 +341,10 @@ function importUsers(firstRound = false) {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersDeleteButton.vue b/resources/js/components/RoomTabMembersDeleteButton.vue
index cf30ba516..62c86c173 100644
--- a/resources/js/components/RoomTabMembersDeleteButton.vue
+++ b/resources/js/components/RoomTabMembersDeleteButton.vue
@@ -111,7 +111,10 @@ function deleteMember() {
modalVisible.value = false;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersEditButton.vue b/resources/js/components/RoomTabMembersEditButton.vue
index 8a02bed35..098b2812c 100644
--- a/resources/js/components/RoomTabMembersEditButton.vue
+++ b/resources/js/components/RoomTabMembersEditButton.vue
@@ -178,7 +178,10 @@ function save() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinks.vue b/resources/js/components/RoomTabPersonalizedLinks.vue
index 0a752d5b5..5fac0e884 100644
--- a/resources/js/components/RoomTabPersonalizedLinks.vue
+++ b/resources/js/components/RoomTabPersonalizedLinks.vue
@@ -317,7 +317,10 @@ function loadData(page = null) {
})
.catch((error) => {
paginator.revertFirst();
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabPersonalizedLinksAddButton.vue b/resources/js/components/RoomTabPersonalizedLinksAddButton.vue
index 2fbef8be3..e882dae91 100644
--- a/resources/js/components/RoomTabPersonalizedLinksAddButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksAddButton.vue
@@ -171,7 +171,10 @@ function save() {
) {
formErrors.set(error.response.data.errors);
} else {
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
}
})
.finally(() => {
diff --git a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
index cd2e998ad..98f3a4872 100644
--- a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
@@ -120,14 +120,20 @@ function deleteLink() {
// deleting failed
if (error.response) {
// personalized link not found
- if (error.response.status === env.HTTP_NOT_FOUND) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model !== "Room"
+ ) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
emit("notFound");
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
index 7dde482ad..e362983f5 100644
--- a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
@@ -189,7 +189,10 @@ function save() {
// editing failed
if (error.response) {
// token not found
- if (error.response.status === env.HTTP_NOT_FOUND) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model !== "Room"
+ ) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
emit("notFound");
@@ -200,7 +203,10 @@ function save() {
formErrors.set(error.response.data.errors);
return;
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
}
})
.finally(() => {
diff --git a/resources/js/components/RoomTabRecordings.vue b/resources/js/components/RoomTabRecordings.vue
index 76dd9ada9..12294a175 100644
--- a/resources/js/components/RoomTabRecordings.vue
+++ b/resources/js/components/RoomTabRecordings.vue
@@ -440,7 +440,10 @@ function loadData(page = null) {
}
loadingError.value = true;
paginator.revertFirst();
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isBusy.value = false;
diff --git a/resources/js/components/RoomTabRecordingsDeleteButton.vue b/resources/js/components/RoomTabRecordingsDeleteButton.vue
index 326f8f533..a943d1030 100644
--- a/resources/js/components/RoomTabRecordingsDeleteButton.vue
+++ b/resources/js/components/RoomTabRecordingsDeleteButton.vue
@@ -97,13 +97,19 @@ function deleteRecording() {
// editing failed
if (error.response) {
// recording not found
- if (error.response.status === env.HTTP_NOT_FOUND) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model !== "Room"
+ ) {
toast.error(t("rooms.flash.recording_gone"));
emit("notFound");
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabRecordingsEditButton.vue b/resources/js/components/RoomTabRecordingsEditButton.vue
index f07787a4d..97b412d65 100644
--- a/resources/js/components/RoomTabRecordingsEditButton.vue
+++ b/resources/js/components/RoomTabRecordingsEditButton.vue
@@ -236,7 +236,10 @@ function save() {
// editing failed
if (error.response) {
// recording not found
- if (error.response.status === env.HTTP_NOT_FOUND) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model !== "Room"
+ ) {
toast.error(t("rooms.flash.recording_gone"));
modalVisible.value = false;
emit("notFound");
@@ -248,7 +251,10 @@ function save() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabSettings.vue b/resources/js/components/RoomTabSettings.vue
index 2b03e4877..24f20c6ad 100644
--- a/resources/js/components/RoomTabSettings.vue
+++ b/resources/js/components/RoomTabSettings.vue
@@ -429,7 +429,10 @@ function load() {
loaded.value = true;
})
.catch((error) => {
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabStreaming.vue b/resources/js/components/RoomTabStreaming.vue
index 37d527e84..14f9d0f76 100644
--- a/resources/js/components/RoomTabStreaming.vue
+++ b/resources/js/components/RoomTabStreaming.vue
@@ -170,7 +170,7 @@ async function streamingCommand(command) {
if (error.response.status === env.HTTP_ROOM_NOT_RUNNING) {
emit("settingsChanged");
}
- api.error(error);
+ api.error(error, { redirectOnRoomModelNotFound: true });
})
.finally(() => {
autoReload();
diff --git a/resources/js/components/RoomTabStreamingConfigButton.vue b/resources/js/components/RoomTabStreamingConfigButton.vue
index 9a34fd515..2842a8b10 100644
--- a/resources/js/components/RoomTabStreamingConfigButton.vue
+++ b/resources/js/components/RoomTabStreamingConfigButton.vue
@@ -272,7 +272,7 @@ function save() {
) {
formErrors.set(error.response.data.errors);
} else {
- api.error(error);
+ api.error(error, { redirectOnRoomModelNotFound: true });
}
})
.finally(() => {
diff --git a/resources/js/components/RoomTransferOwnershipButton.vue b/resources/js/components/RoomTransferOwnershipButton.vue
index 641abd82c..9e22b4269 100644
--- a/resources/js/components/RoomTransferOwnershipButton.vue
+++ b/resources/js/components/RoomTransferOwnershipButton.vue
@@ -235,7 +235,10 @@ function transferOwnership() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/services/Api.js b/resources/js/services/Api.js
index 9f2ba0c93..abe8620da 100644
--- a/resources/js/services/Api.js
+++ b/resources/js/services/Api.js
@@ -119,16 +119,14 @@ export class Api {
this.toast.error(this.t("app.flash.unauthorized"));
}
- handleModelNotFound(error) {
- const model =
- error.response && error.response.data
- ? error.response.data.model
- : undefined;
-
- const ids =
- error.response && error.response.data
- ? error.response.data.ids
- : undefined;
+ handleModelNotFound(error, options) {
+ const data = error.response?.data;
+ const model = data?.model;
+ const ids = data?.ids;
+
+ if (model === "Room" && options.redirectOnRoomModelNotFound === true) {
+ this.router.push({ name: "404" });
+ }
this.toast.error(
this.t("app.flash.model_not_found", {
diff --git a/resources/js/views/RoomsView.vue b/resources/js/views/RoomsView.vue
index 7e4431f30..05be64e15 100644
--- a/resources/js/views/RoomsView.vue
+++ b/resources/js/views/RoomsView.vue
@@ -439,10 +439,9 @@ function load() {
})
.catch((error) => {
if (error.response) {
- // Room not found
+ // Room not found (Always redirect to 404 view)
if (error.response.status === env.HTTP_NOT_FOUND) {
router.push({ name: "404" });
- return;
}
// Room auth token is invalid
@@ -515,10 +514,9 @@ function reload() {
})
.catch((error) => {
if (error.response) {
- // Room not found
+ // Room not found (Always redirect to 404 view)
if (error.response.status === env.HTTP_NOT_FOUND) {
router.push({ name: "404" });
- return;
}
// Room auth token is invalid
@@ -674,7 +672,10 @@ function authenticate(type, codeOrToken) {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
authLoading.value = false;
diff --git a/tests/Frontend/e2e/RoomsViewGeneral.cy.js b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
index b5c433eb1..47babd3a3 100644
--- a/tests/Frontend/e2e/RoomsViewGeneral.cy.js
+++ b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
@@ -2795,6 +2795,11 @@ describe("Room View general", function () {
cy.url()
.should("include", "/404")
.should("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.server_error.message_{"message":"No query results for model [App\\\\Room] abc-def-123"}',
+ 'app.flash.server_error.error_code_{"statusCode":404}',
+ ]);
});
it("auto-reload", function () {
@@ -2930,6 +2935,11 @@ describe("Room View general", function () {
cy.url()
.should("include", "/404")
.should("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.server_error.message_{"message":"No query results for model [App\\\\Room] abc-def-123"}',
+ 'app.flash.server_error.error_code_{"statusCode":404}',
+ ]);
});
it("reload with access code errors", function () {
From 5e14f884d7ea19aa2706212194455731a73421d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Tue, 17 Mar 2026 08:23:45 +0100
Subject: [PATCH 04/18] Adjust room tests
---
.../js/components/RoomMembershipButton.vue | 5 +-
.../RoomTabMembersAddSingleModal.vue | 10 +-
.../RoomTabStreamingConfigButton.vue | 2 +-
tests/Frontend/e2e/RoomsViewDescription.cy.js | 28 +++
tests/Frontend/e2e/RoomsViewFiles.cy.js | 21 +++
.../e2e/RoomsViewFilesFileActions.cy.js | 111 +++++++++++-
tests/Frontend/e2e/RoomsViewGeneral.cy.js | 163 ++++++++++++++++++
tests/Frontend/e2e/RoomsViewHistory.cy.js | 25 +++
.../e2e/RoomsViewHistoryMeetingActions.cy.js | 24 +--
tests/Frontend/e2e/RoomsViewMeetings.cy.js | 148 ++++++++++++++++
tests/Frontend/e2e/RoomsViewMembers.cy.js | 25 +++
.../e2e/RoomsViewMembersBulkActions.cy.js | 114 ++++++++++++
.../e2e/RoomsViewMembersMemberActions.cy.js | 112 ++++++++++++
.../e2e/RoomsViewPersonalizedLinks.cy.js | 32 ++++
...omsViewPersonalizedLinksTokenActions.cy.js | 99 +++++++++++
tests/Frontend/e2e/RoomsViewRecordings.cy.js | 22 +++
.../RoomsViewRecordingsRecordingActions.cy.js | 84 ++++++++-
tests/Frontend/e2e/RoomsViewSettings.cy.js | 77 ++++++++-
tests/Frontend/e2e/RoomsViewStreaming.cy.js | 20 +++
.../e2e/RoomsViewStreamingConfigActions.cy.js | 48 ++++++
20 files changed, 1143 insertions(+), 27 deletions(-)
diff --git a/resources/js/components/RoomMembershipButton.vue b/resources/js/components/RoomMembershipButton.vue
index 4723d8da2..1b6955422 100644
--- a/resources/js/components/RoomMembershipButton.vue
+++ b/resources/js/components/RoomMembershipButton.vue
@@ -156,7 +156,10 @@ function leaveMembership() {
modalVisible.value = false;
})
.catch((error) => {
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersAddSingleModal.vue b/resources/js/components/RoomTabMembersAddSingleModal.vue
index d99ccc778..318d72781 100644
--- a/resources/js/components/RoomTabMembersAddSingleModal.vue
+++ b/resources/js/components/RoomTabMembersAddSingleModal.vue
@@ -192,10 +192,7 @@ function asyncFind(query) {
})
.catch((error) => {
tooManyResults.value = false;
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingSearch.value = false;
@@ -242,7 +239,10 @@ function save() {
return;
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: true,
+ });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabStreamingConfigButton.vue b/resources/js/components/RoomTabStreamingConfigButton.vue
index 2842a8b10..36158d370 100644
--- a/resources/js/components/RoomTabStreamingConfigButton.vue
+++ b/resources/js/components/RoomTabStreamingConfigButton.vue
@@ -228,7 +228,7 @@ function loadConfig() {
response.data.data.system_default_pause_image;
})
.catch((error) => {
- api.error(error);
+ api.error(error, { redirectOnRoomModelNotFound: true });
modelLoadingError.value = true;
})
.finally(() => {
diff --git a/tests/Frontend/e2e/RoomsViewDescription.cy.js b/tests/Frontend/e2e/RoomsViewDescription.cy.js
index 58076a92c..f5882eb45 100644
--- a/tests/Frontend/e2e/RoomsViewDescription.cy.js
+++ b/tests/Frontend/e2e/RoomsViewDescription.cy.js
@@ -462,6 +462,34 @@ describe("Rooms view description", function () {
"api/v1/rooms/abc-def-123/description",
"description",
);
+
+ // Reload page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ // Check with 404 error (room not found)
+ cy.intercept("PUT", "api/v1/rooms/abc-def-123/description", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("saveDescriptionRequest");
+
+ cy.get('[data-test="room-description-edit-button"]').click();
+ cy.get('[data-test="tip-tap-editor"]').should("be.visible");
+ cy.get('[data-test="room-description-save-button"]').click();
+
+ cy.wait("@saveDescriptionRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ // Check that error message gets shown
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("description changes", function () {
diff --git a/tests/Frontend/e2e/RoomsViewFiles.cy.js b/tests/Frontend/e2e/RoomsViewFiles.cy.js
index 942f32a2c..0f2fd3611 100644
--- a/tests/Frontend/e2e/RoomsViewFiles.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFiles.cy.js
@@ -721,6 +721,27 @@ describe("Rooms View Files", function () {
cy.get('[data-test="paginator-page"]')
.eq(0)
.should("have.attr", "data-p-active", "true");
+
+ // Check with 404 error (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/files*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomFilesRequest");
+
+ cy.reload();
+ cy.wait("@roomFilesRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ // Check that error message gets shown
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("load files page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js b/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
index ad8b086f8..55417004a 100644
--- a/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
@@ -332,6 +332,39 @@ describe("Rooms view files file actions", function () {
"/api/v1/rooms/abc-def-123/files",
"files",
);
+
+ // Reload page
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomFilesRequest(true);
+ cy.reload();
+
+ // Check 404 error (room not found)
+ cy.intercept("POST", "/api/v1/rooms/abc-def-123/files", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("uploadFileRequest");
+
+ cy.get('[data-test="room-files-upload-button"]').click();
+ cy.get('[data-test="room-files-upload-dialog"]')
+ .should("be.visible")
+ .find("#file")
+ .selectFile("tests/Frontend/fixtures/files/testFile.txt", {
+ force: true,
+ });
+
+ cy.wait("@uploadFileRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "abc-def-123");
+
+ // Check that error message is shown
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("delete file", function () {
@@ -417,7 +450,9 @@ describe("Rooms view files file actions", function () {
cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/files/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "RoomFile",
+ ids: [3],
},
}).as("deleteFileRequest");
@@ -504,6 +539,41 @@ describe("Rooms view files file actions", function () {
"/api/v1/rooms/abc-def-123/files/1",
"files",
);
+
+ // Reload page
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomFilesRequest(true);
+ cy.reload();
+
+ // Check with 404 error (room not found)
+ cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/files/1", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("deleteFileRequest");
+
+ cy.get('[data-test="room-file-item"]')
+ .eq(0)
+ .find('[data-test="room-files-delete-button"]')
+ .click();
+
+ cy.get('[data-test="room-files-delete-dialog"]')
+ .should("be.visible")
+ .find('[data-test="dialog-continue-button"]')
+ .click();
+
+ cy.wait("@deleteFileRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "abc-def-123");
+
+ // Check that error message is shown
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("change file settings", function () {
@@ -613,7 +683,9 @@ describe("Rooms view files file actions", function () {
cy.intercept("PUT", "/api/v1/rooms/abc-def-123/files/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "RoomFile",
+ ids: [3],
},
}).as("editFileRequest");
@@ -724,6 +796,41 @@ describe("Rooms view files file actions", function () {
"/api/v1/rooms/abc-def-123/files/1",
"files",
);
+
+ // Reload page
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomFilesRequest(true);
+ cy.reload();
+
+ // Check with 404 error (room not found)
+ cy.intercept("PUT", "/api/v1/rooms/abc-def-123/files/1", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("editFileRequest");
+
+ cy.get('[data-test="room-file-item"]')
+ .eq(0)
+ .find('[data-test="room-files-edit-button"]')
+ .click();
+
+ cy.get('[data-test="room-files-edit-dialog"]')
+ .should("be.visible")
+ .find('[data-test="dialog-save-button"]')
+ .click();
+
+ cy.wait("@editFileRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "abc-def-123");
+
+ // Check that error message is shown
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("download file with terms of use", function () {
diff --git a/tests/Frontend/e2e/RoomsViewGeneral.cy.js b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
index 47babd3a3..651f58c7f 100644
--- a/tests/Frontend/e2e/RoomsViewGeneral.cy.js
+++ b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
@@ -2357,6 +2357,46 @@ describe("Room View general", function () {
cy.contains("auth.login").should("be.visible");
+ // Visit room page again
+ cy.fixture("room.json").then((room) => {
+ room.data.owner = {
+ id: 2,
+ name: "Max Doe",
+ };
+ room.data.description = "Test
";
+ room.data.allow_membership = true;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123*", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+
+ cy.wait("@roomRequest");
+
+ // Check join membership with 404 error (room not found)
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/membership*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("joinMembershipRequest");
+
+ cy.get('[data-test="room-join-membership-button"]').click();
+
+ cy.wait("@joinMembershipRequest");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
+
// Reload room with user being a member of the room
cy.fixture("room.json").then((room) => {
room.data.owner = {
@@ -2448,6 +2488,46 @@ describe("Room View general", function () {
// Check that access code overlay is shown
cy.get('[data-test="room-access-code-overlay"]').should("be.visible");
+
+ // Reload room with user being a member of the room
+ cy.fixture("room.json").then((room) => {
+ room.data.owner = {
+ id: 2,
+ name: "Max Doe",
+ };
+ room.data.description = "Test
";
+ room.data.allow_membership = true;
+ room.data.is_member = true;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123*", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+
+ cy.wait("@roomRequest");
+
+ // Check end membership with 404 error (room not found)
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/membership", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("endMembershipRequest");
+
+ cy.get('[data-test="room-end-membership-button"]').click();
+
+ cy.get('[data-test="end-membership-dialog"]').should("be.visible");
+ cy.get('[data-test="dialog-continue-button"]').click();
+
+ cy.wait("@endMembershipRequest");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
});
it("trigger favorites button", function () {
@@ -2622,6 +2702,46 @@ describe("Room View general", function () {
cy.contains("auth.login").should("be.visible");
+ // Visit room page again
+ cy.fixture("room.json").then((room) => {
+ room.data.owner = {
+ id: 2,
+ name: "Max Doe",
+ };
+ room.data.description = "Test
";
+ room.data.allow_membership = true;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+
+ cy.wait("@roomRequest");
+
+ // Test add to favorites with 404 error (room not found)
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("addFavoritesRequest");
+
+ cy.get('[data-test="room-favorites-button"]').click();
+
+ cy.wait("@addFavoritesRequest");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
+
// Reload room but room is already in favorites
cy.fixture("room.json").then((room) => {
room.data.owner = {
@@ -2696,6 +2816,49 @@ describe("Room View general", function () {
// Check that access code overlay is shown
cy.get('[data-test="room-access-code-overlay"]').should("be.visible");
+
+ // Reload room but room is already not in favorites
+ cy.fixture("room.json").then((room) => {
+ room.data.owner = {
+ id: 2,
+ name: "Max Doe",
+ };
+ room.data.description = "Test
";
+ room.data.allow_membership = true;
+ room.data.is_favorite = true;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ // Test remove from favorites with 404 error (room not found)
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("deleteFavoritesRequest");
+
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.remove")
+ .click();
+
+ cy.wait("@deleteFavoritesRequest");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("visit with guest forbidden", function () {
diff --git a/tests/Frontend/e2e/RoomsViewHistory.cy.js b/tests/Frontend/e2e/RoomsViewHistory.cy.js
index 7af126f5e..d1548e679 100644
--- a/tests/Frontend/e2e/RoomsViewHistory.cy.js
+++ b/tests/Frontend/e2e/RoomsViewHistory.cy.js
@@ -496,6 +496,31 @@ describe("Rooms view history", function () {
"api/v1/rooms/abc-def-123/meetings*",
"history",
);
+
+ // Reload page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ // Check with 404 error (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/meetings*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomHistoryRequest");
+
+ cy.get("#tab-history").click();
+ cy.wait("@roomHistoryRequest");
+
+ // Check that redirect to 404 page works and that error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("load history page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js b/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
index edd734fd7..40371d111 100644
--- a/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
@@ -139,8 +139,9 @@ describe("Rooms view history meeting actions", function () {
{
statusCode: 404,
body: {
- message:
- "No query results for model [App\\Models\\Meeting] 3a3e504a-d2c4-431c-8ca1-a62598e66761",
+ message: "model_not_found",
+ model: "Meeting",
+ ids: ["3a3e504a-d2c4-431c-8ca1-a62598e66761"],
},
},
).as("statsRequest");
@@ -153,10 +154,9 @@ describe("Rooms view history meeting actions", function () {
cy.wait("@statsRequest");
// Check that error message is shown
- cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model [App\\\\Models\\\\Meeting] 3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
- ]);
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Meeting","ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
+ );
// Check if dialog is closed
cy.get('[data-test="room-history-statistic-dialog"]').should("not.exist");
@@ -477,8 +477,9 @@ describe("Rooms view history meeting actions", function () {
{
statusCode: 404,
body: {
- message:
- "No query results for model [App\\Models\\Meeting] 3a3e504a-d2c4-431c-8ca1-a62598e66761",
+ message: "model_not_found",
+ model: "Meeting",
+ ids: ["3a3e504a-d2c4-431c-8ca1-a62598e66761"],
},
},
).as("attendanceRequest");
@@ -491,10 +492,9 @@ describe("Rooms view history meeting actions", function () {
cy.wait("@attendanceRequest");
// Check that error message is shown
- cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model [App\\\\Models\\\\Meeting] 3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
- ]);
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Meeting","ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
+ );
// Check if dialog is closed
cy.get('[data-test="room-history-attendance-dialog"]').should("not.exist");
diff --git a/tests/Frontend/e2e/RoomsViewMeetings.cy.js b/tests/Frontend/e2e/RoomsViewMeetings.cy.js
index b0d10adf7..aafc2a32d 100644
--- a/tests/Frontend/e2e/RoomsViewMeetings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMeetings.cy.js
@@ -1345,6 +1345,51 @@ describe("Rooms view meetings", function () {
"have.text",
"rooms.start",
);
+
+ // Reload page
+ cy.fixture("room.json").then((room) => {
+ room.data.last_meeting = {
+ start: "2023-08-21T08:18:28.000000Z",
+ end: null,
+ };
+ room.data.current_user = null;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+ cy.reload();
+
+ // Test with 404 error (room not found)
+ cy.intercept("POST", "/api/v1/rooms/abc-def-123/join*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("joinRequest");
+
+ // Try to join meeting
+ cy.get('[data-test="room-join-button"]').click();
+
+ cy.get('[data-test="room-join-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get("#record-attendance-agreement").should("not.be.checked").click();
+ cy.get("#record-agreement").should("not.be.checked").click();
+ cy.get("#record-video-agreement").should("not.be.checked").click();
+ cy.get('[data-test="dialog-continue-button"]').click();
+ });
+
+ cy.wait("@joinRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("join meeting load requirements errors", function () {
@@ -1432,6 +1477,7 @@ describe("Rooms view meetings", function () {
message: "require_code",
},
}).as("preJoinRequest");
+ cy.interceptRoomFilesRequest();
// Try to join meeting
cy.get('[data-test="room-join-button"]').click();
@@ -1487,6 +1533,44 @@ describe("Rooms view meetings", function () {
// Check dialog is closed
cy.get('[data-test="room-join-dialog"]').should("not.exist");
+
+ // Reload room
+ cy.fixture("room.json").then((room) => {
+ room.data.last_meeting = {
+ start: "2023-08-21T08:18:28.000000Z",
+ end: null,
+ };
+ room.data.current_user = null;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123*", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+
+ cy.wait("@roomRequest");
+
+ // Check with 404 error (room not found)
+ cy.intercept("OPTIONS", "api/v1/rooms/abc-def-123/join*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("preJoinRequest");
+
+ // Try to join meeting
+ cy.get('[data-test="room-join-button"]').click();
+ cy.wait("@preJoinRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("join running meeting with dark mode", function () {
@@ -2849,6 +2933,49 @@ describe("Rooms view meetings", function () {
"eq",
`${Cypress.expose("redirectBaseUrl")}/bigbluebutton?foo=a&bar=b`,
);
+
+ // Reload room
+ cy.fixture("room.json").then((room) => {
+ room.data.current_user = null;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+
+ cy.wait("@roomRequest");
+
+ // Try with 404 error (room not found)
+ cy.intercept("POST", "/api/v1/rooms/abc-def-123/start*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("startRequest");
+
+ cy.get('[data-test="room-start-button"]').click();
+ cy.get('[data-test="room-join-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get("#record-attendance-agreement").should("not.be.checked").click();
+ cy.get("#record-agreement").should("not.be.checked").click();
+ cy.get("#record-video-agreement").should("not.be.checked").click();
+ cy.get('[data-test="dialog-continue-button"]').click();
+ });
+
+ cy.wait("@startRequest");
+
+ // Check if redirect worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("start meeting load requirements errors", function () {
@@ -3012,6 +3139,27 @@ describe("Rooms view meetings", function () {
// Check dialog is closed
cy.get('[data-test="room-join-dialog"]').should("not.exist");
+
+ // Test 404 error (room not found)
+ cy.intercept("OPTIONS", "api/v1/rooms/abc-def-123/start*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("preStartRequest");
+
+ // Try to start meeting
+ cy.get('[data-test="room-start-button"]').click();
+ cy.wait("@preStartRequest");
+
+ // Check if redirect worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("start meeting with dark mode", function () {
diff --git a/tests/Frontend/e2e/RoomsViewMembers.cy.js b/tests/Frontend/e2e/RoomsViewMembers.cy.js
index 3f1215a14..4d4d459e3 100644
--- a/tests/Frontend/e2e/RoomsViewMembers.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembers.cy.js
@@ -484,6 +484,31 @@ describe("Rooms view members", function () {
"api/v1/rooms/abc-def-123/member*",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ // Test 404 error (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/member*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomMembersRequest");
+
+ cy.get("#tab-members").click();
+
+ cy.wait("@roomMembersRequest");
+
+ // Check that redirect to 404 page works and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("load members page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
index 52a7fd3e7..2261a03d5 100644
--- a/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
@@ -408,6 +408,43 @@ describe("Rooms view members bulk actions", function () {
"api/v1/rooms/abc-def-123/member/bulk",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ cy.get("#tab-members").should("be.visible").click();
+
+ // Select all users
+ cy.get('[data-test="room-members-select-all-checkbox"]').click();
+
+ // Test bulk edit with 404 error (room not found)
+ cy.intercept("PUT", "api/v1/rooms/abc-def-123/member/bulk", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("bulkEditRequest");
+
+ cy.get('[data-test="room-members-bulk-edit-button"]')
+ .should("be.visible")
+ .click();
+
+ cy.get('[data-test="room-members-bulk-edit-dialog"]').should("be.visible");
+ cy.get('[data-test="dialog-save-button"]').click();
+
+ cy.wait("@bulkEditRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("bulk delete members", function () {
@@ -682,6 +719,45 @@ describe("Rooms view members bulk actions", function () {
"api/v1/rooms/abc-def-123/member/bulk",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ cy.get("#tab-members").should("be.visible").click();
+
+ // Select all users
+ cy.get('[data-test="room-members-select-all-checkbox"] > input').click();
+
+ // Test bulk delete with 404 error (room not found)
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/member/bulk", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("bulkDeleteRequest");
+
+ cy.get('[data-test="room-members-bulk-delete-button"]')
+ .should("be.visible")
+ .click();
+
+ cy.get('[data-test="room-members-bulk-delete-dialog"]').should(
+ "be.visible",
+ );
+ cy.get('[data-test="dialog-continue-button"]').click();
+
+ cy.wait("@bulkDeleteRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("bulk import members", function () {
@@ -1386,5 +1462,43 @@ describe("Rooms view members bulk actions", function () {
"api/v1/rooms/abc-def-123/member/bulk",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ cy.get("#tab-members").should("be.visible").click();
+
+ // Test bulk import with 404 error (room not found)
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/member/bulk", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("bulkImportRequest");
+
+ cy.get('[data-test="room-members-add-button"]').click();
+ cy.get("#overlay_menu_1")
+ .should("have.text", "rooms.members.bulk_import_users")
+ .click();
+
+ cy.get('[data-test="room-members-bulk-import-dialog"]').should(
+ "be.visible",
+ );
+ cy.get("#user-emails").type("\n");
+ cy.get('[data-test="dialog-continue-button"]').click();
+
+ cy.wait("@bulkImportRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
});
diff --git a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
index d2fea1dd4..ba9cd1949 100644
--- a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
@@ -432,6 +432,44 @@ describe("Rooms view members member actions", function () {
"/api/v1/rooms/abc-def-123/member",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomMembersRequest();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+ cy.wait("@roomMembersRequest");
+
+ cy.get("#tab-members").click();
+
+ // Test add new member with 404 error (room not found)
+ cy.get('[data-test="room-members-add-button"]').click();
+
+ cy.get("#overlay_menu_0")
+ .should("have.text", "rooms.members.add_single_user")
+ .click();
+
+ cy.get('[data-test="room-members-add-single-dialog"]').should("be.visible");
+
+ cy.intercept("POST", "/api/v1/rooms/abc-def-123/member", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("addUserRequest");
+
+ cy.get('[data-test="dialog-save-button"]').click();
+
+ cy.wait("@addUserRequest");
+
+ // Check that user is redirected to 404 page and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("edit member", function () {
@@ -636,6 +674,43 @@ describe("Rooms view members member actions", function () {
"/api/v1/rooms/abc-def-123/member/6",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomMembersRequest();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ cy.get("#tab-members").click();
+ cy.wait("@roomMembersRequest");
+
+ // Test edit member with 404 error (room not found)
+ cy.get('[data-test="room-member-item"]')
+ .eq(0)
+ .find('[data-test="room-members-edit-button"]')
+ .click();
+
+ cy.get('[data-test="room-members-edit-dialog"]').should("be.visible");
+
+ cy.intercept("PUT", "/api/v1/rooms/abc-def-123/member/5", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("editUserRequest");
+
+ cy.get('[data-test="dialog-save-button"]').click();
+
+ cy.wait("@editUserRequest");
+
+ // Check that user is redirected to 404 page and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("delete member", function () {
@@ -797,5 +872,42 @@ describe("Rooms view members member actions", function () {
"/api/v1/rooms/abc-def-123/member/6",
"members",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomMembersRequest();
+
+ cy.reload();
+
+ cy.wait("@roomRequest");
+ cy.get("#tab-members").click();
+ cy.wait("@roomMembersRequest");
+
+ // Test delete member with 404 error (room not found)
+ cy.get('[data-test="room-member-item"]')
+ .eq(0)
+ .find('[data-test="room-members-delete-button"]')
+ .click();
+
+ cy.get('[data-test="room-members-delete-dialog"]').should("be.visible");
+
+ cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/member/5", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("deleteMemberRequest");
+
+ cy.get('[data-test="dialog-continue-button"]').click();
+
+ cy.wait("@deleteMemberRequest");
+
+ // Check that user is redirected to 404 page and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
});
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
index 721f7b187..95f1d2082 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
@@ -496,6 +496,38 @@ describe("Rooms view personalized links", function () {
"api/v1/rooms/abc-def-123/personalizedLinks*",
"tokens",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ // Check with 404 error (room not found)
+ cy.intercept(
+ {
+ method: "GET",
+ url: "api/v1/rooms/abc-def-123/personalizedLinks*",
+ },
+ {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ },
+ ).as("roomPersonalizedLinksRequest");
+
+ cy.get("#tab-tokens").click();
+
+ cy.wait("@roomPersonalizedLinksRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("load personalized links page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
index ba56784e5..af6f97dda 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
@@ -234,6 +234,37 @@ describe("Rooms view personalized links actions", function () {
"/api/v1/rooms/abc-def-123/personalizedLinks/",
"tokens",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+ cy.get("#tab-tokens").should("be.visible").click();
+ cy.wait("@roomRequest");
+ cy.wait("@roomPersonalizedLinksRequest");
+
+ // Test add personalized link with 404 error (room not found)
+ cy.intercept("POST", "/api/v1/rooms/abc-def-123/personalizedLinks/", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("addLinkRequest");
+
+ cy.get('[data-test="room-personalized-links-add-button"]').click();
+ cy.get('[data-test="room-personalized-links-add-dialog"]').should(
+ "be.visible",
+ );
+ cy.get('[data-test="dialog-save-button"]').click();
+
+ cy.wait("@addLinkRequest");
+
+ // Check that redirect to 404 page works and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("edit personalized link", function () {
@@ -523,6 +554,40 @@ describe("Rooms view personalized links actions", function () {
"/api/v1/rooms/abc-def-123/personalizedLinks/1",
"tokens",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+ cy.get("#tab-tokens").should("be.visible").click();
+ cy.wait("@roomRequest");
+ cy.wait("@roomPersonalizedLinksRequest");
+
+ // Test edit personalized link with 404 error (room not found)
+ cy.intercept("PUT", "/api/v1/rooms/abc-def-123/personalizedLinks/1", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("editLinkRequest");
+
+ cy.get('[data-test="room-personalized-link-item"]')
+ .eq(0)
+ .find('[data-test="room-personalized-links-edit-button"]')
+ .click();
+ cy.get('[data-test="room-personalized-links-edit-dialog"]').should(
+ "be.visible",
+ );
+ cy.get('[data-test="dialog-save-button"]').click();
+
+ cy.wait("@editLinkRequest");
+
+ // Check that redirect to 404 page works and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("delete personalized link", function () {
@@ -716,6 +781,40 @@ describe("Rooms view personalized links actions", function () {
"/api/v1/rooms/abc-def-123/personalizedLinks/1",
"tokens",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+ cy.get("#tab-tokens").should("be.visible").click();
+ cy.wait("@roomRequest");
+ cy.wait("@roomPersonalizedLinksRequest");
+
+ // Test delete personalized link with 404 error (room not found)
+ cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/personalizedLinks/1", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("deleteLinkRequest");
+
+ cy.get('[data-test="room-personalized-link-item"]')
+ .eq(0)
+ .find('[data-test="room-personalized-links-delete-button"]')
+ .click();
+ cy.get('[data-test="room-personalized-links-delete-dialog"]').should(
+ "be.visible",
+ );
+ cy.get('[data-test="dialog-continue-button"]').click();
+
+ cy.wait("@deleteLinkRequest");
+
+ // Check that redirect to 404 page works and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("copy personalized link", function () {
diff --git a/tests/Frontend/e2e/RoomsViewRecordings.cy.js b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
index 59d97b389..1de5fb405 100644
--- a/tests/Frontend/e2e/RoomsViewRecordings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
@@ -760,6 +760,28 @@ describe("Rooms view recordings", function () {
cy.get('[data-test="paginator-page"]')
.eq(0)
.should("have.attr", "data-p-active", "true");
+
+ // Check with 404 error (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/recordings*", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomRecordingsRequest");
+
+ // Reload page
+ cy.reload();
+
+ cy.wait("@roomRecordingsRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("load recordings page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
index 342a5899c..592c7e30e 100644
--- a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
@@ -878,7 +878,9 @@ describe("Rooms view recordings recording actions", function () {
{
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "Recording",
+ ids: ["f9569db6d5e8fb2fd2f57d367d5482b36837b9d8-1663666775"],
},
},
).as("deleteRecordingRequest");
@@ -964,6 +966,45 @@ describe("Rooms view recordings recording actions", function () {
"api/v1/rooms/abc-def-123/recordings/e0cfa18c5fd75a42bd7947d8549321b03abf1daf-1660728035",
"recordings",
);
+
+ // Reload room
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomRecordingsRequests();
+
+ cy.reload();
+ cy.get("#tab-recordings").should("be.visible").click();
+
+ // Check with 404 error (room not found)
+ cy.intercept(
+ "DELETE",
+ "api/v1/rooms/abc-def-123/recordings/e0cfa18c5fd75a42bd7947d8549321b03abf1daf-1660728035",
+ {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ },
+ ).as("deleteRecordingRequest");
+
+ cy.get('[data-test="room-recording-item"]')
+ .eq(0)
+ .find('[data-test="room-recordings-delete-button"]')
+ .click();
+
+ cy.get('[data-test="room-recordings-delete-dialog"]')
+ .should("be.visible")
+ .find('[data-test="dialog-continue-button"]')
+ .click();
+
+ cy.wait("@deleteRecordingRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("edit recording", function () {
@@ -1317,5 +1358,46 @@ describe("Rooms view recordings recording actions", function () {
"api/v1/rooms/abc-def-123/recordings/e0cfa18c5fd75a42bd7947d8549321b03abf1daf-1660728035",
"recordings",
);
+
+ // Reload room
+ cy.interceptRoomViewRequests();
+ cy.interceptRoomRecordingsRequests();
+
+ cy.reload();
+ cy.get("#tab-recordings").should("be.visible").click();
+
+ cy.wait("@roomRecordingsRequest");
+
+ // Check with 404 error (room not found)
+ cy.intercept(
+ "PUT",
+ "api/v1/rooms/abc-def-123/recordings/e0cfa18c5fd75a42bd7947d8549321b03abf1daf-1660728035",
+ {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ },
+ ).as("editRecordingRequest");
+
+ cy.get('[data-test="room-recording-item"]')
+ .eq(0)
+ .find('[data-test="room-recordings-edit-button"]')
+ .click();
+
+ cy.get('[data-test="room-recordings-edit-dialog"]')
+ .should("be.visible")
+ .find('[data-test="dialog-save-button"]')
+ .click();
+
+ cy.wait("@editRecordingRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
});
diff --git a/tests/Frontend/e2e/RoomsViewSettings.cy.js b/tests/Frontend/e2e/RoomsViewSettings.cy.js
index fb9eeed22..e99e27606 100644
--- a/tests/Frontend/e2e/RoomsViewSettings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewSettings.cy.js
@@ -414,6 +414,32 @@ describe("Rooms view settings", function () {
"api/v1/rooms/abc-def-123/settings",
"settings",
);
+
+ // Reload room
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ // Check with 404 error (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/settings", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomSettingsRequest");
+
+ cy.get("#tab-settings").click();
+
+ cy.wait("@roomSettingsRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("load settings with different permissions", function () {
@@ -1716,6 +1742,11 @@ describe("Rooms view settings", function () {
// Check with 404 error
cy.intercept("DELETE", "api/v1/rooms/abc-def-123", {
statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
}).as("roomDeleteRequest");
cy.get("[data-test=room-delete-dialog]")
@@ -1725,12 +1756,18 @@ describe("Rooms view settings", function () {
cy.wait("@roomDeleteRequest");
- cy.checkToastMessage([
- "app.flash.server_error.empty_message",
- 'app.flash.server_error.error_code_{"statusCode":404}',
- ]);
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
+
+ // Reload room page
+ cy.visit("/rooms/abc-def-123#tab=settings");
+
+ cy.wait("@roomSettingsRequest");
+
+ // Open delete dialog again
+ cy.get('[data-test="room-delete-button"]').click();
- // Check that modal stays open
cy.get("[data-test=room-delete-dialog]").should("be.visible");
// Check with 500 error
@@ -2257,5 +2294,35 @@ describe("Rooms view settings", function () {
"api/v1/rooms/abc-def-123/transfer",
"settings",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.get("#tab-settings").click();
+
+ cy.wait("@roomSettingsRequest");
+
+ // Check with 404 error (room not found)
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/transfer", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("transferOwnershipRequest");
+
+ cy.get('[data-test="room-transfer-ownership-button"]').click();
+ cy.get('[data-test="room-transfer-ownership-dialog"]').should("be.visible");
+ cy.get('[data-test="dialog-continue-button"]').click();
+
+ cy.wait("@transferOwnershipRequest");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
});
diff --git a/tests/Frontend/e2e/RoomsViewStreaming.cy.js b/tests/Frontend/e2e/RoomsViewStreaming.cy.js
index ee3d562e5..6e10d107b 100644
--- a/tests/Frontend/e2e/RoomsViewStreaming.cy.js
+++ b/tests/Frontend/e2e/RoomsViewStreaming.cy.js
@@ -786,5 +786,25 @@ describe("Rooms view streaming", function () {
"contain",
"rooms.streaming.no_running_meeting",
);
+
+ // Check 404 error on reload (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/streaming/status", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomStreamingStatus");
+
+ cy.get('[data-test="streaming-reload-button"]').click();
+ cy.wait("@roomStreamingStatus");
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
});
diff --git a/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js b/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
index a24011106..92905de5f 100644
--- a/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
@@ -277,6 +277,27 @@ describe("Rooms view streaming config actions", function () {
// Close dialog
cy.get('[data-test="dialog-cancel-button"]').click();
});
+
+ // Check with 404 error (room not found)
+ cy.intercept("GET", "api/v1/rooms/abc-def-123/streaming/config", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomStreamingConfig");
+
+ cy.get('[data-test="streaming-config-button"]').should("be.visible");
+ cy.get('[data-test="streaming-config-button"]').click();
+
+ cy.wait("@roomStreamingConfig");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("edit settings", function () {
@@ -598,6 +619,33 @@ describe("Rooms view streaming config actions", function () {
// Close dialog
cy.get('[data-test="dialog-cancel-button"]').click();
});
+
+ // Check with 404 error (room not found)
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/streaming/config", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "Room",
+ ids: ["abc-def-123"],
+ },
+ }).as("saveConfigRequest");
+
+ cy.get('[data-test="streaming-config-button"]').click();
+ cy.get('[data-test="room-streaming-config-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get('[data-test="dialog-save-button"]')
+ .should("include.text", "app.save")
+ .click();
+ });
+
+ cy.wait("@saveConfigRequest");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage(
+ 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ );
});
it("view/edit settings with different permissions", function () {
From c97057a0cb5e70ffbe86910582339efbfc33bb5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Wed, 18 Mar 2026 20:07:17 +0100
Subject: [PATCH 05/18] Improve error messages
---
app/Exceptions/Handler.php | 3 ++-
lang/en/app.php | 11 ++++++++++-
.../components/RoomTabFilesDeleteButton.vue | 3 ++-
.../js/components/RoomTabFilesEditButton.vue | 3 ++-
.../RoomTabPersonalizedLinksDeleteButton.vue | 3 ++-
.../RoomTabPersonalizedLinksEditButton.vue | 3 ++-
.../RoomTabRecordingsDeleteButton.vue | 3 ++-
.../RoomTabRecordingsEditButton.vue | 3 ++-
resources/js/constants/modelNames.js | 1 +
resources/js/services/Api.js | 16 +++++++++++-----
.../e2e/AdminRolesIndexRoleActions.cy.js | 6 ++----
.../e2e/AdminRolesViewRoleActions.cy.js | 6 ++----
.../AdminRoomTypesIndexRoomTypeActions.cy.js | 6 ++----
.../AdminRoomTypesViewRoomTypeActions.cy.js | 6 ++----
...minServerPoolsIndexServerPoolActions.cy.js | 6 ++----
...dminServerPoolsViewServerPoolActions.cy.js | 6 ++----
.../e2e/AdminServersIndexServerActions.cy.js | 6 ++----
.../e2e/AdminServersViewServerActions.cy.js | 6 ++----
.../e2e/AdminUsersIndexUserActions.cy.js | 6 ++----
.../e2e/AdminUsersViewUserActions.cy.js | 12 ++++--------
tests/Frontend/e2e/RoomsViewDescription.cy.js | 4 ++--
tests/Frontend/e2e/RoomsViewFiles.cy.js | 4 ++--
.../e2e/RoomsViewFilesFileActions.cy.js | 16 ++++++++--------
tests/Frontend/e2e/RoomsViewGeneral.cy.js | 19 ++++++++++++-------
tests/Frontend/e2e/RoomsViewHistory.cy.js | 4 ++--
.../e2e/RoomsViewHistoryMeetingActions.cy.js | 8 ++++----
tests/Frontend/e2e/RoomsViewMeetings.cy.js | 16 ++++++++--------
tests/Frontend/e2e/RoomsViewMembers.cy.js | 4 ++--
.../e2e/RoomsViewMembersBulkActions.cy.js | 12 ++++++------
.../e2e/RoomsViewMembersMemberActions.cy.js | 12 ++++++------
.../e2e/RoomsViewPersonalizedLinks.cy.js | 4 ++--
...omsViewPersonalizedLinksTokenActions.cy.js | 12 ++++++------
tests/Frontend/e2e/RoomsViewRecordings.cy.js | 4 ++--
.../RoomsViewRecordingsRecordingActions.cy.js | 10 +++++-----
tests/Frontend/e2e/RoomsViewSettings.cy.js | 12 ++++++------
tests/Frontend/e2e/RoomsViewStreaming.cy.js | 4 ++--
.../e2e/RoomsViewStreamingConfigActions.cy.js | 8 ++++----
tests/Frontend/fixtures/en.json | 16 +++++++++++++++-
38 files changed, 152 insertions(+), 132 deletions(-)
create mode 100644 resources/js/constants/modelNames.js
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 18321caff..fdebd15bb 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -7,6 +7,7 @@
use Illuminate\Foundation\ViteException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Str;
use Psr\Log\LogLevel;
use Spatie\LaravelIgnition\Exceptions\ViewException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -85,7 +86,7 @@ public function register(): void
if ($modelNotFoundException) {
$json = [
'message' => 'model_not_found',
- 'model' => class_basename($modelNotFoundException->getModel()),
+ 'model' => Str::snake(class_basename($modelNotFoundException->getModel())),
'ids' => $modelNotFoundException->getIds(),
];
diff --git a/lang/en/app.php b/lang/en/app.php
index 880ca7f9c..0b9adc4ed 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -64,7 +64,16 @@
'flash' => [
'client_error' => 'An unknown error occurred in the application!',
'guests_only' => 'The request can only be made by guests!',
- 'model_not_found' => ':model with id :ids was not found!',
+ 'model_not_found' => [
+ 'fallback' => 'The :model with the id :ids was not found!',
+ 'meeting' => 'The meeting with the id :ids was not found!',
+ 'role' => 'The role with the id :ids was not found!',
+ 'room' => 'The room with the id :ids was not found!',
+ 'room_type' => 'The room type with the id :ids was not found!',
+ 'server' => 'The server with the id :ids was not found!',
+ 'server_pool' => 'The server pool with the id :ids was not found!',
+ 'user' => 'The user with the id :ids was not found!',
+ ],
'server_error' => [
'empty_message' => 'An error occurred on the server during request!',
'error_code' => 'Error code: :statusCode',
diff --git a/resources/js/components/RoomTabFilesDeleteButton.vue b/resources/js/components/RoomTabFilesDeleteButton.vue
index b933ea9e1..a05f61978 100644
--- a/resources/js/components/RoomTabFilesDeleteButton.vue
+++ b/resources/js/components/RoomTabFilesDeleteButton.vue
@@ -53,6 +53,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
+import { ROOM_MODEL } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -103,7 +104,7 @@ function deleteFile() {
// file not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== "Room"
+ error.response.data?.model !== ROOM_MODEL
) {
toast.error(t("rooms.flash.file_gone"));
emit("notFound");
diff --git a/resources/js/components/RoomTabFilesEditButton.vue b/resources/js/components/RoomTabFilesEditButton.vue
index a4c6bc3d5..4f2d2f074 100644
--- a/resources/js/components/RoomTabFilesEditButton.vue
+++ b/resources/js/components/RoomTabFilesEditButton.vue
@@ -100,6 +100,7 @@ import { ref, watch } from "vue";
import { useFormErrors } from "../composables/useFormErrors.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
+import { ROOM_MODEL } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -197,7 +198,7 @@ function save() {
// file not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== "Room"
+ error.response.data?.model !== ROOM_MODEL
) {
toast.error(t("rooms.flash.file_gone"));
emit("notFound");
diff --git a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
index 98f3a4872..1def73a01 100644
--- a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
@@ -59,6 +59,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
+import { ROOM_MODEL } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -122,7 +123,7 @@ function deleteLink() {
// personalized link not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== "Room"
+ error.response.data?.model !== ROOM_MODEL
) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
index e362983f5..768956560 100644
--- a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
@@ -110,6 +110,7 @@ import { ref } from "vue";
import env from "../env.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
+import { ROOM_MODEL } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -191,7 +192,7 @@ function save() {
// token not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== "Room"
+ error.response.data?.model !== ROOM_MODEL
) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
diff --git a/resources/js/components/RoomTabRecordingsDeleteButton.vue b/resources/js/components/RoomTabRecordingsDeleteButton.vue
index a943d1030..a3c7abf0f 100644
--- a/resources/js/components/RoomTabRecordingsDeleteButton.vue
+++ b/resources/js/components/RoomTabRecordingsDeleteButton.vue
@@ -53,6 +53,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
+import { ROOM_MODEL } from "../constants/modelNames.js";
const props = defineProps({
recordingId: {
@@ -99,7 +100,7 @@ function deleteRecording() {
// recording not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== "Room"
+ error.response.data?.model !== ROOM_MODEL
) {
toast.error(t("rooms.flash.recording_gone"));
emit("notFound");
diff --git a/resources/js/components/RoomTabRecordingsEditButton.vue b/resources/js/components/RoomTabRecordingsEditButton.vue
index 97b412d65..2dfcfb140 100644
--- a/resources/js/components/RoomTabRecordingsEditButton.vue
+++ b/resources/js/components/RoomTabRecordingsEditButton.vue
@@ -130,6 +130,7 @@ import * as _ from "lodash-es";
import { useSettingsStore } from "../stores/settings.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
+import { ROOM_MODEL } from "../constants/modelNames.js";
const props = defineProps({
recordingId: {
@@ -238,7 +239,7 @@ function save() {
// recording not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== "Room"
+ error.response.data?.model !== ROOM_MODEL
) {
toast.error(t("rooms.flash.recording_gone"));
modalVisible.value = false;
diff --git a/resources/js/constants/modelNames.js b/resources/js/constants/modelNames.js
new file mode 100644
index 000000000..545d0b65c
--- /dev/null
+++ b/resources/js/constants/modelNames.js
@@ -0,0 +1 @@
+export const ROOM_MODEL = "room";
diff --git a/resources/js/services/Api.js b/resources/js/services/Api.js
index abe8620da..8943da5f4 100644
--- a/resources/js/services/Api.js
+++ b/resources/js/services/Api.js
@@ -6,6 +6,7 @@ import { useAuthStore } from "../stores/auth";
import { useRouter } from "vue-router";
import { EVENT_FORBIDDEN, EVENT_UNAUTHORIZED } from "../constants/events.js";
import EventBus from "./EventBus.js";
+import { ROOM_MODEL } from "../constants/modelNames.js";
axios.defaults.withCredentials = true;
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
@@ -16,6 +17,7 @@ export class Api {
this.router = useRouter();
this.toast = useToast();
this.t = i18n.global.t;
+ this.te = i18n.global.te;
}
/**
@@ -124,15 +126,19 @@ export class Api {
const model = data?.model;
const ids = data?.ids;
- if (model === "Room" && options.redirectOnRoomModelNotFound === true) {
+ if (model === ROOM_MODEL && options.redirectOnRoomModelNotFound === true) {
this.router.push({ name: "404" });
}
this.toast.error(
- this.t("app.flash.model_not_found", {
- model: model,
- ids: ids ? `${ids.join(", ")}` : "",
- }),
+ this.te("app.flash.model_not_found." + model)
+ ? this.t("app.flash.model_not_found." + model, {
+ ids: ids ? `${ids.join(", ")}` : "",
+ })
+ : this.t("app.flash.model_not_found.fallback", {
+ model: model,
+ ids: ids ? `${ids.join(", ")}` : "",
+ }),
);
}
diff --git a/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js b/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js
index c52b00e6f..50b329bc2 100644
--- a/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js
+++ b/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js
@@ -179,7 +179,7 @@ describe("Admin roles index role actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Role",
+ model: "role",
ids: [3],
},
}).as("deleteRoleRequest");
@@ -193,9 +193,7 @@ describe("Admin roles index role actions", function () {
// Check that dialog is closed and that error message is shown
cy.get('[data-test="roles-delete-dialog"]').should("not.exist");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Role","ids":"3"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.role_{"ids":"3"}');
// Check that role is not in the list anymore
cy.get('[data-test="role-item"]').should("have.length", 2);
diff --git a/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js b/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js
index 32a204e61..0f250f6e2 100644
--- a/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js
+++ b/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js
@@ -142,7 +142,7 @@ describe("Admin roles view role actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Role",
+ model: "role",
ids: [2],
},
}).as("deleteRoleRequest");
@@ -155,9 +155,7 @@ describe("Admin roles view role actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/roles").and("not.include", "/2");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Role","ids":"2"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.role_{"ids":"2"}');
// Reload view and open delete dialog again
cy.visit("/admin/roles/2");
diff --git a/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js b/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js
index 333a7cd1a..0a927ad0d 100644
--- a/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js
+++ b/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js
@@ -341,7 +341,7 @@ describe("Admin room types index room type actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "RoomType",
+ model: "room_type",
ids: [3],
},
}).as("deleteRoomTypeRequest");
@@ -357,9 +357,7 @@ describe("Admin room types index room type actions", function () {
cy.get('[data-test="room-types-delete-dialog"]').should("not.exist");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"RoomType","ids":"3"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.room_type_{"ids":"3"}');
// Check that room type is not there anymore
cy.get('[data-test="room-type-item"]').should("have.length", 2);
diff --git a/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js b/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js
index e852fd1e6..50405df27 100644
--- a/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js
+++ b/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js
@@ -292,7 +292,7 @@ describe("Admin room types view room type actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "RoomType",
+ model: "room_type",
ids: [3],
},
}).as("deleteRoomTypeRequest");
@@ -306,9 +306,7 @@ describe("Admin room types view room type actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/room_types").and("not.include", "/3");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"RoomType","ids":"3"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.room_type_{"ids":"3"}');
// Reload view and open delete dialog again
cy.visit("/admin/room_types/3");
diff --git a/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js b/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js
index e0f517f52..4ee467bf0 100644
--- a/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js
+++ b/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js
@@ -216,7 +216,7 @@ describe("Admin server pools index server pool actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "ServerPool",
+ model: "server_pool",
ids: [1],
},
}).as("deleteServerPoolRequest");
@@ -230,9 +230,7 @@ describe("Admin server pools index server pool actions", function () {
// Check that dialog is closed and error message is shown
cy.get('[data-test="server-pools-delete-dialog"]').should("not.exist");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"ServerPool","ids":"1"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.server_pool_{"ids":"1"}');
// Check that server pool is not in list anymore
cy.get('[data-test="server-pool-item"]').should("have.length", 1);
diff --git a/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js b/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js
index 9cdd9956c..299e2711e 100644
--- a/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js
+++ b/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js
@@ -167,7 +167,7 @@ describe("Admin server pools view", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "ServerPool",
+ model: "server_pool",
ids: [1],
},
}).as("deleteServerPoolRequest");
@@ -180,9 +180,7 @@ describe("Admin server pools view", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/server_pools").and("not.include", "/1");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"ServerPool","ids":"1"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.server_pool_{"ids":"1"}');
// Reload view and open delete dialog again
cy.visit("/admin/server_pools/1");
diff --git a/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js b/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js
index c3db6e498..0df2407ec 100644
--- a/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js
+++ b/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js
@@ -168,7 +168,7 @@ describe("Admin servers index server actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Server",
+ model: "server",
ids: [3],
},
}).as("deleteServerRequest");
@@ -182,9 +182,7 @@ describe("Admin servers index server actions", function () {
// Check that dialog is closed and error message is shown
cy.get('[data-test="servers-delete-dialog"]').should("not.exist");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Server","ids":"3"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.server_{"ids":"3"}');
// Check that server is not in list anymore
cy.get('[data-test="server-item"]').should("have.length", 3);
diff --git a/tests/Frontend/e2e/AdminServersViewServerActions.cy.js b/tests/Frontend/e2e/AdminServersViewServerActions.cy.js
index 692d3798d..cbe6fe503 100644
--- a/tests/Frontend/e2e/AdminServersViewServerActions.cy.js
+++ b/tests/Frontend/e2e/AdminServersViewServerActions.cy.js
@@ -140,7 +140,7 @@ describe("Admin servers view server actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Server",
+ model: "server",
ids: [1],
},
}).as("deleteServerRequest");
@@ -154,9 +154,7 @@ describe("Admin servers view server actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/servers").and("not.include", "/1");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Server","ids":"1"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.server_{"ids":"1"}');
// Reload view and open delete dialog again
cy.visit("/admin/servers/1");
diff --git a/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js b/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js
index e418bbf94..08931d4b4 100644
--- a/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js
+++ b/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js
@@ -170,7 +170,7 @@ describe("Admin users index user actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "User",
+ model: "user",
ids: [3],
},
}).as("deleteUserRequest");
@@ -184,9 +184,7 @@ describe("Admin users index user actions", function () {
// Check that dialog is closed and error message is shown
cy.get('[data-test="users-delete-dialog"]').should("not.exist");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"User","ids":"3"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.user_{"ids":"3"}');
// Check that user is not in list anymore
cy.get('[data-test="user-item"]').should("have.length", 3);
diff --git a/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js b/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js
index 8fa4cc32f..a48463c9e 100644
--- a/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js
+++ b/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js
@@ -132,7 +132,7 @@ describe("Admin users view user actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "User",
+ model: "user",
ids: [2],
},
}).as("deleteUserRequest");
@@ -146,9 +146,7 @@ describe("Admin users view user actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/users").and("not.include", "/2");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"User","ids":"2"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.user_{"ids":"2"}');
// Reload view and open delete dialog again
cy.visit("/admin/users/2");
@@ -259,7 +257,7 @@ describe("Admin users view user actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "User",
+ model: "user",
ids: [2],
},
}).as("resetPasswordRequest");
@@ -273,9 +271,7 @@ describe("Admin users view user actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/users").and("not.include", "/2");
- cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"User","ids":"2"}',
- );
+ cy.checkToastMessage('app.flash.model_not_found.user_{"ids":"2"}');
// Reload view and open reset password dialog again
cy.visit("/admin/users/2");
diff --git a/tests/Frontend/e2e/RoomsViewDescription.cy.js b/tests/Frontend/e2e/RoomsViewDescription.cy.js
index f5882eb45..abed2b153 100644
--- a/tests/Frontend/e2e/RoomsViewDescription.cy.js
+++ b/tests/Frontend/e2e/RoomsViewDescription.cy.js
@@ -472,7 +472,7 @@ describe("Rooms view description", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("saveDescriptionRequest");
@@ -488,7 +488,7 @@ describe("Rooms view description", function () {
// Check that error message gets shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewFiles.cy.js b/tests/Frontend/e2e/RoomsViewFiles.cy.js
index 0f2fd3611..06843dd57 100644
--- a/tests/Frontend/e2e/RoomsViewFiles.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFiles.cy.js
@@ -727,7 +727,7 @@ describe("Rooms View Files", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomFilesRequest");
@@ -740,7 +740,7 @@ describe("Rooms View Files", function () {
// Check that error message gets shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js b/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
index 55417004a..b9d0ca1ec 100644
--- a/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
@@ -343,7 +343,7 @@ describe("Rooms view files file actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("uploadFileRequest");
@@ -363,7 +363,7 @@ describe("Rooms view files file actions", function () {
// Check that error message is shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -451,7 +451,7 @@ describe("Rooms view files file actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "RoomFile",
+ model: "room_file",
ids: [3],
},
}).as("deleteFileRequest");
@@ -550,7 +550,7 @@ describe("Rooms view files file actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("deleteFileRequest");
@@ -572,7 +572,7 @@ describe("Rooms view files file actions", function () {
// Check that error message is shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -684,7 +684,7 @@ describe("Rooms view files file actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "RoomFile",
+ model: "room_file",
ids: [3],
},
}).as("editFileRequest");
@@ -807,7 +807,7 @@ describe("Rooms view files file actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("editFileRequest");
@@ -829,7 +829,7 @@ describe("Rooms view files file actions", function () {
// Check that error message is shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewGeneral.cy.js b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
index 651f58c7f..bacb3d686 100644
--- a/tests/Frontend/e2e/RoomsViewGeneral.cy.js
+++ b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
@@ -2381,7 +2381,7 @@ describe("Room View general", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("joinMembershipRequest");
@@ -2394,7 +2394,7 @@ describe("Room View general", function () {
cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
// Reload room with user being a member of the room
@@ -2514,7 +2514,7 @@ describe("Room View general", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("endMembershipRequest");
@@ -2528,6 +2528,11 @@ describe("Room View general", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+
+ // Check that error message is shown
+ cy.checkToastMessage(
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
+ );
});
it("trigger favorites button", function () {
@@ -2726,7 +2731,7 @@ describe("Room View general", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("addFavoritesRequest");
@@ -2739,7 +2744,7 @@ describe("Room View general", function () {
cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
// Reload room but room is already in favorites
@@ -2842,7 +2847,7 @@ describe("Room View general", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("deleteFavoritesRequest");
@@ -2857,7 +2862,7 @@ describe("Room View general", function () {
cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewHistory.cy.js b/tests/Frontend/e2e/RoomsViewHistory.cy.js
index d1548e679..a5f1a4cc0 100644
--- a/tests/Frontend/e2e/RoomsViewHistory.cy.js
+++ b/tests/Frontend/e2e/RoomsViewHistory.cy.js
@@ -508,7 +508,7 @@ describe("Rooms view history", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomHistoryRequest");
@@ -519,7 +519,7 @@ describe("Rooms view history", function () {
// Check that redirect to 404 page works and that error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js b/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
index 40371d111..a1d999e81 100644
--- a/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
@@ -140,7 +140,7 @@ describe("Rooms view history meeting actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Meeting",
+ model: "meeting",
ids: ["3a3e504a-d2c4-431c-8ca1-a62598e66761"],
},
},
@@ -155,7 +155,7 @@ describe("Rooms view history meeting actions", function () {
// Check that error message is shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Meeting","ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
+ 'app.flash.model_not_found.meeting_{"ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
);
// Check if dialog is closed
@@ -478,7 +478,7 @@ describe("Rooms view history meeting actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Meeting",
+ model: "meeting",
ids: ["3a3e504a-d2c4-431c-8ca1-a62598e66761"],
},
},
@@ -493,7 +493,7 @@ describe("Rooms view history meeting actions", function () {
// Check that error message is shown
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Meeting","ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
+ 'app.flash.model_not_found.meeting_{"ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
);
// Check if dialog is closed
diff --git a/tests/Frontend/e2e/RoomsViewMeetings.cy.js b/tests/Frontend/e2e/RoomsViewMeetings.cy.js
index aafc2a32d..efc12ebf9 100644
--- a/tests/Frontend/e2e/RoomsViewMeetings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMeetings.cy.js
@@ -1366,7 +1366,7 @@ describe("Rooms view meetings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("joinRequest");
@@ -1388,7 +1388,7 @@ describe("Rooms view meetings", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -1557,7 +1557,7 @@ describe("Rooms view meetings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("preJoinRequest");
@@ -1569,7 +1569,7 @@ describe("Rooms view meetings", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -2953,7 +2953,7 @@ describe("Rooms view meetings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("startRequest");
@@ -2974,7 +2974,7 @@ describe("Rooms view meetings", function () {
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -3145,7 +3145,7 @@ describe("Rooms view meetings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("preStartRequest");
@@ -3158,7 +3158,7 @@ describe("Rooms view meetings", function () {
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewMembers.cy.js b/tests/Frontend/e2e/RoomsViewMembers.cy.js
index 4d4d459e3..1f4cea804 100644
--- a/tests/Frontend/e2e/RoomsViewMembers.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembers.cy.js
@@ -494,7 +494,7 @@ describe("Rooms view members", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomMembersRequest");
@@ -507,7 +507,7 @@ describe("Rooms view members", function () {
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
index 2261a03d5..290e89427 100644
--- a/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
@@ -425,7 +425,7 @@ describe("Rooms view members bulk actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("bulkEditRequest");
@@ -443,7 +443,7 @@ describe("Rooms view members bulk actions", function () {
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -736,7 +736,7 @@ describe("Rooms view members bulk actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("bulkDeleteRequest");
@@ -756,7 +756,7 @@ describe("Rooms view members bulk actions", function () {
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -1476,7 +1476,7 @@ describe("Rooms view members bulk actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("bulkImportRequest");
@@ -1498,7 +1498,7 @@ describe("Rooms view members bulk actions", function () {
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
index ba9cd1949..e3adede6d 100644
--- a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
@@ -456,7 +456,7 @@ describe("Rooms view members member actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("addUserRequest");
@@ -468,7 +468,7 @@ describe("Rooms view members member actions", function () {
// Check that user is redirected to 404 page and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -697,7 +697,7 @@ describe("Rooms view members member actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("editUserRequest");
@@ -709,7 +709,7 @@ describe("Rooms view members member actions", function () {
// Check that user is redirected to 404 page and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -895,7 +895,7 @@ describe("Rooms view members member actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("deleteMemberRequest");
@@ -907,7 +907,7 @@ describe("Rooms view members member actions", function () {
// Check that user is redirected to 404 page and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
index 95f1d2082..fefd7960b 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
@@ -513,7 +513,7 @@ describe("Rooms view personalized links", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
},
@@ -526,7 +526,7 @@ describe("Rooms view personalized links", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
index af6f97dda..5f4c7c9ac 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
@@ -247,7 +247,7 @@ describe("Rooms view personalized links actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("addLinkRequest");
@@ -263,7 +263,7 @@ describe("Rooms view personalized links actions", function () {
// Check that redirect to 404 page works and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -567,7 +567,7 @@ describe("Rooms view personalized links actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("editLinkRequest");
@@ -586,7 +586,7 @@ describe("Rooms view personalized links actions", function () {
// Check that redirect to 404 page works and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -794,7 +794,7 @@ describe("Rooms view personalized links actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("deleteLinkRequest");
@@ -813,7 +813,7 @@ describe("Rooms view personalized links actions", function () {
// Check that redirect to 404 page works and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewRecordings.cy.js b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
index 1de5fb405..7ec1a6800 100644
--- a/tests/Frontend/e2e/RoomsViewRecordings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
@@ -766,7 +766,7 @@ describe("Rooms view recordings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomRecordingsRequest");
@@ -780,7 +780,7 @@ describe("Rooms view recordings", function () {
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
index 592c7e30e..dd9b6c8be 100644
--- a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
@@ -879,7 +879,7 @@ describe("Rooms view recordings recording actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Recording",
+ model: "recording",
ids: ["f9569db6d5e8fb2fd2f57d367d5482b36837b9d8-1663666775"],
},
},
@@ -982,7 +982,7 @@ describe("Rooms view recordings recording actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
},
@@ -1003,7 +1003,7 @@ describe("Rooms view recordings recording actions", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -1376,7 +1376,7 @@ describe("Rooms view recordings recording actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
},
@@ -1397,7 +1397,7 @@ describe("Rooms view recordings recording actions", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewSettings.cy.js b/tests/Frontend/e2e/RoomsViewSettings.cy.js
index e99e27606..12c10b83c 100644
--- a/tests/Frontend/e2e/RoomsViewSettings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewSettings.cy.js
@@ -426,7 +426,7 @@ describe("Rooms view settings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomSettingsRequest");
@@ -438,7 +438,7 @@ describe("Rooms view settings", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -1744,7 +1744,7 @@ describe("Rooms view settings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomDeleteRequest");
@@ -1757,7 +1757,7 @@ describe("Rooms view settings", function () {
cy.wait("@roomDeleteRequest");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
// Reload room page
@@ -2308,7 +2308,7 @@ describe("Rooms view settings", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("transferOwnershipRequest");
@@ -2322,7 +2322,7 @@ describe("Rooms view settings", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewStreaming.cy.js b/tests/Frontend/e2e/RoomsViewStreaming.cy.js
index 6e10d107b..aa46a1af2 100644
--- a/tests/Frontend/e2e/RoomsViewStreaming.cy.js
+++ b/tests/Frontend/e2e/RoomsViewStreaming.cy.js
@@ -792,7 +792,7 @@ describe("Rooms view streaming", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomStreamingStatus");
@@ -804,7 +804,7 @@ describe("Rooms view streaming", function () {
cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js b/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
index 92905de5f..9de91ac25 100644
--- a/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
@@ -283,7 +283,7 @@ describe("Rooms view streaming config actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("roomStreamingConfig");
@@ -296,7 +296,7 @@ describe("Rooms view streaming config actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
@@ -625,7 +625,7 @@ describe("Rooms view streaming config actions", function () {
statusCode: 404,
body: {
message: "model_not_found",
- model: "Room",
+ model: "room",
ids: ["abc-def-123"],
},
}).as("saveConfigRequest");
@@ -644,7 +644,7 @@ describe("Rooms view streaming config actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
cy.checkToastMessage(
- 'app.flash.model_not_found_{"model":"Room","ids":"abc-def-123"}',
+ 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
);
});
diff --git a/tests/Frontend/fixtures/en.json b/tests/Frontend/fixtures/en.json
index 4e7bcd7a7..9c7aea205 100644
--- a/tests/Frontend/fixtures/en.json
+++ b/tests/Frontend/fixtures/en.json
@@ -1,5 +1,19 @@
{
- "data": {},
+ "data": {
+ "app": {
+ "flash": {
+ "model_not_found": {
+ "meeting": "app.flash.model_not_found.meeting_{\"ids\":\":ids\"}",
+ "role": "app.flash.model_not_found.role_{\"ids\":\":ids\"}",
+ "room": "app.flash.model_not_found.room_{\"ids\":\":ids\"}",
+ "room_type": "app.flash.model_not_found.room_type_{\"ids\":\":ids\"}",
+ "server": "app.flash.model_not_found.server_{\"ids\":\":ids\"}",
+ "server_pool": "app.flash.model_not_found.server_pool_{\"ids\":\":ids\"}",
+ "user": "app.flash.model_not_found.user_{\"ids\":\":ids\"}"
+ }
+ }
+ }
+ },
"meta": {
"dateTimeFormat": {
"dateShort": {
From 935d372363fba36b7ba2b2d6dc81d5e345860ecd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Sun, 22 Mar 2026 10:28:35 +0100
Subject: [PATCH 06/18] Start adjusting backend tests
---
.../Backend/Feature/api/v1/RecordingTest.php | 35 +++++++++-
tests/Backend/Feature/api/v1/RoleTest.php | 25 ++++++-
.../Backend/Feature/api/v1/Room/FileTest.php | 57 ++++++++++++++--
.../Feature/api/v1/Room/MembershipTest.php | 7 +-
.../api/v1/Room/RoomPersonalizedLinkTest.php | 68 ++++++++++++++++---
.../Backend/Feature/api/v1/Room/RoomTest.php | 53 +++++++++++++--
tests/Backend/Feature/api/v1/RoomTypeTest.php | 27 +++++++-
.../Backend/Feature/api/v1/ServerPoolTest.php | 27 +++++++-
tests/Backend/Feature/api/v1/ServerTest.php | 38 ++++++++++-
tests/Backend/Feature/api/v1/UserTest.php | 29 ++++++--
10 files changed, 329 insertions(+), 37 deletions(-)
diff --git a/tests/Backend/Feature/api/v1/RecordingTest.php b/tests/Backend/Feature/api/v1/RecordingTest.php
index 112042ed8..392582200 100644
--- a/tests/Backend/Feature/api/v1/RecordingTest.php
+++ b/tests/Backend/Feature/api/v1/RecordingTest.php
@@ -1093,6 +1093,17 @@ public function test_update()
$this->assertTrue($podcast->disabled);
$this->assertFalse($presentation->disabled);
$this->assertTrue($notes->disabled);
+
+ // Test deleted recording
+ $recording->delete();
+
+ $this->putJson(route('api.v1.rooms.recordings.update', ['room' => $room->id, 'recording' => $recording->id]), $payload)
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'recording',
+ 'ids' => [$recording->id],
+ ]);
}
public function test_update_permissions()
@@ -1190,7 +1201,12 @@ public function test_update_invalid_data()
$otherRoom = Room::factory()->create();
$this->actingAs($otherRoom->owner)
->putJson(route('api.v1.rooms.recordings.update', ['room' => $otherRoom->id, 'recording' => $recording->id]), $payload)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'recording',
+ 'ids' => [$recording->id],
+ ]);
}
@@ -1222,6 +1238,16 @@ public function test_delete()
// Check storage
$this->assertDirectoryDoesNotExist(Storage::disk('recordings')->path($recording->id));
+
+ // Test delete again
+ $this->actingAs($room->owner)
+ ->deleteJson(route('api.v1.rooms.recordings.destroy', ['room' => $room->id, 'recording' => $recording->id]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'recording',
+ 'ids' => [$recording->id],
+ ]);
}
public function test_delete_on_room_delete()
@@ -1319,7 +1345,12 @@ public function test_delete_invalid_data()
$otherRoom = Room::factory()->create();
$this->actingAs($otherRoom->owner)
->deleteJson(route('api.v1.rooms.recordings.destroy', ['room' => $otherRoom->id, 'recording' => $recording->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'recording',
+ 'ids' => [$recording->id],
+ ]);
}
public function test_access_recording_resource()
diff --git a/tests/Backend/Feature/api/v1/RoleTest.php b/tests/Backend/Feature/api/v1/RoleTest.php
index fbb05f92a..00132090b 100644
--- a/tests/Backend/Feature/api/v1/RoleTest.php
+++ b/tests/Backend/Feature/api/v1/RoleTest.php
@@ -239,6 +239,17 @@ public function test_update()
$this->putJson(route('api.v1.roles.update', ['role' => $role]), $changes)
->assertUnprocessable()
->assertJsonValidationErrors(['permissions', 'name', 'room_limit']);
+
+ // Test deleted
+ $role->delete();
+
+ $this->putJson(route('api.v1.roles.update', ['role' => $role]), $changes)
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'role',
+ 'ids' => [$role->id],
+ ]);
}
public function test_update_permission_lost()
@@ -324,7 +335,13 @@ public function test_show()
$roleB->permissions()->attach($permission->id);
$this->actingAs($user)->getJson(route('api.v1.roles.show', ['role' => self::INVALID_ID]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'role',
+ 'ids' => [self::INVALID_ID],
+ ]);
+
$this->getJson(route('api.v1.roles.show', ['role' => $roleA]))
->assertStatus(200)
->assertJsonFragment([
@@ -356,7 +373,11 @@ public function test_delete()
$superuserRole->permissions()->attach($permission->id);
$role->permissions()->attach($permission->id);
- $this->deleteJson(route('api.v1.roles.destroy', ['role' => self::INVALID_ID]))->assertNotFound();
+ $this->deleteJson(route('api.v1.roles.destroy', ['role' => self::INVALID_ID]))->assertNotFound()->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'role',
+ 'ids' => [self::INVALID_ID],
+ ]);
// check if superuser role cannot be deleted
$this->deleteJson(route('api.v1.roles.destroy', ['role' => $superuserRole]))->assertStatus(403);
diff --git a/tests/Backend/Feature/api/v1/Room/FileTest.php b/tests/Backend/Feature/api/v1/Room/FileTest.php
index 011dbe49c..69ace11a4 100644
--- a/tests/Backend/Feature/api/v1/Room/FileTest.php
+++ b/tests/Backend/Feature/api/v1/Room/FileTest.php
@@ -1077,7 +1077,14 @@ public function test_files_delete()
// Testing delete again
$this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.files.destroy', ['room' => $this->room->id, 'file' => $room_file]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => [
+ $room_file->id,
+ ],
+ ]);
// Check if file was deleted as well
Storage::disk('local')->assertMissing($this->room->id.'/'.$this->file_valid->hashName());
@@ -1128,13 +1135,27 @@ public function test_delete_file_url_manipulation()
// Testing for room without permission
$this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.files.destroy', ['room' => $other_room->id, 'file' => $room_file]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => [
+ $room_file->id,
+ ],
+ ]);
// Testing for room with permission
$other_room->owner()->associate($this->room->owner);
$other_room->save();
$this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.files.destroy', ['room' => $other_room->id, 'file' => $room_file]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => [
+ $room_file->id,
+ ],
+ ]);
}
/**
@@ -1212,13 +1233,27 @@ public function test_update_file()
$other_room = Room::factory()->create();
// Testing for room without permission
$this->actingAs($this->room->owner)->putJson(route('api.v1.rooms.files.update', ['room' => $other_room->id, 'file' => $room_file]), $params)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => [
+ $room_file->id,
+ ],
+ ]);
// Testing for room with permission
$other_room->owner()->associate($this->room->owner);
$other_room->save();
$this->actingAs($this->room->owner)->putJson(route('api.v1.rooms.files.update', ['room' => $other_room->id, 'file' => $room_file]), $params)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => [
+ $room_file->id,
+ ],
+ ]);
// Testing missing properties
$params = [];
@@ -1234,6 +1269,18 @@ public function test_update_file()
$this->actingAs($this->room->owner)->putJson($route, $params)
->assertJsonValidationErrors(['use_in_meeting', 'download', 'default']);
+
+ // Test deleted
+ $room_file->delete();
+ $this->actingAs($this->room->owner)->putJson($route, $params)
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => [
+ $room_file->id,
+ ],
+ ]);
}
/**
diff --git a/tests/Backend/Feature/api/v1/Room/MembershipTest.php b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
index f85ccb67d..b6f204620 100644
--- a/tests/Backend/Feature/api/v1/Room/MembershipTest.php
+++ b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
@@ -781,7 +781,12 @@ public function test_remove_member()
// Remove member with invalid user
$this->actingAs($owner)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => 0]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [0],
+ ]);
// Remove member as moderator
$this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
diff --git a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
index 5373cff64..d9e401537 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
@@ -100,7 +100,12 @@ public function test_index()
// Testing owner
$this->actingAs($this->room->owner)->getJson(route('api.v1.rooms.personalizedLinks.get', ['room' => 1337]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [1337],
+ ]);
$this->actingAs($this->room->owner)->getJson(route('api.v1.rooms.personalizedLinks.get', ['room' => $this->room]))
->assertSuccessful()
@@ -246,7 +251,14 @@ public function test_create()
// Create as moderator
$this->room->members()->sync([$this->user->id => ['role' => RoomUserRole::MODERATOR]]);
$this->actingAs($this->user)->postJson(route('api.v1.rooms.personalizedLinks.add', ['room' => 1337]), $payload)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [1337],
+ ]
+ );
$this->actingAs($this->user)->postJson(route('api.v1.rooms.personalizedLinks.add', ['room' => $this->room]), $payload)
->assertForbidden();
@@ -340,7 +352,14 @@ public function test_update()
// Update as moderator
$this->room->members()->sync([$this->user->id => ['role' => RoomUserRole::MODERATOR]]);
$this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => 1337, 'link' => $link]), $payload)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [1337],
+ ]);
+
$this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
->assertForbidden();
@@ -401,7 +420,19 @@ public function test_update()
// Check trying to update with wrong room id
$this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $otherRoom, 'link' => $link]), $payload)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJsonFragment(['message' => __('app.errors.personalized_link_not_found')]);
+
+ // Test deleted
+ $link->delete();
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room_personalized_link',
+ 'ids' => [$link->id],
+ ]);
}
public function test_delete()
@@ -452,7 +483,13 @@ public function test_delete()
// Delete not existing
$this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room_personalized_link',
+ 'ids' => [$link->id],
+ ]);
// Delete as owner
$link = RoomPersonalizedLink::factory()->create([
@@ -461,7 +498,13 @@ public function test_delete()
$this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
->assertSuccessful();
$this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room_personalized_link',
+ 'ids' => [$link->id],
+ ]);
// Delete with viewAllPermission
$this->room->members()->sync([]);
@@ -472,11 +515,20 @@ public function test_delete()
// Check trying to delete with wrong room id
$this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $otherRoom, 'link' => $link]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJsonFragment(['message' => __('app.errors.personalized_link_not_found')]);
$this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
->assertSuccessful();
+
+ // Test delete again
$this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room_personalized_link',
+ 'ids' => [$link->id],
+ ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/Room/RoomTest.php b/tests/Backend/Feature/api/v1/Room/RoomTest.php
index 3b1ad7ef9..f678d25ab 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomTest.php
@@ -290,7 +290,12 @@ public function test_delete_room()
// Try again after deleted
$this->actingAs($this->user)->deleteJson(route('api.v1.rooms.destroy', ['room' => $room]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
public function test_transfer_room()
@@ -431,7 +436,12 @@ public function test_room_404_rate_limit()
// Guest trying to access non-existing rooms
for ($i = 0; $i < 10; $i++) {
$this->getJson(route('api.v1.rooms.show', ['room' => 999999]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [999999],
+ ]);
}
// Check route is now rate limited
$this->getJson(route('api.v1.rooms.show', ['room' => 999999]))
@@ -446,7 +456,12 @@ public function test_room_404_rate_limit()
$this->actingAs($room->owner);
for ($i = 0; $i < 10; $i++) {
$this->getJson(route('api.v1.rooms.show', ['room' => 999999]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [999999],
+ ]);
}
// Check route is now rate limited
$this->getJson(route('api.v1.rooms.show', ['room' => 999999]))
@@ -462,11 +477,21 @@ public function test_room_404_rate_limit()
// Time travel 1 minute to reset rate limit
$this->travel(1)->minutes();
$this->getJson(route('api.v1.rooms.show', ['room' => 999999]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [999999],
+ ]);
$this->actingAsGuest();
$this->getJson(route('api.v1.rooms.show', ['room' => 999999]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [999999],
+ ]);
// Time travel 1 minute to reset rate limit
$this->travel(1)->minutes();
@@ -475,7 +500,12 @@ public function test_room_404_rate_limit()
// due to other reasons than the room not existing are not so strictly rate limited
for ($i = 0; $i < 50; $i++) {
$this->actingAs($room->owner)->putJson(route('api.v1.rooms.files.update', ['room' => $room, 'file' => 999999]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_file',
+ 'ids' => ['999999'],
+ ]);
}
}
@@ -1637,6 +1667,17 @@ public function test_room_view()
$room->save();
$this->actingAs($this->user)->getJson(route('api.v1.rooms.show', ['room' => $room]))
->assertJsonPath('data.legacy_code', false);
+
+ // Test deleted
+ $room->delete();
+
+ $this->actingAs($this->user)->getJson(route('api.v1.rooms.show', ['room' => $room]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
/**
diff --git a/tests/Backend/Feature/api/v1/RoomTypeTest.php b/tests/Backend/Feature/api/v1/RoomTypeTest.php
index 2555ba999..0e5710eb6 100644
--- a/tests/Backend/Feature/api/v1/RoomTypeTest.php
+++ b/tests/Backend/Feature/api/v1/RoomTypeTest.php
@@ -325,7 +325,14 @@ public function test_show()
// Test deleted
$roomType->delete();
$this->actingAs($this->user)->getJson(route('api.v1.roomTypes.show', ['roomType' => $roomType->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_type',
+ 'ids' => [
+ $roomType->id,
+ ],
+ ]);
}
/**
@@ -895,7 +902,14 @@ public function test_update()
// Test deleted
$roomType->delete();
$this->actingAs($this->user)->putJson(route('api.v1.roomTypes.update', ['roomType' => $roomType->id]), $data)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_type',
+ 'ids' => [
+ $roomType->id,
+ ],
+ ]);
}
/**
@@ -925,7 +939,14 @@ public function test_delete()
// Test delete again
$this->actingAs($this->user)->deleteJson(route('api.v1.roomTypes.destroy', ['roomType' => $roomType->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room_type',
+ 'ids' => [
+ $roomType->id,
+ ],
+ ]);
$this->assertDatabaseMissing('room_types', ['id' => $roomType->id]);
diff --git a/tests/Backend/Feature/api/v1/ServerPoolTest.php b/tests/Backend/Feature/api/v1/ServerPoolTest.php
index 79c321daa..dfd0c458f 100644
--- a/tests/Backend/Feature/api/v1/ServerPoolTest.php
+++ b/tests/Backend/Feature/api/v1/ServerPoolTest.php
@@ -169,7 +169,14 @@ public function test_show()
// Test deleted
$serverPool->delete();
$this->actingAs($this->user)->getJson(route('api.v1.serverPools.show', ['serverPool' => $serverPool->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server_pool',
+ 'ids' => [
+ $serverPool->id,
+ ],
+ ]);
}
/**
@@ -335,7 +342,14 @@ public function test_update()
// Test deleted
$serverPool->delete();
$this->actingAs($this->user)->putJson(route('api.v1.serverPools.update', ['serverPool' => $serverPool->id]), $data)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server_pool',
+ 'ids' => [
+ $serverPool->id,
+ ],
+ ]);
}
/**
@@ -374,7 +388,14 @@ public function test_delete()
// Test delete again
$this->actingAs($this->user)->deleteJson(route('api.v1.serverPools.destroy', ['serverPool' => $serverPool->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server_pool',
+ 'ids' => [
+ $serverPool->id,
+ ],
+ ]);
$this->assertDatabaseMissing('servers', ['id' => $serverPool->id]);
}
diff --git a/tests/Backend/Feature/api/v1/ServerTest.php b/tests/Backend/Feature/api/v1/ServerTest.php
index d1ba38888..9f8ab50ef 100644
--- a/tests/Backend/Feature/api/v1/ServerTest.php
+++ b/tests/Backend/Feature/api/v1/ServerTest.php
@@ -243,7 +243,12 @@ public function test_show()
$server->save();
$server->delete();
$this->actingAs($this->user)->getJson(route('api.v1.servers.show', ['server' => $server->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server',
+ 'ids' => [$server->id],
+ ]);
}
/**
@@ -390,7 +395,12 @@ public function test_update()
$server->save();
$server->delete();
$this->actingAs($this->user)->putJson(route('api.v1.servers.update', ['server' => $server->id]), $data)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server',
+ 'ids' => [$server->id],
+ ]);
}
/**
@@ -439,7 +449,12 @@ public function test_delete()
// Test delete again
$this->actingAs($this->user)->deleteJson(route('api.v1.servers.destroy', ['server' => $server->id]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server',
+ 'ids' => [$server->id],
+ ]);
$this->assertDatabaseMissing('servers', ['id' => $server->id]);
}
@@ -542,5 +557,22 @@ public function test_panic()
$this->assertEquals(ServerStatus::DISABLED, $server->status);
$this->assertNull($meeting->end);
+
+ // Test deleted
+ $server->status = ServerStatus::DISABLED;
+ $server->save();
+
+ $meeting->end = date('Y-m-d H:i:s');
+ $meeting->save();
+
+ $server->delete();
+
+ $this->actingAs($this->user)->postJson(route('api.v1.servers.panic', ['server' => $server->id]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'server',
+ 'ids' => [$server->id],
+ ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/UserTest.php b/tests/Backend/Feature/api/v1/UserTest.php
index 4fa30b758..3aedd58b6 100644
--- a/tests/Backend/Feature/api/v1/UserTest.php
+++ b/tests/Backend/Feature/api/v1/UserTest.php
@@ -537,7 +537,13 @@ public function test_update()
// Not existing user
$this->actingAs($admin)->putJson(route('api.v1.users.update', ['user' => self::INVALID_ID]), $changes)
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [self::INVALID_ID],
+ ]
+ );
// Check as admin
$changes['updated_at'] = Carbon::now();
@@ -1417,7 +1423,12 @@ public function test_show()
$role->users()->attach([$externalUser->id, $user->id]);
$this->actingAs($user)->getJson(route('api.v1.users.show', ['user' => self::INVALID_ID]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [self::INVALID_ID],
+ ]);
// Existing user
$this->actingAs($user)->getJson(route('api.v1.users.show', ['user' => $externalUser]))
@@ -1481,7 +1492,12 @@ public function test_delete()
->assertForbidden();
// Not existing model
- $this->actingAs($user)->deleteJson(route('api.v1.users.destroy', ['user' => self::INVALID_ID]))->assertNotFound();
+ $this->actingAs($user)->deleteJson(route('api.v1.users.destroy', ['user' => self::INVALID_ID]))->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [self::INVALID_ID],
+ ]);
// User own model
$this->actingAs($user)->deleteJson(route('api.v1.users.destroy', ['user' => $user]))
@@ -1560,7 +1576,12 @@ public function test_reset_password()
$role->users()->attach([$user->id]);
$this->actingAs($user)->postJson(route('api.v1.users.password.reset', ['user' => self::INVALID_ID]))
- ->assertNotFound();
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [self::INVALID_ID],
+ ]);
$this->actingAs($user)->postJson(route('api.v1.users.password.reset', ['user' => $user]))
->assertForbidden();
From 7a96b9cd87384102add77b828d8b4e747e3d10c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Tue, 31 Mar 2026 13:46:40 +0200
Subject: [PATCH 07/18] Continue improving not found error handling and
frontend tests
---
lang/en/app.php | 17 +--
resources/js/components/RoomCard.vue | 2 +
resources/js/components/RoomDeleteButton.vue | 5 +-
.../js/components/RoomFavoriteButton.vue | 3 +-
resources/js/components/RoomHeader.vue | 1 -
resources/js/components/RoomJoinButton.vue | 4 +-
.../js/components/RoomMembershipButton.vue | 10 +-
.../js/components/RoomTabDescription.vue | 5 +-
resources/js/components/RoomTabFiles.vue | 5 +-
.../components/RoomTabFilesDeleteButton.vue | 5 +-
.../js/components/RoomTabFilesEditButton.vue | 5 +-
.../components/RoomTabFilesUploadButton.vue | 5 +-
resources/js/components/RoomTabHistory.vue | 5 +-
resources/js/components/RoomTabMembers.vue | 5 +-
.../RoomTabMembersAddSingleModal.vue | 5 +-
.../RoomTabMembersBulkDeleteButton.vue | 5 +-
.../RoomTabMembersBulkEditButton.vue | 5 +-
.../RoomTabMembersBulkImportModal.vue | 5 +-
.../components/RoomTabMembersDeleteButton.vue | 5 +-
.../components/RoomTabMembersEditButton.vue | 5 +-
.../components/RoomTabPersonalizedLinks.vue | 5 +-
.../RoomTabPersonalizedLinksAddButton.vue | 5 +-
.../RoomTabPersonalizedLinksDeleteButton.vue | 5 +-
.../RoomTabPersonalizedLinksEditButton.vue | 5 +-
resources/js/components/RoomTabRecordings.vue | 5 +-
.../RoomTabRecordingsDeleteButton.vue | 5 +-
.../RoomTabRecordingsEditButton.vue | 5 +-
resources/js/components/RoomTabSettings.vue | 5 +-
resources/js/components/RoomTabStreaming.vue | 2 +-
.../RoomTabStreamingConfigButton.vue | 4 +-
.../RoomTransferOwnershipButton.vue | 5 +-
resources/js/services/Api.js | 23 ++--
resources/js/views/RoomsView.vue | 23 +++-
tests/Frontend/e2e/AdminRolesEdit.cy.js | 16 ++-
.../e2e/AdminRolesIndexRoleActions.cy.js | 5 +-
tests/Frontend/e2e/AdminRolesView.cy.js | 8 +-
.../e2e/AdminRolesViewRoleActions.cy.js | 5 +-
tests/Frontend/e2e/AdminRoomTypesEdit.cy.js | 16 ++-
.../AdminRoomTypesIndexRoomTypeActions.cy.js | 5 +-
tests/Frontend/e2e/AdminRoomTypesView.cy.js | 8 +-
.../AdminRoomTypesViewRoomTypeActions.cy.js | 5 +-
tests/Frontend/e2e/AdminServerPoolsEdit.cy.js | 16 ++-
...minServerPoolsIndexServerPoolActions.cy.js | 6 +-
tests/Frontend/e2e/AdminServerPoolsView.cy.js | 8 +-
...dminServerPoolsViewServerPoolActions.cy.js | 5 +-
tests/Frontend/e2e/AdminServersEdit.cy.js | 16 ++-
.../e2e/AdminServersIndexServerActions.cy.js | 5 +-
tests/Frontend/e2e/AdminServersView.cy.js | 9 +-
.../e2e/AdminServersViewServerActions.cy.js | 33 +++++-
tests/Frontend/e2e/AdminUsersEdit.cy.js | 8 +-
tests/Frontend/e2e/AdminUsersEditBase.cy.js | 8 +-
tests/Frontend/e2e/AdminUsersEditEmail.cy.js | 8 +-
tests/Frontend/e2e/AdminUsersEditOthers.cy.js | 8 +-
.../Frontend/e2e/AdminUsersEditSecurity.cy.js | 16 ++-
.../e2e/AdminUsersIndexUserActions.cy.js | 6 +-
tests/Frontend/e2e/AdminUsersView.cy.js | 8 +-
.../e2e/AdminUsersViewUserActions.cy.js | 10 +-
tests/Frontend/e2e/RoomsViewDescription.cy.js | 14 ++-
tests/Frontend/e2e/RoomsViewFiles.cy.js | 15 ++-
.../e2e/RoomsViewFilesFileActions.cy.js | 39 ++++---
tests/Frontend/e2e/RoomsViewGeneral.cy.js | 109 +++++++++++++++---
tests/Frontend/e2e/RoomsViewHistory.cy.js | 15 ++-
.../e2e/RoomsViewHistoryMeetingActions.cy.js | 14 ++-
tests/Frontend/e2e/RoomsViewMeetings.cy.js | 55 +++++----
tests/Frontend/e2e/RoomsViewMembers.cy.js | 14 ++-
.../e2e/RoomsViewMembersBulkActions.cy.js | 44 ++++---
.../e2e/RoomsViewMembersMemberActions.cy.js | 50 +++++---
.../e2e/RoomsViewPersonalizedLinks.cy.js | 16 ++-
...omsViewPersonalizedLinksTokenActions.cy.js | 48 +++++---
tests/Frontend/e2e/RoomsViewRecordings.cy.js | 15 ++-
.../RoomsViewRecordingsRecordingActions.cy.js | 32 +++--
tests/Frontend/e2e/RoomsViewSettings.cy.js | 78 ++++++++++---
tests/Frontend/e2e/RoomsViewStreaming.cy.js | 15 ++-
.../e2e/RoomsViewStreamingConfigActions.cy.js | 28 +++--
tests/Frontend/fixtures/en.json | 16 +--
75 files changed, 670 insertions(+), 389 deletions(-)
diff --git a/lang/en/app.php b/lang/en/app.php
index 0b9adc4ed..68b020ab1 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -65,14 +65,8 @@
'client_error' => 'An unknown error occurred in the application!',
'guests_only' => 'The request can only be made by guests!',
'model_not_found' => [
- 'fallback' => 'The :model with the id :ids was not found!',
- 'meeting' => 'The meeting with the id :ids was not found!',
- 'role' => 'The role with the id :ids was not found!',
- 'room' => 'The room with the id :ids was not found!',
- 'room_type' => 'The room type with the id :ids was not found!',
- 'server' => 'The server with the id :ids was not found!',
- 'server_pool' => 'The server pool with the id :ids was not found!',
- 'user' => 'The user with the id :ids was not found!',
+ 'title' => 'The :model was not found!',
+ 'details' => ' Model ids: :ids',
],
'server_error' => [
'empty_message' => 'An error occurred on the server during request!',
@@ -105,10 +99,17 @@
'fr' => 'French',
],
'model' => [
+ 'meeting' => 'meeting',
+ 'role' => 'Role',
'roles' => 'role',
+ 'room' => 'Room',
+ 'room_type' => 'Room type',
'room_types' => 'room type',
+ 'server' => 'Server',
+ 'server_pool' => 'Server pool',
'server_pools' => 'server pool',
'servers' => 'server',
+ 'user' => 'User',
'users' => 'user',
],
'model_name' => 'Name',
diff --git a/resources/js/components/RoomCard.vue b/resources/js/components/RoomCard.vue
index af48193fe..93617d18d 100644
--- a/resources/js/components/RoomCard.vue
+++ b/resources/js/components/RoomCard.vue
@@ -35,6 +35,7 @@
@@ -72,6 +73,7 @@
diff --git a/resources/js/components/RoomDeleteButton.vue b/resources/js/components/RoomDeleteButton.vue
index ed0812eef..66e70631b 100644
--- a/resources/js/components/RoomDeleteButton.vue
+++ b/resources/js/components/RoomDeleteButton.vue
@@ -90,10 +90,7 @@ function deleteRoom() {
})
.catch((error) => {
isLoadingAction.value = false;
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
});
}
diff --git a/resources/js/components/RoomFavoriteButton.vue b/resources/js/components/RoomFavoriteButton.vue
index 1cd422a2f..2cf490b75 100644
--- a/resources/js/components/RoomFavoriteButton.vue
+++ b/resources/js/components/RoomFavoriteButton.vue
@@ -35,7 +35,7 @@ const props = defineProps({
},
redirectOnRoomModelNotFound: {
type: Boolean,
- default: false,
+ default: true,
},
});
@@ -60,6 +60,7 @@ function toggleFavorite() {
.call("rooms/" + props.room.id + "/favorites", config)
.catch((error) => {
api.error(error, {
+ // ToDo emit notFound on not found error and handle it in index page (Reload room list)
redirectOnUnauthenticated: props.redirectOnUnauthenticated,
redirectOnRoomModelNotFound: props.redirectOnRoomModelNotFound,
});
diff --git a/resources/js/components/RoomHeader.vue b/resources/js/components/RoomHeader.vue
index e0a87fb68..4f1ea5735 100644
--- a/resources/js/components/RoomHeader.vue
+++ b/resources/js/components/RoomHeader.vue
@@ -33,7 +33,6 @@
v-if="!hideFavorites && authStore.isAuthenticated"
:room="props.room"
:redirect-on-unauthenticated="false"
- :redirect-on-room-model-not-found="true"
@favorites-changed="emit('reload')"
/>
{
isLoadingAction.value = false;
@@ -156,10 +153,7 @@ function leaveMembership() {
modalVisible.value = false;
})
.catch((error) => {
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabDescription.vue b/resources/js/components/RoomTabDescription.vue
index 583b8e113..bb0eeef14 100644
--- a/resources/js/components/RoomTabDescription.vue
+++ b/resources/js/components/RoomTabDescription.vue
@@ -229,10 +229,7 @@ function save() {
editorOpen.value = false;
}
// Handle other errors
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
// Disable saving indicator
diff --git a/resources/js/components/RoomTabFiles.vue b/resources/js/components/RoomTabFiles.vue
index 8fc21ff94..e00bf354a 100644
--- a/resources/js/components/RoomTabFiles.vue
+++ b/resources/js/components/RoomTabFiles.vue
@@ -425,10 +425,7 @@ function loadData(page = null) {
return emit("invalidRoomAuthToken");
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
paginator.revertFirst();
loadingError.value = true;
})
diff --git a/resources/js/components/RoomTabFilesDeleteButton.vue b/resources/js/components/RoomTabFilesDeleteButton.vue
index a05f61978..28f0aeefb 100644
--- a/resources/js/components/RoomTabFilesDeleteButton.vue
+++ b/resources/js/components/RoomTabFilesDeleteButton.vue
@@ -112,10 +112,7 @@ function deleteFile() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabFilesEditButton.vue b/resources/js/components/RoomTabFilesEditButton.vue
index 4f2d2f074..d7901b305 100644
--- a/resources/js/components/RoomTabFilesEditButton.vue
+++ b/resources/js/components/RoomTabFilesEditButton.vue
@@ -211,10 +211,7 @@ function save() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabFilesUploadButton.vue b/resources/js/components/RoomTabFilesUploadButton.vue
index 599e76fa4..c65a8018d 100644
--- a/resources/js/components/RoomTabFilesUploadButton.vue
+++ b/resources/js/components/RoomTabFilesUploadButton.vue
@@ -265,10 +265,7 @@ function uploadFile(file) {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
});
}
diff --git a/resources/js/components/RoomTabHistory.vue b/resources/js/components/RoomTabHistory.vue
index c0a6424f0..c4efa78e0 100644
--- a/resources/js/components/RoomTabHistory.vue
+++ b/resources/js/components/RoomTabHistory.vue
@@ -298,10 +298,7 @@ function loadData(page = null) {
})
.catch((error) => {
paginator.revertFirst();
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabMembers.vue b/resources/js/components/RoomTabMembers.vue
index 031521eec..184c344b0 100644
--- a/resources/js/components/RoomTabMembers.vue
+++ b/resources/js/components/RoomTabMembers.vue
@@ -377,10 +377,7 @@ function loadData(page = null) {
})
.catch((error) => {
paginator.revertFirst();
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabMembersAddSingleModal.vue b/resources/js/components/RoomTabMembersAddSingleModal.vue
index 318d72781..1ef150ca7 100644
--- a/resources/js/components/RoomTabMembersAddSingleModal.vue
+++ b/resources/js/components/RoomTabMembersAddSingleModal.vue
@@ -239,10 +239,7 @@ function save() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersBulkDeleteButton.vue b/resources/js/components/RoomTabMembersBulkDeleteButton.vue
index f3dd54e1e..077b18b1a 100644
--- a/resources/js/components/RoomTabMembersBulkDeleteButton.vue
+++ b/resources/js/components/RoomTabMembersBulkDeleteButton.vue
@@ -130,10 +130,7 @@ function deleteMembers() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersBulkEditButton.vue b/resources/js/components/RoomTabMembersBulkEditButton.vue
index 1f13795f8..273951c3c 100644
--- a/resources/js/components/RoomTabMembersBulkEditButton.vue
+++ b/resources/js/components/RoomTabMembersBulkEditButton.vue
@@ -168,10 +168,7 @@ function save() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersBulkImportModal.vue b/resources/js/components/RoomTabMembersBulkImportModal.vue
index 546f1a5af..aeb8a9983 100644
--- a/resources/js/components/RoomTabMembersBulkImportModal.vue
+++ b/resources/js/components/RoomTabMembersBulkImportModal.vue
@@ -341,10 +341,7 @@ function importUsers(firstRound = false) {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersDeleteButton.vue b/resources/js/components/RoomTabMembersDeleteButton.vue
index 62c86c173..cf30ba516 100644
--- a/resources/js/components/RoomTabMembersDeleteButton.vue
+++ b/resources/js/components/RoomTabMembersDeleteButton.vue
@@ -111,10 +111,7 @@ function deleteMember() {
modalVisible.value = false;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabMembersEditButton.vue b/resources/js/components/RoomTabMembersEditButton.vue
index 098b2812c..8a02bed35 100644
--- a/resources/js/components/RoomTabMembersEditButton.vue
+++ b/resources/js/components/RoomTabMembersEditButton.vue
@@ -178,10 +178,7 @@ function save() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinks.vue b/resources/js/components/RoomTabPersonalizedLinks.vue
index 5fac0e884..0a752d5b5 100644
--- a/resources/js/components/RoomTabPersonalizedLinks.vue
+++ b/resources/js/components/RoomTabPersonalizedLinks.vue
@@ -317,10 +317,7 @@ function loadData(page = null) {
})
.catch((error) => {
paginator.revertFirst();
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabPersonalizedLinksAddButton.vue b/resources/js/components/RoomTabPersonalizedLinksAddButton.vue
index e882dae91..2fbef8be3 100644
--- a/resources/js/components/RoomTabPersonalizedLinksAddButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksAddButton.vue
@@ -171,10 +171,7 @@ function save() {
) {
formErrors.set(error.response.data.errors);
} else {
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
}
})
.finally(() => {
diff --git a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
index 1def73a01..384cf69d1 100644
--- a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
@@ -131,10 +131,7 @@ function deleteLink() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
index 768956560..8b5b54bef 100644
--- a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
@@ -204,10 +204,7 @@ function save() {
formErrors.set(error.response.data.errors);
return;
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
}
})
.finally(() => {
diff --git a/resources/js/components/RoomTabRecordings.vue b/resources/js/components/RoomTabRecordings.vue
index 12294a175..76dd9ada9 100644
--- a/resources/js/components/RoomTabRecordings.vue
+++ b/resources/js/components/RoomTabRecordings.vue
@@ -440,10 +440,7 @@ function loadData(page = null) {
}
loadingError.value = true;
paginator.revertFirst();
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isBusy.value = false;
diff --git a/resources/js/components/RoomTabRecordingsDeleteButton.vue b/resources/js/components/RoomTabRecordingsDeleteButton.vue
index a3c7abf0f..0a1b96d01 100644
--- a/resources/js/components/RoomTabRecordingsDeleteButton.vue
+++ b/resources/js/components/RoomTabRecordingsDeleteButton.vue
@@ -107,10 +107,7 @@ function deleteRecording() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabRecordingsEditButton.vue b/resources/js/components/RoomTabRecordingsEditButton.vue
index 2dfcfb140..ea677de43 100644
--- a/resources/js/components/RoomTabRecordingsEditButton.vue
+++ b/resources/js/components/RoomTabRecordingsEditButton.vue
@@ -252,10 +252,7 @@ function save() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/components/RoomTabSettings.vue b/resources/js/components/RoomTabSettings.vue
index 24f20c6ad..2b03e4877 100644
--- a/resources/js/components/RoomTabSettings.vue
+++ b/resources/js/components/RoomTabSettings.vue
@@ -429,10 +429,7 @@ function load() {
loaded.value = true;
})
.catch((error) => {
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
loadingError.value = true;
})
.finally(() => {
diff --git a/resources/js/components/RoomTabStreaming.vue b/resources/js/components/RoomTabStreaming.vue
index 14f9d0f76..37d527e84 100644
--- a/resources/js/components/RoomTabStreaming.vue
+++ b/resources/js/components/RoomTabStreaming.vue
@@ -170,7 +170,7 @@ async function streamingCommand(command) {
if (error.response.status === env.HTTP_ROOM_NOT_RUNNING) {
emit("settingsChanged");
}
- api.error(error, { redirectOnRoomModelNotFound: true });
+ api.error(error);
})
.finally(() => {
autoReload();
diff --git a/resources/js/components/RoomTabStreamingConfigButton.vue b/resources/js/components/RoomTabStreamingConfigButton.vue
index 36158d370..9a34fd515 100644
--- a/resources/js/components/RoomTabStreamingConfigButton.vue
+++ b/resources/js/components/RoomTabStreamingConfigButton.vue
@@ -228,7 +228,7 @@ function loadConfig() {
response.data.data.system_default_pause_image;
})
.catch((error) => {
- api.error(error, { redirectOnRoomModelNotFound: true });
+ api.error(error);
modelLoadingError.value = true;
})
.finally(() => {
@@ -272,7 +272,7 @@ function save() {
) {
formErrors.set(error.response.data.errors);
} else {
- api.error(error, { redirectOnRoomModelNotFound: true });
+ api.error(error);
}
})
.finally(() => {
diff --git a/resources/js/components/RoomTransferOwnershipButton.vue b/resources/js/components/RoomTransferOwnershipButton.vue
index 9e22b4269..641abd82c 100644
--- a/resources/js/components/RoomTransferOwnershipButton.vue
+++ b/resources/js/components/RoomTransferOwnershipButton.vue
@@ -235,10 +235,7 @@ function transferOwnership() {
return;
}
}
- api.error(error, {
- redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
- });
+ api.error(error, { redirectOnUnauthenticated: false });
})
.finally(() => {
isLoadingAction.value = false;
diff --git a/resources/js/services/Api.js b/resources/js/services/Api.js
index 8943da5f4..bea55edb2 100644
--- a/resources/js/services/Api.js
+++ b/resources/js/services/Api.js
@@ -17,7 +17,6 @@ export class Api {
this.router = useRouter();
this.toast = useToast();
this.t = i18n.global.t;
- this.te = i18n.global.te;
}
/**
@@ -126,19 +125,21 @@ export class Api {
const model = data?.model;
const ids = data?.ids;
- if (model === ROOM_MODEL && options.redirectOnRoomModelNotFound === true) {
- this.router.push({ name: "404" });
+ if (model === ROOM_MODEL && options.redirectOnRoomModelNotFound !== false) {
+ // Redirect to room index page if user is authenticated, otherwise show 404 page, because
+ // unauthenticated user is not able to visit the room index page
+ if (this.auth.isAuthenticated) {
+ this.router.push({ name: "rooms.index" });
+ } else {
+ this.router.push({ name: "404" });
+ }
}
this.toast.error(
- this.te("app.flash.model_not_found." + model)
- ? this.t("app.flash.model_not_found." + model, {
- ids: ids ? `${ids.join(", ")}` : "",
- })
- : this.t("app.flash.model_not_found.fallback", {
- model: model,
- ids: ids ? `${ids.join(", ")}` : "",
- }),
+ this.t("app.flash.model_not_found.title", {
+ model: this.t("app.model." + model),
+ }),
+ this.t("app.flash.model_not_found.details", { ids: `${ids.join(", ")}` }),
);
}
diff --git a/resources/js/views/RoomsView.vue b/resources/js/views/RoomsView.vue
index 05be64e15..0b3036066 100644
--- a/resources/js/views/RoomsView.vue
+++ b/resources/js/views/RoomsView.vue
@@ -441,7 +441,11 @@ function load() {
if (error.response) {
// Room not found (Always redirect to 404 view)
if (error.response.status === env.HTTP_NOT_FOUND) {
- router.push({ name: "404" });
+ if (authStore.isAuthenticated) {
+ router.push({ name: "rooms.index" });
+ } else {
+ router.push({ name: "404" });
+ }
}
// Room auth token is invalid
@@ -462,7 +466,10 @@ function load() {
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: false,
+ });
})
.finally(() => {
// Disable loading indicator
@@ -516,7 +523,11 @@ function reload() {
if (error.response) {
// Room not found (Always redirect to 404 view)
if (error.response.status === env.HTTP_NOT_FOUND) {
- router.push({ name: "404" });
+ if (authStore.isAuthenticated) {
+ router.push({ name: "rooms.index" });
+ } else {
+ router.push({ name: "404" });
+ }
}
// Room auth token is invalid
@@ -535,7 +546,10 @@ function reload() {
return handleGuestsNotAllowed();
}
}
- api.error(error, { redirectOnUnauthenticated: false });
+ api.error(error, {
+ redirectOnUnauthenticated: false,
+ redirectOnRoomModelNotFound: false,
+ });
})
.finally(() => {
// Disable loading indicator
@@ -674,7 +688,6 @@ function authenticate(type, codeOrToken) {
}
api.error(error, {
redirectOnUnauthenticated: false,
- redirectOnRoomModelNotFound: true,
});
})
.finally(() => {
diff --git a/tests/Frontend/e2e/AdminRolesEdit.cy.js b/tests/Frontend/e2e/AdminRolesEdit.cy.js
index 6aeb1e919..0d0a53e6b 100644
--- a/tests/Frontend/e2e/AdminRolesEdit.cy.js
+++ b/tests/Frontend/e2e/AdminRolesEdit.cy.js
@@ -1629,7 +1629,9 @@ describe("Admin roles edit", function () {
cy.intercept("PUT", "api/v1/roles/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "role",
+ ids: [2],
},
}).as("saveChangesRequest");
@@ -1644,8 +1646,8 @@ describe("Admin roles edit", function () {
cy.wait("@rolesRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.role"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Reload
@@ -1792,7 +1794,9 @@ describe("Admin roles edit", function () {
cy.intercept("GET", "api/v1/roles/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "role",
+ ids: [2],
},
}).as("roleRequest");
@@ -1809,8 +1813,8 @@ describe("Admin roles edit", function () {
// Check that error message is shown
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.role"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js b/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js
index 50b329bc2..c149da653 100644
--- a/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js
+++ b/tests/Frontend/e2e/AdminRolesIndexRoleActions.cy.js
@@ -193,7 +193,10 @@ describe("Admin roles index role actions", function () {
// Check that dialog is closed and that error message is shown
cy.get('[data-test="roles-delete-dialog"]').should("not.exist");
- cy.checkToastMessage('app.flash.model_not_found.role_{"ids":"3"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.role"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
+ ]);
// Check that role is not in the list anymore
cy.get('[data-test="role-item"]').should("have.length", 2);
diff --git a/tests/Frontend/e2e/AdminRolesView.cy.js b/tests/Frontend/e2e/AdminRolesView.cy.js
index 726a7a879..7b1a9a048 100644
--- a/tests/Frontend/e2e/AdminRolesView.cy.js
+++ b/tests/Frontend/e2e/AdminRolesView.cy.js
@@ -680,7 +680,9 @@ describe("Admin roles view", function () {
cy.intercept("GET", "api/v1/roles/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "role",
+ ids: [2],
},
}).as("roleRequest");
@@ -697,8 +699,8 @@ describe("Admin roles view", function () {
// Check that error message is shown
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.role"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js b/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js
index 0f250f6e2..c5e81c696 100644
--- a/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js
+++ b/tests/Frontend/e2e/AdminRolesViewRoleActions.cy.js
@@ -155,7 +155,10 @@ describe("Admin roles view role actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/roles").and("not.include", "/2");
- cy.checkToastMessage('app.flash.model_not_found.role_{"ids":"2"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.role"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
+ ]);
// Reload view and open delete dialog again
cy.visit("/admin/roles/2");
diff --git a/tests/Frontend/e2e/AdminRoomTypesEdit.cy.js b/tests/Frontend/e2e/AdminRoomTypesEdit.cy.js
index cf8d54a87..034cb4f55 100644
--- a/tests/Frontend/e2e/AdminRoomTypesEdit.cy.js
+++ b/tests/Frontend/e2e/AdminRoomTypesEdit.cy.js
@@ -2067,7 +2067,9 @@ describe("Admin room types edit", function () {
cy.intercept("PUT", "api/v1/roomTypes/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "room_type",
+ ids: [3],
},
}).as("saveChangesRequest");
@@ -2082,8 +2084,8 @@ describe("Admin room types edit", function () {
cy.wait("@roomTypesRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.room_type"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
]);
// Reload
@@ -2148,7 +2150,9 @@ describe("Admin room types edit", function () {
cy.intercept("GET", "api/v1/roomTypes/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "room_type",
+ ids: [3],
},
}).as("roomTypeRequest");
@@ -2163,8 +2167,8 @@ describe("Admin room types edit", function () {
cy.wait("@roomTypesRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.room_type"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js b/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js
index 0a927ad0d..332e4e44a 100644
--- a/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js
+++ b/tests/Frontend/e2e/AdminRoomTypesIndexRoomTypeActions.cy.js
@@ -357,7 +357,10 @@ describe("Admin room types index room type actions", function () {
cy.get('[data-test="room-types-delete-dialog"]').should("not.exist");
// Check that error message is shown
- cy.checkToastMessage('app.flash.model_not_found.room_type_{"ids":"3"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room_type"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
+ ]);
// Check that room type is not there anymore
cy.get('[data-test="room-type-item"]').should("have.length", 2);
diff --git a/tests/Frontend/e2e/AdminRoomTypesView.cy.js b/tests/Frontend/e2e/AdminRoomTypesView.cy.js
index 3ec2cd60f..fddec5bab 100644
--- a/tests/Frontend/e2e/AdminRoomTypesView.cy.js
+++ b/tests/Frontend/e2e/AdminRoomTypesView.cy.js
@@ -631,7 +631,9 @@ describe("Admin room types view", function () {
cy.intercept("GET", "api/v1/roomTypes/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "room_type",
+ ids: [3],
},
}).as("roomTypeRequest");
@@ -647,8 +649,8 @@ describe("Admin room types view", function () {
// Check that error message is shown
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.room_type"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js b/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js
index 50405df27..1a739b263 100644
--- a/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js
+++ b/tests/Frontend/e2e/AdminRoomTypesViewRoomTypeActions.cy.js
@@ -306,7 +306,10 @@ describe("Admin room types view room type actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/room_types").and("not.include", "/3");
- cy.checkToastMessage('app.flash.model_not_found.room_type_{"ids":"3"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room_type"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
+ ]);
// Reload view and open delete dialog again
cy.visit("/admin/room_types/3");
diff --git a/tests/Frontend/e2e/AdminServerPoolsEdit.cy.js b/tests/Frontend/e2e/AdminServerPoolsEdit.cy.js
index 377882140..edd2b4d53 100644
--- a/tests/Frontend/e2e/AdminServerPoolsEdit.cy.js
+++ b/tests/Frontend/e2e/AdminServerPoolsEdit.cy.js
@@ -610,7 +610,9 @@ describe("Admin server pools edit", function () {
cy.intercept("PUT", "api/v1/serverPools/1", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "server_pool",
+ ids: [1],
},
}).as("saveChangesRequest");
@@ -625,8 +627,8 @@ describe("Admin server pools edit", function () {
cy.wait("@serverPoolsRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.server_pool"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
]);
// Reload
@@ -728,7 +730,9 @@ describe("Admin server pools edit", function () {
cy.intercept("GET", "api/v1/serverPools/1", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "server_pool",
+ ids: [1],
},
}).as("serverPoolRequest");
@@ -743,8 +747,8 @@ describe("Admin server pools edit", function () {
cy.wait("@serverPoolsRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.server_pool"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js b/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js
index 4ee467bf0..64701b0e0 100644
--- a/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js
+++ b/tests/Frontend/e2e/AdminServerPoolsIndexServerPoolActions.cy.js
@@ -230,7 +230,11 @@ describe("Admin server pools index server pool actions", function () {
// Check that dialog is closed and error message is shown
cy.get('[data-test="server-pools-delete-dialog"]').should("not.exist");
- cy.checkToastMessage('app.flash.model_not_found.server_pool_{"ids":"1"}');
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.server_pool"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
+ ]);
// Check that server pool is not in list anymore
cy.get('[data-test="server-pool-item"]').should("have.length", 1);
diff --git a/tests/Frontend/e2e/AdminServerPoolsView.cy.js b/tests/Frontend/e2e/AdminServerPoolsView.cy.js
index 6fef329d9..f76b8e049 100644
--- a/tests/Frontend/e2e/AdminServerPoolsView.cy.js
+++ b/tests/Frontend/e2e/AdminServerPoolsView.cy.js
@@ -229,7 +229,9 @@ describe("Admin server pools view", function () {
cy.intercept("GET", "api/v1/serverPools/1", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "server_pool",
+ ids: [1],
},
}).as("serverPoolRequest");
@@ -244,8 +246,8 @@ describe("Admin server pools view", function () {
cy.wait("@serverPoolsRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.server_pool"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js b/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js
index 299e2711e..e1820beaa 100644
--- a/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js
+++ b/tests/Frontend/e2e/AdminServerPoolsViewServerPoolActions.cy.js
@@ -180,7 +180,10 @@ describe("Admin server pools view", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/server_pools").and("not.include", "/1");
- cy.checkToastMessage('app.flash.model_not_found.server_pool_{"ids":"1"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.server_pool"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
+ ]);
// Reload view and open delete dialog again
cy.visit("/admin/server_pools/1");
diff --git a/tests/Frontend/e2e/AdminServersEdit.cy.js b/tests/Frontend/e2e/AdminServersEdit.cy.js
index 3b02ee5b3..6616bfb98 100644
--- a/tests/Frontend/e2e/AdminServersEdit.cy.js
+++ b/tests/Frontend/e2e/AdminServersEdit.cy.js
@@ -622,7 +622,9 @@ describe("Admin servers edit", function () {
cy.intercept("PUT", "api/v1/servers/1", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "server",
+ ids: [1],
},
}).as("saveChangesRequest");
@@ -637,8 +639,8 @@ describe("Admin servers edit", function () {
cy.wait("@serversRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.server"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
]);
// Reload
@@ -809,7 +811,9 @@ describe("Admin servers edit", function () {
cy.intercept("GET", "api/v1/servers/1", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "server",
+ ids: [1],
},
}).as("serverRequest");
@@ -824,8 +828,8 @@ describe("Admin servers edit", function () {
cy.wait("@serversRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.server"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js b/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js
index 0df2407ec..c4f5b2d57 100644
--- a/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js
+++ b/tests/Frontend/e2e/AdminServersIndexServerActions.cy.js
@@ -182,7 +182,10 @@ describe("Admin servers index server actions", function () {
// Check that dialog is closed and error message is shown
cy.get('[data-test="servers-delete-dialog"]').should("not.exist");
- cy.checkToastMessage('app.flash.model_not_found.server_{"ids":"3"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.server"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
+ ]);
// Check that server is not in list anymore
cy.get('[data-test="server-item"]').should("have.length", 3);
diff --git a/tests/Frontend/e2e/AdminServersView.cy.js b/tests/Frontend/e2e/AdminServersView.cy.js
index ffd6144e3..0d055c16f 100644
--- a/tests/Frontend/e2e/AdminServersView.cy.js
+++ b/tests/Frontend/e2e/AdminServersView.cy.js
@@ -577,7 +577,9 @@ describe("Admin servers view", function () {
cy.intercept("GET", "api/v1/servers/1", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "server",
+ ids: [1],
},
}).as("serverRequest");
@@ -592,10 +594,9 @@ describe("Admin servers view", function () {
cy.wait("@serversRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.server"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
]);
-
// Reload page with 401 error
cy.intercept("GET", "api/v1/servers/1", {
statusCode: 401,
diff --git a/tests/Frontend/e2e/AdminServersViewServerActions.cy.js b/tests/Frontend/e2e/AdminServersViewServerActions.cy.js
index cbe6fe503..9d3034331 100644
--- a/tests/Frontend/e2e/AdminServersViewServerActions.cy.js
+++ b/tests/Frontend/e2e/AdminServersViewServerActions.cy.js
@@ -154,7 +154,10 @@ describe("Admin servers view server actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/servers").and("not.include", "/1");
- cy.checkToastMessage('app.flash.model_not_found.server_{"ids":"1"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.server"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
+ ]);
// Reload view and open delete dialog again
cy.visit("/admin/servers/1");
@@ -450,6 +453,34 @@ describe("Admin servers view server actions", function () {
cy.url().should("include", "/login?redirect=/admin/servers/1");
cy.checkToastMessage("app.flash.unauthenticated");
+
+ // Check with 404 error
+ cy.interceptAdminServersIndexRequests();
+
+ cy.intercept("POST", "api/v1/servers/1/panic", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "server",
+ ids: [1],
+ },
+ }).as("panicRequest");
+
+ cy.visit("/admin/servers/1");
+
+ cy.wait("@serverRequest");
+
+ cy.get('[data-test="servers-panic-button"]').click();
+
+ cy.wait("@panicRequest");
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "/admin/servers").and("not.include", "/1");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.server"}',
+ 'app.flash.model_not_found.details_{"ids":"1"}',
+ ]);
});
it("switch between edit and view", function () {
diff --git a/tests/Frontend/e2e/AdminUsersEdit.cy.js b/tests/Frontend/e2e/AdminUsersEdit.cy.js
index b49417d8c..1f6c96cbb 100644
--- a/tests/Frontend/e2e/AdminUsersEdit.cy.js
+++ b/tests/Frontend/e2e/AdminUsersEdit.cy.js
@@ -272,7 +272,9 @@ describe("Admin users edit", function () {
cy.intercept("GET", "api/v1/users/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("userRequest");
@@ -288,8 +290,8 @@ describe("Admin users edit", function () {
// Check that error message gets shown
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminUsersEditBase.cy.js b/tests/Frontend/e2e/AdminUsersEditBase.cy.js
index b18e34af1..e5729604d 100644
--- a/tests/Frontend/e2e/AdminUsersEditBase.cy.js
+++ b/tests/Frontend/e2e/AdminUsersEditBase.cy.js
@@ -701,7 +701,9 @@ describe("Admin users edit base", function () {
cy.intercept("POST", "api/v1/users/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("saveChangesRequest");
@@ -716,8 +718,8 @@ describe("Admin users edit base", function () {
cy.wait("@usersRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Visit edit page again
diff --git a/tests/Frontend/e2e/AdminUsersEditEmail.cy.js b/tests/Frontend/e2e/AdminUsersEditEmail.cy.js
index 927fdc84c..80c6960a8 100644
--- a/tests/Frontend/e2e/AdminUsersEditEmail.cy.js
+++ b/tests/Frontend/e2e/AdminUsersEditEmail.cy.js
@@ -155,7 +155,9 @@ describe("Admin users edit email", function () {
cy.intercept("PUT", "api/v1/users/2/email", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("saveChangesRequest");
@@ -170,8 +172,8 @@ describe("Admin users edit email", function () {
cy.wait("@usersRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Visit edit page again
diff --git a/tests/Frontend/e2e/AdminUsersEditOthers.cy.js b/tests/Frontend/e2e/AdminUsersEditOthers.cy.js
index ea55d4af6..4a312c239 100644
--- a/tests/Frontend/e2e/AdminUsersEditOthers.cy.js
+++ b/tests/Frontend/e2e/AdminUsersEditOthers.cy.js
@@ -187,7 +187,9 @@ describe("Admin users edit others", function () {
cy.intercept("POST", "api/v1/users/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("saveChangesRequest");
@@ -200,8 +202,8 @@ describe("Admin users edit others", function () {
cy.wait("@usersRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Visit edit page again
diff --git a/tests/Frontend/e2e/AdminUsersEditSecurity.cy.js b/tests/Frontend/e2e/AdminUsersEditSecurity.cy.js
index 3b0f2d9bf..d481139d4 100644
--- a/tests/Frontend/e2e/AdminUsersEditSecurity.cy.js
+++ b/tests/Frontend/e2e/AdminUsersEditSecurity.cy.js
@@ -563,7 +563,9 @@ describe("Admin users edit email", function () {
cy.intercept("PUT", "api/v1/users/2 ", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("saveChangesRequest");
@@ -578,8 +580,8 @@ describe("Admin users edit email", function () {
cy.wait("@usersRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Visit edit page again
@@ -742,7 +744,9 @@ describe("Admin users edit email", function () {
cy.intercept("PUT", "api/v1/users/2/password", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("saveChangesRequest");
@@ -757,8 +761,8 @@ describe("Admin users edit email", function () {
cy.wait("@usersRequest");
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Visit edit page again
diff --git a/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js b/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js
index 08931d4b4..ba1550364 100644
--- a/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js
+++ b/tests/Frontend/e2e/AdminUsersIndexUserActions.cy.js
@@ -184,7 +184,11 @@ describe("Admin users index user actions", function () {
// Check that dialog is closed and error message is shown
cy.get('[data-test="users-delete-dialog"]').should("not.exist");
- cy.checkToastMessage('app.flash.model_not_found.user_{"ids":"3"}');
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"3"}',
+ ]);
// Check that user is not in list anymore
cy.get('[data-test="user-item"]').should("have.length", 3);
diff --git a/tests/Frontend/e2e/AdminUsersView.cy.js b/tests/Frontend/e2e/AdminUsersView.cy.js
index 8c9d4f792..0bb703321 100644
--- a/tests/Frontend/e2e/AdminUsersView.cy.js
+++ b/tests/Frontend/e2e/AdminUsersView.cy.js
@@ -556,7 +556,9 @@ describe("Admin users view", function () {
cy.intercept("GET", "api/v1/users/2", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "user",
+ ids: [2],
},
}).as("userRequest");
@@ -572,8 +574,8 @@ describe("Admin users view", function () {
// Check that error message gets shown
cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"No query results for model"}',
- 'app.flash.server_error.error_code_{"statusCode":404}',
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
]);
// Reload page with 401 error
diff --git a/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js b/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js
index a48463c9e..dbec5df87 100644
--- a/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js
+++ b/tests/Frontend/e2e/AdminUsersViewUserActions.cy.js
@@ -146,7 +146,10 @@ describe("Admin users view user actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/users").and("not.include", "/2");
- cy.checkToastMessage('app.flash.model_not_found.user_{"ids":"2"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
+ ]);
// Reload view and open delete dialog again
cy.visit("/admin/users/2");
@@ -271,7 +274,10 @@ describe("Admin users view user actions", function () {
// Check that redirect worked and error message is shown
cy.url().should("include", "/admin/users").and("not.include", "/2");
- cy.checkToastMessage('app.flash.model_not_found.user_{"ids":"2"}');
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.user"}',
+ 'app.flash.model_not_found.details_{"ids":"2"}',
+ ]);
// Reload view and open reset password dialog again
cy.visit("/admin/users/2");
diff --git a/tests/Frontend/e2e/RoomsViewDescription.cy.js b/tests/Frontend/e2e/RoomsViewDescription.cy.js
index abed2b153..0c096418c 100644
--- a/tests/Frontend/e2e/RoomsViewDescription.cy.js
+++ b/tests/Frontend/e2e/RoomsViewDescription.cy.js
@@ -468,6 +468,7 @@ describe("Rooms view description", function () {
cy.reload();
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
cy.intercept("PUT", "api/v1/rooms/abc-def-123/description", {
statusCode: 404,
body: {
@@ -483,13 +484,16 @@ describe("Rooms view description", function () {
cy.wait("@saveDescriptionRequest");
- // Check that redirect to 404 page worked
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ // Check that redirect to room index page worked
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
// Check that error message gets shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("description changes", function () {
diff --git a/tests/Frontend/e2e/RoomsViewFiles.cy.js b/tests/Frontend/e2e/RoomsViewFiles.cy.js
index 06843dd57..bffa9b16e 100644
--- a/tests/Frontend/e2e/RoomsViewFiles.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFiles.cy.js
@@ -723,6 +723,8 @@ describe("Rooms View Files", function () {
.should("have.attr", "data-p-active", "true");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123/files*", {
statusCode: 404,
body: {
@@ -735,13 +737,16 @@ describe("Rooms View Files", function () {
cy.reload();
cy.wait("@roomFilesRequest");
- // Check that redirect to 404 page worked
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ // Check that redirect to room index page worked
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
// Check that error message gets shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load files page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js b/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
index b9d0ca1ec..81841123f 100644
--- a/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFilesFileActions.cy.js
@@ -339,6 +339,8 @@ describe("Rooms view files file actions", function () {
cy.reload();
// Check 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "/api/v1/rooms/abc-def-123/files", {
statusCode: 404,
body: {
@@ -358,13 +360,14 @@ describe("Rooms view files file actions", function () {
cy.wait("@uploadFileRequest");
- // Check that redirect to 404 page worked
- cy.url().should("include", "/404").and("not.include", "abc-def-123");
+ // Check that redirect to room index page worked
+ cy.url().should("include", "/rooms").and("not.include", "abc-def-123");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("delete file", function () {
@@ -546,6 +549,8 @@ describe("Rooms view files file actions", function () {
cy.reload();
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/files/1", {
statusCode: 404,
body: {
@@ -567,13 +572,14 @@ describe("Rooms view files file actions", function () {
cy.wait("@deleteFileRequest");
- // Check that redirect to 404 page worked
- cy.url().should("include", "/404").and("not.include", "abc-def-123");
+ // Check that redirect to room index page worked
+ cy.url().should("include", "/rooms").and("not.include", "abc-def-123");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("change file settings", function () {
@@ -803,6 +809,8 @@ describe("Rooms view files file actions", function () {
cy.reload();
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("PUT", "/api/v1/rooms/abc-def-123/files/1", {
statusCode: 404,
body: {
@@ -824,13 +832,14 @@ describe("Rooms view files file actions", function () {
cy.wait("@editFileRequest");
- // Check that redirect to 404 page worked
- cy.url().should("include", "/404").and("not.include", "abc-def-123");
+ // Check that redirect to room index page worked
+ cy.url().should("include", "/rooms").and("not.include", "abc-def-123");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("download file with terms of use", function () {
diff --git a/tests/Frontend/e2e/RoomsViewGeneral.cy.js b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
index bacb3d686..69410aa32 100644
--- a/tests/Frontend/e2e/RoomsViewGeneral.cy.js
+++ b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
@@ -2377,6 +2377,8 @@ describe("Room View general", function () {
cy.wait("@roomRequest");
// Check join membership with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "api/v1/rooms/abc-def-123/membership*", {
statusCode: 404,
body: {
@@ -2391,11 +2393,14 @@ describe("Room View general", function () {
cy.wait("@joinMembershipRequest");
// Check that redirect worked and error message is shown
- cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
// Reload room with user being a member of the room
cy.fixture("room.json").then((room) => {
@@ -2527,12 +2532,15 @@ describe("Room View general", function () {
cy.wait("@endMembershipRequest");
// Check that redirect worked and error message is shown
- cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("trigger favorites button", function () {
@@ -2727,6 +2735,8 @@ describe("Room View general", function () {
cy.wait("@roomRequest");
// Test add to favorites with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "api/v1/rooms/abc-def-123/favorites", {
statusCode: 404,
body: {
@@ -2741,11 +2751,14 @@ describe("Room View general", function () {
cy.wait("@addFavoritesRequest");
// Check that redirect worked and error message is shown
- cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
// Reload room but room is already in favorites
cy.fixture("room.json").then((room) => {
@@ -2843,6 +2856,8 @@ describe("Room View general", function () {
cy.wait("@roomRequest");
// Test remove from favorites with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("DELETE", "api/v1/rooms/abc-def-123/favorites", {
statusCode: 404,
body: {
@@ -2859,11 +2874,14 @@ describe("Room View general", function () {
cy.wait("@deleteFavoritesRequest");
// Check that redirect worked and error message is shown
- cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("visit with guest forbidden", function () {
@@ -2951,6 +2969,9 @@ describe("Room View general", function () {
});
it("visit with room not found", function () {
+ // Try with logged in user
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123", {
statusCode: 404,
body: {
@@ -2960,6 +2981,22 @@ describe("Room View general", function () {
cy.visit("/rooms/abc-def-123");
+ // Check redirect to room index page
+ cy.url()
+ .should("include", "/rooms")
+ .should("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.server_error.message_{"message":"No query results for model [App\\\\Room] abc-def-123"}',
+ 'app.flash.server_error.error_code_{"statusCode":404}',
+ ]);
+
+ // Try with guest
+ cy.intercept("GET", "api/v1/currentUser", {});
+
+ cy.visit("/rooms/abc-def-123");
+
+ // Check redirect to 404 page
cy.url()
.should("include", "/404")
.should("not.include", "/rooms/abc-def-123");
@@ -3089,7 +3126,9 @@ describe("Room View general", function () {
cy.wait("@roomRequest");
- // Test reload with room not found
+ // Test reload with room not found and guest user
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123", {
statusCode: 404,
body: {
@@ -3100,6 +3139,7 @@ describe("Room View general", function () {
cy.get('[data-test="reload-room-button"]').click();
cy.wait("@roomRequest");
+ // Check redirect to 404 page worked
cy.url()
.should("include", "/404")
.should("not.include", "/rooms/abc-def-123");
@@ -3108,6 +3148,41 @@ describe("Room View general", function () {
'app.flash.server_error.message_{"message":"No query results for model [App\\\\Room] abc-def-123"}',
'app.flash.server_error.error_code_{"statusCode":404}',
]);
+
+ // Test reload with room not found and logged in user
+ cy.intercept("GET", "api/v1/currentUser", { fixture: "currentUser.json" });
+ cy.fixture("room.json").then((room) => {
+ room.data.allow_membership = true;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+ cy.wait("@roomRequest");
+ cy.contains("Meeting One").should("be.visible");
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ statusCode: 404,
+ body: {
+ message: "No query results for model [App\\Room] abc-def-123",
+ },
+ }).as("roomRequest");
+
+ cy.get('[data-test="reload-room-button"]').click();
+ cy.wait("@roomRequest");
+
+ // Check redirect to room index page worked
+ cy.url()
+ .should("include", "/rooms")
+ .should("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.server_error.message_{"message":"No query results for model [App\\\\Room] abc-def-123"}',
+ 'app.flash.server_error.error_code_{"statusCode":404}',
+ ]);
});
it("reload with access code errors", function () {
diff --git a/tests/Frontend/e2e/RoomsViewHistory.cy.js b/tests/Frontend/e2e/RoomsViewHistory.cy.js
index a5f1a4cc0..1936dd962 100644
--- a/tests/Frontend/e2e/RoomsViewHistory.cy.js
+++ b/tests/Frontend/e2e/RoomsViewHistory.cy.js
@@ -504,6 +504,8 @@ describe("Rooms view history", function () {
cy.wait("@roomRequest");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123/meetings*", {
statusCode: 404,
body: {
@@ -516,11 +518,14 @@ describe("Rooms view history", function () {
cy.get("#tab-history").click();
cy.wait("@roomHistoryRequest");
- // Check that redirect to 404 page works and that error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page works and that error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load history page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js b/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
index a1d999e81..6a9fb3185 100644
--- a/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewHistoryMeetingActions.cy.js
@@ -154,9 +154,10 @@ describe("Rooms view history meeting actions", function () {
cy.wait("@statsRequest");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.meeting_{"ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.meeting"}',
+ 'app.flash.model_not_found.details_{"ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
+ ]);
// Check if dialog is closed
cy.get('[data-test="room-history-statistic-dialog"]').should("not.exist");
@@ -492,9 +493,10 @@ describe("Rooms view history meeting actions", function () {
cy.wait("@attendanceRequest");
// Check that error message is shown
- cy.checkToastMessage(
- 'app.flash.model_not_found.meeting_{"ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.meeting"}',
+ 'app.flash.model_not_found.details_{"ids":"3a3e504a-d2c4-431c-8ca1-a62598e66761"}',
+ ]);
// Check if dialog is closed
cy.get('[data-test="room-history-attendance-dialog"]').should("not.exist");
diff --git a/tests/Frontend/e2e/RoomsViewMeetings.cy.js b/tests/Frontend/e2e/RoomsViewMeetings.cy.js
index efc12ebf9..294d88bf8 100644
--- a/tests/Frontend/e2e/RoomsViewMeetings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMeetings.cy.js
@@ -1352,7 +1352,6 @@ describe("Rooms view meetings", function () {
start: "2023-08-21T08:18:28.000000Z",
end: null,
};
- room.data.current_user = null;
cy.intercept("GET", "api/v1/rooms/abc-def-123", {
statusCode: 200,
@@ -1362,6 +1361,8 @@ describe("Rooms view meetings", function () {
cy.reload();
// Test with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "/api/v1/rooms/abc-def-123/join*", {
statusCode: 404,
body: {
@@ -1385,11 +1386,15 @@ describe("Rooms view meetings", function () {
cy.wait("@joinRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("join meeting load requirements errors", function () {
@@ -1568,9 +1573,11 @@ describe("Rooms view meetings", function () {
// Check that redirect to 404 page worked and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("join running meeting with dark mode", function () {
@@ -2935,20 +2942,16 @@ describe("Rooms view meetings", function () {
);
// Reload room
- cy.fixture("room.json").then((room) => {
- room.data.current_user = null;
-
- cy.intercept("GET", "api/v1/rooms/abc-def-123", {
- statusCode: 200,
- body: room,
- }).as("roomRequest");
- });
+ cy.intercept("GET", "api/v1/rooms/abc-def-123", {
+ fixture: "room.json",
+ }).as("roomRequest");
cy.visit("/rooms/abc-def-123");
cy.wait("@roomRequest");
// Try with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
cy.intercept("POST", "/api/v1/rooms/abc-def-123/start*", {
statusCode: 404,
body: {
@@ -2971,11 +2974,14 @@ describe("Rooms view meetings", function () {
cy.wait("@startRequest");
// Check if redirect worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("start meeting load requirements errors", function () {
@@ -3157,9 +3163,10 @@ describe("Rooms view meetings", function () {
// Check if redirect worked and error message is shown
cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("start meeting with dark mode", function () {
diff --git a/tests/Frontend/e2e/RoomsViewMembers.cy.js b/tests/Frontend/e2e/RoomsViewMembers.cy.js
index 1f4cea804..93873acd8 100644
--- a/tests/Frontend/e2e/RoomsViewMembers.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembers.cy.js
@@ -490,6 +490,7 @@ describe("Rooms view members", function () {
cy.reload();
// Test 404 error (room not found)
+ cy.interceptRoomIndexRequests();
cy.intercept("GET", "api/v1/rooms/abc-def-123/member*", {
statusCode: 404,
body: {
@@ -503,12 +504,15 @@ describe("Rooms view members", function () {
cy.wait("@roomMembersRequest");
- // Check that redirect to 404 page works and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ // Check that redirect to room index page works and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load members page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
index 290e89427..1a9dbb172 100644
--- a/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersBulkActions.cy.js
@@ -421,6 +421,7 @@ describe("Rooms view members bulk actions", function () {
cy.get('[data-test="room-members-select-all-checkbox"]').click();
// Test bulk edit with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
cy.intercept("PUT", "api/v1/rooms/abc-def-123/member/bulk", {
statusCode: 404,
body: {
@@ -439,12 +440,15 @@ describe("Rooms view members bulk actions", function () {
cy.wait("@bulkEditRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("bulk delete members", function () {
@@ -732,6 +736,8 @@ describe("Rooms view members bulk actions", function () {
cy.get('[data-test="room-members-select-all-checkbox"] > input').click();
// Test bulk delete with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("DELETE", "api/v1/rooms/abc-def-123/member/bulk", {
statusCode: 404,
body: {
@@ -752,12 +758,15 @@ describe("Rooms view members bulk actions", function () {
cy.wait("@bulkDeleteRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("bulk import members", function () {
@@ -1472,6 +1481,8 @@ describe("Rooms view members bulk actions", function () {
cy.get("#tab-members").should("be.visible").click();
// Test bulk import with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "api/v1/rooms/abc-def-123/member/bulk", {
statusCode: 404,
body: {
@@ -1494,11 +1505,14 @@ describe("Rooms view members bulk actions", function () {
cy.wait("@bulkImportRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
index e3adede6d..7869c0b38 100644
--- a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
@@ -444,6 +444,8 @@ describe("Rooms view members member actions", function () {
cy.get("#tab-members").click();
// Test add new member with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.get('[data-test="room-members-add-button"]').click();
cy.get("#overlay_menu_0")
@@ -465,11 +467,15 @@ describe("Rooms view members member actions", function () {
cy.wait("@addUserRequest");
- // Check that user is redirected to 404 page and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that user is redirected to room index page and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("edit member", function () {
@@ -686,6 +692,8 @@ describe("Rooms view members member actions", function () {
cy.wait("@roomMembersRequest");
// Test edit member with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.get('[data-test="room-member-item"]')
.eq(0)
.find('[data-test="room-members-edit-button"]')
@@ -706,11 +714,15 @@ describe("Rooms view members member actions", function () {
cy.wait("@editUserRequest");
- // Check that user is redirected to 404 page and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that user is redirected to room index page and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("delete member", function () {
@@ -883,7 +895,9 @@ describe("Rooms view members member actions", function () {
cy.get("#tab-members").click();
cy.wait("@roomMembersRequest");
- // Test delete member with 404 error (room not found)
+ // Test delete member with room index error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.get('[data-test="room-member-item"]')
.eq(0)
.find('[data-test="room-members-delete-button"]')
@@ -904,10 +918,14 @@ describe("Rooms view members member actions", function () {
cy.wait("@deleteMemberRequest");
- // Check that user is redirected to 404 page and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that user is redirected to room index page and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
index fefd7960b..23c4c59ff 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinks.cy.js
@@ -504,6 +504,8 @@ describe("Rooms view personalized links", function () {
cy.wait("@roomRequest");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept(
{
method: "GET",
@@ -523,11 +525,15 @@ describe("Rooms view personalized links", function () {
cy.wait("@roomPersonalizedLinksRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load personalized links page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
index 5f4c7c9ac..380333e97 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
@@ -243,6 +243,8 @@ describe("Rooms view personalized links actions", function () {
cy.wait("@roomPersonalizedLinksRequest");
// Test add personalized link with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "/api/v1/rooms/abc-def-123/personalizedLinks/", {
statusCode: 404,
body: {
@@ -260,11 +262,15 @@ describe("Rooms view personalized links actions", function () {
cy.wait("@addLinkRequest");
- // Check that redirect to 404 page works and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page works and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("edit personalized link", function () {
@@ -563,6 +569,8 @@ describe("Rooms view personalized links actions", function () {
cy.wait("@roomPersonalizedLinksRequest");
// Test edit personalized link with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("PUT", "/api/v1/rooms/abc-def-123/personalizedLinks/1", {
statusCode: 404,
body: {
@@ -583,11 +591,15 @@ describe("Rooms view personalized links actions", function () {
cy.wait("@editLinkRequest");
- // Check that redirect to 404 page works and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page works and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("delete personalized link", function () {
@@ -790,6 +802,8 @@ describe("Rooms view personalized links actions", function () {
cy.wait("@roomPersonalizedLinksRequest");
// Test delete personalized link with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/personalizedLinks/1", {
statusCode: 404,
body: {
@@ -810,11 +824,15 @@ describe("Rooms view personalized links actions", function () {
cy.wait("@deleteLinkRequest");
- // Check that redirect to 404 page works and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page works and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("copy personalized link", function () {
diff --git a/tests/Frontend/e2e/RoomsViewRecordings.cy.js b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
index 7ec1a6800..71876b192 100644
--- a/tests/Frontend/e2e/RoomsViewRecordings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
@@ -762,6 +762,8 @@ describe("Rooms view recordings", function () {
.should("have.attr", "data-p-active", "true");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123/recordings*", {
statusCode: 404,
body: {
@@ -776,12 +778,15 @@ describe("Rooms view recordings", function () {
cy.wait("@roomRecordingsRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load recordings page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
index dd9b6c8be..3dbe58105 100644
--- a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
@@ -975,6 +975,8 @@ describe("Rooms view recordings recording actions", function () {
cy.get("#tab-recordings").should("be.visible").click();
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept(
"DELETE",
"api/v1/rooms/abc-def-123/recordings/e0cfa18c5fd75a42bd7947d8549321b03abf1daf-1660728035",
@@ -1000,11 +1002,15 @@ describe("Rooms view recordings recording actions", function () {
cy.wait("@deleteRecordingRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("edit recording", function () {
@@ -1369,6 +1375,8 @@ describe("Rooms view recordings recording actions", function () {
cy.wait("@roomRecordingsRequest");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept(
"PUT",
"api/v1/rooms/abc-def-123/recordings/e0cfa18c5fd75a42bd7947d8549321b03abf1daf-1660728035",
@@ -1394,10 +1402,14 @@ describe("Rooms view recordings recording actions", function () {
cy.wait("@editRecordingRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewSettings.cy.js b/tests/Frontend/e2e/RoomsViewSettings.cy.js
index 12c10b83c..0b8ada4ab 100644
--- a/tests/Frontend/e2e/RoomsViewSettings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewSettings.cy.js
@@ -422,6 +422,8 @@ describe("Rooms view settings", function () {
cy.wait("@roomRequest");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123/settings", {
statusCode: 404,
body: {
@@ -435,11 +437,15 @@ describe("Rooms view settings", function () {
cy.wait("@roomSettingsRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load settings with different permissions", function () {
@@ -1670,6 +1676,40 @@ describe("Rooms view settings", function () {
"api/v1/rooms/abc-def-123",
"settings",
);
+
+ // Reload room page
+ cy.interceptRoomViewRequests();
+ cy.reload();
+
+ cy.get("#tab-settings").click();
+
+ cy.wait("@roomSettingsRequest");
+
+ // Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
+ cy.intercept("PUT", "api/v1/rooms/abc-def-123", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ });
+
+ cy.get('[data-test="room-settings-save-button"]').click();
+
+ cy.wait("@roomSettingsSaveRequest");
+
+ // Check that redirect to room index page worked
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("delete room", function () {
@@ -1740,6 +1780,8 @@ describe("Rooms view settings", function () {
cy.get("[data-test=room-delete-dialog]").should("be.visible");
// Check with 404 error
+ cy.interceptRoomIndexRequests();
+
cy.intercept("DELETE", "api/v1/rooms/abc-def-123", {
statusCode: 404,
body: {
@@ -1756,9 +1798,15 @@ describe("Rooms view settings", function () {
cy.wait("@roomDeleteRequest");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
// Reload room page
cy.visit("/rooms/abc-def-123#tab=settings");
@@ -2304,6 +2352,8 @@ describe("Rooms view settings", function () {
cy.wait("@roomSettingsRequest");
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "api/v1/rooms/abc-def-123/transfer", {
statusCode: 404,
body: {
@@ -2319,10 +2369,12 @@ describe("Rooms view settings", function () {
cy.wait("@transferOwnershipRequest");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ // Check that redirect to room index page worked and error message is shown
+ cy.url().should("include", "/rooms");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewStreaming.cy.js b/tests/Frontend/e2e/RoomsViewStreaming.cy.js
index aa46a1af2..5a7a80169 100644
--- a/tests/Frontend/e2e/RoomsViewStreaming.cy.js
+++ b/tests/Frontend/e2e/RoomsViewStreaming.cy.js
@@ -788,6 +788,8 @@ describe("Rooms view streaming", function () {
);
// Check 404 error on reload (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123/streaming/status", {
statusCode: 404,
body: {
@@ -800,11 +802,14 @@ describe("Rooms view streaming", function () {
cy.get('[data-test="streaming-reload-button"]').click();
cy.wait("@roomStreamingStatus");
- // Check that redirect to 404 page worked and error message is shown
- cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+ // Check that redirect to room index page worked and error message is shown
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
});
diff --git a/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js b/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
index 9de91ac25..a92235a73 100644
--- a/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewStreamingConfigActions.cy.js
@@ -279,6 +279,8 @@ describe("Rooms view streaming config actions", function () {
});
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("GET", "api/v1/rooms/abc-def-123/streaming/config", {
statusCode: 404,
body: {
@@ -294,10 +296,14 @@ describe("Rooms view streaming config actions", function () {
cy.wait("@roomStreamingConfig");
// Check that redirect worked and error message is shown
- cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("edit settings", function () {
@@ -621,6 +627,8 @@ describe("Rooms view streaming config actions", function () {
});
// Check with 404 error (room not found)
+ cy.interceptRoomIndexRequests();
+
cy.intercept("POST", "api/v1/rooms/abc-def-123/streaming/config", {
statusCode: 404,
body: {
@@ -642,10 +650,14 @@ describe("Rooms view streaming config actions", function () {
cy.wait("@saveConfigRequest");
// Check that redirect worked and error message is shown
- cy.url().should("include", "404").and("not.include", "rooms/abc-def-123");
- cy.checkToastMessage(
- 'app.flash.model_not_found.room_{"ids":"abc-def-123"}',
- );
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("view/edit settings with different permissions", function () {
diff --git a/tests/Frontend/fixtures/en.json b/tests/Frontend/fixtures/en.json
index 9c7aea205..4e7bcd7a7 100644
--- a/tests/Frontend/fixtures/en.json
+++ b/tests/Frontend/fixtures/en.json
@@ -1,19 +1,5 @@
{
- "data": {
- "app": {
- "flash": {
- "model_not_found": {
- "meeting": "app.flash.model_not_found.meeting_{\"ids\":\":ids\"}",
- "role": "app.flash.model_not_found.role_{\"ids\":\":ids\"}",
- "room": "app.flash.model_not_found.room_{\"ids\":\":ids\"}",
- "room_type": "app.flash.model_not_found.room_type_{\"ids\":\":ids\"}",
- "server": "app.flash.model_not_found.server_{\"ids\":\":ids\"}",
- "server_pool": "app.flash.model_not_found.server_pool_{\"ids\":\":ids\"}",
- "user": "app.flash.model_not_found.user_{\"ids\":\":ids\"}"
- }
- }
- }
- },
+ "data": {},
"meta": {
"dateTimeFormat": {
"dateShort": {
From 6ebe7aa70705b5af9ebe91dde8ad77101f0ae726 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Wed, 1 Apr 2026 10:58:13 +0200
Subject: [PATCH 08/18] Improve frontend tests
---
.../js/components/RoomFavoriteButton.vue | 1 -
tests/Frontend/e2e/RoomsIndex.cy.js | 325 +++++++++++++++++-
tests/Frontend/e2e/RoomsViewFiles.cy.js | 26 +-
tests/Frontend/e2e/RoomsViewGeneral.cy.js | 92 ++++-
tests/Frontend/e2e/RoomsViewRecordings.cy.js | 25 +-
5 files changed, 464 insertions(+), 5 deletions(-)
diff --git a/resources/js/components/RoomFavoriteButton.vue b/resources/js/components/RoomFavoriteButton.vue
index 2cf490b75..fd0439d7b 100644
--- a/resources/js/components/RoomFavoriteButton.vue
+++ b/resources/js/components/RoomFavoriteButton.vue
@@ -60,7 +60,6 @@ function toggleFavorite() {
.call("rooms/" + props.room.id + "/favorites", config)
.catch((error) => {
api.error(error, {
- // ToDo emit notFound on not found error and handle it in index page (Reload room list)
redirectOnUnauthenticated: props.redirectOnUnauthenticated,
redirectOnRoomModelNotFound: props.redirectOnRoomModelNotFound,
});
diff --git a/tests/Frontend/e2e/RoomsIndex.cy.js b/tests/Frontend/e2e/RoomsIndex.cy.js
index 3cd1d5504..38f049d7e 100644
--- a/tests/Frontend/e2e/RoomsIndex.cy.js
+++ b/tests/Frontend/e2e/RoomsIndex.cy.js
@@ -1934,7 +1934,7 @@ describe("Room Index", function () {
});
});
- it("trigger favorites button errors", function () {
+ it("trigger favorites button errors (room card)", function () {
cy.fixture("rooms.json").then((rooms) => {
rooms.data = rooms.data.slice(0, 1);
rooms.meta.last_page = 3;
@@ -1997,6 +1997,269 @@ describe("Room Index", function () {
cy.checkToastMessage("app.flash.unauthenticated");
+ // Test add to favorites with 404 error
+ cy.visit("/rooms");
+
+ cy.wait("@roomRequest");
+
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ }).as("addFavoritesRequest");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.add")
+ .click();
+ });
+
+ cy.wait("@addFavoritesRequest");
+
+ // Check that rooms are reloaded and error message is shown
+ cy.wait("@roomRequest").then((interception) => {
+ expect(interception.request.query).to.contain({
+ page: "1",
+ });
+ });
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
+
+ // Visit rooms again with a room that is already a favorite
+ cy.fixture("rooms.json").then((rooms) => {
+ rooms.data = rooms.data.slice(0, 1);
+ rooms.data[0].is_favorite = true;
+
+ rooms.meta.last_page = 3;
+ rooms.meta.per_page = 1;
+ rooms.meta.to = 1;
+
+ cy.intercept("GET", "api/v1/rooms?*", {
+ statusCode: 200,
+ body: rooms,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms");
+
+ cy.wait("@roomRequest");
+
+ // Test remove from favorites with general error
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 500,
+ body: {
+ message: "Test remove favorite error",
+ },
+ }).as("deleteFavoritesRequest");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.remove")
+ .click();
+
+ cy.wait("@deleteFavoritesRequest");
+ cy.wait("@roomRequest");
+ });
+
+ // Check that error message is shown and button stayed the same
+ cy.checkToastMessage([
+ 'app.flash.server_error.message_{"message":"Test remove favorite error"}',
+ 'app.flash.server_error.error_code_{"statusCode":500}',
+ ]);
+
+ // Test remove from favorites with unauthenticated error
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 401,
+ }).as("addFavoritesRequest");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.remove")
+ .click();
+
+ cy.wait("@addFavoritesRequest");
+ cy.wait("@roomRequest");
+ });
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "/login?redirect=/rooms");
+
+ cy.checkToastMessage("app.flash.unauthenticated");
+
+ // Test remove from favorites with 404 error
+ cy.visit("/rooms");
+
+ cy.wait("@roomRequest");
+
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ }).as("deleteFavoritesRequest");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.remove")
+ .click();
+ });
+
+ cy.wait("@deleteFavoritesRequest");
+
+ // Check that rooms are reloaded and error message is shown
+ cy.wait("@roomRequest").then((interception) => {
+ expect(interception.request.query).to.contain({
+ page: "1",
+ });
+ });
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
+ });
+
+ it("trigger favorites button errors (room info dialog)", function () {
+ cy.fixture("rooms.json").then((rooms) => {
+ rooms.data = rooms.data.slice(0, 1);
+ rooms.meta.last_page = 3;
+ rooms.meta.per_page = 1;
+ rooms.meta.to = 1;
+
+ rooms.data[0].short_description = "Room short descriptions";
+
+ cy.intercept("GET", "api/v1/rooms?*", {
+ statusCode: 200,
+ body: rooms,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms");
+
+ cy.wait("@roomRequest");
+
+ // Test add to favorites with general error
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 500,
+ body: {
+ message: "Test add favorite error",
+ },
+ }).as("addFavoritesRequest");
+
+ cy.get('[data-test="room-info-dialog"]').should("not.exist");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-info-button"]').click();
+ });
+
+ cy.get('[data-test="room-info-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.add")
+ .click();
+
+ cy.wait("@addFavoritesRequest");
+ cy.wait("@roomRequest");
+ });
+
+ // Check that error message is shown and button stayed the same
+ cy.checkToastMessage([
+ 'app.flash.server_error.message_{"message":"Test add favorite error"}',
+ 'app.flash.server_error.error_code_{"statusCode":500}',
+ ]);
+
+ // Test add to favorites with unauthenticated error
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 401,
+ }).as("addFavoritesRequest");
+
+ cy.get('[data-test="room-info-dialog"]').should("not.exist");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-info-button"]').click();
+ });
+
+ cy.get('[data-test="room-info-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.add")
+ .click();
+
+ cy.wait("@addFavoritesRequest");
+ cy.wait("@roomRequest");
+ });
+
+ // Check that redirect worked and error message is shown
+ cy.url().should("include", "/login?redirect=/rooms");
+
+ cy.checkToastMessage("app.flash.unauthenticated");
+
+ // Test add to favorites with 404 error
+ cy.visit("/rooms");
+
+ cy.wait("@roomRequest");
+
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ }).as("addFavoritesRequest");
+
+ cy.get('[data-test="room-info-dialog"]').should("not.exist");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-info-button"]').click();
+ });
+
+ cy.get('[data-test="room-info-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.add")
+ .click();
+ });
+
+ cy.wait("@addFavoritesRequest");
+
+ // Check that rooms are reloaded and error message is shown
+ cy.wait("@roomRequest").then((interception) => {
+ expect(interception.request.query).to.contain({
+ page: "1",
+ });
+ });
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
+
// Visit rooms again with a room that is already a favorite
cy.fixture("rooms.json").then((rooms) => {
rooms.data = rooms.data.slice(0, 1);
@@ -2024,8 +2287,16 @@ describe("Room Index", function () {
},
}).as("deleteFavoritesRequest");
+ cy.get('[data-test="room-info-dialog"]').should("not.exist");
+
cy.get('[data-test="room-card"]')
.eq(0)
+ .within(() => {
+ cy.get('[data-test="room-info-button"]').click();
+ });
+
+ cy.get('[data-test="room-info-dialog"]')
+ .should("be.visible")
.within(() => {
cy.get('[data-test="room-favorites-button"]')
.should("have.attr", "aria-label", "rooms.favorites.remove")
@@ -2046,8 +2317,16 @@ describe("Room Index", function () {
statusCode: 401,
}).as("addFavoritesRequest");
+ cy.get('[data-test="room-info-dialog"]').should("not.exist");
+
cy.get('[data-test="room-card"]')
.eq(0)
+ .within(() => {
+ cy.get('[data-test="room-info-button"]').click();
+ });
+
+ cy.get('[data-test="room-info-dialog"]')
+ .should("be.visible")
.within(() => {
cy.get('[data-test="room-favorites-button"]')
.should("have.attr", "aria-label", "rooms.favorites.remove")
@@ -2061,6 +2340,50 @@ describe("Room Index", function () {
cy.url().should("include", "/login?redirect=/rooms");
cy.checkToastMessage("app.flash.unauthenticated");
+
+ // Test remove from favorites with 404 error
+ cy.visit("/rooms");
+
+ cy.wait("@roomRequest");
+
+ cy.intercept("DELETE", "api/v1/rooms/abc-def-123/favorites", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ }).as("deleteFavoritesRequest");
+
+ cy.get('[data-test="room-info-dialog"]').should("not.exist");
+
+ cy.get('[data-test="room-card"]')
+ .eq(0)
+ .within(() => {
+ cy.get('[data-test="room-info-button"]').click();
+ });
+
+ cy.get('[data-test="room-info-dialog"]')
+ .should("be.visible")
+ .within(() => {
+ cy.get('[data-test="room-favorites-button"]')
+ .should("have.attr", "aria-label", "rooms.favorites.remove")
+ .click();
+ });
+
+ cy.wait("@deleteFavoritesRequest");
+
+ // Check that rooms are reloaded and error message is shown
+ cy.wait("@roomRequest").then((interception) => {
+ expect(interception.request.query).to.contain({
+ page: "1",
+ });
+ });
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("error loading rooms", function () {
diff --git a/tests/Frontend/e2e/RoomsViewFiles.cy.js b/tests/Frontend/e2e/RoomsViewFiles.cy.js
index bffa9b16e..ec1a2d922 100644
--- a/tests/Frontend/e2e/RoomsViewFiles.cy.js
+++ b/tests/Frontend/e2e/RoomsViewFiles.cy.js
@@ -722,7 +722,7 @@ describe("Rooms View Files", function () {
.eq(0)
.should("have.attr", "data-p-active", "true");
- // Check with 404 error (room not found)
+ // Check with 404 error (room not found) as authenticated user
cy.interceptRoomIndexRequests();
cy.intercept("GET", "api/v1/rooms/abc-def-123/files*", {
@@ -747,6 +747,30 @@ describe("Rooms View Files", function () {
'app.flash.model_not_found.title_{"model":"app.model.room"}',
'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
]);
+
+ // Check with 404 error (room not found) as guest
+ cy.intercept("GET", "api/v1/currentUser", { data: [] });
+ cy.fixture("room.json").then((room) => {
+ room.data.current_user = null;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123*", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123#tab=files");
+
+ cy.wait("@roomFilesRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ // Check that error message gets shown
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load files page out of range", function () {
diff --git a/tests/Frontend/e2e/RoomsViewGeneral.cy.js b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
index 69410aa32..6b608b718 100644
--- a/tests/Frontend/e2e/RoomsViewGeneral.cy.js
+++ b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
@@ -693,6 +693,65 @@ describe("Room View general", function () {
// Check that access code overlay is hidden
cy.get('[data-test="room-access-code-overlay"]').should("not.exist");
+
+ // Check with 404 error (room not found) as authenticated user
+ cy.interceptRoomIndexRequests();
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/auth", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomAuthRequest");
+
+ cy.reload();
+
+ cy.wait("@roomRequest");
+
+ cy.get('[data-test="room-login-button"]').click();
+
+ cy.wait("@roomAuthRequest");
+
+ // Check that redirect to room index page worked
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "/rooms/abc-def-123");
+
+ // Check that error message is shown
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
+
+ // Check wit 404 error (room not found) as guest
+ cy.intercept("GET", "api/v1/currentUser", {});
+ cy.fixture("room.json").then((room) => {
+ room.data.current_user = null;
+ room.data.authenticated = false;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123*", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+ });
+
+ cy.visit("/rooms/abc-def-123");
+
+ cy.wait("@roomRequest");
+
+ cy.get('[data-test="room-login-button"]').click();
+
+ cy.wait("@roomAuthRequest");
+
+ // Check that redirect to 404 page worked
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ // Check that error message is shown
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("room view with access code errors", function () {
@@ -1589,6 +1648,37 @@ describe("Room View general", function () {
cy.contains("rooms.index.room_component.never_started").should(
"be.visible",
);
+
+ // Check with 404 error
+ cy.intercept("POST", "api/v1/rooms/abc-def-123/auth", {
+ statusCode: 404,
+ body: {
+ message: "model_not_found",
+ model: "room",
+ ids: ["abc-def-123"],
+ },
+ }).as("roomAuthRequest");
+
+ // Visit room with personalized link
+ cy.visit(
+ "/rooms/abc-def-123/xWDCevVTcMys1ftzt3nFPgU56Wf32fopFWgAEBtklSkFU22z1ntA4fBHsHeMygMiOa9szJbNEfBAgEWSLNWg2gcF65PwPZ2ylPQR",
+ );
+
+ cy.wait("@roomAuthRequest").then((interception) => {
+ expect(interception.request.body).to.eql({
+ personalized_link_token:
+ "xWDCevVTcMys1ftzt3nFPgU56Wf32fopFWgAEBtklSkFU22z1ntA4fBHsHeMygMiOa9szJbNEfBAgEWSLNWg2gcF65PwPZ2ylPQR",
+ type: 1,
+ });
+ });
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("room view with personalized link errors", function () {
@@ -3149,7 +3239,7 @@ describe("Room View general", function () {
'app.flash.server_error.error_code_{"statusCode":404}',
]);
- // Test reload with room not found and logged in user
+ // Test reload with room not found and authenticated user
cy.intercept("GET", "api/v1/currentUser", { fixture: "currentUser.json" });
cy.fixture("room.json").then((room) => {
room.data.allow_membership = true;
diff --git a/tests/Frontend/e2e/RoomsViewRecordings.cy.js b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
index 71876b192..3f2260635 100644
--- a/tests/Frontend/e2e/RoomsViewRecordings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordings.cy.js
@@ -761,7 +761,7 @@ describe("Rooms view recordings", function () {
.eq(0)
.should("have.attr", "data-p-active", "true");
- // Check with 404 error (room not found)
+ // Check with 404 error (room not found) as authenticated user
cy.interceptRoomIndexRequests();
cy.intercept("GET", "api/v1/rooms/abc-def-123/recordings*", {
@@ -787,6 +787,29 @@ describe("Rooms view recordings", function () {
'app.flash.model_not_found.title_{"model":"app.model.room"}',
'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
]);
+
+ // Check with 404 error (room not found) as guest
+ cy.intercept("GET", "api/v1/currentUser", {});
+ cy.fixture("room.json").then((room) => {
+ room.data.current_user = null;
+
+ cy.intercept("GET", "api/v1/rooms/abc-def-123*", {
+ statusCode: 200,
+ body: room,
+ }).as("roomRequest");
+
+ cy.visit("/rooms/abc-def-123#tab=recordings");
+
+ cy.wait("@roomRecordingsRequest");
+ });
+
+ // Check that redirect to 404 page worked and error message is shown
+ cy.url().should("include", "/404").and("not.include", "/rooms/abc-def-123");
+
+ cy.checkToastMessage([
+ 'app.flash.model_not_found.title_{"model":"app.model.room"}',
+ 'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
+ ]);
});
it("load recordings page out of range", function () {
From e79ebf2b2679b20436d63634d2e42a53ef923402 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Tue, 7 Apr 2026 09:55:21 +0200
Subject: [PATCH 09/18] Improve 404 error handling
---
resources/js/components/RoomTabFilesDeleteButton.vue | 4 ++--
resources/js/components/RoomTabFilesEditButton.vue | 4 ++--
.../js/components/RoomTabPersonalizedLinksDeleteButton.vue | 4 ++--
.../js/components/RoomTabPersonalizedLinksEditButton.vue | 4 ++--
resources/js/components/RoomTabRecordingsDeleteButton.vue | 4 ++--
resources/js/components/RoomTabRecordingsEditButton.vue | 4 ++--
resources/js/constants/modelNames.js | 5 ++++-
resources/js/services/Api.js | 4 ++--
tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js | 4 +++-
9 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/resources/js/components/RoomTabFilesDeleteButton.vue b/resources/js/components/RoomTabFilesDeleteButton.vue
index 28f0aeefb..e383b1471 100644
--- a/resources/js/components/RoomTabFilesDeleteButton.vue
+++ b/resources/js/components/RoomTabFilesDeleteButton.vue
@@ -53,7 +53,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { ROOM_FILE } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -104,7 +104,7 @@ function deleteFile() {
// file not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM_MODEL
+ error.response.data?.model === ROOM_FILE
) {
toast.error(t("rooms.flash.file_gone"));
emit("notFound");
diff --git a/resources/js/components/RoomTabFilesEditButton.vue b/resources/js/components/RoomTabFilesEditButton.vue
index d7901b305..f602dbc31 100644
--- a/resources/js/components/RoomTabFilesEditButton.vue
+++ b/resources/js/components/RoomTabFilesEditButton.vue
@@ -100,7 +100,7 @@ import { ref, watch } from "vue";
import { useFormErrors } from "../composables/useFormErrors.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { ROOM_FILE } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -198,7 +198,7 @@ function save() {
// file not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM_MODEL
+ error.response.data?.model === ROOM_FILE
) {
toast.error(t("rooms.flash.file_gone"));
emit("notFound");
diff --git a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
index 384cf69d1..57a584477 100644
--- a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
@@ -59,7 +59,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { ROOM } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -123,7 +123,7 @@ function deleteLink() {
// personalized link not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM_MODEL
+ error.response.data?.model !== ROOM
) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
index 8b5b54bef..91bd5a472 100644
--- a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
@@ -110,7 +110,7 @@ import { ref } from "vue";
import env from "../env.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { ROOM } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -192,7 +192,7 @@ function save() {
// token not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM_MODEL
+ error.response.data?.model !== ROOM
) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
diff --git a/resources/js/components/RoomTabRecordingsDeleteButton.vue b/resources/js/components/RoomTabRecordingsDeleteButton.vue
index 0a1b96d01..553d4a80f 100644
--- a/resources/js/components/RoomTabRecordingsDeleteButton.vue
+++ b/resources/js/components/RoomTabRecordingsDeleteButton.vue
@@ -53,7 +53,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { RECORDING } from "../constants/modelNames.js";
const props = defineProps({
recordingId: {
@@ -100,7 +100,7 @@ function deleteRecording() {
// recording not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM_MODEL
+ error.response.data?.model === RECORDING
) {
toast.error(t("rooms.flash.recording_gone"));
emit("notFound");
diff --git a/resources/js/components/RoomTabRecordingsEditButton.vue b/resources/js/components/RoomTabRecordingsEditButton.vue
index ea677de43..654a0d005 100644
--- a/resources/js/components/RoomTabRecordingsEditButton.vue
+++ b/resources/js/components/RoomTabRecordingsEditButton.vue
@@ -130,7 +130,7 @@ import * as _ from "lodash-es";
import { useSettingsStore } from "../stores/settings.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { RECORDING } from "../constants/modelNames.js";
const props = defineProps({
recordingId: {
@@ -239,7 +239,7 @@ function save() {
// recording not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM_MODEL
+ error.response.data?.model === RECORDING
) {
toast.error(t("rooms.flash.recording_gone"));
modalVisible.value = false;
diff --git a/resources/js/constants/modelNames.js b/resources/js/constants/modelNames.js
index 545d0b65c..0e304dc45 100644
--- a/resources/js/constants/modelNames.js
+++ b/resources/js/constants/modelNames.js
@@ -1 +1,4 @@
-export const ROOM_MODEL = "room";
+export const ROOM = "room";
+export const ROOM_FILE = "room_file";
+export const ROOM_PERSONALIZED_LINK = "room_personalized_link";
+export const RECORDING = "recording";
diff --git a/resources/js/services/Api.js b/resources/js/services/Api.js
index bea55edb2..d783aeccc 100644
--- a/resources/js/services/Api.js
+++ b/resources/js/services/Api.js
@@ -6,7 +6,7 @@ import { useAuthStore } from "../stores/auth";
import { useRouter } from "vue-router";
import { EVENT_FORBIDDEN, EVENT_UNAUTHORIZED } from "../constants/events.js";
import EventBus from "./EventBus.js";
-import { ROOM_MODEL } from "../constants/modelNames.js";
+import { ROOM } from "../constants/modelNames.js";
axios.defaults.withCredentials = true;
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
@@ -125,7 +125,7 @@ export class Api {
const model = data?.model;
const ids = data?.ids;
- if (model === ROOM_MODEL && options.redirectOnRoomModelNotFound !== false) {
+ if (model === ROOM && options.redirectOnRoomModelNotFound !== false) {
// Redirect to room index page if user is authenticated, otherwise show 404 page, because
// unauthenticated user is not able to visit the room index page
if (this.auth.isAuthenticated) {
diff --git a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
index 3dbe58105..a6d1debb7 100644
--- a/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewRecordingsRecordingActions.cy.js
@@ -1220,7 +1220,9 @@ describe("Rooms view recordings recording actions", function () {
{
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "recording",
+ ids: ["f9569db6d5e8fb2fd2f57d367d5482b36837b9d8-1663666775"],
},
},
).as("editRecordingRequest");
From 536080861f216a40fd0257fe83a812aa6b5a8362 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Tue, 7 Apr 2026 09:55:43 +0200
Subject: [PATCH 10/18] Improve backend tests
---
.../Backend/Feature/api/v1/RecordingTest.php | 23 ++++++
.../Backend/Feature/api/v1/Room/FileTest.php | 38 +++++++++
.../Feature/api/v1/Room/MembershipTest.php | 79 +++++++++++++++++++
.../api/v1/Room/RoomDescriptionTest.php | 11 +++
.../api/v1/Room/RoomPersonalizedLinkTest.php | 12 +++
.../Feature/api/v1/Room/RoomStatisticTest.php | 11 +++
6 files changed, 174 insertions(+)
diff --git a/tests/Backend/Feature/api/v1/RecordingTest.php b/tests/Backend/Feature/api/v1/RecordingTest.php
index 392582200..fda7590d5 100644
--- a/tests/Backend/Feature/api/v1/RecordingTest.php
+++ b/tests/Backend/Feature/api/v1/RecordingTest.php
@@ -1104,6 +1104,17 @@ public function test_update()
'model' => 'recording',
'ids' => [$recording->id],
]);
+
+ // Test deleted room
+ $room->delete();
+
+ $this->putJson(route('api.v1.rooms.recordings.update', ['room' => $room->id, 'recording' => $recording->id]), $payload)
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
public function test_update_permissions()
@@ -1248,6 +1259,18 @@ public function test_delete()
'model' => 'recording',
'ids' => [$recording->id],
]);
+
+ // Test with deleted room
+ $room->delete();
+
+ $this->actingAs($room->owner)
+ ->deleteJson(route('api.v1.rooms.recordings.destroy', ['room' => $room->id, 'recording' => $recording->id]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
public function test_delete_on_room_delete()
diff --git a/tests/Backend/Feature/api/v1/Room/FileTest.php b/tests/Backend/Feature/api/v1/Room/FileTest.php
index 69ace11a4..0813fc9d3 100644
--- a/tests/Backend/Feature/api/v1/Room/FileTest.php
+++ b/tests/Backend/Feature/api/v1/Room/FileTest.php
@@ -348,6 +348,18 @@ public function test_view_files()
->assertJsonCount(0, 'data')
->assertJsonPath('meta.total', 0)
->assertJsonPath('meta.total_no_filter', 3);
+
+ // Test deleted room
+ $this->room->delete();
+
+ $this->actingAs($this->room->owner)
+ ->getJson(route('api.v1.rooms.files.get', ['room' => $this->room, 'query' => 'test']))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$this->room->id],
+ ]);
}
/**
@@ -1088,6 +1100,19 @@ public function test_files_delete()
// Check if file was deleted as well
Storage::disk('local')->assertMissing($this->room->id.'/'.$this->file_valid->hashName());
+
+ // Test delete with deleted room
+ $this->room->delete();
+
+ $this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.files.destroy', ['room' => $this->room->id, 'file' => $room_file]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [
+ $this->room->id,
+ ],
+ ]);
}
/**
@@ -1281,6 +1306,19 @@ public function test_update_file()
$room_file->id,
],
]);
+
+ // Test deleted room
+ $this->room->delete();
+
+ $this->actingAs($this->room->owner)->putJson($route, $params)
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [
+ $this->room->id,
+ ],
+ ]);
}
/**
diff --git a/tests/Backend/Feature/api/v1/Room/MembershipTest.php b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
index b6f204620..9b617cc0e 100644
--- a/tests/Backend/Feature/api/v1/Room/MembershipTest.php
+++ b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
@@ -630,6 +630,17 @@ public function test_member_list()
$this->actingAs($room->owner)->getJson(route('api.v1.rooms.member.get', ['room' => $room, 'filter' => 'invalid_role']))
->assertJsonCount(5, 'data')
->assertJsonPath('meta.total', 6);
+
+ // Test deleted room
+ $room->delete();
+
+ $this->actingAs($room->owner)->getJson(route('api.v1.rooms.member.get', ['room' => $room, 'filter' => 'invalid_role']))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
/**
@@ -719,6 +730,17 @@ public function test_add_member()
$this->actingAs($this->user)->postJson(route('api.v1.rooms.member.add', ['room' => $room]), ['user' => $newUser->id, 'role' => RoomUserRole::USER])
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
+
+ // Test with deleted room
+ $room->delete();
+
+ $this->actingAs($owner)->postJson(route('api.v1.rooms.member.add', ['room' => $room]), ['user' => $newUser->id, 'role' => RoomUserRole::USER])
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
/**
@@ -803,6 +825,17 @@ public function test_remove_member()
$this->actingAs($newUser)->getJson(route('api.v1.rooms.show', ['room' => $room]))
->assertStatus(200)
->assertJsonFragment(['is_member' => false]);
+
+ // Remove member of deleted room
+ $room->delete();
+
+ $this->actingAs($newUser)->getJson(route('api.v1.rooms.show', ['room' => $room]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
/**
@@ -869,6 +902,17 @@ public function test_change_member_role()
$this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
+
+ // Test with deleted room
+ $room->delete();
+
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
public function test_bulk_import_members()
@@ -1027,6 +1071,17 @@ public function test_bulk_import_members()
$this->actingAs($this->user)->postJson(route('api.v1.rooms.member.bulkImport', ['room' => $room]), ['user_emails' => [$newUser->email], 'role' => RoomUserRole::USER])
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
+
+ // Test with deleted room
+ $room->delete();
+
+ $this->actingAs($owner)->postJson(route('api.v1.rooms.member.bulkImport', ['room' => $room]), ['user_emails' => [$newUser->email], 'role' => RoomUserRole::USER])
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
public function test_bulk_update_members()
@@ -1178,6 +1233,19 @@ public function test_bulk_update_members()
route('api.v1.rooms.member.bulkUpdate', ['room' => $room]),
['users' => [$memberUser->id], 'role' => RoomUserRole::MODERATOR]
)->assertForbidden();
+
+ // Test with deleted room
+ $room->delete();
+
+ $this->actingAs($owner)->putJson(
+ route('api.v1.rooms.member.bulkUpdate', ['room' => $room]),
+ ['users' => [$memberUser->id], 'role' => RoomUserRole::MODERATOR]
+ )->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
public function test_bulk_remove_members()
@@ -1275,5 +1343,16 @@ public function test_bulk_remove_members()
// Remove yourself as co-owner
$this->actingAs($memberCoOwner)->deleteJson(route('api.v1.rooms.member.bulkDestroy', ['room' => $room]), ['users' => [$memberUser->id, $memberCoOwner->id]])
->assertUnprocessable();
+
+ // Test with deleted room
+ $room->delete();
+
+ $this->actingAs($owner)->deleteJson(route('api.v1.rooms.member.bulkDestroy', ['room' => $room]), ['users' => [$memberUser->id]])
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/Room/RoomDescriptionTest.php b/tests/Backend/Feature/api/v1/Room/RoomDescriptionTest.php
index f8f5883f3..6c4bbff71 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomDescriptionTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomDescriptionTest.php
@@ -300,5 +300,16 @@ public function test_update_description_data()
->assertUnprocessable();
$room->refresh();
$this->assertNull($room->description);
+
+ // Test deleted room
+ $room->delete();
+
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.description.update', ['room' => $room]), ['description' => $this->faker->text(100)])
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
index d9e401537..b83abc275 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
@@ -530,5 +530,17 @@ public function test_delete()
'model' => 'room_personalized_link',
'ids' => [$link->id],
]);
+
+ // Test deleted room
+ $this->room->delete();
+
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$this->room->id],
+ ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php b/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php
index df0376b98..1977b0592 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php
@@ -179,6 +179,17 @@ public function test_meeting_list()
$this->actingAs($room->owner)->getJson(route('api.v1.rooms.meetings', ['room' => $room]).'?sort_direction=invalid')
->assertSuccessful()
->assertJsonPath('data.0.id', $meetings[0]->id);
+
+ // Test deleted room
+ $room->delete();
+
+ $this->actingAs($room->owner)->getJson(route('api.v1.rooms.meetings', ['room' => $room]).'?sort_direction=invalid')
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$room->id],
+ ]);
}
/**
From e6c6348e4b91f54d95d7041186aab45ac54ba27a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Wed, 8 Apr 2026 16:47:14 +0200
Subject: [PATCH 11/18] Use scope bindings instead of custom handling
---
.../api/v1/RoomMemberController.php | 18 ++----
.../api/v1/RoomPersonalizedLinkController.php | 28 ++++------
lang/en/app.php | 6 +-
.../components/RoomTabMembersDeleteButton.vue | 12 +++-
.../components/RoomTabMembersEditButton.vue | 12 +++-
.../RoomTabPersonalizedLinksDeleteButton.vue | 4 +-
.../RoomTabPersonalizedLinksEditButton.vue | 4 +-
resources/js/constants/modelNames.js | 1 +
routes/api.php | 38 +++++++------
.../Feature/api/v1/Room/MembershipTest.php | 52 ++++++++++-------
.../api/v1/Room/RoomPersonalizedLinkTest.php | 56 +++++++++++--------
.../e2e/RoomsViewMembersMemberActions.cy.js | 22 ++++----
...omsViewPersonalizedLinksTokenActions.cy.js | 8 ++-
13 files changed, 148 insertions(+), 113 deletions(-)
diff --git a/app/Http/Controllers/api/v1/RoomMemberController.php b/app/Http/Controllers/api/v1/RoomMemberController.php
index 99841c520..4ab2d713a 100644
--- a/app/Http/Controllers/api/v1/RoomMemberController.php
+++ b/app/Http/Controllers/api/v1/RoomMemberController.php
@@ -120,14 +120,11 @@ public function bulkImport(Room $room, BulkImportRequest $request)
*
* @return Response
*/
- public function update(Room $room, User $user, UpdateRoomMemberRequest $request)
+ public function update(Room $room, User $member, UpdateRoomMemberRequest $request)
{
- if (! $room->members->contains($user)) {
- abort(410, __('app.errors.not_member_of_room'));
- }
- $room->members()->updateExistingPivot($user, ['role' => $request->role]);
+ $room->members()->updateExistingPivot($member, ['role' => $request->role]);
- Log::info('Changed role for member {member} to {role} in room {room}', ['room' => $room->getLogLabel(), 'role' => RoomUserRole::from($request->role)->label(), 'member' => $user->getLogLabel()]);
+ Log::info('Changed role for member {member} to {role} in room {room}', ['room' => $room->getLogLabel(), 'role' => RoomUserRole::from($request->role)->label(), 'member' => $member->getLogLabel()]);
return response()->noContent();
}
@@ -153,14 +150,11 @@ public function bulkUpdate(Room $room, BulkUpdateRequest $request)
*
* @return Response
*/
- public function destroy(Room $room, User $user)
+ public function destroy(Room $room, User $member)
{
- if (! $room->members->contains($user)) {
- abort(410, __('app.errors.not_member_of_room'));
- }
- $room->members()->detach($user);
+ $room->members()->detach($member);
- Log::info('Removed member {member} from room {room}', ['room' => $room->getLogLabel(), 'member' => $user->getLogLabel()]);
+ Log::info('Removed member {member} from room {room}', ['room' => $room->getLogLabel(), 'member' => $member->getLogLabel()]);
return response()->noContent();
}
diff --git a/app/Http/Controllers/api/v1/RoomPersonalizedLinkController.php b/app/Http/Controllers/api/v1/RoomPersonalizedLinkController.php
index cb4dd8b5a..0f28c9359 100644
--- a/app/Http/Controllers/api/v1/RoomPersonalizedLinkController.php
+++ b/app/Http/Controllers/api/v1/RoomPersonalizedLinkController.php
@@ -101,20 +101,16 @@ public function store(Room $room, RoomPersonalizedLinkRequest $request)
*
* @return RoomPersonalizedLinkResource
*/
- public function update(Room $room, RoomPersonalizedLink $link, RoomPersonalizedLinkRequest $request)
+ public function update(Room $room, RoomPersonalizedLink $personalizedLink, RoomPersonalizedLinkRequest $request)
{
- if (! $link->room->is($room)) {
- abort(404, __('app.errors.personalized_link_not_found'));
- }
-
- $link->firstname = $request->firstname;
- $link->lastname = $request->lastname;
- $link->role = $request->role;
- $link->save();
+ $personalizedLink->firstname = $request->firstname;
+ $personalizedLink->lastname = $request->lastname;
+ $personalizedLink->role = $request->role;
+ $personalizedLink->save();
- Log::info('Updated personalized room link for guest {name} with the role {role} for room {room}', ['room' => $room->getLogLabel(), 'role' => $link->role->label(), 'name' => $link->fullname]);
+ Log::info('Updated personalized room link for guest {name} with the role {role} for room {room}', ['room' => $room->getLogLabel(), 'role' => $personalizedLink->role->label(), 'name' => $personalizedLink->fullname]);
- return new RoomPersonalizedLinkResource($link);
+ return new RoomPersonalizedLinkResource($personalizedLink);
}
/**
@@ -124,15 +120,11 @@ public function update(Room $room, RoomPersonalizedLink $link, RoomPersonalizedL
*
* @throws \Exception
*/
- public function destroy(Room $room, RoomPersonalizedLink $link)
+ public function destroy(Room $room, RoomPersonalizedLink $personalizedLink)
{
- if (! $link->room->is($room)) {
- abort(404, __('app.errors.personalized_link_not_found'));
- }
-
- $link->delete();
+ $personalizedLink->delete();
- Log::info('Removed personalized room link for guest {name} with the role {role} for room {room}', ['room' => $room->getLogLabel(), 'role' => $link->role->label(), 'name' => $link->fullname]);
+ Log::info('Removed personalized room link for guest {name} with the role {role} for room {room}', ['room' => $room->getLogLabel(), 'role' => $personalizedLink->role->label(), 'name' => $personalizedLink->fullname]);
return response()->noContent();
}
diff --git a/lang/en/app.php b/lang/en/app.php
index 68b020ab1..b4f8f8ad6 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -41,7 +41,7 @@
'membership_disabled' => 'Membership failed! Membership for this room is currently not available.',
'no_room_access' => 'You does not have the necessary permissions, to edit this room.',
'no_server_available' => 'Currently there are no servers available.',
- 'not_member_of_room' => 'The person is not a member of this room (anymore).',
+ 'not_member_of_room' => 'The user is not a member of this room.',
'not_running' => 'Joining the room has failed as it is currently closed.',
'personalized_link_not_found' => 'The personalized room link could not be found.',
'record_agreement_missing' => 'Consent to the recording is required.',
@@ -66,7 +66,7 @@
'guests_only' => 'The request can only be made by guests!',
'model_not_found' => [
'title' => 'The :model was not found!',
- 'details' => ' Model ids: :ids',
+ 'details' => ' Model id: :ids',
],
'server_error' => [
'empty_message' => 'An error occurred on the server during request!',
@@ -99,7 +99,7 @@
'fr' => 'French',
],
'model' => [
- 'meeting' => 'meeting',
+ 'meeting' => 'Meeting',
'role' => 'Role',
'roles' => 'role',
'room' => 'Room',
diff --git a/resources/js/components/RoomTabMembersDeleteButton.vue b/resources/js/components/RoomTabMembersDeleteButton.vue
index cf30ba516..06c481399 100644
--- a/resources/js/components/RoomTabMembersDeleteButton.vue
+++ b/resources/js/components/RoomTabMembersDeleteButton.vue
@@ -56,6 +56,9 @@
import env from "../env";
import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
+import { USER } from "../constants/modelNames.js";
+import { useToast } from "../composables/useToast.js";
+import { useI18n } from "vue-i18n";
const props = defineProps({
roomId: {
@@ -83,6 +86,8 @@ const props = defineProps({
const emit = defineEmits(["deleted", "gone"]);
const api = useApi();
+const toast = useToast();
+const { t } = useI18n();
const modalVisible = ref(false);
const isLoadingAction = ref(false);
@@ -106,9 +111,14 @@ function deleteMember() {
// editing failed
if (error.response) {
// user not found
- if (error.response.status === env.HTTP_GONE) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model === USER
+ ) {
+ toast.error(t("app.errors.not_member_of_room"));
emit("gone");
modalVisible.value = false;
+ return;
}
}
api.error(error, { redirectOnUnauthenticated: false });
diff --git a/resources/js/components/RoomTabMembersEditButton.vue b/resources/js/components/RoomTabMembersEditButton.vue
index 8a02bed35..518837fca 100644
--- a/resources/js/components/RoomTabMembersEditButton.vue
+++ b/resources/js/components/RoomTabMembersEditButton.vue
@@ -99,6 +99,9 @@ import env from "../env";
import { useApi } from "../composables/useApi.js";
import { useFormErrors } from "../composables/useFormErrors.js";
import { ref } from "vue";
+import { USER } from "../constants/modelNames.js";
+import { useToast } from "../composables/useToast.js";
+import { useI18n } from "vue-i18n";
const props = defineProps({
roomId: {
@@ -131,6 +134,8 @@ const emit = defineEmits(["edited", "gone"]);
const api = useApi();
const formErrors = useFormErrors();
+const toast = useToast();
+const { t } = useI18n();
const modalVisible = ref(false);
const newRole = ref(null);
@@ -168,9 +173,14 @@ function save() {
// editing failed
if (error.response) {
// user not found
- if (error.response.status === env.HTTP_GONE) {
+ if (
+ error.response.status === env.HTTP_NOT_FOUND &&
+ error.response.data?.model === USER
+ ) {
+ toast.error(t("app.errors.not_member_of_room"));
emit("gone");
modalVisible.value = false;
+ return;
}
// failed due to form validation errors
if (error.response.status === env.HTTP_UNPROCESSABLE_ENTITY) {
diff --git a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
index 57a584477..aa7f1ca78 100644
--- a/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksDeleteButton.vue
@@ -59,7 +59,7 @@ import { useApi } from "../composables/useApi.js";
import { ref } from "vue";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM } from "../constants/modelNames.js";
+import { ROOM_PERSONALIZED_LINK } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -123,7 +123,7 @@ function deleteLink() {
// personalized link not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM
+ error.response.data?.model === ROOM_PERSONALIZED_LINK
) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
diff --git a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
index 91bd5a472..937988c60 100644
--- a/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
+++ b/resources/js/components/RoomTabPersonalizedLinksEditButton.vue
@@ -110,7 +110,7 @@ import { ref } from "vue";
import env from "../env.js";
import { useToast } from "../composables/useToast.js";
import { useI18n } from "vue-i18n";
-import { ROOM } from "../constants/modelNames.js";
+import { ROOM_PERSONALIZED_LINK } from "../constants/modelNames.js";
const props = defineProps({
roomId: {
@@ -192,7 +192,7 @@ function save() {
// token not found
if (
error.response.status === env.HTTP_NOT_FOUND &&
- error.response.data?.model !== ROOM
+ error.response.data?.model === ROOM_PERSONALIZED_LINK
) {
toast.error(t("rooms.flash.personalized_link_gone"));
modalVisible.value = false;
diff --git a/resources/js/constants/modelNames.js b/resources/js/constants/modelNames.js
index 0e304dc45..60d9f8a1e 100644
--- a/resources/js/constants/modelNames.js
+++ b/resources/js/constants/modelNames.js
@@ -2,3 +2,4 @@ export const ROOM = "room";
export const ROOM_FILE = "room_file";
export const ROOM_PERSONALIZED_LINK = "room_personalized_link";
export const RECORDING = "recording";
+export const USER = "user";
diff --git a/routes/api.php b/routes/api.php
index 57eec82ee..a550ca44a 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -73,7 +73,7 @@
Route::get('rooms', [RoomController::class, 'index'])->name('rooms.index');
Route::post('rooms', [RoomController::class, 'store'])->name('rooms.store');
- Route::middleware('throttle:room-enumeration')->group(function () {
+ Route::middleware('throttle:room-enumeration')->scopeBindings()->group(function () {
Route::post('rooms/{room}/favorites', [RoomController::class, 'addToFavorites'])->name('rooms.favorites.add');
Route::delete('rooms/{room}/favorites', [RoomController::class, 'deleteFromFavorites'])->name('rooms.favorites.delete');
Route::put('rooms/{room}', [RoomController::class, 'update'])->name('rooms.update');
@@ -89,30 +89,33 @@
Route::post('rooms/{room}/membership', [RoomMemberController::class, 'join'])->name('rooms.membership.join');
Route::delete('rooms/{room}/membership', [RoomMemberController::class, 'leave'])->name('rooms.membership.leave');
- // Membership users for mass update & delete
- Route::post('rooms/{room}/member/bulk', [RoomMemberController::class, 'bulkImport'])->name('rooms.member.bulkImport')->middleware('can:manageMembers,room');
- Route::put('rooms/{room}/member/bulk', [RoomMemberController::class, 'bulkUpdate'])->name('rooms.member.bulkUpdate')->middleware('can:manageMembers,room');
- Route::delete('rooms/{room}/member/bulk', [RoomMemberController::class, 'bulkDestroy'])->name('rooms.member.bulkDestroy')->middleware('can:manageMembers,room');
-
// Membership operations by room owner
Route::get('rooms/{room}/member', [RoomMemberController::class, 'index'])->name('rooms.member.get')->middleware('can:viewMembers,room');
- Route::post('rooms/{room}/member', [RoomMemberController::class, 'store'])->name('rooms.member.add')->middleware('can:manageMembers,room');
- Route::put('rooms/{room}/member/{user}', [RoomMemberController::class, 'update'])->name('rooms.member.update')->middleware('can:manageMembers,room');
- Route::delete('rooms/{room}/member/{user}', [RoomMemberController::class, 'destroy'])->name('rooms.member.destroy')->middleware('can:manageMembers,room');
+
+ Route::middleware('can:manageMembers,room')->group(function () {
+ // Membership users for mass update & delete
+ Route::post('rooms/{room}/member/bulk', [RoomMemberController::class, 'bulkImport'])->name('rooms.member.bulkImport');
+ Route::put('rooms/{room}/member/bulk', [RoomMemberController::class, 'bulkUpdate'])->name('rooms.member.bulkUpdate');
+ Route::delete('rooms/{room}/member/bulk', [RoomMemberController::class, 'bulkDestroy'])->name('rooms.member.bulkDestroy');
+
+ Route::post('rooms/{room}/member', [RoomMemberController::class, 'store'])->name('rooms.member.add');
+ Route::put('rooms/{room}/member/{member}', [RoomMemberController::class, 'update'])->name('rooms.member.update');
+ Route::delete('rooms/{room}/member/{member}', [RoomMemberController::class, 'destroy'])->name('rooms.member.destroy');
+ });
// Recording operations
- Route::middleware('can:manageRecordings,room')->scopeBindings()->group(function () {
+ Route::middleware('can:manageRecordings,room')->group(function () {
Route::put('rooms/{room}/recordings/{recording}', [RecordingController::class, 'update'])->name('rooms.recordings.update');
Route::delete('rooms/{room}/recordings/{recording}', [RecordingController::class, 'destroy'])->name('rooms.recordings.destroy');
});
// Streaming operations
- Route::middleware('can:viewStreaming,room')->scopeBindings()->group(function () {
+ Route::middleware('can:viewStreaming,room')->group(function () {
Route::get('rooms/{room}/streaming/config', [RoomStreamingController::class, 'getConfig'])->name('rooms.streaming.config.get');
Route::get('rooms/{room}/streaming/status', [RoomStreamingController::class, 'status'])->name('rooms.streaming.status');
});
- Route::middleware('can:manageStreaming,room')->scopeBindings()->group(function () {
+ Route::middleware('can:manageStreaming,room')->group(function () {
Route::put('rooms/{room}/streaming/config', [RoomStreamingController::class, 'updateConfig'])->name('rooms.streaming.config.update');
Route::post('rooms/{room}/streaming/start', [RoomStreamingController::class, 'start'])->name('rooms.streaming.start');
Route::post('rooms/{room}/streaming/stop', [RoomStreamingController::class, 'stop'])->name('rooms.streaming.stop');
@@ -122,12 +125,15 @@
// Personalized room links
Route::get('rooms/{room}/personalizedLinks', [RoomPersonalizedLinkController::class, 'index'])->name('rooms.personalizedLinks.get')->middleware('can:viewPersonalizedLinks,room');
- Route::post('rooms/{room}/personalizedLinks', [RoomPersonalizedLinkController::class, 'store'])->name('rooms.personalizedLinks.add')->middleware('can:managePersonalizedLinks,room');
- Route::put('rooms/{room}/personalizedLinks/{link}', [RoomPersonalizedLinkController::class, 'update'])->name('rooms.personalizedLinks.update')->middleware('can:managePersonalizedLinks,room');
- Route::delete('rooms/{room}/personalizedLinks/{link}', [RoomPersonalizedLinkController::class, 'destroy'])->name('rooms.personalizedLinks.destroy')->middleware('can:managePersonalizedLinks,room');
+
+ Route::middleware('can:managePersonalizedLinks,room')->group(function () {
+ Route::post('rooms/{room}/personalizedLinks', [RoomPersonalizedLinkController::class, 'store'])->name('rooms.personalizedLinks.add');
+ Route::put('rooms/{room}/personalizedLinks/{personalizedLink}', [RoomPersonalizedLinkController::class, 'update'])->name('rooms.personalizedLinks.update');
+ Route::delete('rooms/{room}/personalizedLinks/{personalizedLink}', [RoomPersonalizedLinkController::class, 'destroy'])->name('rooms.personalizedLinks.destroy');
+ });
// File operations
- Route::middleware('can:manageFiles,room')->scopeBindings()->group(function () {
+ Route::middleware('can:manageFiles,room')->group(function () {
Route::post('rooms/{room}/files', [RoomFileController::class, 'store'])->name('rooms.files.add');
Route::put('rooms/{room}/files/{file}', [RoomFileController::class, 'update'])->name('rooms.files.update');
Route::delete('rooms/{room}/files/{file}', [RoomFileController::class, 'destroy'])->name('rooms.files.destroy');
diff --git a/tests/Backend/Feature/api/v1/Room/MembershipTest.php b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
index 9b617cc0e..eb6e0eccf 100644
--- a/tests/Backend/Feature/api/v1/Room/MembershipTest.php
+++ b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
@@ -767,42 +767,42 @@ public function test_remove_member()
$room->members()->attach($memberCoOwner, ['role' => RoomUserRole::CO_OWNER]);
// Remove member as guest
- $this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertUnauthorized();
// Remove member as non owner
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertForbidden();
// Remove member as user member
- $this->actingAs($memberUser)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->actingAs($memberUser)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertForbidden();
// Remove member as moderator member
- $this->actingAs($memberModerator)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->actingAs($memberModerator)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertForbidden();
// Remove member as co-owner member
- $this->actingAs($memberCoOwner)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->actingAs($memberCoOwner)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertNoContent();
$room->members()->attach($newUser, ['role' => RoomUserRole::USER]);
// Remove with view all rooms permission
$this->user->roles()->attach($this->role);
$this->role->permissions()->attach($this->viewAllPermission);
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertForbidden();
$this->role->permissions()->detach($this->viewAllPermission);
// Remove with manage rooms permission
$this->role->permissions()->attach($this->managePermission);
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
$room->members()->attach($newUser, ['role' => RoomUserRole::USER]);
// Remove member with invalid user
- $this->actingAs($owner)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => 0]))
+ $this->actingAs($owner)->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => 0]))
->assertNotFound()
->assertJson([
'message' => 'model_not_found',
@@ -811,15 +811,20 @@ public function test_remove_member()
]);
// Remove member as moderator
- $this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
+ $this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
->assertNoContent();
// Check member list
$this->assertNull($room->members()->find($newUser));
// Try to remove user again
- $this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'user' => $newUser]))
- ->assertStatus(410);
+ $this->deleteJson(route('api.v1.rooms.member.destroy', ['room' => $room, 'member' => $newUser]))
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [$newUser->id],
+ ]);
// Check if user is no member
$this->actingAs($newUser)->getJson(route('api.v1.rooms.show', ['room' => $room]))
@@ -863,50 +868,55 @@ public function test_change_member_role()
$room->members()->attach($memberCoOwner, ['role' => RoomUserRole::CO_OWNER]);
// Update with wrong role
- $this->actingAs($owner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => 10])
+ $this->actingAs($owner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => 10])
->assertJsonValidationErrors(['role']);
// Update role
- $this->actingAs($owner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($owner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertNoContent();
// Update role for wrong user
- $this->actingAs($owner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $otherUser]), ['role' => RoomUserRole::MODERATOR])
- ->assertStatus(410);
+ $this->actingAs($owner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $otherUser]), ['role' => RoomUserRole::MODERATOR])
+ ->assertNotFound()
+ ->assertJson([
+ 'message' => 'model_not_found',
+ 'model' => 'user',
+ 'ids' => [$otherUser->id],
+ ]);
// Check if member role is changed
$foundNewUser = $room->members()->find($newUser);
$this->assertEquals(RoomUserRole::MODERATOR, $foundNewUser->pivot->role);
// Update role as member user
- $this->actingAs($memberUser)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($memberUser)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertForbidden();
// Update role as member moderator
- $this->actingAs($memberModerator)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($memberModerator)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertForbidden();
// Update role as member co-owner
- $this->actingAs($memberCoOwner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($memberCoOwner)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertNoContent();
// Update role with view all rooms permission
$this->user->roles()->attach($this->role);
$this->role->permissions()->attach($this->viewAllPermission);
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertForbidden();
$this->role->permissions()->detach($this->viewAllPermission);
// Update role with manage rooms permission
$this->role->permissions()->attach($this->managePermission);
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
// Test with deleted room
$room->delete();
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'user' => $newUser]), ['role' => RoomUserRole::MODERATOR])
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.member.update', ['room' => $room, 'member' => $newUser]), ['role' => RoomUserRole::MODERATOR])
->assertNotFound()
->assertJson([
'message' => 'model_not_found',
diff --git a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
index b83abc275..1b3519985 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
@@ -326,7 +326,7 @@ public function test_update()
];
// Update as guest
- $this->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $this->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertUnauthorized()
->assertJsonFragment(['message' => 'Unauthenticated.']);
@@ -342,7 +342,7 @@ public function test_update()
$this->putJson(route('api.v1.rooms.personalizedLinks.update', [
'room' => $this->room,
- 'link' => $link,
+ 'personalizedLink' => $link,
'room_auth_token' => $roomAuthToken->id,
'room_auth_token_type' => RoomAuthTokenType::PERSONALIZED_LINK->value,
]), $payload)
@@ -351,7 +351,7 @@ public function test_update()
// Update as moderator
$this->room->members()->sync([$this->user->id => ['role' => RoomUserRole::MODERATOR]]);
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => 1337, 'link' => $link]), $payload)
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => 1337, 'personalizedLink' => $link]), $payload)
->assertNotFound()
->assertJson(
[
@@ -360,12 +360,12 @@ public function test_update()
'ids' => [1337],
]);
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertForbidden();
// Update as co-owner invalid data
$this->room->members()->sync([$this->user->id => ['role' => RoomUserRole::CO_OWNER]]);
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertJsonValidationErrors([
'firstname',
'lastname',
@@ -378,7 +378,7 @@ public function test_update()
'lastname' => $this->faker->lastName,
'role' => RoomUserRole::USER,
];
- $response = $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $response = $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertSuccessful()
->assertJsonMissingValidationErrors([
'firstname',
@@ -393,7 +393,7 @@ public function test_update()
'lastname' => $this->faker->lastName,
'role' => RoomUserRole::USER,
];
- $response = $this->actingAs($this->room->owner)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $response = $this->actingAs($this->room->owner)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertSuccessful()
->assertJsonMissingValidationErrors([
'firstname',
@@ -410,7 +410,7 @@ public function test_update()
];
$this->room->members()->sync([]);
$this->user->roles()->attach(Role::where(['superuser' => true])->first());
- $response = $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertSuccessful()
->assertJsonMissingValidationErrors([
'firstname',
@@ -419,13 +419,18 @@ public function test_update()
]);
// Check trying to update with wrong room id
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $otherRoom, 'link' => $link]), $payload)
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $otherRoom, 'personalizedLink' => $link]), $payload)
->assertNotFound()
- ->assertJsonFragment(['message' => __('app.errors.personalized_link_not_found')]);
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room_personalized_link',
+ 'ids' => [$link->id],
+ ]);
// Test deleted
$link->delete();
- $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'link' => $link]), $payload)
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
->assertNotFound()
->assertJson(
[
@@ -448,7 +453,7 @@ public function test_delete()
]);
// Delete as guest
- $this->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertUnauthorized()
->assertJsonFragment(['message' => 'Unauthenticated.']);
@@ -464,7 +469,7 @@ public function test_delete()
$this->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', [
'room' => $this->room,
- 'link' => $link,
+ 'personalizedLink' => $link,
'room_auth_token' => $roomAuthToken->id,
'room_auth_token_type' => RoomAuthTokenType::PERSONALIZED_LINK->value,
]))
@@ -473,16 +478,16 @@ public function test_delete()
// Delete as moderator
$this->room->members()->sync([$this->user->id => ['role' => RoomUserRole::MODERATOR]]);
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertForbidden();
// Delete as co-owner
$this->room->members()->sync([$this->user->id => ['role' => RoomUserRole::CO_OWNER]]);
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertSuccessful();
// Delete not existing
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertNotFound()
->assertJson(
[
@@ -495,9 +500,9 @@ public function test_delete()
$link = RoomPersonalizedLink::factory()->create([
'room_id' => $this->room,
]);
- $this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertSuccessful();
- $this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertNotFound()
->assertJson(
[
@@ -514,15 +519,20 @@ public function test_delete()
]);
// Check trying to delete with wrong room id
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $otherRoom, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $otherRoom, 'personalizedLink' => $link]))
->assertNotFound()
- ->assertJsonFragment(['message' => __('app.errors.personalized_link_not_found')]);
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room_personalized_link',
+ 'ids' => [$link->id],
+ ]);
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertSuccessful();
// Test delete again
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertNotFound()
->assertJson(
[
@@ -534,7 +544,7 @@ public function test_delete()
// Test deleted room
$this->room->delete();
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'link' => $link]))
+ $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
->assertNotFound()
->assertJson(
[
diff --git a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
index 7869c0b38..0947f2ca6 100644
--- a/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewMembersMemberActions.cy.js
@@ -580,9 +580,11 @@ describe("Rooms view members member actions", function () {
// Check with member gone
cy.intercept("PUT", "/api/v1/rooms/abc-def-123/member/5", {
- statusCode: 410,
+ statusCode: 404,
body: {
- message: "The person is not a member of this room (anymore).",
+ message: "model_not_found",
+ model: "user",
+ ids: [5],
},
}).as("editUserRequest");
@@ -610,10 +612,7 @@ describe("Rooms view members member actions", function () {
cy.get('[data-test="room-member-item"]').should("have.length", 2);
// Check that error message is shown
- cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"The person is not a member of this room (anymore)."}',
- 'app.flash.server_error.error_code_{"statusCode":410}',
- ]);
+ cy.checkToastMessage("app.errors.not_member_of_room");
// Check with 422 error
cy.get('[data-test="room-member-item"]')
@@ -808,9 +807,11 @@ describe("Rooms view members member actions", function () {
// Check delete with member gone
cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/member/5", {
- statusCode: 410,
+ statusCode: 404,
body: {
- message: "The person is not a member of this room (anymore).",
+ message: "model_not_found",
+ model: "user",
+ ids: [5],
},
}).as("deleteMemberRequest");
@@ -836,10 +837,7 @@ describe("Rooms view members member actions", function () {
cy.get('[data-test="room-member-item"]').should("have.length", 2);
// Check that error message is shown
- cy.checkToastMessage([
- 'app.flash.server_error.message_{"message":"The person is not a member of this room (anymore)."}',
- 'app.flash.server_error.error_code_{"statusCode":410}',
- ]);
+ cy.checkToastMessage("app.errors.not_member_of_room");
// Check with 500 error
cy.get('[data-test="room-member-item"]')
diff --git a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
index 380333e97..8cdf74b72 100644
--- a/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
+++ b/tests/Frontend/e2e/RoomsViewPersonalizedLinksTokenActions.cy.js
@@ -432,7 +432,9 @@ describe("Rooms view personalized links actions", function () {
cy.intercept("PUT", "/api/v1/rooms/abc-def-123/personalizedLinks/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "room_personalized_link",
+ ids: [3],
},
}).as("editLinkRequest");
@@ -706,7 +708,9 @@ describe("Rooms view personalized links actions", function () {
cy.intercept("DELETE", "/api/v1/rooms/abc-def-123/personalizedLinks/3", {
statusCode: 404,
body: {
- message: "No query results for model",
+ message: "model_not_found",
+ model: "room_personalized_link",
+ ids: [3],
},
}).as("deleteLinkRequest");
From f31f2c4672b447a68d1bc93da5d228f6bbeec37e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 10 Apr 2026 09:38:55 +0200
Subject: [PATCH 12/18] Add missing model translations
---
lang/en/app.php | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/lang/en/app.php b/lang/en/app.php
index c3bc93621..eee5aaf70 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -101,18 +101,36 @@
'fr' => 'French',
],
'model' => [
+ 'included_permission_permission' => 'Included permission',
'meeting' => 'Meeting',
+ 'meeting_attendee' => 'Meeting attendee',
+ 'meeting_stat' => 'Meeting stat',
+ 'permission' => 'Permission',
+ 'permission_role' => 'Permission role',
+ 'recording' => 'Recording',
+ 'recording_format' => 'Recording format',
'role' => 'Role',
+ 'role_user' => 'Role user',
'roles' => 'role',
'room' => 'Room',
+ 'room_auth_token' => 'Room auth token',
+ 'room_file' => 'Room file',
+ 'room_personalized_link' => 'Room personalized link',
+ 'room_streaming' => 'Room streaming',
'room_type' => 'Room type',
'room_types' => 'room type',
+ 'room_type_streaming_settings' => 'Room type streaming settings',
+ 'room_user' => 'Room user',
'server' => 'Server',
'server_pool' => 'Server pool',
'server_pools' => 'server pool',
+ 'server_stat' => 'Server stat',
+ 'session' => 'Session',
+ 'session_data' => 'Session data',
'servers' => 'server',
'user' => 'User',
'users' => 'user',
+ 'verify_email' => 'Verify Email',
],
'model_name' => 'Name',
'next' => 'Next',
From fa24bdc2684bf0d20304f67b1a50f90591ca5ffa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 10 Apr 2026 09:43:39 +0200
Subject: [PATCH 13/18] Remove custom 404 handling for server connection check
---
resources/js/views/AdminServersView.vue | 4 ----
1 file changed, 4 deletions(-)
diff --git a/resources/js/views/AdminServersView.vue b/resources/js/views/AdminServersView.vue
index 4a0b85848..1a57f8abb 100644
--- a/resources/js/views/AdminServersView.vue
+++ b/resources/js/views/AdminServersView.vue
@@ -521,10 +521,6 @@ function testConnection() {
health.value = null;
offlineReason.value = null;
- if (error.response && error.response.status === env.HTTP_NOT_FOUND) {
- router.push({ name: "admin.servers" });
- }
-
api.error(error);
})
.finally(() => {
From fb9b10a123cdc2af9784361060cd7235e896829a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 10 Apr 2026 09:55:17 +0200
Subject: [PATCH 14/18] Cleanup backend tests
---
.../Backend/Feature/api/v1/RecordingTest.php | 12 ----
.../Backend/Feature/api/v1/Room/FileTest.php | 25 -------
.../Feature/api/v1/Room/MembershipTest.php | 68 -------------------
.../api/v1/Room/RoomPersonalizedLinkTest.php | 24 +++----
.../Feature/api/v1/Room/RoomStatisticTest.php | 11 ---
5 files changed, 12 insertions(+), 128 deletions(-)
diff --git a/tests/Backend/Feature/api/v1/RecordingTest.php b/tests/Backend/Feature/api/v1/RecordingTest.php
index da80e5a66..525729b5d 100644
--- a/tests/Backend/Feature/api/v1/RecordingTest.php
+++ b/tests/Backend/Feature/api/v1/RecordingTest.php
@@ -1261,18 +1261,6 @@ public function test_delete()
'model' => 'recording',
'ids' => [$recording->id],
]);
-
- // Test with deleted room
- $room->delete();
-
- $this->actingAs($room->owner)
- ->deleteJson(route('api.v1.rooms.recordings.destroy', ['room' => $room->id, 'recording' => $recording->id]))
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
public function test_delete_on_room_delete()
diff --git a/tests/Backend/Feature/api/v1/Room/FileTest.php b/tests/Backend/Feature/api/v1/Room/FileTest.php
index 68538c75d..5eb509afb 100644
--- a/tests/Backend/Feature/api/v1/Room/FileTest.php
+++ b/tests/Backend/Feature/api/v1/Room/FileTest.php
@@ -350,18 +350,6 @@ public function test_view_files()
->assertJsonCount(0, 'data')
->assertJsonPath('meta.total', 0)
->assertJsonPath('meta.total_no_filter', 3);
-
- // Test deleted room
- $this->room->delete();
-
- $this->actingAs($this->room->owner)
- ->getJson(route('api.v1.rooms.files.get', ['room' => $this->room, 'query' => 'test']))
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$this->room->id],
- ]);
}
/**
@@ -1102,19 +1090,6 @@ public function test_files_delete()
// Check if file was deleted as well
Storage::disk('local')->assertMissing($this->room->id.'/'.$this->file_valid->hashName());
-
- // Test delete with deleted room
- $this->room->delete();
-
- $this->actingAs($this->room->owner)->deleteJson(route('api.v1.rooms.files.destroy', ['room' => $this->room->id, 'file' => $room_file]))
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [
- $this->room->id,
- ],
- ]);
}
/**
diff --git a/tests/Backend/Feature/api/v1/Room/MembershipTest.php b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
index fa6d42d23..51fe6241a 100644
--- a/tests/Backend/Feature/api/v1/Room/MembershipTest.php
+++ b/tests/Backend/Feature/api/v1/Room/MembershipTest.php
@@ -632,17 +632,6 @@ public function test_member_list()
$this->actingAs($room->owner)->getJson(route('api.v1.rooms.member.get', ['room' => $room, 'filter' => 'invalid_role']))
->assertJsonCount(5, 'data')
->assertJsonPath('meta.total', 6);
-
- // Test deleted room
- $room->delete();
-
- $this->actingAs($room->owner)->getJson(route('api.v1.rooms.member.get', ['room' => $room, 'filter' => 'invalid_role']))
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
/**
@@ -732,17 +721,6 @@ public function test_add_member()
$this->actingAs($this->user)->postJson(route('api.v1.rooms.member.add', ['room' => $room]), ['user' => $newUser->id, 'role' => RoomUserRole::USER])
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
-
- // Test with deleted room
- $room->delete();
-
- $this->actingAs($owner)->postJson(route('api.v1.rooms.member.add', ['room' => $room]), ['user' => $newUser->id, 'role' => RoomUserRole::USER])
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
/**
@@ -832,17 +810,6 @@ public function test_remove_member()
$this->actingAs($newUser)->getJson(route('api.v1.rooms.show', ['room' => $room]))
->assertStatus(200)
->assertJsonFragment(['is_member' => false]);
-
- // Remove member of deleted room
- $room->delete();
-
- $this->actingAs($newUser)->getJson(route('api.v1.rooms.show', ['room' => $room]))
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
/**
@@ -1083,17 +1050,6 @@ public function test_bulk_import_members()
$this->actingAs($this->user)->postJson(route('api.v1.rooms.member.bulkImport', ['room' => $room]), ['user_emails' => [$newUser->email], 'role' => RoomUserRole::USER])
->assertNoContent();
$this->role->permissions()->detach($this->managePermission);
-
- // Test with deleted room
- $room->delete();
-
- $this->actingAs($owner)->postJson(route('api.v1.rooms.member.bulkImport', ['room' => $room]), ['user_emails' => [$newUser->email], 'role' => RoomUserRole::USER])
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
public function test_bulk_update_members()
@@ -1245,19 +1201,6 @@ public function test_bulk_update_members()
route('api.v1.rooms.member.bulkUpdate', ['room' => $room]),
['users' => [$memberUser->id], 'role' => RoomUserRole::MODERATOR]
)->assertForbidden();
-
- // Test with deleted room
- $room->delete();
-
- $this->actingAs($owner)->putJson(
- route('api.v1.rooms.member.bulkUpdate', ['room' => $room]),
- ['users' => [$memberUser->id], 'role' => RoomUserRole::MODERATOR]
- )->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
public function test_bulk_remove_members()
@@ -1355,16 +1298,5 @@ public function test_bulk_remove_members()
// Remove yourself as co-owner
$this->actingAs($memberCoOwner)->deleteJson(route('api.v1.rooms.member.bulkDestroy', ['room' => $room]), ['users' => [$memberUser->id, $memberCoOwner->id]])
->assertUnprocessable();
-
- // Test with deleted room
- $room->delete();
-
- $this->actingAs($owner)->deleteJson(route('api.v1.rooms.member.bulkDestroy', ['room' => $room]), ['users' => [$memberUser->id]])
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
index 7b3d21a3b..c63cb5cde 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomPersonalizedLinkTest.php
@@ -440,6 +440,18 @@ public function test_update()
'model' => 'room_personalized_link',
'ids' => [$link->id],
]);
+
+ // Test deleted room
+ $this->room->delete();
+
+ $this->actingAs($this->user)->putJson(route('api.v1.rooms.personalizedLinks.update', ['room' => $this->room, 'personalizedLink' => $link]), $payload)
+ ->assertNotFound()
+ ->assertJson(
+ [
+ 'message' => 'model_not_found',
+ 'model' => 'room',
+ 'ids' => [$this->room->id],
+ ]);
}
public function test_delete()
@@ -542,17 +554,5 @@ public function test_delete()
'model' => 'room_personalized_link',
'ids' => [$link->id],
]);
-
- // Test deleted room
- $this->room->delete();
-
- $this->actingAs($this->user)->deleteJson(route('api.v1.rooms.personalizedLinks.destroy', ['room' => $this->room, 'personalizedLink' => $link]))
- ->assertNotFound()
- ->assertJson(
- [
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$this->room->id],
- ]);
}
}
diff --git a/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php b/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php
index 8cf12c956..ef6788e49 100644
--- a/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php
+++ b/tests/Backend/Feature/api/v1/Room/RoomStatisticTest.php
@@ -181,17 +181,6 @@ public function test_meeting_list()
$this->actingAs($room->owner)->getJson(route('api.v1.rooms.meetings', ['room' => $room]).'?sort_direction=invalid')
->assertSuccessful()
->assertJsonPath('data.0.id', $meetings[0]->id);
-
- // Test deleted room
- $room->delete();
-
- $this->actingAs($room->owner)->getJson(route('api.v1.rooms.meetings', ['room' => $room]).'?sort_direction=invalid')
- ->assertNotFound()
- ->assertJson([
- 'message' => 'model_not_found',
- 'model' => 'room',
- 'ids' => [$room->id],
- ]);
}
/**
From 8c048e43d7daaf0d49c67a0c29c1fb3d04550fb3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 10 Apr 2026 16:36:01 +0200
Subject: [PATCH 15/18] Code cleanup
---
lang/en/app.php | 2 +-
tests/Frontend/e2e/RoomsViewGeneral.cy.js | 2 +-
tests/Frontend/e2e/RoomsViewSettings.cy.js | 8 ++++++--
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/lang/en/app.php b/lang/en/app.php
index eee5aaf70..b01ede5b5 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -68,7 +68,7 @@
'guests_only' => 'The request can only be made by guests!',
'model_not_found' => [
'title' => 'The :model was not found!',
- 'details' => ' Model id: :ids',
+ 'details' => 'Model id: :ids',
],
'server_error' => [
'empty_message' => 'An error occurred on the server during request!',
diff --git a/tests/Frontend/e2e/RoomsViewGeneral.cy.js b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
index 6b608b718..695e8e619 100644
--- a/tests/Frontend/e2e/RoomsViewGeneral.cy.js
+++ b/tests/Frontend/e2e/RoomsViewGeneral.cy.js
@@ -724,7 +724,7 @@ describe("Room View general", function () {
'app.flash.model_not_found.details_{"ids":"abc-def-123"}',
]);
- // Check wit 404 error (room not found) as guest
+ // Check with 404 error (room not found) as guest
cy.intercept("GET", "api/v1/currentUser", {});
cy.fixture("room.json").then((room) => {
room.data.current_user = null;
diff --git a/tests/Frontend/e2e/RoomsViewSettings.cy.js b/tests/Frontend/e2e/RoomsViewSettings.cy.js
index 0b8ada4ab..2bb2bd1ef 100644
--- a/tests/Frontend/e2e/RoomsViewSettings.cy.js
+++ b/tests/Frontend/e2e/RoomsViewSettings.cy.js
@@ -1402,6 +1402,8 @@ describe("Rooms view settings", function () {
cy.get('[data-test="room-settings-save-button"]').click();
+ cy.wait("@roomSettingsSaveRequest");
+
// Check that error messages are set
cy.get('[data-test="room-setting-access_code"]').should(
"include.text",
@@ -1695,7 +1697,7 @@ describe("Rooms view settings", function () {
model: "room",
ids: ["abc-def-123"],
},
- });
+ }).as("roomSettingsSaveRequest");
cy.get('[data-test="room-settings-save-button"]').click();
@@ -2370,7 +2372,9 @@ describe("Rooms view settings", function () {
cy.wait("@transferOwnershipRequest");
// Check that redirect to room index page worked and error message is shown
- cy.url().should("include", "/rooms");
+ cy.url()
+ .should("include", "/rooms")
+ .and("not.include", "rooms/abc-def-123");
cy.checkToastMessage([
'app.flash.model_not_found.title_{"model":"app.model.room"}',
From 256bf30993ebae6b8b69ccf8cc4a1487f316fd9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Mon, 13 Apr 2026 17:43:52 +0200
Subject: [PATCH 16/18] Code cleanup
---
lang/en/app.php | 2 +-
resources/js/views/RoomsView.vue | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lang/en/app.php b/lang/en/app.php
index b01ede5b5..33a4c3e13 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -68,7 +68,7 @@
'guests_only' => 'The request can only be made by guests!',
'model_not_found' => [
'title' => 'The :model was not found!',
- 'details' => 'Model id: :ids',
+ 'details' => 'Ids: :ids',
],
'server_error' => [
'empty_message' => 'An error occurred on the server during request!',
diff --git a/resources/js/views/RoomsView.vue b/resources/js/views/RoomsView.vue
index 0b3036066..911886698 100644
--- a/resources/js/views/RoomsView.vue
+++ b/resources/js/views/RoomsView.vue
@@ -439,7 +439,7 @@ function load() {
})
.catch((error) => {
if (error.response) {
- // Room not found (Always redirect to 404 view)
+ // Room not found (Always redirect to 404 view or room index page)
if (error.response.status === env.HTTP_NOT_FOUND) {
if (authStore.isAuthenticated) {
router.push({ name: "rooms.index" });
@@ -521,7 +521,7 @@ function reload() {
})
.catch((error) => {
if (error.response) {
- // Room not found (Always redirect to 404 view)
+ // Room not found (Always redirect to 404 view or room index page)
if (error.response.status === env.HTTP_NOT_FOUND) {
if (authStore.isAuthenticated) {
router.push({ name: "rooms.index" });
From d9c60023f48e36025af578f6b9a0dd3ff8fb4010 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 17 Apr 2026 15:30:36 +0200
Subject: [PATCH 17/18] Cleanup model translations
---
lang/en/app.php | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/lang/en/app.php b/lang/en/app.php
index 33a4c3e13..fe001afa4 100644
--- a/lang/en/app.php
+++ b/lang/en/app.php
@@ -101,36 +101,22 @@
'fr' => 'French',
],
'model' => [
- 'included_permission_permission' => 'Included permission',
'meeting' => 'Meeting',
- 'meeting_attendee' => 'Meeting attendee',
- 'meeting_stat' => 'Meeting stat',
- 'permission' => 'Permission',
- 'permission_role' => 'Permission role',
'recording' => 'Recording',
'recording_format' => 'Recording format',
'role' => 'Role',
- 'role_user' => 'Role user',
'roles' => 'role',
'room' => 'Room',
- 'room_auth_token' => 'Room auth token',
'room_file' => 'Room file',
'room_personalized_link' => 'Room personalized link',
- 'room_streaming' => 'Room streaming',
'room_type' => 'Room type',
'room_types' => 'room type',
- 'room_type_streaming_settings' => 'Room type streaming settings',
- 'room_user' => 'Room user',
'server' => 'Server',
'server_pool' => 'Server pool',
'server_pools' => 'server pool',
- 'server_stat' => 'Server stat',
- 'session' => 'Session',
- 'session_data' => 'Session data',
'servers' => 'server',
'user' => 'User',
'users' => 'user',
- 'verify_email' => 'Verify Email',
],
'model_name' => 'Name',
'next' => 'Next',
From 44f93870b03224077f2b77d8587795e8f5bf3357 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabrina=20W=C3=BCst?=
<119059706+Sabr1n4W@users.noreply.github.com>
Date: Fri, 17 Apr 2026 16:22:49 +0200
Subject: [PATCH 18/18] Update changelog
---
CHANGELOG.md | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdeced3b7..98b8d72ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Changed
+
+- Improved 404 error messages for better readability and clarity ([#86], [#3036])
+- Standardized 404 error handling on admin pages ([#1676], [#3036])
+- Improved and standardized room not found error handling in the room view ([#3036])
+
## [v4.14.1] - 2026-04-09
### Changed
@@ -534,6 +540,7 @@ You can find the changelog for older versions there [here](https://github.com/TH
[#31]: https://github.com/THM-Health/PILOS/issues/31
[#75]: https://github.com/THM-Health/PILOS/issues/75
[#77]: https://github.com/THM-Health/PILOS/issues/77
+[#86]: https://github.com/THM-Health/PILOS/issues/86
[#300]: https://github.com/THM-Health/PILOS/issues/300
[#315]: https://github.com/THM-Health/PILOS/issues/315
[#372]: https://github.com/THM-Health/PILOS/issues/372
@@ -630,6 +637,7 @@ You can find the changelog for older versions there [here](https://github.com/TH
[#1636]: https://github.com/THM-Health/PILOS/issues/1636
[#1651]: https://github.com/THM-Health/PILOS/issues/1651
[#1675]: https://github.com/THM-Health/PILOS/issues/1675
+[#1676]: https://github.com/THM-Health/PILOS/issues/1676
[#1677]: https://github.com/THM-Health/PILOS/issues/1677
[#1678]: https://github.com/THM-Health/PILOS/pull/1678
[#1679]: https://github.com/THM-Health/PILOS/issues/1679
@@ -763,6 +771,7 @@ You can find the changelog for older versions there [here](https://github.com/TH
[#3014]: https://github.com/THM-Health/PILOS/pull/3014
[#3028]: https://github.com/THM-Health/PILOS/issues/3028
[#3029]: https://github.com/THM-Health/PILOS/pull/3029
+[#3036]: https://github.com/THM-Health/PILOS/pull/3036
[unreleased]: https://github.com/THM-Health/PILOS/compare/v4.14.1...develop
[v3.0.0]: https://github.com/THM-Health/PILOS/releases/tag/v3.0.0
[v3.0.1]: https://github.com/THM-Health/PILOS/releases/tag/v3.0.1