Skip to content
This repository has been archived by the owner on Dec 24, 2024. It is now read-only.

Commit

Permalink
feat(node/packageInfo): use a provider creator
Browse files Browse the repository at this point in the history
  • Loading branch information
homer0 committed Jul 17, 2020
1 parent 100fb44 commit fe66556
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 19 deletions.
61 changes: 50 additions & 11 deletions node/packageInfo.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const fs = require('fs-extra');
const { provider } = require('jimple');
const { providerCreator } = require('../shared/jimpleFns');
const { deepAssign } = require('../shared/deepAssign');
/**
* @module node/packageInfo
*/
Expand All @@ -8,6 +9,29 @@ const { provider } = require('jimple');
* @typedef {import('./pathUtils').PathUtils} PathUtils
*/

/**
* @typedef {import('../shared/jimpleFns').ProviderCreatorWithOptions<O>}
* ProviderCreatorWithOptions
* @template O
*/

/**
* @typedef {Object} PackageInfoServiceMap
* @property {string|PathUtils} [pathUtils]
* The name of service for {@link PathUtils} or an instance of it. `pathUtils` by default.
* @parent module:node/packageInfo
*/

/**
* @typedef {Object} PackageInfoProviderOptions
* @property {string} serviceName
* The name that will be used to register the result of
* {@link module:node/packageInfo~packageInfo|packageInfo}. Its default value is `packageInfo`.
* @property {PackageInfoServiceMap} services
* A dictionary with the services that need to be injected on the function.
* @parent module:node/packageInfo
*/

/**
* Gets the contents of the implementation's `package.json`.
*
Expand All @@ -17,21 +41,36 @@ const { provider } = require('jimple');
* @todo This should be `async`, or at least have an async alternative.
*/
const packageInfo = (pathUtils) => fs.readJsonSync(pathUtils.join('package.json'));

/**
* The service provider that once registered on the app container will set the result of
* {@link module:node/packageInfo~packageInfo|packageInfo} as the `packageInfo` resource.
* {@link module:node/packageInfo~packageInfo|packageInfo} as a service.
*
* @example
* // Register it on the container
* container.register(packageInfoProvider);
* // Getting access to the service value
* const info = container.get('packageInfo');
*
* @type {Provider}
* @type {ProviderCreatorWithOptions<PackageInfoProviderOptions>}
* @tutorial packageInfo
*/
const packageInfoProvider = provider((app) => {
app.set('packageInfo', () => packageInfo(app.get('pathUtils')));
const packageInfoProvider = providerCreator((options = {}) => (app) => {
app.set(options.serviceName || 'packageInfo', () => {
/**
* @type {PackageInfoProviderOptions}
* @ignore
*/
const useOptions = deepAssign(
{
services: {
pathUtils: 'pathUtils',
},
},
options,
);

const { pathUtils } = useOptions.services;
const usePathUtils = typeof pathUtils === 'string' ?
app.get(pathUtils) :
pathUtils;

return packageInfo(usePathUtils);
});
});

module.exports.packageInfo = packageInfo;
Expand Down
48 changes: 40 additions & 8 deletions tests/node/packageInfo.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
jest.mock('fs-extra');
jest.mock('jimple', () => ({ provider: jest.fn(() => 'provider') }));
jest.unmock('../../node/packageInfo');
jest.unmock('../../shared/deepAssign');
jest.unmock('../../shared/jimpleFns');

const fs = require('fs-extra');
const { provider } = require('jimple');
const {
packageInfo,
packageInfoProvider,
Expand Down Expand Up @@ -32,7 +32,7 @@ describe('packageInfo', () => {
expect(fs.readJsonSync).toHaveBeenCalledWith('package.json');
});

it('should have a Jimple provider to register the service', () => {
it('should include a provider for the DIC', () => {
// Given
const pathUtils = {
join: jest.fn((rest) => rest),
Expand All @@ -48,21 +48,53 @@ describe('packageInfo', () => {
get: jest.fn(() => pathUtils),
};
let sut = null;
let serviceProvider = null;
let serviceName = null;
let serviceFn = null;
fs.readJsonSync.mockReturnValueOnce(mockedPackage);
// When
[[serviceProvider]] = provider.mock.calls;
serviceProvider(container);
packageInfoProvider.register(container);
[[serviceName, serviceFn]] = container.set.mock.calls;
sut = serviceFn();
// Then
expect(packageInfoProvider).toBe('provider');
expect(provider).toHaveBeenCalledTimes(1);
expect(serviceName).toBe('packageInfo');
expect(sut).toEqual(mockedPackage);
expect(container.get).toHaveBeenCalledTimes(1);
expect(container.get).toHaveBeenCalledWith('pathUtils');
});

it('should allow custom options on its service provider', () => {
// Given
const pathUtils = {
join: jest.fn((rest) => rest),
};
const mockedPackage = {
name: 'batman',
dependencies: {
angular: '0.1',
},
};
const options = {
serviceName: 'MyPackageInfo!',
services: {
pathUtils,
},
};
const container = {
set: jest.fn(),
get: jest.fn(),
};
let sut = null;
let serviceName = null;
let serviceFn = null;
fs.readJsonSync.mockReturnValueOnce(mockedPackage);
// When
packageInfoProvider(options).register(container);
[[serviceName, serviceFn]] = container.set.mock.calls;
sut = serviceFn();
// Then
expect(serviceName).toBe(options.serviceName);
expect(sut).toEqual(mockedPackage);
expect(container.get).toHaveBeenCalledTimes(0);
expect(pathUtils.join).toHaveBeenCalledTimes(1);
});
});

0 comments on commit fe66556

Please sign in to comment.