diff --git a/ui/shared/notifications/redux/__tests__/reduxNotifications.test.jsx b/ui/shared/notifications/redux/__tests__/reduxNotifications.test.jsx
new file mode 100644
index 00000000000..58b7a23ee84
--- /dev/null
+++ b/ui/shared/notifications/redux/__tests__/reduxNotifications.test.jsx
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 - present Instructure, Inc.
+ *
+ * This file is part of Canvas.
+ *
+ * Canvas is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Affero General Public License as published by the Free
+ * Software Foundation, version 3 of the License.
+ *
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Affero General Public License along
+ * with this program. If not, see .
+ */
+
+import {subscribeFlashNotifications, notificationActions, reduceNotifications} from '../actions'
+import * as FlashAlert from '@canvas/alerts/react/FlashAlert'
+
+jest.mock('@canvas/alerts/react/FlashAlert', () => ({
+ showFlashAlert: jest.fn(),
+ destroyContainer: jest.fn(),
+}))
+
+const createMockStore = state => ({
+ subs: [],
+ subscribe(cb) {
+ this.subs.push(cb)
+ },
+ getState: () => state,
+ dispatch: jest.fn(),
+ mockStateChange() {
+ this.subs.forEach(sub => sub())
+ },
+})
+
+describe('Redux Notifications', () => {
+ afterEach(() => {
+ FlashAlert.destroyContainer.mockClear()
+ })
+
+ test('subscribes to a store and calls showFlashAlert for each notification in state', done => {
+ const mockStore = createMockStore({
+ notifications: [
+ {id: '1', message: 'hello'},
+ {id: '2', message: 'world'},
+ ],
+ })
+
+ subscribeFlashNotifications(mockStore)
+ mockStore.mockStateChange()
+
+ setTimeout(() => {
+ expect(FlashAlert.showFlashAlert).toHaveBeenCalledTimes(2)
+ expect(FlashAlert.showFlashAlert).toHaveBeenCalledWith({id: '1', message: 'hello'})
+ expect(FlashAlert.showFlashAlert).toHaveBeenCalledWith({id: '2', message: 'world'})
+
+ done()
+ }, 1)
+ })
+
+ test('subscribes to a store and dispatches clearNotifications for each notification in state', done => {
+ const mockStore = createMockStore({
+ notifications: [
+ {id: '1', message: 'hello'},
+ {id: '2', message: 'world'},
+ ],
+ })
+
+ subscribeFlashNotifications(mockStore)
+ mockStore.mockStateChange()
+
+ setTimeout(() => {
+ expect(mockStore.dispatch).toHaveBeenCalledTimes(2)
+ expect(mockStore.dispatch).toHaveBeenCalledWith(notificationActions.clearNotification('1'))
+ expect(mockStore.dispatch).toHaveBeenCalledWith(notificationActions.clearNotification('2'))
+
+ done()
+ }, 1)
+ })
+})
+
+describe('notificationActions', () => {
+ test('notifyInfo creates action NOTIFY_INFO with type "info" and payload', () => {
+ const action = notificationActions.notifyInfo({message: 'test'})
+ expect(action).toEqual({type: 'NOTIFY_INFO', payload: {type: 'info', message: 'test'}})
+ })
+
+ test('notifyError creates action NOTIFY_ERROR with type "error" and payload', () => {
+ const action = notificationActions.notifyError({message: 'test'})
+ expect(action).toEqual({type: 'NOTIFY_ERROR', payload: {type: 'error', message: 'test'}})
+ })
+
+ test('clearNotification creates action CLEAR_NOTIFICATION', () => {
+ const action = notificationActions.clearNotification()
+ expect(action).toEqual({type: 'CLEAR_NOTIFICATION'})
+ })
+})
+
+describe('reduceNotifications', () => {
+ test('catches any action with err and message and treats it as an error notification', () => {
+ const action = {
+ type: '_NOT_A_REAL_ACTION_',
+ payload: {message: 'hello world', err: 'bad things happened'},
+ }
+ const newState = reduceNotifications([], action)
+ expect(newState).toMatchObject([
+ {type: 'error', message: 'hello world', err: 'bad things happened'},
+ ])
+ })
+
+ test('adds new info notification on NOTIFY_INFO', () => {
+ const newState = reduceNotifications(
+ [],
+ notificationActions.notifyInfo({message: 'hello world'})
+ )
+ expect(newState).toMatchObject([{type: 'info', message: 'hello world'}])
+ })
+
+ test('adds new error notification on NOTIFY_ERROR', () => {
+ const newState = reduceNotifications(
+ [],
+ notificationActions.notifyError({message: 'hello world', err: 'bad things happened'})
+ )
+ expect(newState).toMatchObject([
+ {type: 'error', message: 'hello world', err: 'bad things happened'},
+ ])
+ })
+
+ test('removes notification on CLEAR_NOTIFICATION', () => {
+ const newState = reduceNotifications(
+ [{id: '1', message: 'hello world', type: 'info'}],
+ notificationActions.clearNotification('1')
+ )
+ expect(newState).toEqual([])
+ })
+})
diff --git a/ui/shared/notifications/redux/__tests__/reduxNotificationsSpec.js b/ui/shared/notifications/redux/__tests__/reduxNotificationsSpec.js
deleted file mode 100644
index 6d700724f5d..00000000000
--- a/ui/shared/notifications/redux/__tests__/reduxNotificationsSpec.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2017 - present Instructure, Inc.
- *
- * This file is part of Canvas.
- *
- * Canvas is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Affero General Public License as published by the Free
- * Software Foundation, version 3 of the License.
- *
- * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Affero General Public License along
- * with this program. If not, see .
- */
-
-import {subscribeFlashNotifications, notificationActions, reduceNotifications} from '../actions'
-import * as FlashAlert from '@canvas/alerts/react/FlashAlert'
-
-const createMockStore = state => ({
- subs: [],
- subscribe(cb) {
- this.subs.push(cb)
- },
- getState: () => state,
- dispatch: () => {},
- mockStateChange() {
- this.subs.forEach(sub => sub())
- },
-})
-
-QUnit.module('Redux Notifications')
-
-QUnit.module('subscribeFlashNotifications', {
- teardown() {
- FlashAlert.destroyContainer()
- },
-})
-
-test('subscribes to a store and calls showFlashAlert for each notification in state', assert => {
- const done = assert.async()
- const flashAlertSpy = sinon.spy(FlashAlert, 'showFlashAlert')
- const mockStore = createMockStore({
- notifications: [
- {id: '1', message: 'hello'},
- {id: '2', message: 'world'},
- ],
- })
-
- subscribeFlashNotifications(mockStore)
- mockStore.mockStateChange()
-
- setTimeout(() => {
- equal(flashAlertSpy.callCount, 2)
- deepEqual(flashAlertSpy.firstCall.args, [{id: '1', message: 'hello'}])
- deepEqual(flashAlertSpy.secondCall.args, [{id: '2', message: 'world'}])
- flashAlertSpy.restore()
- done()
- }, 1)
-})
-
-test('subscribes to a store and dispatches clearNotifications for each notification in state', assert => {
- const done = assert.async()
- const mockStore = createMockStore({
- notifications: [
- {id: '1', message: 'hello'},
- {id: '2', message: 'world'},
- ],
- })
- const dispatchSpy = sinon.spy(mockStore, 'dispatch')
-
- subscribeFlashNotifications(mockStore)
- mockStore.mockStateChange()
-
- setTimeout(() => {
- equal(dispatchSpy.callCount, 2)
- deepEqual(dispatchSpy.firstCall.args, [notificationActions.clearNotification('1')])
- deepEqual(dispatchSpy.secondCall.args, [notificationActions.clearNotification('2')])
- dispatchSpy.restore()
- done()
- }, 1)
-})
-
-QUnit.module('notificationActions')
-
-test('notifyInfo creates action NOTIFY_INFO with type "info" and payload', () => {
- const action = notificationActions.notifyInfo({message: 'test'})
- deepEqual(action, {type: 'NOTIFY_INFO', payload: {type: 'info', message: 'test'}})
-})
-
-test('notifyError creates action NOTIFY_ERROR with type "error" and payload', () => {
- const action = notificationActions.notifyError({message: 'test'})
- deepEqual(action, {type: 'NOTIFY_ERROR', payload: {type: 'error', message: 'test'}})
-})
-
-test('clearNotification creates action CLEAR_NOTIFICATION', () => {
- const action = notificationActions.clearNotification()
- deepEqual(action, {type: 'CLEAR_NOTIFICATION'})
-})
-
-QUnit.module('reduceNotifications')
-
-test('catches any action with err and message and treats it as an error notification', () => {
- const action = {
- type: '_NOT_A_REAL_ACTION_',
- payload: {message: 'hello world', err: 'bad things happened'},
- }
- const newState = reduceNotifications([], action)
- equal(newState.length, 1)
- equal(newState[0].type, 'error')
- equal(newState[0].message, 'hello world')
- equal(newState[0].err, 'bad things happened')
-})
-
-test('adds new info notification on NOTIFY_INFO', () => {
- const newState = reduceNotifications([], notificationActions.notifyInfo({message: 'hello world'}))
- equal(newState.length, 1)
- equal(newState[0].type, 'info')
- equal(newState[0].message, 'hello world')
-})
-
-test('adds new error notification on NOTIFY_ERROR', () => {
- const newState = reduceNotifications(
- [],
- notificationActions.notifyError({message: 'hello world', err: 'bad things happened'})
- )
- equal(newState.length, 1)
- equal(newState[0].type, 'error')
- equal(newState[0].message, 'hello world')
- equal(newState[0].err, 'bad things happened')
-})
-
-test('removes notification on CLEAR_NOTIFICATION', () => {
- const newState = reduceNotifications(
- [{id: '1', message: 'hello world', type: 'info'}],
- notificationActions.clearNotification('1')
- )
- equal(newState.length, 0)
-})