Merge pull request #25612 from parmar-abhinav/master-code-2
Add examples for notification:send scaffolder action & improve related tests
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-notifications': patch
|
||||
---
|
||||
|
||||
Add examples for notification:send scaffolder action & improve related tests
|
||||
@@ -38,7 +38,8 @@
|
||||
"@backstage/plugin-notifications-common": "workspace:^",
|
||||
"@backstage/plugin-notifications-node": "workspace:^",
|
||||
"@backstage/plugin-scaffolder-node": "workspace:^",
|
||||
"octokit": "^3.0.0"
|
||||
"octokit": "^3.0.0",
|
||||
"yaml": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* 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 { createSendNotificationAction } from './sendNotification';
|
||||
import { NotificationService } from '@backstage/plugin-notifications-node';
|
||||
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
|
||||
import { examples } from './sendNotification.examples';
|
||||
import yaml from 'yaml';
|
||||
|
||||
describe('notification:send', () => {
|
||||
const notificationService: jest.Mocked<NotificationService> = {
|
||||
send: jest.fn(),
|
||||
};
|
||||
|
||||
let action: TemplateAction<any>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
action = createSendNotificationAction({
|
||||
notifications: notificationService,
|
||||
});
|
||||
});
|
||||
|
||||
const mockContext = createMockActionContext({
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Test notification',
|
||||
},
|
||||
});
|
||||
|
||||
it(`should ${examples[0].description}`, async () => {
|
||||
const input = yaml.parse(examples[0].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
title: 'Test notification',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[1].description}`, async () => {
|
||||
const input = yaml.parse(examples[1].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: {
|
||||
entityRef: ['entity:component:1'],
|
||||
type: 'entity',
|
||||
},
|
||||
payload: {
|
||||
description: 'A security update has been applied. Please review.',
|
||||
title: 'Security Update',
|
||||
link: 'https://example.com/security/update',
|
||||
severity: 'high',
|
||||
scope: 'internal',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[2].description}`, async () => {
|
||||
const input = yaml.parse(examples[2].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: {
|
||||
type: 'entity',
|
||||
entityRef: ['entity:component:1'],
|
||||
},
|
||||
payload: {
|
||||
description: 'Here is your weekly update.',
|
||||
link: undefined,
|
||||
severity: 'low',
|
||||
scope: undefined,
|
||||
title: 'Weekly Update',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[3].description}`, async () => {
|
||||
const input = yaml.parse(examples[3].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
description: 'Version 2.0.0 is now available. Upgrade now!',
|
||||
link: undefined,
|
||||
severity: 'normal',
|
||||
scope: 'public',
|
||||
title: 'New Release Available',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[4].description}`, async () => {
|
||||
const input = yaml.parse(examples[4].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: {
|
||||
type: 'entity',
|
||||
entityRef: ['entity:component:1'],
|
||||
},
|
||||
payload: {
|
||||
description:
|
||||
'A critical bug has been identified. Immediate action required.',
|
||||
link: undefined,
|
||||
scope: 'internal',
|
||||
severity: 'critical',
|
||||
title: 'Critical Bug Found',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[5].description}`, async () => {
|
||||
const input = yaml.parse(examples[5].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: {
|
||||
type: 'broadcast',
|
||||
},
|
||||
payload: {
|
||||
description: 'Server maintenance will occur tonight at 11 PM.',
|
||||
link: undefined,
|
||||
scope: 'internal',
|
||||
severity: 'normal',
|
||||
title: 'Server Maintenance Scheduled',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[6].description}`, async () => {
|
||||
const input = yaml.parse(examples[6].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
description: 'New features have been deployed. Explore them now!',
|
||||
link: undefined,
|
||||
scope: undefined,
|
||||
severity: 'normal',
|
||||
title: 'New Feature Deployment',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[7].description}`, async () => {
|
||||
const input = yaml.parse(examples[7].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
description: undefined,
|
||||
link: undefined,
|
||||
scope: 'internal',
|
||||
severity: 'low',
|
||||
title: 'Holiday Office Closure',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[8].description}`, async () => {
|
||||
const input = yaml.parse(examples[8].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
description:
|
||||
"Don't forget, the weekly meeting is scheduled for tomorrow.",
|
||||
link: undefined,
|
||||
scope: 'internal',
|
||||
severity: undefined,
|
||||
title: 'Reminder: Weekly Meeting Tomorrow',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[9].description}`, async () => {
|
||||
const input = yaml.parse(examples[9].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
title: 'Important Announcement',
|
||||
description:
|
||||
'Please read the latest announcement regarding the upcoming changes.',
|
||||
link: undefined,
|
||||
scope: undefined,
|
||||
severity: 'high',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[10].description}`, async () => {
|
||||
const input = yaml.parse(examples[10].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: { type: 'broadcast' },
|
||||
payload: {
|
||||
title: 'Broadcast Notification',
|
||||
description: 'This is a broadcast notification',
|
||||
link: undefined,
|
||||
scope: undefined,
|
||||
severity: 'low',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`should ${examples[11].description}`, async () => {
|
||||
const input = yaml.parse(examples[11].example).steps[0].input;
|
||||
const ctx = Object.assign({}, mockContext, {
|
||||
input: input,
|
||||
});
|
||||
await action.handler(ctx);
|
||||
expect(notificationService.send).toHaveBeenCalledWith({
|
||||
recipients: {
|
||||
type: 'entity',
|
||||
entityRef: ['entity:service1'],
|
||||
},
|
||||
payload: {
|
||||
title: 'Entity Notification',
|
||||
description: 'This is a notification for entity service1',
|
||||
link: undefined,
|
||||
scope: undefined,
|
||||
severity: 'normal',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* 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 { TemplateExample } from '@backstage/plugin-scaffolder-node';
|
||||
import yaml from 'yaml';
|
||||
|
||||
export const examples: TemplateExample[] = [
|
||||
{
|
||||
description: 'Sends a notification with minimal options',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Test notification',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description: 'Sends a notification with entity recipients and link',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'entity',
|
||||
entityRefs: ['entity:component:1'],
|
||||
title: 'Security Update',
|
||||
info: 'A security update has been applied. Please review.',
|
||||
link: 'https://example.com/security/update',
|
||||
severity: 'high',
|
||||
scope: 'internal',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with entity recipients and optional flag',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'entity',
|
||||
entityRefs: ['entity:component:1'],
|
||||
title: 'Weekly Update',
|
||||
info: 'Here is your weekly update.',
|
||||
severity: 'low',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with broadcast recipients and custom scope',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'New Release Available',
|
||||
info: 'Version 2.0.0 is now available. Upgrade now!',
|
||||
severity: 'normal',
|
||||
scope: 'public',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with entity recipients and custom severity',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'entity',
|
||||
entityRefs: ['entity:component:1'],
|
||||
title: 'Critical Bug Found',
|
||||
info: 'A critical bug has been identified. Immediate action required.',
|
||||
severity: 'critical',
|
||||
scope: 'internal',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description: 'Sends a notification with broadcast recipients and no link',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Server Maintenance Scheduled',
|
||||
info: 'Server maintenance will occur tonight at 11 PM.',
|
||||
severity: 'normal',
|
||||
scope: 'internal',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with broadcast recipients and optional flag',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'New Feature Deployment',
|
||||
info: 'New features have been deployed. Explore them now!',
|
||||
severity: 'normal',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with broadcast recipients and no description',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Holiday Office Closure',
|
||||
severity: 'low',
|
||||
scope: 'internal',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with broadcast recipients and no severity',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Reminder: Weekly Meeting Tomorrow',
|
||||
info: "Don't forget, the weekly meeting is scheduled for tomorrow.",
|
||||
scope: 'internal',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description: 'Sends a notification with broadcast recipients and no scope',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Important Announcement',
|
||||
info: 'Please read the latest announcement regarding the upcoming changes.',
|
||||
severity: 'high',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description: 'Sends a notification with optional parameters',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification',
|
||||
input: {
|
||||
recipients: 'broadcast',
|
||||
title: 'Broadcast Notification',
|
||||
info: 'This is a broadcast notification',
|
||||
severity: 'low',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description:
|
||||
'Sends a notification with entity recipients and optional set to false',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
id: 'sendNotification',
|
||||
action: 'notification:send',
|
||||
name: 'Send Notification to Entity',
|
||||
input: {
|
||||
recipients: 'entity',
|
||||
entityRefs: ['entity:service1'],
|
||||
title: 'Entity Notification',
|
||||
info: 'This is a notification for entity service1',
|
||||
severity: 'normal',
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
];
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
NotificationSeverity,
|
||||
} from '@backstage/plugin-notifications-common';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { examples } from './sendNotification.examples';
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -42,6 +43,7 @@ export function createSendNotificationAction(options: {
|
||||
}>({
|
||||
id: 'notification:send',
|
||||
description: 'Sends a notification using NotificationService',
|
||||
examples,
|
||||
schema: {
|
||||
input: {
|
||||
type: 'object',
|
||||
|
||||
Reference in New Issue
Block a user