1import { shellDumpsysPackage } from './fixtures/adb-output';
2import { asMock } from '../../../../__tests__/asMock';
3import { CommandError } from '../../../../utils/errors';
4import { AndroidDeviceManager } from '../AndroidDeviceManager';
5import {
6  Device,
7  getPackageInfoAsync,
8  launchActivityAsync,
9  openAppIdAsync,
10  openUrlAsync,
11} from '../adb';
12
13jest.mock('../adbReverse', () => ({
14  startAdbReverseAsync: jest.fn(),
15}));
16jest.mock('../adb', () => ({
17  getPackageInfoAsync: jest.fn(),
18  launchActivityAsync: jest.fn(),
19  openAppIdAsync: jest.fn(),
20  openUrlAsync: jest.fn(),
21}));
22
23const asDevice = (device: Partial<Device>): Device => device as Device;
24
25function createDevice() {
26  return new AndroidDeviceManager(asDevice({ name: 'Pixel 5', pid: '123' }));
27}
28
29describe('getAppVersionAsync', () => {
30  it(`gets the version from an installed app`, async () => {
31    const device = createDevice();
32    asMock(getPackageInfoAsync).mockResolvedValueOnce(shellDumpsysPackage);
33    await expect(device.getAppVersionAsync('foobar')).resolves.toBe('2.23.2');
34  });
35  it(`returns null when the app is not installed`, async () => {
36    const device = createDevice();
37    asMock(getPackageInfoAsync).mockResolvedValueOnce('');
38    await expect(device.getAppVersionAsync('foobar')).resolves.toBe(null);
39  });
40});
41
42describe('launchActivityAsync', () => {
43  it(`asserts that the app is not installed`, async () => {
44    const device = createDevice();
45    asMock(launchActivityAsync).mockImplementationOnce(() => {
46      throw new CommandError('APP_NOT_INSTALLED', '...');
47    });
48    await expect(device.launchActivityAsync).rejects.toThrow(/run:android/);
49  });
50  it(`asserts that an unexpected error occurred`, async () => {
51    const device = createDevice();
52    asMock(launchActivityAsync).mockImplementationOnce(() => {
53      throw new Error('...');
54    });
55    await expect(device.launchActivityAsync).rejects.toThrow(/\.\.\./);
56  });
57});
58
59describe('openUrlAsync', () => {
60  it('opens Expo Go before launching into Expo Go', async () => {
61    const device = createDevice();
62    await device.openUrlAsync('exp://foobar');
63    expect(openAppIdAsync).toBeCalledWith({ pid: '123' }, { applicationId: 'host.exp.exponent' });
64    expect(openUrlAsync).toBeCalledWith({ pid: '123' }, { url: 'exp://foobar' });
65  });
66  it('opens a URL on a device', async () => {
67    const device = createDevice();
68    await device.openUrlAsync('http://foobar');
69    expect(openAppIdAsync).not.toBeCalled();
70    expect(openUrlAsync).toBeCalledWith({ pid: '123' }, { url: 'http://foobar' });
71  });
72  it('launches nonstandard URL', async () => {
73    const device = createDevice();
74    // @ts-expect-error
75    device.launchActivityAsync = jest.fn(async () => {});
76    await device.openUrlAsync('@foobar');
77    expect(device.launchActivityAsync).toHaveBeenCalledWith('@foobar');
78  });
79});
80