initial commit
[squeep-log-helper] / test / lib / file-scope.js
diff --git a/test/lib/file-scope.js b/test/lib/file-scope.js
new file mode 100644 (file)
index 0000000..889ded6
--- /dev/null
@@ -0,0 +1,282 @@
+/* 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