Skip to content

Commit

Permalink
add slackv2 notification
Browse files Browse the repository at this point in the history
  • Loading branch information
eschutho committed Jun 20, 2024
1 parent fc9bc17 commit b1e31fd
Show file tree
Hide file tree
Showing 23 changed files with 861 additions and 422 deletions.
1 change: 1 addition & 0 deletions UPDATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ assists people when migrating to a new version.
translations inside the python package. This includes the .mo files needed by pybabel on the
backend, as well as the .json files used by the frontend. If you were doing anything before
as part of your bundling to expose translation packages, it's probably not needed anymore.
- [29264](https://github.com/apache/superset/pull/29264) Slack has updated its file upload api, and we are now supporting this new api in Superset, although the Slack api is not backward compatible. The original Slack integration is deprecated and we will require a new Slack scope `channels:read` to be added to Slack workspaces in order to use this new api. In an upcoming release, we will make this new Slack scope mandatory and remove the old Slack functionality.

### Potential Downtime

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export enum FeatureFlag {
AlertsAttachReports = 'ALERTS_ATTACH_REPORTS',
AlertReports = 'ALERT_REPORTS',
AlertReportTabs = 'ALERT_REPORT_TABS',
AlertReportSlackV2 = 'ALERT_REPORT_SLACK_V2',
AllowFullCsvExport = 'ALLOW_FULL_CSV_EXPORT',
AvoidColorsCollision = 'AVOID_COLORS_COLLISION',
ChartPluginsExperimental = 'CHART_PLUGINS_EXPERIMENTAL',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jest.mock('@superset-ui/core', () => ({

jest.mock('src/features/databases/state.ts', () => ({
useCommonConf: () => ({
ALERT_REPORTS_NOTIFICATION_METHODS: ['Email', 'Slack'],
ALERT_REPORTS_NOTIFICATION_METHODS: ['Email', 'Slack', 'SlackV2'],
}),
}));

Expand Down
18 changes: 16 additions & 2 deletions superset-frontend/src/features/alerts/AlertReportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
]);

setNotificationAddState(
notificationSettings.length === allowedNotificationMethods.length
notificationSettings.length === allowedNotificationMethodsCount
? 'hidden'
: 'disabled',
);
Expand Down Expand Up @@ -1235,6 +1235,20 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
enforceValidation();
}, [validationStatus]);

const allowedNotificationMethodsCount = useMemo(
() =>
allowedNotificationMethods.reduce((accum: string[], setting: string) => {
if (
accum.some(nm => nm.includes('slack')) &&
setting.toLowerCase().includes('slack')
) {
return accum;
}
return [...accum, setting.toLowerCase()];
}, []).length,
[allowedNotificationMethods],
);

// Show/hide
if (isHidden && show) {
setIsHidden(false);
Expand Down Expand Up @@ -1743,7 +1757,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
))}
{
// Prohibit 'add notification method' button if only one present
allowedNotificationMethods.length > notificationSettings.length && (
allowedNotificationMethodsCount > notificationSettings.length && (
<NotificationMethodAdd
data-test="notification-add"
status={notificationAddState}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 { render, screen, fireEvent } from 'spec/helpers/testing-library';
import { NotificationMethod } from './NotificationMethod';
import { NotificationSetting } from '../types';

const mockOnUpdate = jest.fn();
const mockOnRemove = jest.fn();
const mockOnInputChange = jest.fn();
const mockSetErrorSubject = jest.fn();

const mockSetting: NotificationSetting = {
method: 'Email',
recipients: 'test@example.com',
options: ['Email', 'Slack', 'SlackV2'],
};

const mockEmailSubject = 'Test Subject';
const mockDefaultSubject = 'Default Subject';

describe('NotificationMethod', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should render the component', () => {
render(
<NotificationMethod
setting={mockSetting}
index={0}
onUpdate={mockOnUpdate}
onRemove={mockOnRemove}
onInputChange={mockOnInputChange}
email_subject={mockEmailSubject}
defaultSubject={mockDefaultSubject}
setErrorSubject={mockSetErrorSubject}
/>,
);

expect(screen.getByText('Notification Method')).toBeInTheDocument();
expect(
screen.getByText('Email subject name (optional)'),
).toBeInTheDocument();
expect(screen.getByText('Email recipients')).toBeInTheDocument();
});

it('should call onUpdate when the method is changed', () => {
render(
<NotificationMethod
setting={mockSetting}
index={0}
onUpdate={mockOnUpdate}
onRemove={mockOnRemove}
onInputChange={mockOnInputChange}
email_subject={mockEmailSubject}
defaultSubject={mockDefaultSubject}
setErrorSubject={mockSetErrorSubject}
/>,
);

const select = screen.getByLabelText('Delivery method');
fireEvent.change(select, { target: { value: 'Slack' } });

expect(mockOnUpdate).toHaveBeenCalledWith(0, {
...mockSetting,
method: 'Slack',
recipients: '',
});
});

it('should call onRemove when the delete button is clicked', () => {
render(
<NotificationMethod
setting={mockSetting}
index={1}
onUpdate={mockOnUpdate}
onRemove={mockOnRemove}
onInputChange={mockOnInputChange}
email_subject={mockEmailSubject}
defaultSubject={mockDefaultSubject}
setErrorSubject={mockSetErrorSubject}
/>,
);

const deleteButton = screen.getByRole('button');
fireEvent.click(deleteButton);

expect(mockOnRemove).toHaveBeenCalledWith(1);
});

it('should call onRecipientsChange when the recipients value is changed', () => {
render(
<NotificationMethod
setting={mockSetting}
index={0}
onUpdate={mockOnUpdate}
onRemove={mockOnRemove}
onInputChange={mockOnInputChange}
email_subject={mockEmailSubject}
defaultSubject={mockDefaultSubject}
setErrorSubject={mockSetErrorSubject}
/>,
);

const recipientsInput = screen.getByTestId('recipients');
fireEvent.change(recipientsInput, {
target: { value: 'test1@example.com' },
});

expect(mockOnUpdate).toHaveBeenCalledWith(0, {
...mockSetting,
recipients: 'test1@example.com',
});
});

it('should call onSlackRecipientsChange when the slack recipients value is changed', () => {
render(
<NotificationMethod
setting={{ ...mockSetting, method: 'Slack' }}
index={0}
onUpdate={mockOnUpdate}
onRemove={mockOnRemove}
onInputChange={mockOnInputChange}
email_subject={mockEmailSubject}
defaultSubject={mockDefaultSubject}
setErrorSubject={mockSetErrorSubject}
/>,
);

const slackRecipientsInput = screen.getByLabelText('Select channels');
fireEvent.change(slackRecipientsInput, [
{ label: 'User 1', value: 'user1' },
{ label: 'User 2', value: 'user2' },
]);

expect(mockOnUpdate).toHaveBeenCalledWith(0, {
...mockSetting,
recipients: 'user1,user2',
});
});

it('should call onSubjectChange when the email subject value is changed', () => {
render(
<NotificationMethod
setting={mockSetting}
index={0}
onUpdate={mockOnUpdate}
onRemove={mockOnRemove}
onInputChange={mockOnInputChange}
email_subject={mockEmailSubject}
defaultSubject={mockDefaultSubject}
setErrorSubject={mockSetErrorSubject}
/>,
);

const subjectInput = screen.getByPlaceholderText('Default Subject');
fireEvent.change(subjectInput, { target: { value: 'Test Subject' } });

expect(mockOnInputChange).toHaveBeenCalled();
});
});
Loading

0 comments on commit b1e31fd

Please sign in to comment.