889ded6cf860abf6d891f4d36290038c5512fb35
[squeep-log-helper] / test / lib / file-scope.js
1 /* eslint-env mocha */
2 'use strict';
3
4 const assert = require('assert');
5 const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
6 const fs = require('fs');
7 const {
8 readPackageJSON,
9 fileScope,
10 locatePackageBase,
11 defaultOptions,
12 pathExists,
13 FileScopeError,
14 } = require('../../lib/file-scope');
15
16 describe('File Scope', function () {
17 let noentError;
18
19 before(function () {
20 noentError = new Error('ENOENT: no such file or directory');
21 Object.assign(noentError, {
22 errno: -2,
23 syscall: 'stat',
24 code: 'ENOENT',
25 });
26 });
27
28 afterEach(function () {
29 sinon.restore();
30 });
31
32 describe('FileScopeError', function () {
33 it('covers', function () {
34 const e = new FileScopeError('beep');
35 assert.strictEqual(e.name, 'FileScopeError');
36 });
37 }); // FileScopeError
38
39 describe('readPackageJSON', function () {
40 let filepath;
41 beforeEach(function () {
42 filepath = '/path/to/package.json';
43 sinon.stub(fs, 'readFileSync').returns(`{
44 "name": "@example/package",
45 "version": "3.1.4"
46 }`);
47 });
48 it('covers success', function () {
49 const result = readPackageJSON(filepath);
50 assert.strictEqual(result.name, '@example/package');
51 assert.strictEqual(result.version, '3.1.4');
52 });
53 it('covers failure', function () {
54 fs.readFileSync.throws();
55 const result = readPackageJSON(filepath);
56 assert.strictEqual(result.name, '(unknown)');
57 assert.strictEqual(result.version, '(unknown)');
58 });
59 }); // readJSONFile
60
61 describe('pathExists', function () {
62 let p;
63 beforeEach(function () {
64 p = '/path/to/package';
65 sinon.stub(fs, 'statSync').returns();
66 });
67 it('returns true when path exists', function () {
68 const result = pathExists(p);
69 assert.strictEqual(result, true);
70 });
71 it('returns false when path does not exist', function () {
72 fs.statSync.throws(noentError);
73 const result = pathExists(p);
74 assert.strictEqual(result, false);
75 });
76 it('raises other error', function () {
77 const expectedError = new Error('oh no');
78 fs.statSync.throws(expectedError);
79 assert.throws(() => pathExists(p), expectedError);
80 });
81 }); // pathExists
82
83 describe('locatePackageBase', function () {
84 let filepath;
85
86 beforeEach(function () {
87 filepath = '/path/to/package/lib/file.js';
88 sinon.stub(fs, 'statSync');
89 });
90
91 it('covers unstubbed result', function () {
92 sinon.restore();
93 locatePackageBase(__filename);
94 });
95
96 it('locates the package base', function () {
97 fs.statSync
98 .onCall(0).throws(noentError)
99 .onCall(1).returns()
100 ;
101 const result = locatePackageBase(filepath);
102 assert.strictEqual(result, '/path/to/package/');
103 });
104
105 it('cannot locate the package base', function () {
106 fs.statSync.throws(noentError);
107 assert.throws(() => locatePackageBase(filepath), FileScopeError);
108 });
109
110 it('propagates unknown error', function () {
111 const expectedException = new Error('oh no');
112 fs.statSync
113 .onCall(0).throws(noentError)
114 .onCall(1).throws(expectedException)
115 ;
116 assert.throws(() => locatePackageBase(filepath), expectedException);
117 });
118 }); // locatePackageBase
119
120 describe('defaultOptions', function () {
121 let packageBase, expected;
122 beforeEach(function () {
123 packageBase = '/path/to/package';
124 sinon.stub(fs, 'statSync').returns();
125 expected = {
126 includePath: false,
127 includePackage: false,
128 includeVersion: false,
129 leftTrim: 0,
130 _errorEncountered: false,
131 errorPrefix: '?',
132 delimiter: ':',
133 };
134 });
135 it('covers no path', function () {
136 const options = defaultOptions();
137 assert.deepStrictEqual(options, expected);
138 });
139 it('covers default', function () {
140 expected.includePath = true;
141 fs.statSync.throws(noentError);
142 const options = defaultOptions(packageBase);
143 assert.deepStrictEqual(options, expected);
144 });
145 it('covers lib package', function () {
146 expected.includePath = true;
147 expected.includePackage = true;
148 expected.includeVersion = true;
149 expected.leftTrim = 4;
150 const options = defaultOptions(packageBase);
151 assert.deepStrictEqual(options, expected);
152 });
153 it('covers src package', function () {
154 expected.includePath = true;
155 expected.leftTrim = 4;
156 fs.statSync.onCall(0).throws(noentError);
157 const options = defaultOptions(packageBase);
158 assert.deepStrictEqual(options, expected);
159 });
160 it('covers error', function () {
161 const expectedError = new Error('oh no');
162 fs.statSync.throws(expectedError);
163 expected._errorEncountered = true;
164 const options = defaultOptions(packageBase);
165 assert.deepStrictEqual(options, expected);
166 });
167 }); // defaultOptions
168
169 describe('fileScope', function () {
170 let filepath, options, method;
171 beforeEach(function () {
172 filepath = '/path/to/package/lib/deep/file.js';
173 sinon.stub(fs, 'statSync')
174 .onCall(0).throws(noentError) // deep
175 .onCall(1).throws(noentError) // lib
176 .onCall(2).returns() // packageBase
177 ;
178 sinon.stub(fs, 'readFileSync').returns(`{
179 "name": "@example/package",
180 "version": "3.1.4"
181 }`);
182 options = {
183 includePath: true,
184 includePackage: false,
185 includeVersion: false,
186 };
187 method = 'method';
188 });
189
190 it('defaults', function () {
191 filepath = '/path/to/package/code/module/file.js';
192 fs.statSync
193 .onCall(3).throws(noentError) // no lib
194 .onCall(4).throws(noentError) // no src
195 ;
196 const result = fileScope(filepath)(method);
197 assert.strictEqual(result, 'code/module/file:method');
198 });
199
200 it('everything', function () {
201 options.includePath = true;
202 options.includePackage = true;
203 options.includeVersion = true;
204 const result = fileScope(filepath, options)(method);
205 assert.strictEqual(result, '@example/package@3.1.4:deep/file:method');
206 });
207
208 it('minimal', function () {
209 options.includePath = false;
210 options.includePackage = false;
211 options.includeVersion = false;
212 const result = fileScope(filepath, options)(method);
213 assert.strictEqual(result, 'file:method');
214 });
215
216 it('package only', function () {
217 options.includePath = false;
218 options.includePackage = true;
219 options.includeVersion = false;
220 const result = fileScope(filepath, options)(method);
221 assert.strictEqual(result, '@example/package:file:method');
222 });
223
224 it('covers no package root', function () {
225 options.includePackage = true;
226 fs.statSync.restore()
227 sinon.stub(fs, 'statSync').throws(noentError);
228 fs.readFileSync.throws(noentError);
229 const result = fileScope(filepath, options)(method);
230 assert.strictEqual(result, '?:(unknown):file:method');
231 });
232
233 it('covers exception while finding package root', function () {
234 const expectedException = new Error('oh no');
235 options.includePackage = true;
236 fs.statSync.restore()
237 sinon.stub(fs, 'statSync').throws(expectedException);
238 fs.readFileSync.throws(noentError);
239 const result = fileScope(filepath, options)(method);
240 assert.strictEqual(result, '?:(unknown):file:method');
241 });
242
243 it('handles index.js', function () {
244 filepath = '/path/to/package/src/deep/index.js';
245 fs.statSync
246 .onCall(3).throws(noentError) // no lib
247 .onCall(4).returns() // src
248 ;
249 const result = fileScope(filepath)(method);
250 assert.strictEqual(result, 'deep:method');
251 });
252
253 it('handles index.js when including path', function () {
254 filepath = '/path/to/package/code/folder/deep/index.js';
255 fs.statSync.restore();
256 sinon.stub(fs, 'statSync')
257 .throws(noentError)
258 .onCall(3).returns() // packageBase found
259 // no lib
260 // no src
261 ;
262 const result = fileScope(filepath)(method);
263 assert.strictEqual(result, 'code/folder/deep:method');
264 });
265
266 it('handles index.js when not including path', function () {
267 filepath = '/path/to/package/code/folder/deep/index.ts';
268 fs.statSync.restore();
269 sinon.stub(fs, 'statSync')
270 .throws(noentError)
271 .onCall(3).returns() // packageBase found
272 // no lib
273 // no src
274 ;
275 const result = fileScope(filepath, { includePath: false })(method);
276 assert.strictEqual(result, 'deep:method');
277 });
278
279 }); // fileScope
280
281
282 }); // File Scope