diff --git a/api/types/accesslist/convert/v1/accesslist_test.go b/api/types/accesslist/convert/v1/accesslist_test.go index 7dfc131435da0..5958934a04e64 100644 --- a/api/types/accesslist/convert/v1/accesslist_test.go +++ b/api/types/accesslist/convert/v1/accesslist_test.go @@ -42,12 +42,17 @@ func TestWithOwnersIneligibleStatusField(t *testing.T) { Name: "dne", IneligibleStatus: accesslistv1.IneligibleStatus_INELIGIBLE_STATUS_USER_NOT_EXIST, }, + { + Name: "unspecified", + IneligibleStatus: accesslistv1.IneligibleStatus_INELIGIBLE_STATUS_UNSPECIFIED, + }, } owners := []accesslist.Owner{ {Name: "expired"}, {Name: "missing"}, {Name: "dne"}, + {Name: "unspecified"}, } al := &accesslist.AccessList{ Spec: accesslist.Spec{ @@ -72,6 +77,10 @@ func TestWithOwnersIneligibleStatusField(t *testing.T) { Name: "dne", IneligibleStatus: accesslistv1.IneligibleStatus_INELIGIBLE_STATUS_USER_NOT_EXIST.String(), }, + { + Name: "unspecified", + IneligibleStatus: "", + }, })) } diff --git a/web/packages/teleport/src/TopBar/Notifications/Notifications.test.tsx b/web/packages/teleport/src/TopBar/Notifications/Notifications.test.tsx new file mode 100644 index 0000000000000..26b5f0d304d9c --- /dev/null +++ b/web/packages/teleport/src/TopBar/Notifications/Notifications.test.tsx @@ -0,0 +1,120 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { MemoryRouter } from 'react-router'; +import { render, screen } from 'design/utils/testing'; + +import { createTeleportContext } from 'teleport/mocks/contexts'; +import { ContextProvider } from 'teleport'; + +import { + StoreNotifications, + NotificationKind, +} from 'teleport/stores/storeNotifications'; + +import { Notifications } from './Notifications'; + +beforeAll(() => { + jest.useFakeTimers(); + jest.setSystemTime(new Date('2023-01-20')); +}); + +afterAll(() => { + jest.useRealTimers(); +}); + +test('due dates and overdue dates', async () => { + const ctx = createTeleportContext(); + const store = new StoreNotifications(); + + store.setNotifications([ + { + item: { + kind: NotificationKind.AccessList, + resourceName: 'carrot', + route: '', + }, + id: '1', + date: new Date('2023-01-25'), + }, + // overdue 10 days + { + item: { + kind: NotificationKind.AccessList, + resourceName: 'carrot', + route: '', + }, + id: '2', + date: new Date('2023-01-10'), + }, + // overdue month + { + item: { + kind: NotificationKind.AccessList, + resourceName: 'carrot', + route: '', + }, + id: '3', + date: new Date('2022-12-20'), + }, + ]); + + ctx.storeNotifications = store; + + render( + + + + + + ); + + // no need to click on button for render. + // it's already in the dom but hidden. + + expect(screen.queryAllByTestId('note-item')).toHaveLength(3); + + expect( + screen.getByText(/overdue for a review 10 days ago/i) + ).toBeInTheDocument(); + + expect( + screen.getByText(/overdue for a review about 1 month ago/i) + ).toBeInTheDocument(); + + expect( + screen.getByText(/needs your review within 5 days/i) + ).toBeInTheDocument(); +}); + +test('no notes', async () => { + const ctx = createTeleportContext(); + + render( + + + + + + ); + + // no need to click on button for render. + // it's already in the dom but hidden. + + expect(screen.queryByTestId('note-item')).not.toBeInTheDocument(); + expect(screen.getByText(/no notifications/i)).toBeInTheDocument(); +}); diff --git a/web/packages/teleport/src/TopBar/Notifications/Notifications.tsx b/web/packages/teleport/src/TopBar/Notifications/Notifications.tsx index 650af19a086bc..647340e5e428c 100644 --- a/web/packages/teleport/src/TopBar/Notifications/Notifications.tsx +++ b/web/packages/teleport/src/TopBar/Notifications/Notifications.tsx @@ -60,6 +60,7 @@ export function Notifications() { open={open} $transitionDelay={currentTransitionDelay} key={notice.id} + data-testid="note-item" > setOpen(false)} /> @@ -100,6 +101,15 @@ function NotificationItem({ notice: Notification; close(): void; }) { + const today = new Date(); + const numDays = formatDistanceToNow(notice.date); + + let dueText; + if (notice.date <= today) { + dueText = `was overdue for a review ${numDays} ago`; + } else { + dueText = `needs your review within ${numDays}`; + } switch (notice.item.kind) { case NotificationKind.AccessList: return ( @@ -109,8 +119,7 @@ function NotificationItem({ - Access list {notice.item.resourceName} needs your review - within {formatDistanceToNow(notice.date)}. + Access list {notice.item.resourceName} {dueText}.