Skip to content

Commit ff27413

Browse files
[fix] Support Android Studio path that JetBrains Toolbox installs to on Windows (#2682)
* JetBrains Toolbox installs Android Studio into a slightly different path than the one detected by doctor. Support this alternate path for folks who aren't using nuget to install Android Studio. * extra scenario double-check * Update .husky/pre-commit * Update packages/cli-doctor/src/tools/healthchecks/androidStudio.ts * we couldn't write to a readonly property on the actual process object, so inject a writable propery for the test. there is a slightly nicer way to do this in jest 29+ with 'replaceProperty', I added some TODO comments as a reminder when someone upgrades jest later. --------- Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
1 parent 7c8951c commit ff27413

File tree

2 files changed

+91
-3
lines changed

2 files changed

+91
-3
lines changed

packages/cli-doctor/src/tools/healthchecks/__tests__/androidStudio.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,65 @@ describe('androidStudio', () => {
7474
}".`,
7575
);
7676
});
77+
78+
it('detects Android Studio in the fallback Windows installation path', async () => {
79+
// Make CLI think Android Studio was not found
80+
environmentInfo.IDEs['Android Studio'] = 'Not Found';
81+
// Force platform to win32 for the test
82+
// TODO: use cleaner jest.replaceProperty in jest 29+
83+
const originalPlatform = process.platform;
84+
Object.defineProperty(process, 'platform', {
85+
value: 'win32',
86+
writable: true,
87+
configurable: true,
88+
});
89+
90+
// First WMIC (primary) returns empty, second (fallback) returns version
91+
(execa as unknown as jest.Mock)
92+
.mockResolvedValueOnce({stdout: ''})
93+
.mockResolvedValueOnce({stdout: '4.2.1.0'});
94+
95+
const diagnostics = await androidStudio.getDiagnostics(environmentInfo);
96+
97+
expect(diagnostics.needsToBeFixed).toBe(false);
98+
expect(diagnostics.version).toBe('4.2.1.0');
99+
100+
// Restore original platform
101+
// TODO: use cleaner mockRestore in jest 29+
102+
Object.defineProperty(process, 'platform', {
103+
value: originalPlatform,
104+
writable: true,
105+
configurable: true,
106+
});
107+
});
108+
109+
it('detects when Android Studio is also not in fallback installation path', async () => {
110+
// Make CLI think Android Studio was not found
111+
environmentInfo.IDEs['Android Studio'] = 'Not Found';
112+
// Force the platform to win32 for the test
113+
// TODO: use cleaner jest.replaceProperty in jest 29+
114+
const originalPlatform = process.platform;
115+
Object.defineProperty(process, 'platform', {
116+
value: 'win32',
117+
writable: true,
118+
configurable: true,
119+
});
120+
121+
// First WMIC (primary) returns empty, second (fallback) returns version
122+
(execa as unknown as jest.Mock)
123+
.mockResolvedValueOnce({stdout: ''})
124+
.mockResolvedValueOnce({stdout: ''});
125+
126+
const diagnostics = await androidStudio.getDiagnostics(environmentInfo);
127+
128+
expect(diagnostics.needsToBeFixed).toBe(true);
129+
130+
// Restore original platform
131+
// TODO: use cleaner mockRestore in jest 29+
132+
Object.defineProperty(process, 'platform', {
133+
value: originalPlatform,
134+
writable: true,
135+
configurable: true,
136+
});
137+
});
77138
});

packages/cli-doctor/src/tools/healthchecks/androidStudio.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,43 @@ export default {
2424
if (needsToBeFixed && process.platform === 'win32') {
2525
const archSuffix = process.arch === 'x64' ? '64' : '';
2626

27-
const androidStudioPath = join(
27+
// Check if Android Studio is installed in one of its default locations
28+
const primaryAndroidStudioPath = join(
2829
getUserAndroidPath(),
2930
'android-studio',
3031
'bin',
3132
`studio${archSuffix}.exe`,
3233
).replace(/\\/g, '\\\\');
3334
const {stdout} = await executeCommand(
34-
`wmic datafile where name="${androidStudioPath}" get Version`,
35+
`wmic datafile where name="${primaryAndroidStudioPath}" get Version`,
3536
);
36-
const version = stdout.replace(/(\r\n|\n|\r)/gm, '').trim();
37+
let version = stdout.replace(/(\r\n|\n|\r)/gm, '').trim();
38+
39+
if (version !== '') {
40+
return {
41+
needsToBeFixed: false,
42+
version,
43+
};
44+
}
45+
46+
// 2) fallback path under %LOCALAPPDATA%\Programs\Android Studio
47+
// This is the path used by the JetBrains Toolbox / Android Studio installer
48+
const altBase = process.env.LOCALAPPDATA || '';
49+
const fallbackPath = join(
50+
altBase,
51+
'Programs',
52+
'Android Studio',
53+
'bin',
54+
`studio${archSuffix}.exe`,
55+
).replace(/\\/g, '\\\\');
56+
try {
57+
const {stdout} = await executeCommand(
58+
`wmic datafile where name="${fallbackPath}" get Version`,
59+
);
60+
version = stdout.replace(/(\r\n|\n|\r)/gm, '').trim();
61+
} catch {
62+
version = '';
63+
}
3764

3865
if (version === '') {
3966
return missing;

0 commit comments

Comments
 (0)