Skip to content

Commit f259491

Browse files
committed
[rush-lib] Add plugin autoinstaller update regression test
1 parent e1ecf7a commit f259491

1 file changed

Lines changed: 150 additions & 0 deletions

File tree

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
jest.mock(`@rushstack/package-deps-hash`, () => {
5+
return {
6+
getRepoRoot(dir: string): string {
7+
return dir;
8+
},
9+
getDetailedRepoStateAsync(): IDetailedRepoState {
10+
return {
11+
hasSubmodules: false,
12+
hasUncommittedChanges: false,
13+
files: new Map([['common/config/rush/npm-shrinkwrap.json', 'hash']]),
14+
symlinks: new Map()
15+
};
16+
},
17+
getRepoChangesAsync(): ReadonlyMap<string, string> {
18+
return new Map();
19+
},
20+
getGitHashForFiles(filePaths: Iterable<string>): ReadonlyMap<string, string> {
21+
return new Map(Array.from(filePaths, (filePath: string) => [filePath, filePath]));
22+
},
23+
hashFilesAsync(rootDirectory: string, filePaths: Iterable<string>): Promise<ReadonlyMap<string, string>> {
24+
return Promise.resolve(new Map(Array.from(filePaths, (filePath: string) => [filePath, filePath])));
25+
}
26+
};
27+
});
28+
29+
import './mockRushCommandLineParser';
30+
31+
import { FileSystem, JsonFile } from '@rushstack/node-core-library';
32+
import type { IDetailedRepoState } from '@rushstack/package-deps-hash';
33+
import { Autoinstaller } from '../../logic/Autoinstaller';
34+
import type { IRushPluginManifestJson } from '../../pluginFramework/PluginLoader/PluginLoaderBase';
35+
import { BaseInstallAction } from '../actions/BaseInstallAction';
36+
import {
37+
getCommandLineParserInstanceAsync,
38+
isolateEnvironmentConfigurationForTests,
39+
type IEnvironmentConfigIsolation
40+
} from './TestUtils';
41+
42+
interface IPluginTestPaths {
43+
autoinstallerStorePath: string;
44+
sourceCommandLineJsonPath: string;
45+
sourceManifestPath: string;
46+
destinationCommandLineJsonPath: string;
47+
destinationManifestPath: string;
48+
}
49+
50+
function convertToCrLf(content: string): string {
51+
return content.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n');
52+
}
53+
54+
function mockAutoinstallerPrepareAsync(): jest.SpyInstance<Promise<void>, []> {
55+
return jest.spyOn(Autoinstaller.prototype, 'prepareAsync').mockResolvedValue(undefined);
56+
}
57+
58+
function seedPluginFilesWithCrLf(repoPath: string, packageName: string): IPluginTestPaths {
59+
const autoinstallerPath: string = `${repoPath}/common/autoinstallers/plugins`;
60+
const autoinstallerStorePath: string = `${autoinstallerPath}/rush-plugins`;
61+
const installedPluginPath: string = `${autoinstallerPath}/node_modules/${packageName}`;
62+
const sourcePluginPath: string = `${repoPath}/${packageName}`;
63+
const sourceManifestPath: string = `${installedPluginPath}/rush-plugin-manifest.json`;
64+
const sourceCommandLineJsonPath: string = `${installedPluginPath}/command-line.json`;
65+
const destinationManifestPath: string = `${autoinstallerStorePath}/${packageName}/rush-plugin-manifest.json`;
66+
const destinationCommandLineJsonPath: string = `${autoinstallerStorePath}/${packageName}/${packageName}/command-line.json`;
67+
68+
FileSystem.copyFiles({
69+
sourcePath: sourcePluginPath,
70+
destinationPath: installedPluginPath
71+
});
72+
73+
const manifestJson: IRushPluginManifestJson = JsonFile.load(
74+
`${sourcePluginPath}/rush-plugin-manifest.json`
75+
);
76+
manifestJson.plugins[0].commandLineJsonFilePath = 'command-line.json';
77+
FileSystem.writeFile(sourceManifestPath, convertToCrLf(`${JSON.stringify(manifestJson, undefined, 2)}\n`), {
78+
ensureFolderExists: true
79+
});
80+
81+
const commandLineJsonFixturePath: string = destinationCommandLineJsonPath;
82+
const commandLineJsonContent: string = FileSystem.readFile(commandLineJsonFixturePath);
83+
FileSystem.writeFile(sourceCommandLineJsonPath, convertToCrLf(commandLineJsonContent), {
84+
ensureFolderExists: true
85+
});
86+
87+
return {
88+
autoinstallerStorePath,
89+
sourceCommandLineJsonPath,
90+
sourceManifestPath,
91+
destinationCommandLineJsonPath,
92+
destinationManifestPath
93+
};
94+
}
95+
96+
function expectFileToUseLfLineEndings(filePath: string): void {
97+
const content: string = FileSystem.readFile(filePath);
98+
expect(content).toContain('\n');
99+
expect(content).not.toContain('\r\n');
100+
}
101+
102+
describe('RushPluginAutoinstallerUpdate', () => {
103+
let _envIsolation: IEnvironmentConfigIsolation;
104+
105+
beforeEach(() => {
106+
_envIsolation = isolateEnvironmentConfigurationForTests();
107+
});
108+
109+
afterEach(() => {
110+
_envIsolation.restore();
111+
jest.restoreAllMocks();
112+
});
113+
114+
it('update() creates destination folders that do not exist when writing plugin files', async () => {
115+
const repoName: string = 'pluginWithBuildCommandRepo';
116+
const packageName: string = 'rush-build-command-plugin';
117+
const { parser, repoPath } = await getCommandLineParserInstanceAsync(repoName, 'update');
118+
const {
119+
autoinstallerStorePath,
120+
sourceCommandLineJsonPath,
121+
sourceManifestPath,
122+
destinationCommandLineJsonPath,
123+
destinationManifestPath
124+
} = seedPluginFilesWithCrLf(repoPath, packageName);
125+
126+
FileSystem.ensureEmptyFolder(autoinstallerStorePath);
127+
128+
expect(FileSystem.exists(destinationManifestPath)).toBe(false);
129+
expect(FileSystem.exists(destinationCommandLineJsonPath)).toBe(false);
130+
expect(FileSystem.readFile(sourceManifestPath)).toContain('\r\n');
131+
expect(FileSystem.readFile(sourceCommandLineJsonPath)).toContain('\r\n');
132+
133+
const prepareAsyncSpy = mockAutoinstallerPrepareAsync();
134+
const baseInstallActionPrototype: { runAsync(): Promise<void> } =
135+
BaseInstallAction.prototype as unknown as { runAsync(): Promise<void> };
136+
const runAsyncSpy = jest.spyOn(baseInstallActionPrototype, 'runAsync').mockResolvedValue(undefined);
137+
138+
try {
139+
await expect(parser.executeAsync()).resolves.toEqual(true);
140+
} finally {
141+
runAsyncSpy.mockRestore();
142+
prepareAsyncSpy.mockRestore();
143+
}
144+
145+
expect(FileSystem.exists(destinationManifestPath)).toBe(true);
146+
expect(FileSystem.exists(destinationCommandLineJsonPath)).toBe(true);
147+
expectFileToUseLfLineEndings(destinationManifestPath);
148+
expectFileToUseLfLineEndings(destinationCommandLineJsonPath);
149+
});
150+
});

0 commit comments

Comments
 (0)