mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-19 16:42:17 +03:00
276 lines
10 KiB
JavaScript
276 lines
10 KiB
JavaScript
|
const assert = require('assert');
|
||
|
const sinon = require('sinon');
|
||
|
const SlackNotifications = require('../lib/SlackNotifications');
|
||
|
const nock = require('nock');
|
||
|
const ObjectId = require('bson-objectid').default;
|
||
|
const got = require('got');
|
||
|
const ghostVersion = require('@tryghost/version');
|
||
|
|
||
|
describe('SlackNotifications', function () {
|
||
|
let slackNotifications;
|
||
|
let loggingErrorStub;
|
||
|
|
||
|
beforeEach(function () {
|
||
|
loggingErrorStub = sinon.stub();
|
||
|
|
||
|
slackNotifications = new SlackNotifications({
|
||
|
logging: {
|
||
|
warn: () => {},
|
||
|
error: loggingErrorStub
|
||
|
},
|
||
|
siteUrl: 'https://ghost.example',
|
||
|
webhookUrl: 'https://slack-webhook.example'
|
||
|
});
|
||
|
|
||
|
nock('https://slack-webhook.example')
|
||
|
.post('/')
|
||
|
.reply(200, {message: 'success'});
|
||
|
});
|
||
|
|
||
|
afterEach(function () {
|
||
|
sinon.restore();
|
||
|
nock.cleanAll();
|
||
|
});
|
||
|
|
||
|
describe('notifyMilestoneReceived', function () {
|
||
|
let sendStub;
|
||
|
|
||
|
beforeEach(function () {
|
||
|
sendStub = slackNotifications.send = sinon.stub().resolves();
|
||
|
});
|
||
|
|
||
|
afterEach(function () {
|
||
|
sinon.restore();
|
||
|
});
|
||
|
|
||
|
it('Sends a notification to Slack for achieved ARR Milestone - no meta', async function () {
|
||
|
await slackNotifications.notifyMilestoneReceived({
|
||
|
milestone: {
|
||
|
id: ObjectId().toHexString(),
|
||
|
name: 'arr-1000-usd',
|
||
|
type: 'arr',
|
||
|
createdAt: '2023-02-15T00:00:00.000Z',
|
||
|
emailSentAt: '2023-02-15T00:00:00.000Z',
|
||
|
value: 1000,
|
||
|
currency: 'gbp'
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const expectedResult = {
|
||
|
unfurl_links: false,
|
||
|
username: 'Ghost Milestone Service',
|
||
|
attachments: [{
|
||
|
color: '#36a64f',
|
||
|
blocks: [
|
||
|
{
|
||
|
type: 'header',
|
||
|
text: {
|
||
|
type: 'plain_text',
|
||
|
text: ':tada: ARR Milestone £1,000.00 reached!',
|
||
|
emoji: true
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
text: {
|
||
|
type: 'mrkdwn',
|
||
|
text: 'New *ARR Milestone* achieved for <https://ghost.example|https://ghost.example>'
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: 'divider'
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
fields: [
|
||
|
{
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Milestone:*\n£1,000.00'
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
text: {
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Email sent:*\n15 Feb 2023'
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
}]
|
||
|
};
|
||
|
|
||
|
assert(sendStub.calledOnce === true);
|
||
|
assert(sendStub.calledWith(expectedResult, 'https://slack-webhook.example') === true);
|
||
|
});
|
||
|
|
||
|
it('Sends a notification to Slack for achieved Members Milestone and shows reason when imported members', async function () {
|
||
|
await slackNotifications.notifyMilestoneReceived({
|
||
|
milestone: {
|
||
|
id: ObjectId().toHexString(),
|
||
|
name: 'members-50000',
|
||
|
type: 'members',
|
||
|
createdAt: null,
|
||
|
emailSentAt: null,
|
||
|
value: 50000
|
||
|
},
|
||
|
meta: {
|
||
|
currentMembers: 59857,
|
||
|
reason: 'import'
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const expectedResult = {
|
||
|
unfurl_links: false,
|
||
|
username: 'Ghost Milestone Service',
|
||
|
attachments: [{
|
||
|
color: '#36a64f',
|
||
|
blocks: [
|
||
|
{
|
||
|
type: 'header',
|
||
|
text: {
|
||
|
type: 'plain_text',
|
||
|
text: ':tada: Members Milestone 50,000 reached!',
|
||
|
emoji: true
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
text: {
|
||
|
type: 'mrkdwn',
|
||
|
text: 'New *Members Milestone* achieved for <https://ghost.example|https://ghost.example>'
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: 'divider'
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
fields: [
|
||
|
{
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Milestone:*\n50,000'
|
||
|
},
|
||
|
{
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Current Members:*\n59,857'
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
text: {
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Email sent:*\nno / has imported members'
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
}]
|
||
|
};
|
||
|
|
||
|
assert(sendStub.calledOnce === true);
|
||
|
assert(sendStub.calledWith(expectedResult, 'https://slack-webhook.example') === true);
|
||
|
});
|
||
|
|
||
|
it('Shows the correct reason for email not send when last email was too recent', async function () {
|
||
|
await slackNotifications.notifyMilestoneReceived({
|
||
|
milestone: {
|
||
|
id: ObjectId().toHexString(),
|
||
|
name: 'arr-1000-eur',
|
||
|
type: 'arr',
|
||
|
currency: 'eur',
|
||
|
createdAt: '2023-02-15T00:00:00.000Z',
|
||
|
emailSentAt: null,
|
||
|
value: 1000
|
||
|
},
|
||
|
meta: {
|
||
|
currentARR: 1005,
|
||
|
reason: 'email'
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const expectedResult = {
|
||
|
unfurl_links: false,
|
||
|
username: 'Ghost Milestone Service',
|
||
|
attachments: [{
|
||
|
color: '#36a64f',
|
||
|
blocks: [
|
||
|
{
|
||
|
type: 'header',
|
||
|
text: {
|
||
|
type: 'plain_text',
|
||
|
text: ':tada: ARR Milestone €1,000.00 reached!',
|
||
|
emoji: true
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
text: {
|
||
|
type: 'mrkdwn',
|
||
|
text: 'New *ARR Milestone* achieved for <https://ghost.example|https://ghost.example>'
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
type: 'divider'
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
fields: [
|
||
|
{
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Milestone:*\n€1,000.00'
|
||
|
},
|
||
|
{
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Current ARR:*\n€1,005.00'
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
type: 'section',
|
||
|
text: {
|
||
|
type: 'mrkdwn',
|
||
|
text: '*Email sent:*\nno / last email too recent'
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
}]
|
||
|
};
|
||
|
|
||
|
assert(sendStub.calledOnce === true);
|
||
|
assert(sendStub.calledWith(expectedResult, 'https://slack-webhook.example') === true);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('send', function () {
|
||
|
it('Sends with correct requestOptions', async function () {
|
||
|
const gotStub = sinon.stub(got, 'post').resolves();
|
||
|
sinon.stub(ghostVersion, 'original').value('5.0.0');
|
||
|
|
||
|
const expectedRequestOptions = [
|
||
|
'https://slack-webhook.com',
|
||
|
{
|
||
|
body: '{"data":"test"}',
|
||
|
headers: {'user-agent': 'Ghost/5.0.0 (https://github.com/TryGhost/Ghost)'}
|
||
|
}
|
||
|
];
|
||
|
|
||
|
await slackNotifications.send({data: 'test'}, 'https://slack-webhook.com');
|
||
|
assert(loggingErrorStub.callCount === 0);
|
||
|
assert(gotStub.calledOnce === true);
|
||
|
const gotStubArgs = gotStub.getCall(0).args;
|
||
|
assert.deepEqual(gotStubArgs, expectedRequestOptions);
|
||
|
});
|
||
|
|
||
|
it('Throws when invalid URL is passed', async function () {
|
||
|
await slackNotifications.send({}, 'https://invalid-url');
|
||
|
assert(loggingErrorStub.callCount === 1);
|
||
|
});
|
||
|
|
||
|
it('Throws when no URL is passed', async function () {
|
||
|
await slackNotifications.send({}, null);
|
||
|
assert(loggingErrorStub.callCount === 1);
|
||
|
});
|
||
|
});
|
||
|
});
|