Skip to content

Commit db6a68e

Browse files
author
Akos Kitta
committed
fix: board list labels
1 parent 42b8175 commit db6a68e

File tree

4 files changed

+285
-12
lines changed

4 files changed

+285
-12
lines changed

arduino-ide-extension/src/common/protocol/board-list.ts

+26-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { nls } from '@theia/core/lib/common/nls';
21
import type { Mutable } from '@theia/core/lib/common/types';
32
import type { Defined } from '../types';
43
import { naturalCompare } from '../utils';
@@ -20,6 +19,8 @@ import {
2019
selectBoard,
2120
unconfirmedBoard,
2221
unknownBoard,
22+
notConnected,
23+
boardIdentifierLabel,
2324
} from './boards-service';
2425

2526
/**
@@ -257,23 +258,32 @@ export interface BoardListLabels {
257258

258259
function createBoardListLabels(
259260
boardsConfig: BoardsConfig,
261+
allPorts: readonly DetectedPort[],
260262
selectedItem: BoardListItem | undefined
261263
): BoardListLabels {
262264
const { selectedBoard, selectedPort } = boardsConfig;
263265
const boardLabel = selectedBoard?.name || selectBoard;
264-
const boardFqbn = selectedBoard?.fqbn;
265-
let tooltip = `${boardLabel}${boardFqbn ? ` (${boardFqbn})` : ''}${
266-
selectedPort ? `\n${selectedPort.address}` : ''
267-
}`;
268-
if (selectedPort && !selectedItem) {
269-
tooltip += ` ${nls.localize(
270-
'arduino/common/notConnected',
271-
'[not connected]'
272-
)}`;
266+
let tooltip = '';
267+
if (!selectedBoard && !selectedPort) {
268+
tooltip = selectBoard;
269+
} else {
270+
if (selectedBoard) {
271+
tooltip += boardIdentifierLabel(selectedBoard);
272+
}
273+
if (selectedPort) {
274+
if (tooltip) {
275+
tooltip += '\n';
276+
}
277+
tooltip += selectedPort.address;
278+
const index = findMatchingPortIndex(selectedPort, allPorts);
279+
if (index < 0) {
280+
tooltip += ` ${notConnected}`;
281+
}
282+
}
273283
}
274284
return {
275285
boardLabel,
276-
portProtocol: selectedPort?.protocol,
286+
portProtocol: selectedBoard ? selectedPort?.protocol : undefined,
277287
tooltip,
278288
selected: Boolean(selectedItem),
279289
};
@@ -407,9 +417,13 @@ export function createBoardList(
407417
}
408418
items.sort(boardListItemComparator);
409419
const selectedIndex = findSelectedIndex(boardsConfig, items);
410-
const labels = createBoardListLabels(boardsConfig, items[selectedIndex]);
411420
const boards = collectBoards(items);
412421
const allPorts = collectPorts(items, detectedPorts);
422+
const labels = createBoardListLabels(
423+
boardsConfig,
424+
allPorts,
425+
items[selectedIndex]
426+
);
413427
return {
414428
labels,
415429
items,

arduino-ide-extension/src/common/protocol/boards-service.ts

+4
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,10 @@ export const selectBoard = nls.localize(
871871
'arduino/board/selectBoard',
872872
'Select Board'
873873
);
874+
export const notConnected = nls.localize(
875+
'arduino/common/notConnected',
876+
'[not connected]'
877+
);
874878

875879
/**
876880
* The returned promise resolves to a `BoardInfo` if available to show in the UI or an info message explaining why showing the board info is not possible.

arduino-ide-extension/src/test/common/board-list.test.ts

+147
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { expect } from 'chai';
22
import {
3+
BoardListLabels,
34
createBoardList,
45
EditBoardsConfigActionParams,
56
isInferredBoardListItem,
@@ -8,6 +9,8 @@ import {
89
} from '../../common/protocol/board-list';
910
import {
1011
emptyBoardsConfig,
12+
notConnected,
13+
selectBoard,
1114
unconfirmedBoard,
1215
} from '../../common/protocol/boards-service';
1316
import {
@@ -22,6 +25,7 @@ import {
2225
esp32S3DevModule,
2326
history,
2427
mkr1000,
28+
mkr1000NetworkPort,
2529
mkr1000SerialPort,
2630
nanoEsp32DetectsMultipleEsp32BoardsSerialPort,
2731
nanoEsp32SerialPort,
@@ -32,6 +36,149 @@ import {
3236
} from './fixtures';
3337

3438
describe('board-list', () => {
39+
describe('boardList#labels', () => {
40+
it('should handle no selected board+port', () => {
41+
const { labels } = createBoardList({});
42+
const expected: BoardListLabels = {
43+
boardLabel: selectBoard,
44+
portProtocol: undefined,
45+
selected: false,
46+
tooltip: selectBoard,
47+
};
48+
expect(labels).to.be.deep.equal(expected);
49+
});
50+
51+
it('should handle port selected (port discovered)', () => {
52+
const { labels } = createBoardList(
53+
{
54+
...detectedPort(unoSerialPort, uno),
55+
},
56+
{ selectedBoard: undefined, selectedPort: unoSerialPort }
57+
);
58+
const expected: BoardListLabels = {
59+
boardLabel: selectBoard,
60+
portProtocol: undefined,
61+
selected: false,
62+
tooltip: unoSerialPort.address,
63+
};
64+
expect(labels).to.be.deep.equal(expected);
65+
});
66+
67+
it('should handle port selected (port not discovered)', () => {
68+
const { labels } = createBoardList(
69+
{
70+
...detectedPort(mkr1000SerialPort, mkr1000),
71+
},
72+
{ selectedBoard: undefined, selectedPort: unoSerialPort }
73+
);
74+
const expected: BoardListLabels = {
75+
boardLabel: selectBoard,
76+
portProtocol: undefined,
77+
selected: false,
78+
tooltip: `${unoSerialPort.address} ${notConnected}`,
79+
};
80+
expect(labels).to.be.deep.equal(expected);
81+
});
82+
83+
it('should handle board selected (with FQBN)', () => {
84+
const { labels } = createBoardList(
85+
{},
86+
{ selectedBoard: uno, selectedPort: undefined }
87+
);
88+
const expected: BoardListLabels = {
89+
boardLabel: uno.name,
90+
portProtocol: undefined,
91+
selected: false,
92+
tooltip: `${uno.name} (${uno.fqbn})`,
93+
};
94+
expect(labels).to.be.deep.equal(expected);
95+
});
96+
97+
it('should handle board selected (no FQBN)', () => {
98+
const { labels } = createBoardList(
99+
{},
100+
{
101+
selectedBoard: { name: 'my board', fqbn: undefined },
102+
selectedPort: undefined,
103+
}
104+
);
105+
const expected: BoardListLabels = {
106+
boardLabel: 'my board',
107+
portProtocol: undefined,
108+
selected: false,
109+
tooltip: 'my board',
110+
};
111+
expect(labels).to.be.deep.equal(expected);
112+
});
113+
114+
it('should handle both selected (port not detected)', () => {
115+
const { labels } = createBoardList(
116+
{
117+
...detectedPort(mkr1000SerialPort, mkr1000),
118+
},
119+
{ selectedBoard: mkr1000, selectedPort: unoSerialPort }
120+
);
121+
const expected: BoardListLabels = {
122+
boardLabel: mkr1000.name,
123+
portProtocol: 'serial',
124+
selected: false,
125+
tooltip: `${mkr1000.name} (${mkr1000.fqbn})\n${unoSerialPort.address} ${notConnected}`,
126+
};
127+
expect(labels).to.be.deep.equal(expected);
128+
});
129+
130+
it('should handle both selected (board not discovered)', () => {
131+
const { labels } = createBoardList(
132+
{
133+
...detectedPort(unoSerialPort, uno),
134+
},
135+
{ selectedBoard: mkr1000, selectedPort: unoSerialPort }
136+
);
137+
const expected: BoardListLabels = {
138+
boardLabel: mkr1000.name,
139+
portProtocol: 'serial',
140+
selected: false,
141+
tooltip: `${mkr1000.name} (${mkr1000.fqbn})\n${unoSerialPort.address}`,
142+
};
143+
expect(labels).to.be.deep.equal(expected);
144+
});
145+
146+
it('should handle both selected (no FQBN)', () => {
147+
const { labels } = createBoardList(
148+
{
149+
...detectedPort(unoSerialPort, { name: 'my board', fqbn: undefined }),
150+
},
151+
{
152+
selectedBoard: { name: 'my board', fqbn: undefined },
153+
selectedPort: unoSerialPort,
154+
}
155+
);
156+
const expected: BoardListLabels = {
157+
boardLabel: 'my board',
158+
portProtocol: 'serial',
159+
selected: true,
160+
tooltip: `my board\n${unoSerialPort.address}`,
161+
};
162+
expect(labels).to.be.deep.equal(expected);
163+
});
164+
165+
it('should handle both selected', () => {
166+
const { labels } = createBoardList(
167+
{
168+
...detectedPort(mkr1000NetworkPort, mkr1000),
169+
},
170+
{ selectedBoard: mkr1000, selectedPort: mkr1000NetworkPort }
171+
);
172+
const expected: BoardListLabels = {
173+
boardLabel: mkr1000.name,
174+
portProtocol: 'network',
175+
selected: true,
176+
tooltip: `${mkr1000.name} (${mkr1000.fqbn})\n${mkr1000NetworkPort.address}`,
177+
};
178+
expect(labels).to.be.deep.equal(expected);
179+
});
180+
});
181+
35182
describe('createBoardList', () => {
36183
it('should sort the items deterministically', () => {
37184
const { items } = createBoardList(detectedPorts);

arduino-ide-extension/src/test/common/boards-service.test.ts

+108
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { Mutable } from '@theia/core/lib/common/types';
22
import { expect } from 'chai';
33
import {
4+
boardIdentifierEquals,
5+
boardIdentifierComparator,
46
BoardInfo,
57
getBoardInfo,
68
noNativeSerialPort,
@@ -13,6 +15,112 @@ import { createBoardList } from '../../common/protocol/board-list';
1315
import { firstToUpperCase } from '../../common/utils';
1416

1517
describe('boards-service', () => {
18+
describe('boardIdentifierEquals', () => {
19+
it('should not be equal when the names equal but the FQBNs are different', () => {
20+
const actual = boardIdentifierEquals(
21+
{ name: 'a', fqbn: 'a:b:c' },
22+
{ name: 'a', fqbn: 'x:y:z' }
23+
);
24+
expect(actual).to.be.false;
25+
});
26+
27+
it('should not be equal when the names equal but the FQBNs are different (undefined)', () => {
28+
const actual = boardIdentifierEquals(
29+
{ name: 'a', fqbn: 'a:b:c' },
30+
{ name: 'a', fqbn: undefined }
31+
);
32+
expect(actual).to.be.false;
33+
});
34+
35+
it("should be equal when the names do not match but the FQBNs are the same (it's something IDE2 assumes to be handled by the platform or CLI)", () => {
36+
const actual = boardIdentifierEquals(
37+
{ name: 'a', fqbn: 'a:b:c' },
38+
{ name: 'b', fqbn: 'a:b:c' }
39+
);
40+
expect(actual).to.be.true;
41+
});
42+
43+
it('should be equal when the names equal and the FQBNs are missing', () => {
44+
const actual = boardIdentifierEquals(
45+
{ name: 'a', fqbn: undefined },
46+
{ name: 'a', fqbn: undefined }
47+
);
48+
expect(actual).to.be.true;
49+
});
50+
51+
it('should be equal when both the name and FQBN are the same, but one of the FQBN has board config options', () => {
52+
const actual = boardIdentifierEquals(
53+
{ name: 'a', fqbn: 'a:b:c:menu_1=value' },
54+
{ name: 'a', fqbn: 'a:b:c' }
55+
);
56+
expect(actual).to.be.true;
57+
});
58+
59+
it('should not be equal when both the name and FQBN are the same, but one of the FQBN has board config options (looseFqbn: false)', () => {
60+
const actual = boardIdentifierEquals(
61+
{ name: 'a', fqbn: 'a:b:c:menu_1=value' },
62+
{ name: 'a', fqbn: 'a:b:c' },
63+
{ looseFqbn: false }
64+
);
65+
expect(actual).to.be.false;
66+
});
67+
});
68+
69+
describe('boardIdentifierComparator', () => {
70+
it('should sort items before falsy', () =>
71+
expect(
72+
boardIdentifierComparator({ name: 'a', fqbn: 'a:b:c' }, undefined)
73+
).to.be.equal(-1));
74+
75+
it("should sort 'arduino' boards before others", () =>
76+
expect(
77+
boardIdentifierComparator(
78+
{ name: 'b', fqbn: 'arduino:b:c' },
79+
{ name: 'a', fqbn: 'x:y:z' }
80+
)
81+
).to.be.equal(-1));
82+
83+
it("should sort 'arduino' boards before others (other is falsy)", () =>
84+
expect(
85+
boardIdentifierComparator(
86+
{ name: 'b', fqbn: 'arduino:b:c' },
87+
{ name: 'a', fqbn: undefined }
88+
)
89+
).to.be.equal(-1));
90+
91+
it("should sort boards by 'name' (with FQBNs)", () =>
92+
expect(
93+
boardIdentifierComparator(
94+
{ name: 'b', fqbn: 'a:b:c' },
95+
{ name: 'a', fqbn: 'x:y:z' }
96+
)
97+
).to.be.equal(1));
98+
99+
it("should sort boards by 'name' (no FQBNs)", () =>
100+
expect(
101+
boardIdentifierComparator(
102+
{ name: 'b', fqbn: undefined },
103+
{ name: 'a', fqbn: undefined }
104+
)
105+
).to.be.equal(1));
106+
107+
it("should sort boards by 'name' (one FQBN)", () =>
108+
expect(
109+
boardIdentifierComparator(
110+
{ name: 'b', fqbn: 'a:b:c' },
111+
{ name: 'a', fqbn: undefined }
112+
)
113+
).to.be.equal(1));
114+
115+
it("should sort boards by 'name' (both 'arduino' vendor)", () =>
116+
expect(
117+
boardIdentifierComparator(
118+
{ name: 'b', fqbn: 'arduino:b:c' },
119+
{ name: 'a', fqbn: 'arduino:y:z' }
120+
)
121+
).to.be.equal(1));
122+
});
123+
16124
describe('getBoardInfo', () => {
17125
const vid = '0x0';
18126
const pid = '0x1';

0 commit comments

Comments
 (0)