From 2503f4a5699700b56247a94a51f38d64dfbf4ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E8=BF=82=E8=BF=82?= Date: Tue, 23 Nov 2021 15:53:18 +0800 Subject: [PATCH] fix: fix can't clear the notifications (#518) * fix: fix can't clear the notifications * test: update tests * test: ignore render tests --- src/controller/__tests__/notification.test.ts | 29 +++-------- src/controller/notification.tsx | 48 +++++-------------- .../__tests__/notificationService.test.ts | 8 ++++ src/services/notificationService.ts | 10 ++++ .../__snapshots__/statusBarView.test.tsx.snap | 43 +++++++++++++++-- .../__tests__/statusBarView.test.tsx | 12 ++++- .../notification/statusBarView/index.tsx | 32 +++++++++++-- stories/extensions/test/testPane.tsx | 7 +++ 8 files changed, 120 insertions(+), 69 deletions(-) diff --git a/src/controller/__tests__/notification.test.ts b/src/controller/__tests__/notification.test.ts index 7fc670a3c..2e2ed0cc1 100644 --- a/src/controller/__tests__/notification.test.ts +++ b/src/controller/__tests__/notification.test.ts @@ -13,12 +13,6 @@ const notificationService = container.resolve(NotificationService); const statusBarService = container.resolve(StatusBarService); const builtinService = container.resolve(BuiltinService); -jest.mock('react-dom', () => { - return { - render: jest.fn(), - }; -}); - describe('The notification controller', () => { test('Should support initialize the service', () => { notificationController.initView(); @@ -94,34 +88,23 @@ describe('The notification controller', () => { expect(notificationService.getState().data).toHaveLength(0); }); - test('Should support to toggleNotifications', () => { - expect( - (notificationController as any)._notificationPane - ).toBeUndefined(); - expect(notificationService.getState().showNotifications).toBeFalsy(); - notificationController.toggleNotifications(); - - expect( - (notificationController as any)._notificationPane - ).not.toBeUndefined(); - expect(notificationService.getState().showNotifications).toBeTruthy(); - }); - test('Should support to execute onClick', () => { - expect(notificationService.getState().showNotifications).toBeTruthy(); + expect(notificationService.getState().showNotifications).toBeFalsy(); notificationController.onClick({} as any, { id: 'test' }); - expect(notificationService.getState().showNotifications).toBeFalsy(); + expect(notificationService.getState().showNotifications).toBeTruthy(); }); test('Should support to execute onActionBarClick', () => { - expect(notificationService.getState().showNotifications).toBeFalsy(); + notificationService.add([{ id: 1, value: 'test' }]); + expect(notificationService.getState().data).toHaveLength(1); notificationController.onActionBarClick({} as any, { id: constants.NOTIFICATION_CLEAR_ALL_ID, }); - expect(notificationService.getState().showNotifications).toBeTruthy(); + expect(notificationService.getState().data).toHaveLength(0); + expect(notificationService.getState().showNotifications).toBeTruthy(); notificationController.onActionBarClick({} as any, { id: constants.NOTIFICATION_HIDE_ID, }); diff --git a/src/controller/notification.tsx b/src/controller/notification.tsx index ba7cbfc81..ddbe21cda 100644 --- a/src/controller/notification.tsx +++ b/src/controller/notification.tsx @@ -1,23 +1,17 @@ import 'reflect-metadata'; import { container, singleton } from 'tsyringe'; import React from 'react'; -import ReactDOM from 'react-dom'; import { connect } from 'mo/react'; import { Float, IStatusBarItem } from 'mo/model'; import { Controller } from 'mo/react/controller'; import { IActionBarItemProps } from 'mo/components/actionBar'; import { INotificationItem } from 'mo/model/notification'; -import { - NotificationPane, - NotificationStatusBarView, -} from 'mo/workbench/notification'; +import { NotificationStatusBarView } from 'mo/workbench/notification'; import { IStatusBarService, StatusBarService, INotificationService, NotificationService, - ILayoutService, - LayoutService, IBuiltinService, BuiltinService, } from 'mo/services'; @@ -41,29 +35,20 @@ export class NotificationController implements INotificationController { private readonly notificationService: INotificationService; private readonly statusBarService: IStatusBarService; - private readonly layoutService: ILayoutService; private readonly builtinService: IBuiltinService; constructor() { super(); this.notificationService = container.resolve(NotificationService); this.statusBarService = container.resolve(StatusBarService); - this.layoutService = container.resolve(LayoutService); this.builtinService = container.resolve(BuiltinService); } public onCloseNotification = (item: INotificationItem): void => { - if (typeof item.id === 'number' || typeof item.id === 'string') { - this.notificationService.remove(item.id); - } + this.notificationService.remove(item.id); }; - private _notificationPane: HTMLDivElement | undefined = undefined; - public toggleNotifications() { - if (!this._notificationPane) { - this.renderNotificationPane(); - } this.notificationService.toggleNotification(); } @@ -82,7 +67,7 @@ export class NotificationController } = this.builtinService.getConstants(); if (action === NOTIFICATION_CLEAR_ALL_ID) { - this.notificationService.toggleNotification(); + this.notificationService.clear(); } else if (action === NOTIFICATION_HIDE_ID) { this.toggleNotifications(); } @@ -100,12 +85,19 @@ export class NotificationController this.notificationService, NotificationStatusBarView ); + /* istanbul ignore next */ const defaultNotification = { ...builtInNotification, actionBar: [NOTIFICATION_CLEAR_ALL, NOTIFICATION_HIDE].filter( Boolean ) as IActionBarItemProps[], - render: () => , + render: () => ( + + ), }; this.notificationService.setState({ ...defaultNotification, @@ -113,22 +105,4 @@ export class NotificationController this.statusBarService.add(defaultNotification, Float.right); } } - - public renderNotificationPane() { - const NotificationPaneView = connect( - this.notificationService, - NotificationPane - ); - const root = this.layoutService.container; - const container = document.createElement('div'); - root?.appendChild(container); - ReactDOM.render( - , - container - ); - this._notificationPane = container; - } } diff --git a/src/services/__tests__/notificationService.test.ts b/src/services/__tests__/notificationService.test.ts index 1dd1a4020..198f64d74 100644 --- a/src/services/__tests__/notificationService.test.ts +++ b/src/services/__tests__/notificationService.test.ts @@ -94,4 +94,12 @@ describe('The Notification Service', () => { notificationService.toggleNotification(); expect(notificationService.getState().showNotifications).toBeTruthy(); }); + + test('Should support to clear all notifications', () => { + notificationService.add([{ id: 1, value: 'test' }]); + expect(notificationService.getState().data).toHaveLength(1); + + notificationService.clear(); + expect(notificationService.getState().data).toHaveLength(0); + }); }); diff --git a/src/services/notificationService.ts b/src/services/notificationService.ts index b97cb8f77..0a83629f5 100644 --- a/src/services/notificationService.ts +++ b/src/services/notificationService.ts @@ -32,6 +32,10 @@ export interface INotificationService extends Component { * Toggle the Notification view between display or hidden */ toggleNotification(): void; + /** + * Clear the notifications + */ + clear(): void; /** * Reset notifications, this will clear the pending notifications */ @@ -117,6 +121,12 @@ export class NotificationService return null; } + public clear() { + this.setState({ + data: [], + }); + } + public reset() { this.setState({ id: '', diff --git a/src/workbench/notification/__tests__/__snapshots__/statusBarView.test.tsx.snap b/src/workbench/notification/__tests__/__snapshots__/statusBarView.test.tsx.snap index 9bbb18a6a..4bdb00e66 100644 --- a/src/workbench/notification/__tests__/__snapshots__/statusBarView.test.tsx.snap +++ b/src/workbench/notification/__tests__/__snapshots__/statusBarView.test.tsx.snap @@ -1,7 +1,44 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Test Notification StatusBar View Component Match The NotificationStatusBarView snapshot 1`] = ` - +Array [ + , +
+
+ + Notifications + +
+
    +
+
+
+
+ + +
+
+
, +] `; diff --git a/src/workbench/notification/__tests__/statusBarView.test.tsx b/src/workbench/notification/__tests__/statusBarView.test.tsx index ccafb8952..b2457dc19 100644 --- a/src/workbench/notification/__tests__/statusBarView.test.tsx +++ b/src/workbench/notification/__tests__/statusBarView.test.tsx @@ -10,7 +10,10 @@ import { expectFnCalled } from '@test/utils'; describe('Test Notification StatusBar View Component', () => { test('Match The NotificationStatusBarView snapshot', () => { const component = renderer.create( - + ); expect(component.toJSON()).toMatchSnapshot(); }); @@ -18,7 +21,12 @@ describe('Test Notification StatusBar View Component', () => { test('Should display the bell dot icon', () => { const { rerender } = render(); expect(select('.codicon-bell-dot')).not.toBeInTheDocument(); - rerender(); + rerender( + + ); expect(select('.codicon-bell-dot')).toBeInTheDocument(); }); diff --git a/src/workbench/notification/statusBarView/index.tsx b/src/workbench/notification/statusBarView/index.tsx index 93f0743d8..f6c2c67d9 100644 --- a/src/workbench/notification/statusBarView/index.tsx +++ b/src/workbench/notification/statusBarView/index.tsx @@ -1,11 +1,35 @@ import React, { memo } from 'react'; import { Icon } from 'mo/components/icon'; -import { IStatusBarItem } from 'mo/model/workbench/statusBar'; +import type { INotification } from 'mo/model'; +import { NotificationPane } from '../notificationPane'; +import type { INotificationController } from 'mo/controller'; -export function NotificationStatusBarView(props: IStatusBarItem) { - const { data = [], onClick } = props; +export function NotificationStatusBarView( + props: INotification & Partial +) { + const { + data = [], + onClick, + showNotifications, + id, + actionBar, + onActionBarClick, + onCloseNotification, + } = props; const hasNotifications = data.length > 0; const renderIcon = hasNotifications ? 'bell-dot' : 'bell'; - return ; + return ( + <> + + + + ); } export default memo(NotificationStatusBarView); diff --git a/stories/extensions/test/testPane.tsx b/stories/extensions/test/testPane.tsx index 1df8c47ba..196593d5e 100644 --- a/stories/extensions/test/testPane.tsx +++ b/stories/extensions/test/testPane.tsx @@ -229,6 +229,10 @@ export type GenericClassDecorator = (target: T) => void;`, } }; + const toggleNotification = function () { + molecule.notification.toggleNotification(); + }; + const openCommand = function () {}; const appendMenu = function () { @@ -345,6 +349,9 @@ PARTITIONED BY (ds string) lifecycle 1000; +

MenuBar: