1import chalk from 'chalk';
2
3import * as Log from '../../../../log';
4import { selectAsync } from '../../../../utils/prompts';
5import * as Security from '../Security';
6import {
7  resolveCertificateSigningIdentityAsync,
8  selectDevelopmentTeamAsync,
9} from '../resolveCertificateSigningIdentity';
10import * as Settings from '../settings';
11
12jest.mock('../../../../log');
13jest.mock('../../../../utils/prompts');
14const asMock = <T extends (...args: any[]) => any>(fn: T): jest.MockedFunction<T> =>
15  fn as jest.MockedFunction<T>;
16
17jest.mock('../../../../utils/interactive', () => ({
18  isInteractive: jest.fn(() => true),
19}));
20
21jest.mock('../settings', () => ({
22  getLastDeveloperCodeSigningIdAsync: jest.fn(),
23  setLastDeveloperCodeSigningIdAsync: jest.fn(),
24}));
25
26jest.mock('../Security', () => ({
27  resolveCertificateSigningInfoAsync: jest.fn(),
28  resolveIdentitiesAsync: jest.fn(),
29}));
30
31describe(selectDevelopmentTeamAsync, () => {
32  it(`formats prompt`, async () => {
33    const identities = [
34      {
35        developmentTeams: [],
36        signingCertificateId: 'XXX',
37        codeSigningInfo: 'Apple Development: Evan Bacon (XXX)',
38        appleTeamName: '650 Industries, Inc.',
39        appleTeamId: 'A1BCDEF234',
40      },
41      {
42        developmentTeams: [],
43        signingCertificateId: 'YYY',
44        codeSigningInfo: 'Apple Developer: Nave Nocab (YYY)',
45        appleTeamId: '12345ABCD',
46      },
47    ];
48    const preferredId = 'A1BCDEF234';
49    await selectDevelopmentTeamAsync(identities, preferredId);
50
51    expect(selectAsync).toBeCalledWith('Development team for signing the app', [
52      {
53        title: '650 Industries, Inc. (A1BCDEF234) - Apple Development: Evan Bacon (XXX)',
54        value: 0,
55      },
56      { title: ' (12345ABCD) - Apple Developer: Nave Nocab (YYY)', value: 1 },
57    ]);
58  });
59});
60
61describe(resolveCertificateSigningIdentityAsync, () => {
62  it(`asserts when no IDs are provided`, async () => {
63    const ids = [];
64    await expect(resolveCertificateSigningIdentityAsync(ids)).rejects.toThrow(
65      'No code signing certificates are available to use.'
66    );
67    expect(Log.log).toBeCalledWith(
68      expect.stringMatching(/Your computer requires some additional setup/)
69    );
70  });
71
72  it(`prompts when there are more than one signing identities`, async () => {
73    asMock(Settings.getLastDeveloperCodeSigningIdAsync).mockResolvedValue('YYY');
74    asMock(Security.resolveIdentitiesAsync).mockResolvedValueOnce([
75      {
76        signingCertificateId: 'XXX',
77        codeSigningInfo: 'Apple Development: Evan Bacon (XXX)',
78        appleTeamName: '650 Industries, Inc.',
79        appleTeamId: 'A1BCDEF234',
80      },
81      {
82        signingCertificateId: 'YYY',
83        codeSigningInfo: 'Apple Developer: Nave Nocab (YYY)',
84        appleTeamId: '12345ABCD',
85      },
86    ]);
87
88    asMock(selectAsync).mockResolvedValueOnce(0);
89
90    await expect(resolveCertificateSigningIdentityAsync(['YYY', 'XXX'])).resolves.toEqual({
91      appleTeamId: expect.any(String),
92      codeSigningInfo: expect.any(String),
93      signingCertificateId: 'YYY',
94    });
95
96    expect(selectAsync).toBeCalledWith(expect.any(String), [
97      {
98        // Formatted the preferred ID as bold and sorted it first.
99        title: chalk.bold(' (12345ABCD) - Apple Developer: Nave Nocab (YYY)'),
100        value: 0,
101      },
102      expect.anything(),
103    ]);
104
105    // Store the preferred ID for the next time.
106    expect(Settings.setLastDeveloperCodeSigningIdAsync).toBeCalledWith('YYY');
107  });
108
109  it(`auto selects the first ID when there is only one`, async () => {
110    asMock(Security.resolveCertificateSigningInfoAsync).mockResolvedValue({
111      signingCertificateId: 'XXX',
112    });
113
114    await expect(resolveCertificateSigningIdentityAsync(['YYY'])).resolves.toEqual({
115      signingCertificateId: 'XXX',
116    });
117
118    // Ensure that we only store the value when the user manually selects it.
119    expect(Settings.setLastDeveloperCodeSigningIdAsync).toBeCalledTimes(0);
120  });
121});
122