• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15/* eslint-env browser, jasmine */
16import {last, take} from 'rxjs/operators';
17
18import {SerialMock} from './serial_mock';
19import {DeviceLockedError, WebSerialTransport} from './web_serial_transport';
20
21describe('WebSerialTransport', () => {
22  let serialMock: SerialMock;
23  beforeEach(() => {
24    serialMock = new SerialMock();
25  });
26
27  it('is disconnected before connecting', () => {
28    const transport = new WebSerialTransport(serialMock as Serial);
29    expect(transport.connected.getValue()).toBeFalse();
30  });
31
32  it('reports that it has connected', async () => {
33    const transport = new WebSerialTransport(serialMock as Serial);
34    await transport.connect();
35    expect(serialMock.serialPort.open).toHaveBeenCalled();
36    expect(transport.connected.getValue()).toBeTrue();
37  });
38
39  it('emits chunks as they arrive from the device', async () => {
40    const transport = new WebSerialTransport(serialMock as Serial);
41    await transport.connect();
42    const data = new Uint8Array([1, 2, 3]);
43    const emitted = transport.chunks.pipe(take(1)).toPromise();
44    serialMock.dataFromDevice(data);
45
46    expect(await emitted).toEqual(data);
47    expect(transport.connected.getValue()).toBeTrue();
48    expect(serialMock.serialPort.readable.locked).toBeTrue();
49    expect(serialMock.serialPort.writable.locked).toBeTrue();
50  });
51
52  it('is disconnected when it reaches the final chunk', async () => {
53    const transport = new WebSerialTransport(serialMock as Serial);
54    await transport.connect();
55    const disconnectPromise = transport.connected
56      .pipe(take(2), last())
57      .toPromise();
58    serialMock.closeFromDevice();
59
60    expect(await disconnectPromise).toBeFalse();
61  });
62
63  it('waits for the writer to be ready', async () => {
64    const transport = new WebSerialTransport(serialMock as Serial);
65    await transport.connect();
66    const data = new Uint8Array([1, 2, 3]);
67
68    const dataToDevice = serialMock.dataToDevice.pipe(take(1)).toPromise();
69
70    let writtenData: Uint8Array | undefined = undefined;
71    dataToDevice.then(data => {
72      writtenData = data;
73    });
74
75    const sendPromise = transport.sendChunk(data);
76    expect(writtenData).toBeUndefined();
77    await sendPromise;
78    expect(writtenData).toBeDefined();
79  });
80
81  it('sends chunks to the device', async () => {
82    const transport = new WebSerialTransport(serialMock as Serial);
83    await transport.connect();
84    const data = new Uint8Array([1, 2, 3]);
85
86    const dataToDevice = serialMock.dataToDevice.pipe(take(1)).toPromise();
87
88    await transport.sendChunk(data);
89    expect(await dataToDevice).toEqual(data);
90  });
91
92  it('throws an error on failing to connect', async () => {
93    const connectError = new Error('Example connection error');
94    spyOn(serialMock, 'requestPort').and.throwError(connectError);
95    const transport = new WebSerialTransport(serialMock as Serial);
96    await expectAsync(transport.connect()).toBeRejectedWith(connectError);
97  });
98
99  it("emits connection errors in the 'errors' observable", async () => {
100    const transport = new WebSerialTransport(serialMock as Serial);
101    await transport.connect();
102
103    const reportedErrorPromise = transport.errors.pipe(take(1)).toPromise();
104    serialMock.serialPort.errorFromDevice(new Error());
105
106    expect(await reportedErrorPromise).toEqual(new DeviceLockedError());
107  });
108});
109