forked from microsoft/rushstack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFileDiffTest.ts
More file actions
98 lines (82 loc) · 4 KB
/
FileDiffTest.ts
File metadata and controls
98 lines (82 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
import * as path from 'path';
import { PackageJsonLookup } from './PackageJsonLookup';
import { Text } from './Text';
import { FileSystem } from './FileSystem';
import { PosixModeBits } from './PosixModeBits';
/**
* Implements a unit testing strategy that generates output files, and then
* compares them against the expected input. If the files are different, then
* the test fails.
*
* @public
*/
export class FileDiffTest {
private static _packageJsonLookup: PackageJsonLookup = new PackageJsonLookup();
/**
* Clears the internal file cache.
* @remarks
* Call this method if changes have been made to the package.json files on disk.
*/
public static clearCache(): void {
this._packageJsonLookup.clearCache();
}
/**
* Sets up a folder in the temp directory where the unit test should write its output files
* to be diffed. Any previous contents of the folder will be deleted.
*
* @param unitTestDirName - the "__dirname" variable, evaluated in the context of the unit test
* @param testModule - the name of the class being unit tested; must contain only letters, numbers, and underscores.
* @returns A fully qualified path of the folder where the unit test should write its output
*/
public static prepareFolder(unitTestDirName: string, testModule: string): string {
const packageJsonFolderPath: string | undefined
= this._packageJsonLookup.tryGetPackageFolderFor(unitTestDirName);
if (packageJsonFolderPath === undefined) {
throw new Error('Unable to find a package.json in any parent folder of ' + unitTestDirName);
}
if (!/^[a-zA-Z0-9_]+$/.test(testModule)) {
throw new Error('Invalid test module name: ' + testModule);
}
const diffTestPath: string = path.join(packageJsonFolderPath, 'temp', 'diff-tests', testModule);
FileSystem.ensureFolder(diffTestPath);
FileSystem.ensureEmptyFolder(diffTestPath);
return diffTestPath;
}
/**
* Compares the contents of two files, and returns true if they are equivalent.
* Note that these files are not normally edited by a human; the "equivalence"
* comparison here is intended to ignore spurious changes that might be introduced
* by a tool, e.g. Git newline normalization or an editor that strips
* whitespace when saving.
*/
public static assertEqual(actualFilePath: string, expectedFilePath: string): void {
const actualContent: string = FileSystem.readFile(actualFilePath);
const expectedContent: string = FileSystem.readFile(expectedFilePath);
// NOTE: "\s" also matches "\r" and "\n"
const normalizedActual: string = FileDiffTest._getNormalizedContent(actualContent);
const normalizedExpected: string = FileDiffTest._getNormalizedContent(expectedContent);
if (normalizedActual !== normalizedExpected) {
// Copy the expected file into the same folder as the actual file for easier comparisons
const expectedCopyFilename: string = path.join(path.dirname(actualFilePath), path.basename(expectedFilePath));
if (FileSystem.exists(expectedCopyFilename)) {
throw new Error('The FileDiffTest failed, but the expected output cannot be copied because'
+ ' the file already exists:\n' + expectedCopyFilename);
}
FileSystem.copyFile({
sourcePath: expectedFilePath,
destinationPath: expectedCopyFilename
});
// Set to read-only so that developer doesn't accidentally modify the wrong file
FileSystem.changePosixModeBits(expectedCopyFilename, PosixModeBits.AllRead);
throw new Error('The test output file does not match the expected input:\n'
+ actualFilePath);
}
}
private static _getNormalizedContent(s: string): string {
return Text.convertToLf(s) // convert to Unix-style newlines
.replace(/\s+\n/g, '\n') // strip spaces from end of line
.replace(/\n+$/g, ''); // strip newlines from end of file
}
}