UNPKG

3.46 kBPlain TextView Raw
1// Copyright IBM Corp. 2018. All Rights Reserved.
2// Node module: @loopback/testlab
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6import {
7 appendFile,
8 copy,
9 emptyDir,
10 ensureDir,
11 ensureDirSync,
12 pathExists,
13 remove,
14 writeJson,
15} from 'fs-extra';
16import {parse, resolve} from 'path';
17
18/**
19 * TestSandbox class provides a convenient way to get a reference to a
20 * sandbox folder in which you can perform operations for testing purposes.
21 */
22export class TestSandbox {
23 // Path of the TestSandbox
24 private _path?: string;
25
26 public get path(): string {
27 if (!this._path) {
28 throw new Error(
29 `TestSandbox instance was deleted. Create a new instance.`,
30 );
31 }
32 return this._path;
33 }
34
35 /**
36 * Will create a directory if it doesn't already exist. If it exists, you
37 * still get an instance of the TestSandbox.
38 *
39 * @param path - Path of the TestSandbox. If relative (it will be resolved relative to cwd()).
40 */
41 constructor(path: string) {
42 // resolve ensures path is absolute / makes it absolute (relative to cwd())
43 this._path = resolve(path);
44 ensureDirSync(this.path);
45 }
46
47 /**
48 * Returns the path of the TestSandbox
49 */
50 getPath(): string {
51 return this.path;
52 }
53
54 /**
55 * Resets the TestSandbox. (Remove all files in it).
56 */
57 async reset(): Promise<void> {
58 // Decache files from require's cache so future tests aren't affected incase
59 // a file is recreated in sandbox with the same file name but different
60 // contents after resetting the sandbox.
61 for (const key in require.cache) {
62 if (key.startsWith(this.path)) {
63 delete require.cache[key];
64 }
65 }
66
67 await emptyDir(this.path);
68 }
69
70 /**
71 * Deletes the TestSandbox.
72 */
73 async delete(): Promise<void> {
74 await remove(this.path);
75 delete this._path;
76 }
77
78 /**
79 * Makes a directory in the TestSandbox
80 *
81 * @param dir - Name of directory to create (relative to TestSandbox path)
82 */
83 async mkdir(dir: string): Promise<void> {
84 await ensureDir(resolve(this.path, dir));
85 }
86
87 /**
88 * Copies a file from src to the TestSandbox. If copying a `.js` file which
89 * has an accompanying `.js.map` file in the src file location, the dest file
90 * will have its sourceMappingURL updated to point to the original file as
91 * an absolute path so you don't need to copy the map file.
92 *
93 * @param src - Absolute path of file to be copied to the TestSandbox
94 * @param dest - Optional. Destination filename of the copy operation
95 * (relative to TestSandbox). Original filename used if not specified.
96 */
97 async copyFile(src: string, dest?: string): Promise<void> {
98 dest = dest
99 ? resolve(this.path, dest)
100 : resolve(this.path, parse(src).base);
101
102 await copy(src, dest);
103
104 if (parse(src).ext === '.js' && pathExists(src + '.map')) {
105 const srcMap = src + '.map';
106 await appendFile(dest, `\n//# sourceMappingURL=${srcMap}`);
107 }
108 }
109
110 /**
111 * Creates a new file and writes the given data serialized as JSON.
112 *
113 * @param dest - Destination filename, optionally including a relative path.
114 * @param data - The data to write.
115 */
116 async writeJsonFile(dest: string, data: unknown): Promise<void> {
117 dest = resolve(this.path, dest);
118 const destDir = parse(dest).dir;
119 await ensureDir(destDir);
120 return writeJson(dest, data, {spaces: 2});
121 }
122}