diff --git a/static/app/components/selectMembers/index.tsx b/static/app/components/selectMembers/index.tsx index 6b85552f4c20d1..277c45df84a7ad 100644 --- a/static/app/components/selectMembers/index.tsx +++ b/static/app/components/selectMembers/index.tsx @@ -32,6 +32,7 @@ type Props = { onChange: (value: any) => any; organization: Organization; value: any; + ariaLabel?: string; disabled?: boolean; onInputChange?: (value: any) => any; placeholder?: string; @@ -174,7 +175,7 @@ class SelectMembers extends Component { }; render() { - const {placeholder, styles} = this.props; + const {placeholder, styles, ariaLabel} = this.props; // If memberList is still loading we need to disable a placeholder Select, // otherwise `react-select` will call `loadOptions` and prematurely load @@ -185,6 +186,7 @@ class SelectMembers extends Component { return ( , filterText: string) => option?.data?.searchKey?.indexOf(filterText) > -1 } diff --git a/static/app/views/automations/components/actions/email.tsx b/static/app/views/automations/components/actions/email.tsx index 822c465e6df18f..6aa793df930adc 100644 --- a/static/app/views/automations/components/actions/email.tsx +++ b/static/app/views/automations/components/actions/email.tsx @@ -130,7 +130,7 @@ function IdentifierField() { return ( { return subfilterWithoutId; }; -const stripActionId = (action: any) => { +const stripActionFields = (action: Action) => { const {id: _id, ...actionWithoutId} = action; + + // Strip targetDisplay from email action config + if (action.type === ActionType.EMAIL && action.config) { + const {targetDisplay: _targetDisplay, ...configWithoutTargetDisplay} = action.config; + return { + ...actionWithoutId, + config: configWithoutTargetDisplay, + }; + } + return actionWithoutId; }; @@ -45,7 +55,7 @@ const stripDataConditionGroupId = (group: any) => { return { ...groupWithoutId, conditions: group.conditions?.map(stripDataConditionId) || [], - actions: group.actions?.map(stripActionId) || [], + actions: group.actions?.map(stripActionFields) || [], }; }; diff --git a/static/app/views/automations/new.spec.tsx b/static/app/views/automations/new.spec.tsx index d995be094db98c..f54d37a183ed56 100644 --- a/static/app/views/automations/new.spec.tsx +++ b/static/app/views/automations/new.spec.tsx @@ -1,5 +1,7 @@ import {AutomationFixture} from 'sentry-fixture/automations'; +import {MemberFixture} from 'sentry-fixture/member'; import {OrganizationFixture} from 'sentry-fixture/organization'; +import {UserFixture} from 'sentry-fixture/user'; import { ActionHandlerFixture, DataConditionHandlerFixture, @@ -18,6 +20,9 @@ import AutomationNewSettings from 'sentry/views/automations/new'; describe('AutomationNewSettings', () => { const organization = OrganizationFixture({features: ['workflow-engine-ui']}); + const mockMember = MemberFixture({ + user: UserFixture({id: '1', name: 'Moo Deng', email: 'moo.deng@sentry.io'}), + }); beforeEach(() => { MockApiClient.clearMockResponses(); @@ -32,6 +37,11 @@ describe('AutomationNewSettings', () => { handlerGroup: ActionGroup.NOTIFICATION, integrations: [{id: '1', name: 'My Slack Workspace'}], }), + ActionHandlerFixture({ + type: ActionType.EMAIL, + handlerGroup: ActionGroup.NOTIFICATION, + integrations: [], + }), ], }); @@ -63,11 +73,16 @@ describe('AutomationNewSettings', () => { ], }); - // Users endpoint fetched by AutomationBuilder for member selectors + // Users/members endpoints fetched by AutomationBuilder for member selectors MockApiClient.addMockResponse({ url: `/organizations/${organization.slug}/users/`, method: 'GET', - body: [], + body: [mockMember], + }); + MockApiClient.addMockResponse({ + url: `/organizations/${organization.slug}/members/`, + method: 'GET', + body: [mockMember], }); // Detectors list used by EditConnectedMonitors inside the form @@ -107,6 +122,17 @@ describe('AutomationNewSettings', () => { await selectEvent.select(screen.getByRole('textbox', {name: 'Add action'}), 'Slack'); await userEvent.type(screen.getByRole('textbox', {name: 'Target'}), '#alerts'); + // Add an email action + await selectEvent.select( + screen.getByRole('textbox', {name: 'Add action'}), + 'Notify on preferred channel' + ); + await selectEvent.select( + screen.getByRole('textbox', {name: 'Notification target type'}), + 'Member' + ); + await selectEvent.select(screen.getByRole('textbox', {name: 'User'}), 'Moo Deng'); + // Submit the form await userEvent.click(screen.getByRole('button', {name: 'Create Alert'})); @@ -115,7 +141,7 @@ describe('AutomationNewSettings', () => { expect.anything(), expect.objectContaining({ data: { - name: 'Notify #alerts via Slack', + name: 'Notify #alerts via Slack, Notify Moo Deng', triggers: { logicType: 'any-short', conditions: [ @@ -148,6 +174,15 @@ describe('AutomationNewSettings', () => { data: {}, status: 'active', }, + { + type: 'email', + config: { + targetType: 'user', + targetIdentifier: '1', + }, + data: {}, + status: 'active', + }, ], }, ],