-
Notifications
You must be signed in to change notification settings - Fork 6
First-cut new session, connection, and testing model page E2E tests #583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
87806bb
f213876
149ba99
2caa80b
9c13361
44be331
3cde798
ea855be
3a8e616
2c97803
bd67da5
cfae3f5
274c4c2
c1bf6a4
52893a5
15c63e3
3c5c44a
d353173
49c48f3
ad89519
b5c81bb
e0f1c60
d70f96a
b1fbba4
a61a634
db61b1d
c928fd8
5c2100c
0278cf8
360cc63
fa911b2
8e9c791
1f28286
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { | ||
| BoardVersion, | ||
| ConnectionStatus, | ||
| ConnectionStatusEvent, | ||
| DeviceConnectionEventMap, | ||
| DeviceWebBluetoothConnection, | ||
| TypedEventTarget, | ||
| } from "@microbit/microbit-connection"; | ||
|
|
||
| export class MockWebBluetoothConnection | ||
| extends TypedEventTarget<DeviceConnectionEventMap> | ||
| implements DeviceWebBluetoothConnection | ||
| { | ||
| status: ConnectionStatus = ConnectionStatus.NO_AUTHORIZED_DEVICE; | ||
|
|
||
| async initialize(): Promise<void> {} | ||
| dispose(): void {} | ||
|
|
||
| private mockStatus(newStatus: ConnectionStatus) { | ||
| this.dispatchTypedEvent("status", new ConnectionStatusEvent(newStatus)); | ||
| } | ||
|
|
||
| async connect(): Promise<ConnectionStatus> { | ||
| this.mockStatus(ConnectionStatus.CONNECTING); | ||
| await new Promise((resolve) => setTimeout(resolve, 100)); | ||
| this.mockStatus(ConnectionStatus.CONNECTED); | ||
| return ConnectionStatus.CONNECTED; | ||
| } | ||
| getBoardVersion(): BoardVersion | undefined { | ||
| return "V2"; | ||
| } | ||
| async disconnect(): Promise<void> {} | ||
| async serialWrite(_data: string): Promise<void> {} | ||
|
|
||
| clearDevice(): void {} | ||
| setNameFilter(_name: string): void {} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { | ||
| AfterRequestDevice, | ||
| BeforeRequestDevice, | ||
| BoardVersion, | ||
| ConnectionStatus, | ||
| ConnectionStatusEvent, | ||
| DeviceConnectionEventMap, | ||
| DeviceWebUSBConnection, | ||
| FlashDataSource, | ||
| FlashOptions, | ||
| TypedEventTarget, | ||
| } from "@microbit/microbit-connection"; | ||
|
|
||
| /** | ||
| * A mock USB connection used during end-to-end testing. | ||
| */ | ||
| export class MockWebUSBConnection | ||
| extends TypedEventTarget<DeviceConnectionEventMap> | ||
| implements DeviceWebUSBConnection | ||
| { | ||
| status: ConnectionStatus = ConnectionStatus.NO_AUTHORIZED_DEVICE; | ||
|
|
||
| private fakeDeviceId: number | undefined = 123; | ||
|
|
||
| constructor() { | ||
| super(); | ||
| // Make globally available to allow e2e tests to configure interactions. | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access | ||
| (window as any).mockUsb = this; | ||
| this.fakeDeviceId = Math.round(Math.random() * 1000); | ||
| } | ||
|
|
||
| async initialize(): Promise<void> {} | ||
| dispose(): void {} | ||
|
|
||
| mockDeviceId(deviceId: number | undefined) { | ||
| this.fakeDeviceId = deviceId; | ||
| } | ||
|
|
||
| private mockStatus(newStatus: ConnectionStatus) { | ||
| this.dispatchTypedEvent("status", new ConnectionStatusEvent(newStatus)); | ||
| } | ||
|
|
||
| async connect(): Promise<ConnectionStatus> { | ||
| this.dispatchTypedEvent("beforerequestdevice", new BeforeRequestDevice()); | ||
| await new Promise((resolve) => setTimeout(resolve, 100)); | ||
| this.dispatchTypedEvent("afterrequestdevice", new AfterRequestDevice()); | ||
| await new Promise((resolve) => setTimeout(resolve, 100)); | ||
| this.mockStatus(ConnectionStatus.CONNECTED); | ||
| return ConnectionStatus.CONNECTED; | ||
| } | ||
| getDeviceId(): number | undefined { | ||
| return this.fakeDeviceId; | ||
| } | ||
| getBoardVersion(): BoardVersion | undefined { | ||
| return "V2"; | ||
| } | ||
| async flash( | ||
| _dataSource: FlashDataSource, | ||
| options: FlashOptions | ||
| ): Promise<void> { | ||
| await new Promise((resolve) => setTimeout(resolve, 100)); | ||
| options.progress(50, options.partial); | ||
|
Check failure on line 63 in src/device/mockUsb.ts
|
||
| await new Promise((resolve) => setTimeout(resolve, 100)); | ||
| options.progress(undefined, options.partial); | ||
|
Check failure on line 65 in src/device/mockUsb.ts
|
||
| } | ||
| async disconnect(): Promise<void> {} | ||
| async serialWrite(_data: string): Promise<void> {} | ||
| clearDevice(): void {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| /** | ||
| * (c) 2024, Micro:bit Educational Foundation and contributors | ||
| * | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
| import { expect, type Page } from "@playwright/test"; | ||
| import { MockWebUSBConnection } from "../../device/mockUsb"; | ||
|
|
||
| export class ConnectionDialogs { | ||
| constructor(public readonly page: Page) {} | ||
|
|
||
| async close() { | ||
| await this.page.getByLabel("Close").click(); | ||
| } | ||
|
|
||
| async waitForText(name: string) { | ||
| await this.page.getByText(name).waitFor(); | ||
| } | ||
|
|
||
| private async clickNext() { | ||
| await this.page.getByRole("button", { name: "Next" }).click(); | ||
| } | ||
|
|
||
| async bluetoothDownloadProgram() { | ||
| await this.waitForText("What you need to connect using Web Bluetooth"); | ||
| await this.clickNext(); | ||
| await this.waitForText("Connect USB cable to micro:bit"); | ||
| await this.clickNext(); | ||
| await this.waitForText("Download data collection program to micro:bit"); | ||
| await this.clickNext(); | ||
| } | ||
|
|
||
| async expectManualTransferProgramDialog() { | ||
| await expect( | ||
| this.page.getByText("Transfer saved hex file to micro:bit") | ||
| ).toBeVisible(); | ||
| } | ||
|
|
||
| async mockUsbDeviceNotSelected() { | ||
| await this.page.evaluate(() => { | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access | ||
| const mockUsb = (window as any).mockUsb as MockWebUSBConnection; | ||
| mockUsb.mockDeviceId(undefined); | ||
| }); | ||
| } | ||
|
|
||
| async bluetoothConnect() { | ||
| await this.bluetoothDownloadProgram(); | ||
| await this.waitForText("Downloading the data collection program"); | ||
| await this.waitForText("Disconnect USB and connect battery pack"); | ||
| await this.clickNext(); | ||
| await this.waitForText("Copy pattern"); | ||
| await this.enterBluetoothPattern(); | ||
| await this.clickNext(); | ||
| await this.waitForText("Connect to micro:bit using Web Bluetooth"); | ||
| await this.clickNext(); | ||
| await this.waitForText("Connect using Web Bluetooth"); | ||
| } | ||
|
|
||
| async enterBluetoothPattern() { | ||
| await this.page.locator(".css-1jvu5j > .chakra-button").first().click(); | ||
| await this.page.locator("div:nth-child(11) > .chakra-button").click(); | ||
| await this.page.locator("div:nth-child(17) > .chakra-button").click(); | ||
| await this.page.locator("div:nth-child(23) > .chakra-button").click(); | ||
| await this.page.locator("div:nth-child(29) > .chakra-button").click(); | ||
microbit-matt-hillsdon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.