Skip to content

Commit 965a4f9

Browse files
committed
feat: make node-notifier an optional dependency
1 parent c588c18 commit 965a4f9

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

packages/jest-reporters/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"jest-runtime": "^24.9.0",
2424
"jest-util": "^24.9.0",
2525
"jest-worker": "^24.6.0",
26-
"node-notifier": "^5.4.3",
2726
"slash": "^3.0.0",
2827
"source-map": "^0.6.0",
2928
"string-length": "^3.1.0"
@@ -39,6 +38,9 @@
3938
"@types/node-notifier": "^5.4.0",
4039
"strip-ansi": "^5.0.0"
4140
},
41+
"optionalDependencies": {
42+
"node-notifier": "^5.4.3"
43+
},
4244
"engines": {
4345
"node": ">= 8"
4446
},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
beforeEach(() => {
8+
jest.resetModules();
9+
});
10+
11+
test('without node-notifier notify_impl uses mock function that throws an error', () => {
12+
jest.doMock('node-notifier', () => {
13+
const error: any = new Error("Cannot find module 'node-notifier'");
14+
error.code = 'MODULE_NOT_FOUND';
15+
throw error;
16+
});
17+
const notify = require('../notify_impl').default;
18+
const arg = jest.fn();
19+
expect(() => notify(arg)).toThrow(
20+
'notify reporter requires optional dependeny node-notifier but it was not found',
21+
);
22+
});
23+
24+
test('notify_impl throws the error when require throws an unexpected error', () => {
25+
const error = new Error('unexpected require error');
26+
jest.doMock('node-notifier', () => {
27+
throw error;
28+
});
29+
expect(() => require('../notify_impl')).toThrow(error);
30+
});
31+
32+
test('notify_impl uses node-notifier when it is available', () => {
33+
const mockNodeNotifier = {notify: jest.fn()};
34+
jest.doMock('node-notifier', () => mockNodeNotifier);
35+
const notify = require('../notify_impl').default;
36+
// notify would be object equal to mockNodeNotifier.notify except we had
37+
// to bind it to mockNodeNotifier, which returns a new function. so
38+
// instead of expect(notify).toBe(mockNodeNotifier.notify) we need to
39+
// check that the arguments and return values are forwarded, and that
40+
// `this` is set to the module.
41+
const arg = jest.fn();
42+
const result = notify(arg);
43+
expect(mockNodeNotifier.notify).toBeCalledTimes(1);
44+
expect(mockNodeNotifier.notify).toBeCalledWith(arg);
45+
expect(mockNodeNotifier.notify).toReturnWith(result);
46+
expect(mockNodeNotifier.notify.mock.instances[0]).toEqual(mockNodeNotifier);
47+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
export default getNotifier();
8+
9+
/**
10+
* Return a notifier implementation.
11+
*
12+
* node-notifier is an optional dependency so it may not be installed.
13+
* If node-notifier is not found then a stub notifier is returned that throws
14+
* an error whenever it is used.
15+
*/
16+
function getNotifier(): Notify {
17+
try {
18+
const notifier: typeof import('node-notifier') = require('node-notifier');
19+
return notifier.notify.bind(notifier);
20+
} catch (ex) {
21+
if (ex.code !== 'MODULE_NOT_FOUND') {
22+
throw ex;
23+
}
24+
return () => {
25+
throw Error(
26+
'notify reporter requires optional dependeny node-notifier but it was not found',
27+
);
28+
};
29+
}
30+
}
31+
32+
export type Notify = (
33+
notification?: Notification,
34+
callback?: NotificationCallback,
35+
) => unknown;
36+
37+
interface Notification {
38+
title?: string;
39+
message?: string;
40+
icon?: string;
41+
closeLabel?: string;
42+
actions?: string | Array<string>;
43+
timeout?: number;
44+
}
45+
46+
interface NotificationCallback {
47+
(err: Error | null, response: string, metadata?: NotificationMetadata): void;
48+
}
49+
50+
interface NotificationMetadata {
51+
activationValue?: string;
52+
}

packages/jest-reporters/src/notify_reporter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import * as util from 'util';
1010
import exit = require('exit');
1111
import {Config} from '@jest/types';
1212
import {AggregatedResult} from '@jest/test-result';
13-
import {notify} from 'node-notifier';
1413
import {Context, TestSchedulerContext} from './types';
1514
import BaseReporter from './base_reporter';
15+
import notify from './notify_impl';
1616

1717
const isDarwin = process.platform === 'darwin';
1818

0 commit comments

Comments
 (0)