Skip to content

Commit

Permalink
feat: make node-notifier an optional dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
Caleb ツ Everett authored and everett1992 committed Sep 6, 2019
1 parent c588c18 commit 965a4f9
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
4 changes: 3 additions & 1 deletion packages/jest-reporters/package.json
Expand Up @@ -23,7 +23,6 @@
"jest-runtime": "^24.9.0",
"jest-util": "^24.9.0",
"jest-worker": "^24.6.0",
"node-notifier": "^5.4.3",
"slash": "^3.0.0",
"source-map": "^0.6.0",
"string-length": "^3.1.0"
Expand All @@ -39,6 +38,9 @@
"@types/node-notifier": "^5.4.0",
"strip-ansi": "^5.0.0"
},
"optionalDependencies": {
"node-notifier": "^5.4.3"
},
"engines": {
"node": ">= 8"
},
Expand Down
47 changes: 47 additions & 0 deletions packages/jest-reporters/src/__tests__/notify_impl.test.ts
@@ -0,0 +1,47 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
beforeEach(() => {
jest.resetModules();
});

test('without node-notifier notify_impl uses mock function that throws an error', () => {
jest.doMock('node-notifier', () => {
const error: any = new Error("Cannot find module 'node-notifier'");
error.code = 'MODULE_NOT_FOUND';
throw error;
});
const notify = require('../notify_impl').default;
const arg = jest.fn();
expect(() => notify(arg)).toThrow(
'notify reporter requires optional dependeny node-notifier but it was not found',
);
});

test('notify_impl throws the error when require throws an unexpected error', () => {
const error = new Error('unexpected require error');
jest.doMock('node-notifier', () => {
throw error;
});
expect(() => require('../notify_impl')).toThrow(error);
});

test('notify_impl uses node-notifier when it is available', () => {
const mockNodeNotifier = {notify: jest.fn()};
jest.doMock('node-notifier', () => mockNodeNotifier);
const notify = require('../notify_impl').default;
// notify would be object equal to mockNodeNotifier.notify except we had
// to bind it to mockNodeNotifier, which returns a new function. so
// instead of expect(notify).toBe(mockNodeNotifier.notify) we need to
// check that the arguments and return values are forwarded, and that
// `this` is set to the module.
const arg = jest.fn();
const result = notify(arg);
expect(mockNodeNotifier.notify).toBeCalledTimes(1);
expect(mockNodeNotifier.notify).toBeCalledWith(arg);
expect(mockNodeNotifier.notify).toReturnWith(result);
expect(mockNodeNotifier.notify.mock.instances[0]).toEqual(mockNodeNotifier);
});
52 changes: 52 additions & 0 deletions packages/jest-reporters/src/notify_impl.ts
@@ -0,0 +1,52 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export default getNotifier();

/**
* Return a notifier implementation.
*
* node-notifier is an optional dependency so it may not be installed.
* If node-notifier is not found then a stub notifier is returned that throws
* an error whenever it is used.
*/
function getNotifier(): Notify {
try {
const notifier: typeof import('node-notifier') = require('node-notifier');
return notifier.notify.bind(notifier);
} catch (ex) {
if (ex.code !== 'MODULE_NOT_FOUND') {
throw ex;
}
return () => {
throw Error(
'notify reporter requires optional dependeny node-notifier but it was not found',
);
};
}
}

export type Notify = (
notification?: Notification,
callback?: NotificationCallback,
) => unknown;

interface Notification {
title?: string;
message?: string;
icon?: string;
closeLabel?: string;
actions?: string | Array<string>;
timeout?: number;
}

interface NotificationCallback {
(err: Error | null, response: string, metadata?: NotificationMetadata): void;
}

interface NotificationMetadata {
activationValue?: string;
}
2 changes: 1 addition & 1 deletion packages/jest-reporters/src/notify_reporter.ts
Expand Up @@ -10,9 +10,9 @@ import * as util from 'util';
import exit = require('exit');
import {Config} from '@jest/types';
import {AggregatedResult} from '@jest/test-result';
import {notify} from 'node-notifier';
import {Context, TestSchedulerContext} from './types';
import BaseReporter from './base_reporter';
import notify from './notify_impl';

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

Expand Down

0 comments on commit 965a4f9

Please sign in to comment.