Skip to content

Commit

Permalink
Finish device tests
Browse files Browse the repository at this point in the history
  • Loading branch information
robmosca committed Dec 13, 2023
1 parent 1ba5449 commit 38e20d6
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 24 deletions.
4 changes: 2 additions & 2 deletions src/Ri5devBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { decodeBase64, formatFilesize } from './utils';

export class DeviceTreeItem extends vscode.TreeItem {
constructor() {
const { name } = getDeviceInfo();
const { name, firmwareVersion } = getDeviceInfo();
super(name, vscode.TreeItemCollapsibleState.Collapsed);
this.tooltip = name;
this.description = 'No version available';
this.description = firmwareVersion || 'No version available';
this.contextValue = 'device';
this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded;
}
Expand Down
38 changes: 27 additions & 11 deletions src/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ class Device extends EventEmitter {
});
}

async retrieveHubInfo() {
const info = (await APIRequest(this.serialPort!, 'get_hub_info', {})) as {
firmware: {
version: number[];
checksum: string;
};
};
const [major, minor, patch, build] = info.firmware.version;

this.firmwareVersion = `${major}.${minor}.${String(patch).padStart(
2,
'0',
)}.${String(build).padStart(4, '0')}-${info.firmware.checksum}`;
}

getSlots() {
return this.storageStatus?.slots;
}
Expand Down Expand Up @@ -113,14 +128,12 @@ class Device extends EventEmitter {
old_slotid: fromSlotId,
new_slotid: toSlotId,
});
await this.refreshStorageStatus();
this.emit('change');
return this.refreshStorageStatus();
}

async removeProgram(slotId: number) {
await this.executeSlotSpecificCommand('remove_project', slotId);
await this.refreshStorageStatus();
this.emit('change');
return this.refreshStorageStatus();
}

async uploadProgram(prgName: string, prgText: string, slotId: number) {
Expand Down Expand Up @@ -182,7 +195,7 @@ class Device extends EventEmitter {
}
},
);
});
}).then(() => this.retrieveHubInfo());
}

disconnect() {
Expand Down Expand Up @@ -243,16 +256,19 @@ export async function runProgramOnDevice(slotId: number) {
return device?.runProgram(slotId);
}

export async function removeProgramFromDevice(slotId: number) {
return device?.removeProgram(slotId);
export async function stopProgramOnDevice() {
return device?.stopProgram();
}

export function stopProgramOnDevice() {
device?.stopProgram();
export async function moveProgramOnDevice(
fromSlotId: number,
toSlotId: number,
) {
return device?.moveProgram(fromSlotId, toSlotId);
}

export function moveProgramOnDevice(fromSlotId: number, toSlotId: number) {
device?.moveProgram(fromSlotId, toSlotId);
export async function removeProgramFromDevice(slotId: number) {
return device?.removeProgram(slotId);
}

export function uploadProgramToDevice(
Expand Down
171 changes: 160 additions & 11 deletions src/test/device.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import {
removeProgramFromDevice,
uploadProgramToDevice,
getDeviceSlots,
stopProgramOnDevice,
moveProgramOnDevice,
addDeviceOnChangeCallbak,
getDeviceInfo,
removeDeviceAllListeners,
} from '../device';
import { SerialPortMock } from 'serialport';
import * as chai from 'chai';
Expand Down Expand Up @@ -74,25 +79,48 @@ describe('Device', () => {
};
};

const basicMockAPIRequestStub = () => {
APIRequestStub.callsFake((port, method) => {
if (method === 'get_storage_status') {
return Promise.resolve(getStorageInfo());
} else if (method === 'get_hub_info') {
return Promise.resolve({
firmware: {
version: [1, 2, 3, 0],
checksum: '1e60',
},
});
} else {
return Promise.resolve({});
}
});
};

describe('connectDevice', function () {
it('should connect to the device and refresh storage status', async function () {
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

expect(isDeviceConnected()).to.be.true;

expect(APIRequestStub).to.have.been.calledOnce;
expect(APIRequestStub).to.have.been.calledTwice;
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'get_storage_status',
{},
);
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'get_hub_info',
{},
);
});

it('should throw an error if the device is already connected', async function () {
createPortMock('');
basicMockAPIRequestStub();

await connectDevice(deviceName);

Expand Down Expand Up @@ -139,7 +167,7 @@ describe('Device', () => {
describe('disconnectDevice', function () {
it('should disconnect the device', async function () {
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

Expand All @@ -160,7 +188,7 @@ describe('Device', () => {
describe('runProgramOnDevice', function () {
it('should run a program on a device slot', async function () {
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

Expand All @@ -179,7 +207,7 @@ describe('Device', () => {

it('should throw an error if the slot is not valid', async function () {
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

Expand All @@ -199,29 +227,90 @@ describe('Device', () => {
});
});

describe('stopProgramOnDevice', function () {
it('should stop a running program on a device slot', async function () {
createPortMock('');
basicMockAPIRequestStub();

await connectDevice(deviceName);

APIRequestStub.reset();
APIRequestStub.resolves({});

stopProgramOnDevice();

expect(APIRequestStub).to.have.been.calledOnce;
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'program_terminate',
{},
sinon.match.any,
);
});
});

describe('moveProgramOnDevice', function () {
it('should move a program from one slot to another', async function () {
createPortMock('');
basicMockAPIRequestStub();

await connectDevice(deviceName);

APIRequestStub.reset();
APIRequestStub.resolves({});
const onChangeFn = sinon.spy();

addDeviceOnChangeCallbak(onChangeFn);

await moveProgramOnDevice(12, 15);

expect(APIRequestStub).to.have.been.calledTwice;
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'move_project',
{ old_slotid: 12, new_slotid: 15 },
);
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'get_storage_status',
{},
);
expect(onChangeFn).to.have.been.calledOnce;
});
});

describe('removeProgramFromDevice', function () {
it('should remove a program from a device slot', async function () {
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

APIRequestStub.reset();
APIRequestStub.resolves({});
const onChangeFn = sinon.spy();

removeProgramFromDevice(12);
addDeviceOnChangeCallbak(onChangeFn);

expect(APIRequestStub).to.have.been.calledOnce;
await removeProgramFromDevice(12);

expect(APIRequestStub).to.have.been.calledTwice;
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'remove_project',
{ slotid: 12 },
);
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'get_storage_status',
{},
);
expect(onChangeFn).to.have.been.calledOnce;
});

it('should throw an error if the slot is not valid', async function () {
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

Expand Down Expand Up @@ -255,7 +344,7 @@ describe('Device', () => {
},
};
createPortMock('');
APIRequestStub.resolves(getStorageInfo());
basicMockAPIRequestStub();

await connectDevice(deviceName);

Expand All @@ -275,10 +364,13 @@ describe('Device', () => {
print("...but it's a good start!")
`;
const size = prgText.length;
const onChangeFn = sinon.spy();

addDeviceOnChangeCallbak(onChangeFn);

await uploadProgramToDevice('Program 3', prgText, 12);

expect(APIRequestStub.callCount).to.equal(14);
expect(APIRequestStub.callCount).to.equal(15);
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'start_write_program',
Expand All @@ -294,6 +386,11 @@ describe('Device', () => {
},
},
);
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'get_hub_info',
{},
);
expect(APIRequestStub).to.have.been.calledWith(
sinon.match.any,
'write_package',
Expand All @@ -313,6 +410,58 @@ describe('Device', () => {
...defaultSlots,
...additionalSlots,
});
expect(onChangeFn).to.have.been.calledOnce;
});
});

describe('getDeviceInfo', function () {
it('should return the device info', async function () {
createPortMock('');
basicMockAPIRequestStub();

await connectDevice(deviceName);

const info = getDeviceInfo();

expect(info).to.deep.equal({
name: '/dev/mock',
firmwareVersion: '1.2.03.0000-1e60',
});
});
});

describe('getDeviceSlots', function () {
it('should return the device slots', async function () {
createPortMock('');
basicMockAPIRequestStub();

await connectDevice(deviceName);

const slots = await getDeviceSlots();

expect(slots).to.deep.equal(defaultSlots);
});
});

describe('removeDeviceAllListeners', function () {
it('should remove all listeners', async function () {
createPortMock('');
basicMockAPIRequestStub();

await connectDevice(deviceName);

const onChangeFn = sinon.spy();
addDeviceOnChangeCallbak(onChangeFn);

await removeProgramFromDevice(12);

expect(onChangeFn).to.have.been.calledOnce;

removeDeviceAllListeners();

await removeProgramFromDevice(12);

expect(onChangeFn).to.have.been.calledOnce;
});
});
});

0 comments on commit 38e20d6

Please sign in to comment.