Skip to content

Commit

Permalink
test(connect): THP e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
szymonlesisz committed Dec 12, 2024
1 parent 3eb7529 commit e3976a6
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/template-connect-test-params.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ jobs:
run: sed -i "/\"node\"/d" package.json
- if: ${{ inputs.testEnv == 'node' }}
run: yarn workspaces focus @trezor/connect
run: yarn install
run: yarn workspace @trezor/transport-bridge build:js

- if: ${{ inputs.cache_tx == 'true' }}
run: echo "ADDITIONAL_ARGS=-c" >> "$GITHUB_ENV"
Expand Down
4 changes: 3 additions & 1 deletion docker/docker-compose.connect-test.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
version: "3.9"
services:
trezor-user-env-unix:
image: ghcr.io/trezor/trezor-user-env:36dfd1174f56dde0b0b85b3acd927bfda4a63043
image: ghcr.io/trezor/trezor-user-env:d029907396738bfff46cc58990aa503140f95f9a@sha256:f83c29a9b882aaf530c7b6f07aafabd650299213d438a70e93bcc4f4d634901e
environment:
- SDL_VIDEODRIVER=dummy
- XDG_RUNTIME_DIR=/var/tmp
volumes:
- ../:/trezor-suite
network_mode: host
2 changes: 1 addition & 1 deletion packages/connect/e2e/__fixtures__/signTransactionDecred.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export default {
},
{
// https://github.com/trezor/trezor-firmware/pull/2703/
rules: ['<2.8.2'],
rules: ['<2.9.9'],
success: false,
},
],
Expand Down
23 changes: 19 additions & 4 deletions packages/connect/e2e/common.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,11 @@ export const setup = async (
TrezorUserEnvLink.state = options;

// after all is done, start bridge again
await TrezorUserEnvLink.startBridge(
// @ts-expect-error
process.env.TESTS_TRANSPORT,
);
// await TrezorUserEnvLink.startBridge(
// // @ts-expect-error
// process.env.TESTS_TRANSPORT,
// );
await TrezorUserEnvLink.startBridge('node-bridge');
};

export const initTrezorConnect = async (
Expand Down Expand Up @@ -164,17 +165,31 @@ export const initTrezorConnect = async (
setTimeout(() => TrezorUserEnvLink.send({ type: 'emulator-press-yes' }), 1);
});

// TrezorConnect.on('ui-request_passphrase', () => {
// TrezorConnect.uiResponse({
// type: 'ui-receive_passphrase',
// payload: { value: '' },
// });
// });

await TrezorConnect.init({
manifest: {
appUrl: 'tests.connect.trezor.io',
email: '[email protected]',
},
transports: ['BridgeTransport'],
// transports: ['UdpTransport'],
debug: false,
popup: false,
pendingTransportEvent: true,
transportReconnect: false,
connectSrc: process.env.TREZOR_CONNECT_SRC, // custom source for karma tests
thp: {
hostName: 'TrezorConnect',
staticKeys: '0007070707070707070707070707070707070707070707070707070707070747',
knownCredentials: [],
pairingMethods: ['NoMethod'] as any,
},
...options,
});
};
Expand Down
142 changes: 142 additions & 0 deletions packages/connect/e2e/tests/device/thpPairing.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { getController, initTrezorConnect, setup } from '../../common.setup';
import TrezorConnect, { ConnectSettings, Device } from '../../../src';

describe('THP pairing', () => {
const controller = getController();

beforeAll(async () => {
await setup(controller, { mnemonic: 'mnemonic_all' });
});

afterEach(() => {
TrezorConnect.dispose();
});

const waitForDevice = async (settings: Partial<ConnectSettings['thp']>) => {
await initTrezorConnect(controller, {
thp: {
hostName: 'TrezorConnect',
staticKeys: '0007070707070707070707070707070707070707070707070707070707070747',
knownCredentials: [],
pairingMethods: [],
...settings,
},
});

return new Promise<Device>((resolve, reject) => {
const onDeviceConnected = (device: Device) => {
TrezorConnect.removeAllListeners('device-connect');
TrezorConnect.removeAllListeners('device-connect_unacquired');
if (device.type === 'unreadable') {
reject(new Error('Device unreadable'));
}
resolve(device);
};
TrezorConnect.on('device-connect', onDeviceConnected);
TrezorConnect.on('device-connect_unacquired', onDeviceConnected);
});
};

it('ThpPairing NoMethod', async () => {
await waitForDevice({ pairingMethods: ['NoMethod'] });

const address = await TrezorConnect.getAddress({
// device,
path: "m/44'/0'/0'/1/1",
showOnTrezor: true,
});
expect(address).toMatchObject({ success: true });
});

it('ThpPairing CodeEntry', async () => {
const device = await waitForDevice({ pairingMethods: ['CodeEntry'] });

TrezorConnect.on('ui-request_thp_pairing', async ({ device }) => {
const state = await controller.getDebugState(device.protocolState.channel);
TrezorConnect.removeAllListeners('ui-request_thp_pairing');
TrezorConnect.uiResponse({
type: 'ui-receive_thp_pairing_tag',
payload: {
source: 'code-entry',
value: state.thp_pairing_code_entry_code.toString(),
},
});
});

const address = await TrezorConnect.getAddress({
device,
path: "m/44'/0'/0'/1/1",
// showOnTrezor: true,
});
expect(address).toMatchObject({ success: true });
});

it('ThpPairing QrCode', async () => {
const device = await waitForDevice({ pairingMethods: ['QrCode'] });

TrezorConnect.on('ui-request_thp_pairing', async ({ device }) => {
const state = await controller.getDebugState(device.protocolState.channel);
TrezorConnect.removeAllListeners('ui-request_thp_pairing');
TrezorConnect.uiResponse({
type: 'ui-receive_thp_pairing_tag',
payload: { source: 'qr-code', value: state.thp_pairing_code_qr_code },
});
});

const address = await TrezorConnect.getAddress({
device,
path: "m/44'/0'/0'/1/1",
// showOnTrezor: true,
});
expect(address).toMatchObject({ success: true });
});

it('ThpPairing NFC_Unidirectional', async () => {
const device = await waitForDevice({ pairingMethods: ['NFC_Unidirectional'] });

TrezorConnect.on('ui-request_thp_pairing', async ({ device }) => {
// await new Promise(resolve => setTimeout(resolve, 1000));
const state = await controller.getDebugState(device.protocolState.channel);
TrezorConnect.removeAllListeners('ui-request_thp_pairing');
TrezorConnect.uiResponse({
type: 'ui-receive_thp_pairing_tag',
payload: { source: 'nfc', value: state.thp_pairing_code_nfc_unidirectional },
});
});

const address = await TrezorConnect.getAddress({
device,
path: "m/44'/0'/0'/1/1",
// showOnTrezor: true,
});
expect(address).toMatchObject({ success: true });
});

it('ThpPairing no matching method. device unreadable', async () => {
const device = await waitForDevice({
pairingMethods: ['FooBar', undefined, 1234, null, {}] as any,
});
expect(device.type).toEqual('unreadable');
});

it('ThpPairing using known credentials', async () => {
const device = await waitForDevice({
pairingMethods: ['CodeEntry'],
knownCredentials: [
{
trezor_static_pubkey:
'38d6437ef1d67a4742265281de1e9a68df28774636f34b5e3e336d3ab90e671c',
credential:
'0a0f0a0d5472657a6f72436f6e6e6563741220f53793b13dffe2a4f01c2c7272aecc75b8596cf0fce4b09efd4fb353696a179b',
},
],
});

const address = await TrezorConnect.getAddress({
device,
path: "m/44'/0'/0'/1/1",
showOnTrezor: true,
});
expect(address).toMatchObject({ success: true });
});
});
8 changes: 6 additions & 2 deletions packages/trezor-user-env-link/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,12 @@ export class TrezorUserEnvLinkClass extends TypedEmitter<WebsocketClientEvents>

return null;
}
async getDebugState() {
const { response } = await this.client.send({ type: 'emulator-get-debug-state' });

async getDebugState(thp_channel_id?: string) {
const { response } = await this.client.send({
type: 'emulator-get-debug-state',
thp_channel_id,
});

return response;
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci/connect-test-matrix-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const groups = {
api: {
name: 'api',
pattern:
'authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test',
'authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test thpPairing',
includeFilter: '',
},
// temporarily created group for flaky test - to spend less time on reruns and to make test result in CI more readable without investigating long logs
Expand Down

0 comments on commit e3976a6

Please sign in to comment.