--- /dev/null
+/* eslint-env mocha */
+'use strict';
+
+const assert = require('assert');
+const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
+const fs = require('fs');
+const {
+ readPackageJSON,
+ fileScope,
+ locatePackageBase,
+ defaultOptions,
+ pathExists,
+ FileScopeError,
+} = require('../../lib/file-scope');
+
+describe('File Scope', function () {
+ let noentError;
+
+ before(function () {
+ noentError = new Error('ENOENT: no such file or directory');
+ Object.assign(noentError, {
+ errno: -2,
+ syscall: 'stat',
+ code: 'ENOENT',
+ });
+ });
+
+ afterEach(function () {
+ sinon.restore();
+ });
+
+ describe('FileScopeError', function () {
+ it('covers', function () {
+ const e = new FileScopeError('beep');
+ assert.strictEqual(e.name, 'FileScopeError');
+ });
+ }); // FileScopeError
+
+ describe('readPackageJSON', function () {
+ let filepath;
+ beforeEach(function () {
+ filepath = '/path/to/package.json';
+ sinon.stub(fs, 'readFileSync').returns(`{
+ "name": "@example/package",
+ "version": "3.1.4"
+ }`);
+ });
+ it('covers success', function () {
+ const result = readPackageJSON(filepath);
+ assert.strictEqual(result.name, '@example/package');
+ assert.strictEqual(result.version, '3.1.4');
+ });
+ it('covers failure', function () {
+ fs.readFileSync.throws();
+ const result = readPackageJSON(filepath);
+ assert.strictEqual(result.name, '(unknown)');
+ assert.strictEqual(result.version, '(unknown)');
+ });
+ }); // readJSONFile
+
+ describe('pathExists', function () {
+ let p;
+ beforeEach(function () {
+ p = '/path/to/package';
+ sinon.stub(fs, 'statSync').returns();
+ });
+ it('returns true when path exists', function () {
+ const result = pathExists(p);
+ assert.strictEqual(result, true);
+ });
+ it('returns false when path does not exist', function () {
+ fs.statSync.throws(noentError);
+ const result = pathExists(p);
+ assert.strictEqual(result, false);
+ });
+ it('raises other error', function () {
+ const expectedError = new Error('oh no');
+ fs.statSync.throws(expectedError);
+ assert.throws(() => pathExists(p), expectedError);
+ });
+ }); // pathExists
+
+ describe('locatePackageBase', function () {
+ let filepath;
+
+ beforeEach(function () {
+ filepath = '/path/to/package/lib/file.js';
+ sinon.stub(fs, 'statSync');
+ });
+
+ it('covers unstubbed result', function () {
+ sinon.restore();
+ locatePackageBase(__filename);
+ });
+
+ it('locates the package base', function () {
+ fs.statSync
+ .onCall(0).throws(noentError)
+ .onCall(1).returns()
+ ;
+ const result = locatePackageBase(filepath);
+ assert.strictEqual(result, '/path/to/package/');
+ });
+
+ it('cannot locate the package base', function () {
+ fs.statSync.throws(noentError);
+ assert.throws(() => locatePackageBase(filepath), FileScopeError);
+ });
+
+ it('propagates unknown error', function () {
+ const expectedException = new Error('oh no');
+ fs.statSync
+ .onCall(0).throws(noentError)
+ .onCall(1).throws(expectedException)
+ ;
+ assert.throws(() => locatePackageBase(filepath), expectedException);
+ });
+ }); // locatePackageBase
+
+ describe('defaultOptions', function () {
+ let packageBase, expected;
+ beforeEach(function () {
+ packageBase = '/path/to/package';
+ sinon.stub(fs, 'statSync').returns();
+ expected = {
+ includePath: false,
+ includePackage: false,
+ includeVersion: false,
+ leftTrim: 0,
+ _errorEncountered: false,
+ errorPrefix: '?',
+ delimiter: ':',
+ };
+ });
+ it('covers no path', function () {
+ const options = defaultOptions();
+ assert.deepStrictEqual(options, expected);
+ });
+ it('covers default', function () {
+ expected.includePath = true;
+ fs.statSync.throws(noentError);
+ const options = defaultOptions(packageBase);
+ assert.deepStrictEqual(options, expected);
+ });
+ it('covers lib package', function () {
+ expected.includePath = true;
+ expected.includePackage = true;
+ expected.includeVersion = true;
+ expected.leftTrim = 4;
+ const options = defaultOptions(packageBase);
+ assert.deepStrictEqual(options, expected);
+ });
+ it('covers src package', function () {
+ expected.includePath = true;
+ expected.leftTrim = 4;
+ fs.statSync.onCall(0).throws(noentError);
+ const options = defaultOptions(packageBase);
+ assert.deepStrictEqual(options, expected);
+ });
+ it('covers error', function () {
+ const expectedError = new Error('oh no');
+ fs.statSync.throws(expectedError);
+ expected._errorEncountered = true;
+ const options = defaultOptions(packageBase);
+ assert.deepStrictEqual(options, expected);
+ });
+ }); // defaultOptions
+
+ describe('fileScope', function () {
+ let filepath, options, method;
+ beforeEach(function () {
+ filepath = '/path/to/package/lib/deep/file.js';
+ sinon.stub(fs, 'statSync')
+ .onCall(0).throws(noentError) // deep
+ .onCall(1).throws(noentError) // lib
+ .onCall(2).returns() // packageBase
+ ;
+ sinon.stub(fs, 'readFileSync').returns(`{
+ "name": "@example/package",
+ "version": "3.1.4"
+ }`);
+ options = {
+ includePath: true,
+ includePackage: false,
+ includeVersion: false,
+ };
+ method = 'method';
+ });
+
+ it('defaults', function () {
+ filepath = '/path/to/package/code/module/file.js';
+ fs.statSync
+ .onCall(3).throws(noentError) // no lib
+ .onCall(4).throws(noentError) // no src
+ ;
+ const result = fileScope(filepath)(method);
+ assert.strictEqual(result, 'code/module/file:method');
+ });
+
+ it('everything', function () {
+ options.includePath = true;
+ options.includePackage = true;
+ options.includeVersion = true;
+ const result = fileScope(filepath, options)(method);
+ assert.strictEqual(result, '@example/package@3.1.4:deep/file:method');
+ });
+
+ it('minimal', function () {
+ options.includePath = false;
+ options.includePackage = false;
+ options.includeVersion = false;
+ const result = fileScope(filepath, options)(method);
+ assert.strictEqual(result, 'file:method');
+ });
+
+ it('package only', function () {
+ options.includePath = false;
+ options.includePackage = true;
+ options.includeVersion = false;
+ const result = fileScope(filepath, options)(method);
+ assert.strictEqual(result, '@example/package:file:method');
+ });
+
+ it('covers no package root', function () {
+ options.includePackage = true;
+ fs.statSync.restore()
+ sinon.stub(fs, 'statSync').throws(noentError);
+ fs.readFileSync.throws(noentError);
+ const result = fileScope(filepath, options)(method);
+ assert.strictEqual(result, '?:(unknown):file:method');
+ });
+
+ it('covers exception while finding package root', function () {
+ const expectedException = new Error('oh no');
+ options.includePackage = true;
+ fs.statSync.restore()
+ sinon.stub(fs, 'statSync').throws(expectedException);
+ fs.readFileSync.throws(noentError);
+ const result = fileScope(filepath, options)(method);
+ assert.strictEqual(result, '?:(unknown):file:method');
+ });
+
+ it('handles index.js', function () {
+ filepath = '/path/to/package/src/deep/index.js';
+ fs.statSync
+ .onCall(3).throws(noentError) // no lib
+ .onCall(4).returns() // src
+ ;
+ const result = fileScope(filepath)(method);
+ assert.strictEqual(result, 'deep:method');
+ });
+
+ it('handles index.js when including path', function () {
+ filepath = '/path/to/package/code/folder/deep/index.js';
+ fs.statSync.restore();
+ sinon.stub(fs, 'statSync')
+ .throws(noentError)
+ .onCall(3).returns() // packageBase found
+ // no lib
+ // no src
+ ;
+ const result = fileScope(filepath)(method);
+ assert.strictEqual(result, 'code/folder/deep:method');
+ });
+
+ it('handles index.js when not including path', function () {
+ filepath = '/path/to/package/code/folder/deep/index.ts';
+ fs.statSync.restore();
+ sinon.stub(fs, 'statSync')
+ .throws(noentError)
+ .onCall(3).returns() // packageBase found
+ // no lib
+ // no src
+ ;
+ const result = fileScope(filepath, { includePath: false })(method);
+ assert.strictEqual(result, 'deep:method');
+ });
+
+ }); // fileScope
+
+
+}); // File Scope