Skip to content

Commit f25779a

Browse files
Merge pull request #1057 from NordicSemiconductor/enhance/jlink-warning
Enhance J-Link warning
2 parents 20868be + 5d2a232 commit f25779a

File tree

8 files changed

+99
-441
lines changed

8 files changed

+99
-441
lines changed

Changelog.minor.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ release the new version.
99

1010
## Unreleased
1111

12+
### Changed
13+
14+
- #1057: Show J-Link warning also for local apps.
15+
16+
## 5.1.0
17+
1218
### Fixed
1319

1420
- #1037: Aligned "Update all apps" button with the list of the apps

package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
},
9797
"devDependencies": {
9898
"@electron/notarize": "^2.2.0",
99-
"@nordicsemiconductor/pc-nrfconnect-shared": "^188.0.0",
99+
"@nordicsemiconductor/pc-nrfconnect-shared": "^191.0.0",
100100
"@playwright/test": "^1.16.3",
101101
"@testing-library/user-event": "^14.4.3",
102102
"@types/chmodr": "1.0.0",

src/launcher/util/appCompatibilityWarning.test.ts

Lines changed: 46 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,35 @@
44
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
55
*/
66

7-
import { NrfutilSandbox } from '@nordicsemiconductor/pc-nrfconnect-shared/nrfutil';
8-
import { resolveModuleVersion } from '@nordicsemiconductor/pc-nrfconnect-shared/nrfutil/moduleVersion';
7+
import {
8+
getJlinkCompatibility,
9+
prepareSandbox,
10+
} from '@nordicsemiconductor/pc-nrfconnect-shared/nrfutil';
911
import { inspect } from 'util';
1012

1113
import { LaunchableApp } from '../../ipc/apps';
1214
import { createDownloadableTestApp } from '../../test/testFixtures';
1315
import appCompatibilityWarning, {
1416
checkEngineIsSupported,
1517
checkEngineVersionIsSet,
18+
checkJLinkRequirements,
1619
} from './appCompatibilityWarning';
1720

1821
const requiringEngine = (engineVersion?: string): LaunchableApp =>
1922
createDownloadableTestApp(undefined, { engineVersion });
2023

21-
const failingCheck = {
24+
const failingCheck = (warning: string) => ({
2225
isDecided: true,
2326
isCompatible: false,
24-
warning: expect.anything(),
27+
warning,
2528
longWarning: expect.anything(),
26-
};
29+
});
2730

2831
const undecidedCheck = {
2932
isDecided: false,
3033
};
3134

32-
jest.mock('@nordicsemiconductor/pc-nrfconnect-shared/nrfutil/sandbox', () => ({
33-
__esModule: true,
34-
default: () =>
35-
Promise.resolve({
36-
getModuleVersion: () => Promise.resolve([]),
37-
} as unknown as NrfutilSandbox),
38-
}));
35+
jest.mock('@nordicsemiconductor/pc-nrfconnect-shared/nrfutil');
3936

4037
jest.mock('@nordicsemiconductor/pc-nrfconnect-shared', () => ({
4138
...jest.requireActual('@nordicsemiconductor/pc-nrfconnect-shared'),
@@ -52,7 +49,11 @@ describe('check compatibility of an app with the launcher', () => {
5249
requiringEngine(undefined),
5350
'irrelevant'
5451
)
55-
).toMatchObject(failingCheck);
52+
).toMatchObject(
53+
failingCheck(
54+
'The app does not specify which nRF Connect for Desktop versions it supports'
55+
)
56+
);
5657
});
5758

5859
it('is undecided if any engine version is set', () => {
@@ -93,7 +94,38 @@ describe('check compatibility of an app with the launcher', () => {
9394
it('fails if the app requires a higher version', () => {
9495
expect(
9596
checkEngineIsSupported(requiringEngine('^2.0.0'), '1.2.3')
96-
).toMatchObject(failingCheck);
97+
).toMatchObject(
98+
failingCheck(
99+
'The app only supports nRF Connect for Desktop ^2.0.0, which does not match your currently installed version'
100+
)
101+
);
102+
});
103+
});
104+
105+
describe('Check if the tested version of J-Link is installed', () => {
106+
const app = (nrfutilDeviceVersion: string) =>
107+
createDownloadableTestApp(undefined, {
108+
nrfutil: { device: [nrfutilDeviceVersion] },
109+
});
110+
111+
it('Calls resolveModuleVersion exactly once per version of nrfutil-device', async () => {
112+
jest.mocked(prepareSandbox).mockResolvedValue({
113+
// @ts-expect-error -- I do not understand et how to fix this TypeScript error, but this is only a test, test ¯\_(ツ)_/¯
114+
getModuleVersion: () => [],
115+
});
116+
117+
const mockedGetSandbox = jest
118+
.mocked(getJlinkCompatibility)
119+
.mockClear()
120+
// @ts-expect-error -- As above
121+
.mockResolvedValue({});
122+
123+
await checkJLinkRequirements(app('3.0.0'), '5.0.0');
124+
await checkJLinkRequirements(app('3.0.0'), '5.0.0');
125+
await checkJLinkRequirements(app('3.0.1'), '5.0.0');
126+
await checkJLinkRequirements(app('3.0.2'), '5.0.0');
127+
128+
expect(mockedGetSandbox).toBeCalledTimes(3);
97129
});
98130
});
99131

@@ -180,71 +212,5 @@ describe('check compatibility of an app with the launcher', () => {
180212
}
181213
);
182214
});
183-
184-
describe('Jlink Tests', () => {
185-
const app = (nrfutilDeviceVersion: string): LaunchableApp => ({
186-
engineVersion: '5.0.0',
187-
source: '',
188-
latestVersion: 'v1.0.0',
189-
isWithdrawn: false,
190-
name: 'name',
191-
displayName: '',
192-
iconPath: '',
193-
description: 'All versions are exactly as specified',
194-
currentVersion: 'v1.0.0',
195-
versions: {
196-
'v1.0.0': {
197-
tarballUrl: '',
198-
nrfutilModules: { device: [nrfutilDeviceVersion] },
199-
},
200-
},
201-
installed: {
202-
path: '',
203-
},
204-
});
205-
206-
it(`No installed J-Link`, async () => {
207-
jest.mocked(resolveModuleVersion).mockReturnValue(undefined);
208-
209-
expect(
210-
(await appCompatibilityWarning(app('2.0.0'), '5.0.0'))
211-
?.warning
212-
).toBe(
213-
'Required SEGGER J-Link not found: expected version V7.88j'
214-
);
215-
});
216-
217-
it(`Wrong JLink version`, async () => {
218-
jest.mocked(resolveModuleVersion).mockReturnValue({
219-
expectedVersion: {
220-
versionFormat: 'string',
221-
version: 'JLink_V7.94i',
222-
},
223-
name: 'JlinkARM',
224-
versionFormat: 'string',
225-
version: 'JLink_V7.94e',
226-
});
227-
228-
expect(
229-
(await appCompatibilityWarning(app('2.0.2'), '5.0.0'))
230-
?.warning
231-
).toBe(
232-
'Untested version V7.94e of SEGGER J-Link found: expected at least version V7.94i'
233-
);
234-
});
235-
236-
it('Calls resolveModuleVersion exactly once per version of nrfutil-device', async () => {
237-
const mockedGetSandbox = jest
238-
.mocked(resolveModuleVersion)
239-
.mockReset();
240-
241-
await appCompatibilityWarning(app('3.0.0'), '5.0.0');
242-
await appCompatibilityWarning(app('3.0.0'), '5.0.0');
243-
await appCompatibilityWarning(app('3.0.1'), '5.0.0');
244-
await appCompatibilityWarning(app('3.0.2'), '5.0.0');
245-
246-
expect(mockedGetSandbox).toBeCalledTimes(3);
247-
});
248-
});
249215
});
250216
});

src/launcher/util/appCompatibilityWarning.tsx

Lines changed: 39 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@ import {
99
getUserDataDir,
1010
launcherConfig,
1111
} from '@nordicsemiconductor/pc-nrfconnect-shared';
12-
import { resolveModuleVersion } from '@nordicsemiconductor/pc-nrfconnect-shared/nrfutil/moduleVersion';
13-
import getSandbox from '@nordicsemiconductor/pc-nrfconnect-shared/nrfutil/sandbox';
12+
import {
13+
getJlinkCompatibility as getJlinkCompatibilityFromModuleVersion,
14+
prepareSandbox,
15+
} from '@nordicsemiconductor/pc-nrfconnect-shared/nrfutil';
1416
import { memoize } from 'lodash';
1517
import semver from 'semver';
1618

17-
import { isDownloadable, isWithdrawn, LaunchableApp } from '../../ipc/apps';
1819
import {
19-
existingIsOlderThanExpected,
20-
strippedVersionName,
21-
} from './jlinkVersion';
20+
isDownloadable,
21+
isInstalled,
22+
isWithdrawn,
23+
LaunchableApp,
24+
} from '../../ipc/apps';
2225
import Link from './Link';
2326
import minimalRequiredAppVersions from './minimalRequiredAppVersions';
2427

@@ -163,117 +166,86 @@ const checkMinimalRequiredAppVersions: AppCompatibilityChecker = app => {
163166
);
164167
};
165168

166-
const nrfutilDeviceToJLink = (device: string) => {
167-
// According to https://docs.nordicsemi.com/bundle/nrfutil/page/guides/installing.html#prerequisites
168-
if (semver.lt(device, '2.0.0')) {
169-
return 'V7.80c';
170-
}
171-
172-
if (semver.lt(device, '2.1.0')) {
173-
return 'V7.88j';
174-
}
175-
176-
if (semver.lt(device, '2.5.4')) {
177-
return 'V7.94e';
178-
}
179-
180-
return 'V7.94i';
181-
};
182-
183-
const getJlinkVersionDependency = memoize(
184-
async (nrfutilDeviceVersion: string) => {
185-
const userDir = getUserDataDir();
186-
const sandbox = await getSandbox(
187-
userDir,
188-
'device',
189-
nrfutilDeviceVersion
190-
);
191-
const moduleVersion = await sandbox.getModuleVersion();
169+
const getJlinkCompatibility = memoize(async (nrfutilDeviceVersion: string) => {
170+
const userDir = getUserDataDir();
171+
const sandbox = await prepareSandbox(
172+
userDir,
173+
'device',
174+
nrfutilDeviceVersion
175+
);
176+
const moduleVersion = await sandbox.getModuleVersion();
192177

193-
return resolveModuleVersion('JlinkARM', moduleVersion.dependencies);
194-
}
195-
);
178+
return getJlinkCompatibilityFromModuleVersion(moduleVersion);
179+
});
196180

197-
const checkJLinkRequirements: AppCompatibilityChecker = async (
181+
export const checkJLinkRequirements: AppCompatibilityChecker = async (
198182
app: LaunchableApp
199183
) => {
200-
if (!isDownloadable(app)) {
184+
if (!isInstalled(app)) {
201185
return undecided;
202186
}
203187

204-
const deviceVersion =
205-
app.versions?.[app.currentVersion]?.nrfutilModules?.device?.at(0);
188+
const deviceVersion = app.nrfutil?.device?.at(0);
206189

207190
if (!deviceVersion) {
208191
return undecided;
209192
}
210193

211-
const jlinkVersionDependency = await getJlinkVersionDependency(
212-
deviceVersion
213-
);
214-
const noJlinkInstalled = jlinkVersionDependency?.version == null;
215-
if (noJlinkInstalled) {
216-
const requiredVersion = nrfutilDeviceToJLink(deviceVersion);
194+
const jlinkCompatibility = await getJlinkCompatibility(deviceVersion);
195+
196+
if (jlinkCompatibility.kind === 'No J-Link installed') {
197+
const { requiredJlink } = jlinkCompatibility;
217198

218199
return incompatible(
219200
'Missing dependency',
220-
`Required SEGGER J-Link not found: expected version ${requiredVersion}`,
201+
`Required SEGGER J-Link not found: expected version V${requiredJlink}`,
221202
<div className="tw-flex tw-flex-col tw-gap-2">
222-
<div>This app requires SEGGER J-Link {requiredVersion}.</div>
203+
<div>This app requires SEGGER J-Link V{requiredJlink}.</div>
223204
<div>
224205
<Link href="https://www.segger.com/downloads/jlink/">
225206
Download
226207
</Link>{' '}
227208
and install the SEGGER J-Link Software and Documentation
228-
pack {requiredVersion}. Restart nRF Connect for Desktop
209+
pack V{requiredJlink}. Restart nRF Connect for Desktop
229210
afterwards.
230211
</div>
231212
</div>,
232213
{
233214
warningKind: WarningKind.JLINK,
234215
app: app.name,
235216
nrfutilDevice: deviceVersion,
236-
requiredJlink: requiredVersion,
237-
actualJlink: 'none',
217+
...jlinkCompatibility,
238218
}
239219
);
240220
}
241221

242-
if (
243-
jlinkVersionDependency.expectedVersion &&
244-
existingIsOlderThanExpected(jlinkVersionDependency)
245-
) {
246-
const expectedVersionNumber = strippedVersionName(
247-
jlinkVersionDependency.expectedVersion
248-
);
249-
const actualVersionNumber = strippedVersionName(jlinkVersionDependency);
222+
if (jlinkCompatibility.kind === 'Outdated J-Link') {
223+
const { actualJlink, requiredJlink } = jlinkCompatibility;
250224

251225
return incompatible(
252226
'Outdated dependency',
253-
`Untested version V${actualVersionNumber} of SEGGER J-Link found: ` +
254-
`expected at least version V${expectedVersionNumber}`,
227+
`Untested version V${actualJlink} of SEGGER J-Link found: ` +
228+
`expected at least version V${requiredJlink}`,
255229
<div className="tw-flex tw-flex-col tw-gap-2">
256230
<div>
257-
This app was tested with SEGGER J-Link V
258-
{expectedVersionNumber} but version V{actualVersionNumber}{' '}
259-
was found on your system.
231+
This app was tested with SEGGER J-Link V{requiredJlink} but
232+
version V{actualJlink} was found on your system.
260233
</div>
261234
<div>This app might not work as expected!</div>
262235
<div>
263236
<Link href="https://www.segger.com/downloads/jlink/">
264237
Download
265238
</Link>{' '}
266239
and install the SEGGER J-Link Software and Documentation
267-
pack V{expectedVersionNumber}. Restart nRF Connect for
268-
Desktop afterwards.
240+
pack V{requiredJlink}. Restart nRF Connect for Desktop
241+
afterwards.
269242
</div>
270243
</div>,
271244
{
272245
warningKind: WarningKind.JLINK,
273246
app: app.name,
274247
nrfutilDevice: deviceVersion,
275-
requiredJlink: jlinkVersionDependency.expectedVersion.version,
276-
actualJlink: jlinkVersionDependency.version,
248+
...jlinkCompatibility,
277249
}
278250
);
279251
}

0 commit comments

Comments
 (0)