v8r 4.2.0 → 4.3.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/CHANGELOG.md +14 -0
- package/config-schema.json +11 -0
- package/package.json +6 -5
- package/src/bootstrap.js +50 -1
- package/src/cache.js +6 -19
- package/src/cli.js +16 -15
- package/src/glob.js +80 -3
- package/src/output-formatters.js +18 -1
- package/src/plugins.js +10 -13
- package/src/test-helpers.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 📦 [4.3.0](https://www.npmjs.com/package/v8r/v/4.3.0) - 2025-04-21
|
|
4
|
+
|
|
5
|
+
* Add ignore patern files. v8r now looks for ignore patterns in `.v8rignore` by default.
|
|
6
|
+
More info: https://chris48s.github.io/v8r/ignoring-files/
|
|
7
|
+
* Include the prop name in `additionalProperty` log message.
|
|
8
|
+
* Allow config file to contain `$schema` key.
|
|
9
|
+
* Fix: Clear the cache on init if TTL is 0.
|
|
10
|
+
|
|
11
|
+
## 📦 [4.2.1](https://www.npmjs.com/package/v8r/v/4.2.1) - 2024-12-14
|
|
12
|
+
|
|
13
|
+
* Upgrade to flat-cache 6.
|
|
14
|
+
This release revamps how cache is stored and invalidated internally
|
|
15
|
+
but should have no user-visible impact
|
|
16
|
+
|
|
3
17
|
## 📦 [4.2.0](https://www.npmjs.com/package/v8r/v/4.2.0) - 2024-10-24
|
|
4
18
|
|
|
5
19
|
* Add `V8R_CONFIG_FILE` environment variable.
|
package/config-schema.json
CHANGED
|
@@ -65,6 +65,14 @@
|
|
|
65
65
|
"description": "Exit with code 0 even if an error was encountered. True means a non-zero exit code is only issued if validation could be completed successfully and one or more files were invalid",
|
|
66
66
|
"type": "boolean"
|
|
67
67
|
},
|
|
68
|
+
"ignorePatternFiles": {
|
|
69
|
+
"description": "A list of files containing glob patterns to ignore",
|
|
70
|
+
"uniqueItems": true,
|
|
71
|
+
"type": "array",
|
|
72
|
+
"items": {
|
|
73
|
+
"type": "string"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
68
76
|
"patterns": {
|
|
69
77
|
"type": "array",
|
|
70
78
|
"description": "One or more filenames or glob patterns describing local file or files to validate",
|
|
@@ -87,6 +95,9 @@
|
|
|
87
95
|
"type": "string",
|
|
88
96
|
"pattern": "^(package:|file:)"
|
|
89
97
|
}
|
|
98
|
+
},
|
|
99
|
+
"$schema": {
|
|
100
|
+
"type": "string"
|
|
90
101
|
}
|
|
91
102
|
}
|
|
92
103
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "v8r",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "A command-line JSON, YAML and TOML validator that's on your wavelength",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "V8R_CACHE_NAME=v8r-test c8 --reporter=text mocha \"src/**/*.spec.js\"",
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
"chalk": "^5.0.0",
|
|
34
34
|
"cosmiconfig": "^9.0.0",
|
|
35
35
|
"decamelize": "^6.0.0",
|
|
36
|
-
"flat-cache": "^
|
|
36
|
+
"flat-cache": "^6.1.4",
|
|
37
37
|
"glob": "^10.1.0",
|
|
38
38
|
"global-agent": "^3.0.0",
|
|
39
39
|
"got": "^13.0.0",
|
|
40
|
+
"ignore": "^7.0.0",
|
|
40
41
|
"is-url": "^1.2.4",
|
|
41
42
|
"js-yaml": "^4.0.0",
|
|
42
43
|
"json5": "^2.2.0",
|
|
@@ -47,13 +48,13 @@
|
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"c8": "^10.1.2",
|
|
49
50
|
"eslint": "^9.9.0",
|
|
50
|
-
"eslint-config-prettier": "^
|
|
51
|
+
"eslint-config-prettier": "^10.1.2",
|
|
51
52
|
"eslint-plugin-jsdoc": "^50.2.2",
|
|
52
53
|
"eslint-plugin-mocha": "^10.0.3",
|
|
53
54
|
"eslint-plugin-prettier": "^5.0.0",
|
|
54
|
-
"mocha": "^
|
|
55
|
+
"mocha": "^11.0.1",
|
|
55
56
|
"mock-cwd": "^1.0.0",
|
|
56
|
-
"nock": "^
|
|
57
|
+
"nock": "^14.0.4",
|
|
57
58
|
"prettier": "^3.0.0",
|
|
58
59
|
"prettier-plugin-jsdoc": "^1.3.0"
|
|
59
60
|
},
|
package/src/bootstrap.js
CHANGED
|
@@ -76,13 +76,51 @@ function parseArgs(argv, config, documentFormats, outputFormats) {
|
|
|
76
76
|
)} (from config file ${getRelativeFilePath(config)})`;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
const ignoreFilesOpts = {
|
|
80
|
+
describe: "A list of files containing glob patterns to ignore",
|
|
81
|
+
};
|
|
82
|
+
let ignoreFilesDefault = [".v8rignore"];
|
|
83
|
+
ignoreFilesOpts.defaultDescription = `${JSON.stringify(ignoreFilesDefault)}`;
|
|
84
|
+
if (Object.keys(config.config).includes("ignorePatternFiles")) {
|
|
85
|
+
ignoreFilesDefault = config.config.ignorePatternFiles;
|
|
86
|
+
ignoreFilesOpts.defaultDescription = `${JSON.stringify(
|
|
87
|
+
ignoreFilesDefault,
|
|
88
|
+
)} (from config file ${getRelativeFilePath(config)})`;
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
parser
|
|
80
92
|
.command(
|
|
93
|
+
// command
|
|
81
94
|
command,
|
|
95
|
+
|
|
96
|
+
// description
|
|
82
97
|
`Validate local ${documentFormats.join("/")} files against schema(s)`,
|
|
98
|
+
|
|
99
|
+
// builder
|
|
83
100
|
(yargs) => {
|
|
84
101
|
yargs.positional("patterns", patternsOpts);
|
|
85
102
|
},
|
|
103
|
+
|
|
104
|
+
// handler
|
|
105
|
+
(args) => {
|
|
106
|
+
/*
|
|
107
|
+
Yargs doesn't allow .conflicts() with an argument that has a default
|
|
108
|
+
value (it considers the arg "set" even if we just use the default)
|
|
109
|
+
so we need to apply the default values here.
|
|
110
|
+
*/
|
|
111
|
+
if (args.ignorePatternFiles === undefined) {
|
|
112
|
+
args.ignorePatternFiles = args["ignore-pattern-files"] =
|
|
113
|
+
ignoreFilesDefault;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (args.ignore === false) {
|
|
117
|
+
args.ignorePatternFiles = args["ignore-pattern-files"] = [];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (args.ignore === undefined) {
|
|
121
|
+
args.ignore = true;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
86
124
|
)
|
|
87
125
|
.version(
|
|
88
126
|
// Workaround for https://github.com/yargs/yargs/issues/1934
|
|
@@ -110,7 +148,7 @@ function parseArgs(argv, config, documentFormats, outputFormats) {
|
|
|
110
148
|
alias: "c",
|
|
111
149
|
array: true,
|
|
112
150
|
describe:
|
|
113
|
-
"
|
|
151
|
+
"A list of local paths or URLs of custom catalogs to use prior to schemastore.org",
|
|
114
152
|
})
|
|
115
153
|
.conflicts("schema", "catalogs")
|
|
116
154
|
.option("ignore-errors", {
|
|
@@ -121,6 +159,17 @@ function parseArgs(argv, config, documentFormats, outputFormats) {
|
|
|
121
159
|
"means a non-zero exit code is only issued if validation could be " +
|
|
122
160
|
"completed successfully and one or more files were invalid",
|
|
123
161
|
})
|
|
162
|
+
.option("ignore-pattern-files", {
|
|
163
|
+
type: "string",
|
|
164
|
+
array: true,
|
|
165
|
+
describe: "A list of files containing glob patterns to ignore",
|
|
166
|
+
...ignoreFilesOpts,
|
|
167
|
+
})
|
|
168
|
+
.option("no-ignore", {
|
|
169
|
+
type: "boolean",
|
|
170
|
+
describe: "Disable all ignore files",
|
|
171
|
+
})
|
|
172
|
+
.conflicts("ignore-pattern-files", "no-ignore")
|
|
124
173
|
.option("cache-ttl", {
|
|
125
174
|
type: "number",
|
|
126
175
|
default: 600,
|
package/src/cache.js
CHANGED
|
@@ -3,26 +3,14 @@ import logger from "./logger.js";
|
|
|
3
3
|
import { parseSchema } from "./parser.js";
|
|
4
4
|
|
|
5
5
|
class Cache {
|
|
6
|
-
constructor(flatCache
|
|
6
|
+
constructor(flatCache) {
|
|
7
7
|
this.cache = flatCache;
|
|
8
|
-
this.ttl = ttl;
|
|
8
|
+
this.ttl = this.cache._cache.ttl || 0;
|
|
9
9
|
this.callCounter = {};
|
|
10
10
|
this.callLimit = 10;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Object.entries(this.cache.all()).forEach(
|
|
15
|
-
function ([url, cachedResponse]) {
|
|
16
|
-
if (!("timestamp" in cachedResponse) || !("body" in cachedResponse)) {
|
|
17
|
-
logger.debug(`Cache error: deleting malformed response`);
|
|
18
|
-
this.cache.removeKey(url);
|
|
19
|
-
} else if (Date.now() > cachedResponse.timestamp + this.ttl) {
|
|
20
|
-
logger.debug(`Cache stale: deleting cached response from ${url}`);
|
|
21
|
-
this.cache.removeKey(url);
|
|
22
|
-
}
|
|
23
|
-
this.cache.save(true);
|
|
24
|
-
}.bind(this),
|
|
25
|
-
);
|
|
11
|
+
if (this.ttl === 0) {
|
|
12
|
+
this.cache.clear();
|
|
13
|
+
}
|
|
26
14
|
}
|
|
27
15
|
|
|
28
16
|
limitDepth(url) {
|
|
@@ -51,7 +39,6 @@ class Cache {
|
|
|
51
39
|
|
|
52
40
|
async fetch(url) {
|
|
53
41
|
this.limitDepth(url);
|
|
54
|
-
this.expire();
|
|
55
42
|
const cachedResponse = this.cache.getKey(url);
|
|
56
43
|
if (cachedResponse !== undefined) {
|
|
57
44
|
logger.debug(`Cache hit: using cached response from ${url}`);
|
|
@@ -63,7 +50,7 @@ class Cache {
|
|
|
63
50
|
const resp = await got(url);
|
|
64
51
|
const parsedBody = parseSchema(resp.body, url);
|
|
65
52
|
if (this.ttl > 0) {
|
|
66
|
-
this.cache.setKey(url, {
|
|
53
|
+
this.cache.setKey(url, { body: parsedBody });
|
|
67
54
|
this.cache.save(true);
|
|
68
55
|
}
|
|
69
56
|
return parsedBody;
|
package/src/cli.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import
|
|
4
|
+
import { FlatCache } from "flat-cache";
|
|
5
5
|
import isUrl from "is-url";
|
|
6
6
|
import { validate } from "./ajv.js";
|
|
7
7
|
import { bootstrap } from "./bootstrap.js";
|
|
8
8
|
import { Cache } from "./cache.js";
|
|
9
9
|
import { getCatalogs, getMatchForFilename } from "./catalogs.js";
|
|
10
|
-
import { getFiles } from "./glob.js";
|
|
10
|
+
import { getFiles, NotFound } from "./glob.js";
|
|
11
11
|
import { getFromUrlOrFile } from "./io.js";
|
|
12
12
|
import logger from "./logger.js";
|
|
13
13
|
import { getDocumentLocation } from "./output-formatters.js";
|
|
@@ -27,11 +27,15 @@ function secondsToMilliseconds(seconds) {
|
|
|
27
27
|
return seconds * 1000;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function getFlatCache() {
|
|
30
|
+
function getFlatCache(ttl) {
|
|
31
|
+
let cache;
|
|
31
32
|
if (process.env.V8R_CACHE_NAME) {
|
|
32
|
-
|
|
33
|
+
cache = new FlatCache({ cacheId: process.env.V8R_CACHE_NAME, ttl: ttl });
|
|
34
|
+
} else {
|
|
35
|
+
cache = new FlatCache({ cacheId: "v8rv2", cacheDir: CACHE_DIR, ttl: ttl });
|
|
33
36
|
}
|
|
34
|
-
|
|
37
|
+
cache.load();
|
|
38
|
+
return cache;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
async function validateDocument(
|
|
@@ -166,21 +170,18 @@ function resultsToStatusCode(results, ignoreErrors) {
|
|
|
166
170
|
function Validator() {
|
|
167
171
|
return async function (config, plugins) {
|
|
168
172
|
let filenames = [];
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
try {
|
|
174
|
+
filenames = await getFiles(config.patterns, config.ignorePatternFiles);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
if (e instanceof NotFound) {
|
|
177
|
+
logger.error(e.message);
|
|
173
178
|
return EXIT.NOT_FOUND;
|
|
174
179
|
}
|
|
175
|
-
|
|
180
|
+
throw e;
|
|
176
181
|
}
|
|
177
182
|
|
|
178
|
-
// de-dupe and sort
|
|
179
|
-
filenames = [...new Set(filenames)];
|
|
180
|
-
filenames.sort((a, b) => a.localeCompare(b));
|
|
181
|
-
|
|
182
183
|
const ttl = secondsToMilliseconds(config.cacheTtl || 0);
|
|
183
|
-
const cache = new Cache(getFlatCache(
|
|
184
|
+
const cache = new Cache(getFlatCache(ttl));
|
|
184
185
|
|
|
185
186
|
let results = [];
|
|
186
187
|
for (const filename of filenames) {
|
package/src/glob.js
CHANGED
|
@@ -1,13 +1,90 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import { glob } from "glob";
|
|
4
|
+
import ignore from "ignore";
|
|
2
5
|
import logger from "./logger.js";
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
class NotFound extends Error {}
|
|
8
|
+
|
|
9
|
+
async function getMatches(pattern) {
|
|
5
10
|
try {
|
|
6
|
-
return await glob(pattern, { dot: true
|
|
11
|
+
return await glob(pattern, { dot: true });
|
|
7
12
|
} catch (e) {
|
|
8
13
|
logger.error(e.message);
|
|
9
14
|
return [];
|
|
10
15
|
}
|
|
11
16
|
}
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
async function exists(path) {
|
|
19
|
+
try {
|
|
20
|
+
await fs.promises.access(path);
|
|
21
|
+
return true;
|
|
22
|
+
} catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function filterIgnores(filenames, ignorePatterns) {
|
|
28
|
+
const ig = ignore();
|
|
29
|
+
for (const patterns of ignorePatterns) {
|
|
30
|
+
ig.add(patterns);
|
|
31
|
+
}
|
|
32
|
+
return ig.filter(filenames);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function readIgnoreFiles(filenames) {
|
|
36
|
+
let content = [];
|
|
37
|
+
for (const filename of filenames) {
|
|
38
|
+
const abspath = path.join(process.cwd(), filename);
|
|
39
|
+
if (await exists(abspath)) {
|
|
40
|
+
content.push(await fs.promises.readFile(abspath, "utf8"));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return content;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getSeparator() {
|
|
47
|
+
return process.platform == "win32" ? "\\" : "/";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function getFiles(patterns, ignorePatternFiles) {
|
|
51
|
+
let filenames = [];
|
|
52
|
+
|
|
53
|
+
// find all the files matching input globs
|
|
54
|
+
for (const pattern of patterns) {
|
|
55
|
+
const matches = await getMatches(pattern);
|
|
56
|
+
if (matches.length === 0) {
|
|
57
|
+
throw new NotFound(`Pattern '${pattern}' did not match any files`);
|
|
58
|
+
}
|
|
59
|
+
filenames = filenames.concat(matches);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// de-dupe
|
|
63
|
+
filenames = [...new Set(filenames)];
|
|
64
|
+
|
|
65
|
+
// process ignores
|
|
66
|
+
const ignorePatterns = await readIgnoreFiles(ignorePatternFiles);
|
|
67
|
+
let filteredFilenames = await filterIgnores(filenames, ignorePatterns);
|
|
68
|
+
|
|
69
|
+
const diff = filenames.filter((x) => filteredFilenames.indexOf(x) < 0);
|
|
70
|
+
if (diff.length > 0) {
|
|
71
|
+
logger.debug(
|
|
72
|
+
`Ignoring file(s):\n ${diff.join("\n ")}\nbased on ignore patterns in\n ${ignorePatternFiles.join("\n ")}`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// finally, sort
|
|
77
|
+
filteredFilenames.sort((a, b) => a.localeCompare(b));
|
|
78
|
+
|
|
79
|
+
if (filteredFilenames.length === 0) {
|
|
80
|
+
throw new NotFound(`Could not find any files to validate`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const sep = getSeparator();
|
|
84
|
+
filteredFilenames = filteredFilenames.map((fn) =>
|
|
85
|
+
!fn.startsWith(".." + sep) ? "." + sep + fn : fn,
|
|
86
|
+
);
|
|
87
|
+
return filteredFilenames;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { getFiles, NotFound };
|
package/src/output-formatters.js
CHANGED
|
@@ -9,8 +9,25 @@ function getDocumentLocation(result) {
|
|
|
9
9
|
|
|
10
10
|
function formatErrors(location, errors) {
|
|
11
11
|
const ajv = new Ajv();
|
|
12
|
+
let formattedErrors = [];
|
|
13
|
+
|
|
14
|
+
if (errors) {
|
|
15
|
+
formattedErrors = errors.map(function (error) {
|
|
16
|
+
if (
|
|
17
|
+
error.keyword === "additionalProperties" &&
|
|
18
|
+
typeof error.params.additionalProperty === "string"
|
|
19
|
+
) {
|
|
20
|
+
return {
|
|
21
|
+
...error,
|
|
22
|
+
message: `${error.message}, found additional property '${error.params.additionalProperty}'`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return error;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
return (
|
|
13
|
-
ajv.errorsText(
|
|
30
|
+
ajv.errorsText(formattedErrors, {
|
|
14
31
|
separator: "\n",
|
|
15
32
|
dataVar: location + "#",
|
|
16
33
|
}) + "\n"
|
package/src/plugins.js
CHANGED
|
@@ -37,10 +37,9 @@ class BasePlugin {
|
|
|
37
37
|
*
|
|
38
38
|
* @param {string} contents - The unparsed file content.
|
|
39
39
|
* @param {string} fileLocation - The file path. Filenames are resolved and
|
|
40
|
-
* normalised
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* present in the input filename or pattern.
|
|
40
|
+
* normalised using dot-relative notation. This means relative paths in the
|
|
41
|
+
* current directory will be prefixed with `./` (or `.\` on Windows) even if
|
|
42
|
+
* this was not present in the input filename or pattern.
|
|
44
43
|
* @param {string | undefined} parser - If the user has specified a parser to
|
|
45
44
|
* use for this file in a custom schema, this will be passed to
|
|
46
45
|
* `parseInputFile` in the `parser` param.
|
|
@@ -77,10 +76,9 @@ class BasePlugin {
|
|
|
77
76
|
* @param {ValidationResult} result - Result of attempting to validate this
|
|
78
77
|
* document.
|
|
79
78
|
* @param {string} fileLocation - The document file path. Filenames are
|
|
80
|
-
* resolved and normalised
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* was not present in the input filename or pattern.
|
|
79
|
+
* resolved and normalised using dot-relative notation. This means relative
|
|
80
|
+
* paths in the current directory will be prefixed with `./` (or `.\` on
|
|
81
|
+
* Windows) even if this was not present in the input filename or pattern.
|
|
84
82
|
* @param {string} format - The user's requested output format as specified in
|
|
85
83
|
* the config file or via the `--format` command line argument.
|
|
86
84
|
* @returns {string | undefined} Log message
|
|
@@ -201,11 +199,10 @@ async function loadAllPlugins(userPlugins) {
|
|
|
201
199
|
/**
|
|
202
200
|
* @typedef {object} ValidationResult
|
|
203
201
|
* @property {string} fileLocation - Path of the document that was validated.
|
|
204
|
-
* Filenames are resolved and normalised
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* filename or pattern.
|
|
202
|
+
* Filenames are resolved and normalised using dot-relative notation. This
|
|
203
|
+
* means relative paths in the current directory will be prefixed with `./`
|
|
204
|
+
* (or `.\` on Windows) even if this was not present in the input filename or
|
|
205
|
+
* pattern.
|
|
209
206
|
* @property {number | null} documentIndex - Some file formats allow multiple
|
|
210
207
|
* documents to be embedded in one file (e.g:
|
|
211
208
|
* [yaml](https://www.yaml.info/learn/document.html)). In these cases,
|
package/src/test-helpers.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { clearCacheById } from "flat-cache";
|
|
2
2
|
import logger from "./logger.js";
|
|
3
3
|
|
|
4
4
|
const origWriteOut = logger.writeOut;
|
|
@@ -7,7 +7,7 @@ const testCacheName = process.env.V8R_CACHE_NAME;
|
|
|
7
7
|
const env = process.env;
|
|
8
8
|
|
|
9
9
|
function setUp() {
|
|
10
|
-
|
|
10
|
+
clearCacheById(testCacheName);
|
|
11
11
|
logger.resetStdout();
|
|
12
12
|
logger.resetStderr();
|
|
13
13
|
logger.writeOut = function () {};
|
|
@@ -16,7 +16,7 @@ function setUp() {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function tearDown() {
|
|
19
|
-
|
|
19
|
+
clearCacheById(testCacheName);
|
|
20
20
|
logger.resetStdout();
|
|
21
21
|
logger.resetStderr();
|
|
22
22
|
logger.writeOut = origWriteOut;
|