diff --git a/src/authz-module/data/api.ts b/src/authz-module/data/api.ts
index 2ff3724..1821956 100644
--- a/src/authz-module/data/api.ts
+++ b/src/authz-module/data/api.ts
@@ -40,7 +40,7 @@ export type PermissionsByRole = {
userCount: number;
};
export interface PutAssignTeamMembersRoleResponse {
- completed: { user: string; status: string }[];
+ completed: { userIdentifier: string; status: string }[];
errors: { userIdentifier: string; error: string }[];
}
diff --git a/src/authz-module/libraries-manager/ToastManagerContext.test.tsx b/src/authz-module/libraries-manager/ToastManagerContext.test.tsx
index fe67c41..23bfc9a 100644
--- a/src/authz-module/libraries-manager/ToastManagerContext.test.tsx
+++ b/src/authz-module/libraries-manager/ToastManagerContext.test.tsx
@@ -137,4 +137,80 @@ describe('ToastManagerContext', () => {
expect(logError).toHaveBeenCalled();
expect(retryFn).toHaveBeenCalled();
});
+
+ it('respects custom delay when provided', async () => {
+ const user = userEvent.setup();
+
+ const DelayTestComponent = () => {
+ const { showToast } = useToastManager();
+
+ const handleShowToastWithDelay = () => showToast({
+ message: 'Custom delay toast',
+ type: 'success',
+ delay: 1000, // Custom 1 second delay
+ });
+
+ return (
+
+ );
+ };
+
+ renderWrapper(
+
+
+ ,
+ );
+
+ const showButton = screen.getByText('Show Toast With Custom Delay');
+ await user.click(showButton);
+
+ await waitFor(() => {
+ expect(screen.getByText('Custom delay toast')).toBeInTheDocument();
+ });
+
+ await waitFor(() => {
+ expect(screen.getByText('Custom delay toast')).toBeInTheDocument();
+ }, { timeout: 600 });
+
+ // Toast should disappear after the custom delay (1000ms)
+ await waitFor(() => {
+ expect(screen.queryByText('Custom delay toast')).not.toBeInTheDocument();
+ }, { timeout: 1200 });
+ });
+
+ it('uses default delay when delay prop is not provided', async () => {
+ const user = userEvent.setup();
+
+ const DefaultDelayTestComponent = () => {
+ const { showToast } = useToastManager();
+
+ const handleShowToastWithoutDelay = () => showToast({
+ message: 'Default delay toast',
+ type: 'success',
+ // No delay prop provided
+ });
+
+ return (
+
+ );
+ };
+
+ renderWrapper(
+
+
+ ,
+ );
+
+ const showButton = screen.getByText('Show Toast With Default Delay');
+ await user.click(showButton);
+
+ await waitFor(() => {
+ expect(screen.getByText('Default delay toast')).toBeInTheDocument();
+ });
+
+ // DEFAULT_TOAST_DELAY is 5000ms
+ await waitFor(() => {
+ expect(screen.queryByText('Default delay toast')).not.toBeInTheDocument();
+ }, { timeout: 5050 });
+ }, 5100);
});
diff --git a/src/authz-module/libraries-manager/ToastManagerContext.tsx b/src/authz-module/libraries-manager/ToastManagerContext.tsx
index 12089f4..7f0d9b1 100644
--- a/src/authz-module/libraries-manager/ToastManagerContext.tsx
+++ b/src/authz-module/libraries-manager/ToastManagerContext.tsx
@@ -5,6 +5,7 @@ import { logError } from '@edx/frontend-platform/logging';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Toast } from '@openedx/paragon';
import messages from './messages';
+import { DEFAULT_TOAST_DELAY } from './constants';
type ToastType = 'success' | 'error' | 'error-retry';
@@ -19,11 +20,12 @@ export const ERROR_TOAST_MAP: Record void;
+ delay?: number;
}
const Bold = (chunk: string) => {chunk};
@@ -47,7 +49,7 @@ export const ToastManagerProvider = ({ children }: ToastManagerProviderProps) =>
const [toasts, setToasts] = useState<(AppToast & { visible: boolean })[]>([]);
const showToast = (toast: Omit) => {
- const id = `toast-notification-${Date.now()}`;
+ const id = `toast-notification-${Date.now()}-${Math.floor(Math.random() * 1000000)}`;
const newToast = { ...toast, id, visible: true };
setToasts(prev => [...prev, newToast]);
};
@@ -92,6 +94,7 @@ export const ToastManagerProvider = ({ children }: ToastManagerProviderProps) =>
key={toast.id}
show={toast.visible}
onClose={() => discardToast(toast.id)}
+ delay={toast.delay ?? DEFAULT_TOAST_DELAY}
action={toast.onRetry ? {
onClick: () => {
discardToast(toast.id);
diff --git a/src/authz-module/libraries-manager/components/AddNewTeamMemberModal/AddNewTeamMemberTrigger.test.tsx b/src/authz-module/libraries-manager/components/AddNewTeamMemberModal/AddNewTeamMemberTrigger.test.tsx
index 0939eb4..5ddb309 100644
--- a/src/authz-module/libraries-manager/components/AddNewTeamMemberModal/AddNewTeamMemberTrigger.test.tsx
+++ b/src/authz-module/libraries-manager/components/AddNewTeamMemberModal/AddNewTeamMemberTrigger.test.tsx
@@ -21,20 +21,23 @@ jest.mock('./AddNewTeamMemberModal', () => {
isOpen, close, onSave, isLoading, formValues, handleChangeForm,
}) => (
isOpen ? (
-
-
-
+
+
+