runspec-node 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/finder.d.ts +32 -0
- package/dist/finder.d.ts.map +1 -1
- package/dist/finder.js +66 -5
- package/dist/finder.js.map +1 -1
- package/package.json +1 -1
- package/src/finder.ts +66 -8
- package/tests/test_finder.test.ts +94 -0
package/dist/finder.d.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locate the governing `runspec.toml`.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order mirrors the Python `parse()`:
|
|
5
|
+
* 1. `RUNSPEC_CONFIG` env var — explicit override.
|
|
6
|
+
* 2. an explicit `start` directory, when one is passed.
|
|
7
|
+
* 3. **caller-relative** — walk up from the entry script's directory
|
|
8
|
+
* (`require.main` / `process.argv[1]`). This is what lets an installed
|
|
9
|
+
* runnable find its own config from *any* working directory — e.g. when a
|
|
10
|
+
* controller launches `bin/greet` over SSH with `cwd` = the login home,
|
|
11
|
+
* not the package. Mirrors Python resolving relative to the installed
|
|
12
|
+
* package, "what makes installed entry points work from any working
|
|
13
|
+
* directory".
|
|
14
|
+
* 4. **cwd-relative** — walk up from `process.cwd()` (the historical
|
|
15
|
+
* behaviour, kept as the final fallback).
|
|
16
|
+
*
|
|
17
|
+
* A `runspec.toml` found *inside* a `node_modules` path is ignored: those
|
|
18
|
+
* belong to installed dependencies (including runspec-node's own bundled CLI
|
|
19
|
+
* spec), never the project being discovered.
|
|
20
|
+
*/
|
|
1
21
|
export declare function findConfig(start?: string): {
|
|
2
22
|
configPath: string;
|
|
3
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Ordered, de-duplicated list of directories to walk up from, mirroring the
|
|
26
|
+
* resolution order documented on `findConfig`. Pure (no I/O) so the priority
|
|
27
|
+
* logic is unit-testable without a filesystem fixture.
|
|
28
|
+
*/
|
|
29
|
+
export declare function searchStarts(start: string | undefined, entryDir: string | undefined, cwd: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Walk up from `start` looking for a `runspec.toml`, skipping any found under a
|
|
32
|
+
* `node_modules` path (a dependency's spec, not the project's). Returns the
|
|
33
|
+
* path or null. Exported for testing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function walkUp(start: string): string | null;
|
|
4
36
|
//# sourceMappingURL=finder.d.ts.map
|
package/dist/finder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finder.d.ts","sourceRoot":"","sources":["../src/finder.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"finder.d.ts","sourceRoot":"","sources":["../src/finder.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAoBjE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAM3G;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWnD"}
|
package/dist/finder.js
CHANGED
|
@@ -34,20 +34,81 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.findConfig = findConfig;
|
|
37
|
+
exports.searchStarts = searchStarts;
|
|
38
|
+
exports.walkUp = walkUp;
|
|
37
39
|
const fs = __importStar(require("fs"));
|
|
38
40
|
const path = __importStar(require("path"));
|
|
41
|
+
/**
|
|
42
|
+
* Locate the governing `runspec.toml`.
|
|
43
|
+
*
|
|
44
|
+
* Resolution order mirrors the Python `parse()`:
|
|
45
|
+
* 1. `RUNSPEC_CONFIG` env var — explicit override.
|
|
46
|
+
* 2. an explicit `start` directory, when one is passed.
|
|
47
|
+
* 3. **caller-relative** — walk up from the entry script's directory
|
|
48
|
+
* (`require.main` / `process.argv[1]`). This is what lets an installed
|
|
49
|
+
* runnable find its own config from *any* working directory — e.g. when a
|
|
50
|
+
* controller launches `bin/greet` over SSH with `cwd` = the login home,
|
|
51
|
+
* not the package. Mirrors Python resolving relative to the installed
|
|
52
|
+
* package, "what makes installed entry points work from any working
|
|
53
|
+
* directory".
|
|
54
|
+
* 4. **cwd-relative** — walk up from `process.cwd()` (the historical
|
|
55
|
+
* behaviour, kept as the final fallback).
|
|
56
|
+
*
|
|
57
|
+
* A `runspec.toml` found *inside* a `node_modules` path is ignored: those
|
|
58
|
+
* belong to installed dependencies (including runspec-node's own bundled CLI
|
|
59
|
+
* spec), never the project being discovered.
|
|
60
|
+
*/
|
|
39
61
|
function findConfig(start) {
|
|
40
|
-
|
|
62
|
+
const env = process.env.RUNSPEC_CONFIG;
|
|
63
|
+
if (env && fs.existsSync(env))
|
|
64
|
+
return { configPath: path.resolve(env) };
|
|
65
|
+
// process.argv[1] over require.main.filename: the latter realpath-resolves
|
|
66
|
+
// symlinks, which under `npm link` / workspaces / a local install jumps the
|
|
67
|
+
// entry *out* of the project (to the linked source) and breaks the walk.
|
|
68
|
+
// process.argv[1] preserves the path the binary was actually invoked at —
|
|
69
|
+
// inside the project's node_modules — which is what we want to walk up from.
|
|
70
|
+
const entry = process.argv[1] ?? require.main?.filename;
|
|
71
|
+
const entryDir = entry ? path.dirname(entry) : undefined;
|
|
72
|
+
for (const dir of searchStarts(start, entryDir, process.cwd())) {
|
|
73
|
+
const found = walkUp(dir);
|
|
74
|
+
if (found)
|
|
75
|
+
return { configPath: found };
|
|
76
|
+
}
|
|
77
|
+
throw new Error("No runspec configuration found.\nExpected runspec.toml inside your package directory.\n\nRun 'runspec init' to create one.");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Ordered, de-duplicated list of directories to walk up from, mirroring the
|
|
81
|
+
* resolution order documented on `findConfig`. Pure (no I/O) so the priority
|
|
82
|
+
* logic is unit-testable without a filesystem fixture.
|
|
83
|
+
*/
|
|
84
|
+
function searchStarts(start, entryDir, cwd) {
|
|
85
|
+
const out = [];
|
|
86
|
+
if (start)
|
|
87
|
+
out.push(path.resolve(start));
|
|
88
|
+
if (entryDir)
|
|
89
|
+
out.push(path.resolve(entryDir));
|
|
90
|
+
out.push(path.resolve(cwd));
|
|
91
|
+
return [...new Set(out)];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Walk up from `start` looking for a `runspec.toml`, skipping any found under a
|
|
95
|
+
* `node_modules` path (a dependency's spec, not the project's). Returns the
|
|
96
|
+
* path or null. Exported for testing.
|
|
97
|
+
*/
|
|
98
|
+
function walkUp(start) {
|
|
99
|
+
let dir = path.resolve(start);
|
|
41
100
|
while (true) {
|
|
42
101
|
const runspecToml = path.join(dir, 'runspec.toml');
|
|
43
|
-
if (fs.existsSync(runspecToml)) {
|
|
44
|
-
return
|
|
102
|
+
if (fs.existsSync(runspecToml) && !isInNodeModules(dir)) {
|
|
103
|
+
return runspecToml;
|
|
45
104
|
}
|
|
46
105
|
const parent = path.dirname(dir);
|
|
47
106
|
if (parent === dir)
|
|
48
|
-
|
|
107
|
+
return null;
|
|
49
108
|
dir = parent;
|
|
50
109
|
}
|
|
51
|
-
|
|
110
|
+
}
|
|
111
|
+
function isInNodeModules(dir) {
|
|
112
|
+
return dir.split(path.sep).includes('node_modules');
|
|
52
113
|
}
|
|
53
114
|
//# sourceMappingURL=finder.js.map
|
package/dist/finder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finder.js","sourceRoot":"","sources":["../src/finder.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"finder.js","sourceRoot":"","sources":["../src/finder.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,gCAoBC;AAOD,oCAMC;AAOD,wBAWC;AA1ED,uCAAyB;AACzB,2CAA6B;AAE7B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,UAAU,CAAC,KAAc;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACvC,IAAI,GAAG,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAExE,2EAA2E;IAC3E,4EAA4E;IAC5E,yEAAyE;IACzE,0EAA0E;IAC1E,6EAA6E;IAC7E,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzD,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK;YAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,IAAI,KAAK,CACb,4HAA4H,CAC7H,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,KAAyB,EAAE,QAA4B,EAAE,GAAW;IAC/F,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,KAAK;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACzC,IAAI,QAAQ;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,SAAgB,MAAM,CAAC,KAAa;IAClC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACnD,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YACxD,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AACtD,CAAC"}
|
package/package.json
CHANGED
package/src/finder.ts
CHANGED
|
@@ -1,21 +1,79 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Locate the governing `runspec.toml`.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order mirrors the Python `parse()`:
|
|
8
|
+
* 1. `RUNSPEC_CONFIG` env var — explicit override.
|
|
9
|
+
* 2. an explicit `start` directory, when one is passed.
|
|
10
|
+
* 3. **caller-relative** — walk up from the entry script's directory
|
|
11
|
+
* (`require.main` / `process.argv[1]`). This is what lets an installed
|
|
12
|
+
* runnable find its own config from *any* working directory — e.g. when a
|
|
13
|
+
* controller launches `bin/greet` over SSH with `cwd` = the login home,
|
|
14
|
+
* not the package. Mirrors Python resolving relative to the installed
|
|
15
|
+
* package, "what makes installed entry points work from any working
|
|
16
|
+
* directory".
|
|
17
|
+
* 4. **cwd-relative** — walk up from `process.cwd()` (the historical
|
|
18
|
+
* behaviour, kept as the final fallback).
|
|
19
|
+
*
|
|
20
|
+
* A `runspec.toml` found *inside* a `node_modules` path is ignored: those
|
|
21
|
+
* belong to installed dependencies (including runspec-node's own bundled CLI
|
|
22
|
+
* spec), never the project being discovered.
|
|
23
|
+
*/
|
|
4
24
|
export function findConfig(start?: string): { configPath: string } {
|
|
5
|
-
|
|
25
|
+
const env = process.env.RUNSPEC_CONFIG;
|
|
26
|
+
if (env && fs.existsSync(env)) return { configPath: path.resolve(env) };
|
|
6
27
|
|
|
28
|
+
// process.argv[1] over require.main.filename: the latter realpath-resolves
|
|
29
|
+
// symlinks, which under `npm link` / workspaces / a local install jumps the
|
|
30
|
+
// entry *out* of the project (to the linked source) and breaks the walk.
|
|
31
|
+
// process.argv[1] preserves the path the binary was actually invoked at —
|
|
32
|
+
// inside the project's node_modules — which is what we want to walk up from.
|
|
33
|
+
const entry = process.argv[1] ?? require.main?.filename;
|
|
34
|
+
const entryDir = entry ? path.dirname(entry) : undefined;
|
|
35
|
+
|
|
36
|
+
for (const dir of searchStarts(start, entryDir, process.cwd())) {
|
|
37
|
+
const found = walkUp(dir);
|
|
38
|
+
if (found) return { configPath: found };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
throw new Error(
|
|
42
|
+
"No runspec configuration found.\nExpected runspec.toml inside your package directory.\n\nRun 'runspec init' to create one.",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Ordered, de-duplicated list of directories to walk up from, mirroring the
|
|
48
|
+
* resolution order documented on `findConfig`. Pure (no I/O) so the priority
|
|
49
|
+
* logic is unit-testable without a filesystem fixture.
|
|
50
|
+
*/
|
|
51
|
+
export function searchStarts(start: string | undefined, entryDir: string | undefined, cwd: string): string[] {
|
|
52
|
+
const out: string[] = [];
|
|
53
|
+
if (start) out.push(path.resolve(start));
|
|
54
|
+
if (entryDir) out.push(path.resolve(entryDir));
|
|
55
|
+
out.push(path.resolve(cwd));
|
|
56
|
+
return [...new Set(out)];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Walk up from `start` looking for a `runspec.toml`, skipping any found under a
|
|
61
|
+
* `node_modules` path (a dependency's spec, not the project's). Returns the
|
|
62
|
+
* path or null. Exported for testing.
|
|
63
|
+
*/
|
|
64
|
+
export function walkUp(start: string): string | null {
|
|
65
|
+
let dir = path.resolve(start);
|
|
7
66
|
while (true) {
|
|
8
67
|
const runspecToml = path.join(dir, 'runspec.toml');
|
|
9
|
-
if (fs.existsSync(runspecToml)) {
|
|
10
|
-
return
|
|
68
|
+
if (fs.existsSync(runspecToml) && !isInNodeModules(dir)) {
|
|
69
|
+
return runspecToml;
|
|
11
70
|
}
|
|
12
|
-
|
|
13
71
|
const parent = path.dirname(dir);
|
|
14
|
-
if (parent === dir)
|
|
72
|
+
if (parent === dir) return null;
|
|
15
73
|
dir = parent;
|
|
16
74
|
}
|
|
75
|
+
}
|
|
17
76
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
);
|
|
77
|
+
function isInNodeModules(dir: string): boolean {
|
|
78
|
+
return dir.split(path.sep).includes('node_modules');
|
|
21
79
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { findConfig, searchStarts, walkUp } from '../src/finder';
|
|
5
|
+
|
|
6
|
+
function tmpdir(): string {
|
|
7
|
+
return fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'runspec-finder-'));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function writeToml(dir: string): string {
|
|
11
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
12
|
+
const p = path.join(dir, 'runspec.toml');
|
|
13
|
+
fs.writeFileSync(p, '[greet]\ndescription = "x"\n');
|
|
14
|
+
return p;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('searchStarts — resolution priority', () => {
|
|
18
|
+
it('orders explicit start, then entry dir, then cwd', () => {
|
|
19
|
+
expect(searchStarts('/a', '/b', '/c')).toEqual([path.resolve('/a'), path.resolve('/b'), path.resolve('/c')]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('omits a missing explicit start / entry dir', () => {
|
|
23
|
+
expect(searchStarts(undefined, undefined, '/c')).toEqual([path.resolve('/c')]);
|
|
24
|
+
expect(searchStarts(undefined, '/b', '/c')).toEqual([path.resolve('/b'), path.resolve('/c')]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('de-duplicates while preserving order (cwd === entry dir)', () => {
|
|
28
|
+
expect(searchStarts(undefined, '/same', '/same')).toEqual([path.resolve('/same')]);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('walkUp', () => {
|
|
33
|
+
let dir: string;
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
if (dir) fs.rmSync(dir, { recursive: true, force: true });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('finds runspec.toml walking up from a nested dir', () => {
|
|
39
|
+
dir = tmpdir();
|
|
40
|
+
const toml = writeToml(dir);
|
|
41
|
+
const nested = path.join(dir, 'a', 'b', 'c');
|
|
42
|
+
fs.mkdirSync(nested, { recursive: true });
|
|
43
|
+
expect(walkUp(nested)).toBe(toml);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('ignores a runspec.toml that lives under node_modules', () => {
|
|
47
|
+
dir = tmpdir();
|
|
48
|
+
const projectToml = writeToml(dir); // {root}/runspec.toml — the project's
|
|
49
|
+
// A dependency ships its own runspec.toml (e.g. runspec-node's CLI spec).
|
|
50
|
+
const depDir = path.join(dir, 'node_modules', 'runspec-node', 'dist');
|
|
51
|
+
writeToml(depDir);
|
|
52
|
+
// Walking up from inside node_modules must skip the dep's toml and resolve
|
|
53
|
+
// the project's — this is the installed-CLI discovery case.
|
|
54
|
+
expect(walkUp(depDir)).toBe(projectToml);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('returns null when no runspec.toml exists up the tree', () => {
|
|
58
|
+
dir = tmpdir();
|
|
59
|
+
const nested = path.join(dir, 'x', 'y');
|
|
60
|
+
fs.mkdirSync(nested, { recursive: true });
|
|
61
|
+
expect(walkUp(nested)).toBeNull();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('findConfig', () => {
|
|
66
|
+
let dir: string;
|
|
67
|
+
const savedEnv = process.env.RUNSPEC_CONFIG;
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
if (savedEnv === undefined) delete process.env.RUNSPEC_CONFIG;
|
|
70
|
+
else process.env.RUNSPEC_CONFIG = savedEnv;
|
|
71
|
+
if (dir) fs.rmSync(dir, { recursive: true, force: true });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('honours RUNSPEC_CONFIG when set', () => {
|
|
75
|
+
dir = tmpdir();
|
|
76
|
+
const toml = writeToml(path.join(dir, 'custom'));
|
|
77
|
+
process.env.RUNSPEC_CONFIG = toml;
|
|
78
|
+
// cwd has no toml, but the env var wins regardless.
|
|
79
|
+
expect(findConfig(dir).configPath).toBe(path.resolve(toml));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('resolves from an explicit start dir', () => {
|
|
83
|
+
delete process.env.RUNSPEC_CONFIG;
|
|
84
|
+
dir = tmpdir();
|
|
85
|
+
const toml = writeToml(dir);
|
|
86
|
+
expect(findConfig(path.join(dir, 'sub', 'dir')).configPath).toBe(toml);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('throws a helpful error when nothing is found', () => {
|
|
90
|
+
delete process.env.RUNSPEC_CONFIG;
|
|
91
|
+
dir = tmpdir(); // empty, no runspec.toml anywhere up the chain inside the tmp root
|
|
92
|
+
expect(() => findConfig(dir)).toThrow(/No runspec configuration found/);
|
|
93
|
+
});
|
|
94
|
+
});
|