Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/m365/app/commands/app-get.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import assert from 'assert';
import fs from 'fs';
import sinon from 'sinon';
import { z } from 'zod';
import auth from '../../../Auth.js';
import { cli } from '../../../cli/cli.js';
import { CommandInfo } from '../../../cli/CommandInfo.js';
import { Logger } from '../../../cli/Logger.js';
import { CommandError } from '../../../Command.js';
import request from '../../../request.js';
import { telemetry } from '../../../telemetry.js';
import { entraApp } from '../../../utils/entraApp.js';
import { pid } from '../../../utils/pid.js';
import { session } from '../../../utils/session.js';
import { sinonUtil } from '../../../utils/sinonUtil.js';
import commands from '../commands.js';
import command from './app-get.js';
import { entraApp } from '../../../utils/entraApp.js';

describe(commands.GET, () => {
let log: string[];
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
let commandOptionsSchema: z.ZodTypeAny;

before(() => {
sinon.stub(auth, 'restoreAuth').resolves();
Expand All @@ -33,6 +38,8 @@ describe(commands.GET, () => {
]
}));
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()!;
});

beforeEach(() => {
Expand Down Expand Up @@ -76,9 +83,9 @@ describe(commands.GET, () => {
sinon.stub(entraApp, 'getAppRegistrationByAppId').rejects(new Error(error));

await assert.rejects(command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f'
}
})
}), new CommandError(`App with appId '9b1b1e42-794b-4c71-93ac-5ed92488b67f' not found in Microsoft Entra ID`));
});

Expand All @@ -98,9 +105,9 @@ describe(commands.GET, () => {
sinon.stub(entraApp, 'getAppRegistrationByAppId').resolves(appResponse.value[0]);

await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f'
}
})
});
const call: sinon.SinonSpyCall = loggerLogSpy.lastCall;
assert.strictEqual(call.args[0].id, '340a4aa3-1af6-43ac-87d8-189819003952');
Expand Down
9 changes: 7 additions & 2 deletions src/m365/app/commands/app-get.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { z } from 'zod';
import { Logger } from '../../../cli/Logger.js';
import AppCommand, { AppCommandArgs } from '../../base/AppCommand.js';
import commands from '../commands.js';
import { entraApp } from '../../../utils/entraApp.js';
import AppCommand, { AppCommandArgs, appCommandOptions } from '../../base/AppCommand.js';
import commands from '../commands.js';

class AppGetCommand extends AppCommand {
public get name(): string {
Expand All @@ -12,6 +13,10 @@ class AppGetCommand extends AppCommand {
return 'Retrieves information about the current Microsoft Entra app';
}

public get schema(): z.ZodTypeAny | undefined {
return appCommandOptions;
}

public async commandAction(logger: Logger, args: AppCommandArgs): Promise<void> {
try {
const app = await entraApp.getAppRegistrationByAppId(args.options.appId!);
Expand Down
41 changes: 22 additions & 19 deletions src/m365/app/commands/app-open.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import assert from 'assert';
import fs from 'fs';
import sinon from 'sinon';
import { z } from 'zod';
import auth from '../../../Auth.js';
import { CommandError } from '../../../Command.js';
import { cli } from '../../../cli/cli.js';
import { CommandInfo } from '../../../cli/CommandInfo.js';
import { Logger } from '../../../cli/Logger.js';
import { CommandError } from '../../../Command.js';
import { telemetry } from '../../../telemetry.js';
import { browserUtil } from '../../../utils/browserUtil.js';
import { pid } from '../../../utils/pid.js';
Expand All @@ -20,6 +21,7 @@ describe(commands.OPEN, () => {
let getSettingWithDefaultValueStub: sinon.SinonStub;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
let commandOptionsSchema: z.ZodTypeAny;

before(() => {
sinon.stub(auth, 'restoreAuth').resolves();
Expand All @@ -37,6 +39,7 @@ describe(commands.OPEN, () => {
]
}));
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()!;
});

beforeEach(() => {
Expand Down Expand Up @@ -75,44 +78,44 @@ describe(commands.OPEN, () => {
assert.notStrictEqual(command.description, null);
});

it('fails validation if the appId is not a valid guid', async () => {
const actual = await command.validate({ options: { appId: 'abc' } }, commandInfo);
assert.notStrictEqual(actual, true);
it('fails validation if the appId is not a valid guid', () => {
const actual = commandOptionsSchema.safeParse({ appId: 'abc' });
assert.strictEqual(actual.success, false);
});

it('passes validation if valid appId-guid is specified', async () => {
const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f' } }, commandInfo);
assert.strictEqual(actual, true);
it('passes validation if valid appId-guid is specified', () => {
const actual = commandOptionsSchema.safeParse({ appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f' });
assert.strictEqual(actual.success, true);
});

it('shows message with url when the app specified with the appId is found', async () => {
const appId = "9b1b1e42-794b-4c71-93ac-5ed92488b67f";
await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: appId
}
})
});
assert(loggerLogSpy.calledWith(`Use a web browser to open the page https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/${appId}/isMSAApp/`));
});

it('shows message with url when the app specified with the appId is found (verbose)', async () => {
const appId = "9b1b1e42-794b-4c71-93ac-5ed92488b67f";
await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
verbose: true,
appId: appId
}
})
});
assert(loggerLogSpy.calledWith(`Use a web browser to open the page https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/${appId}/isMSAApp/`));
});

it('shows message with preview-url when the app specified with the appId is found', async () => {
const appId = "9b1b1e42-794b-4c71-93ac-5ed92488b67f";
await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: appId,
preview: true
}
})
});
assert(loggerLogSpy.calledWith(`Use a web browser to open the page https://preview.portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/${appId}/isMSAApp/`));
});
Expand All @@ -131,9 +134,9 @@ describe(commands.OPEN, () => {

const appId = "9b1b1e42-794b-4c71-93ac-5ed92488b67f";
await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: appId
}
})
});
assert(loggerLogSpy.calledWith(`Opening the following page in your browser: https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/${appId}/isMSAApp/`));
});
Expand All @@ -152,10 +155,10 @@ describe(commands.OPEN, () => {

const appId = "9b1b1e42-794b-4c71-93ac-5ed92488b67f";
await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: appId,
preview: true
}
})
});
assert(loggerLogSpy.calledWith(`Opening the following page in your browser: https://preview.portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/${appId}/isMSAApp/`));
});
Expand All @@ -174,10 +177,10 @@ describe(commands.OPEN, () => {

const appId = "9b1b1e42-794b-4c71-93ac-5ed92488b67f";
await assert.rejects(command.action(logger, {
options: {
options: commandOptionsSchema.parse({
appId: appId,
preview: true
}
})
}), new CommandError('An error occurred'));
assert(loggerLogSpy.calledWith(`Opening the following page in your browser: https://preview.portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/${appId}/isMSAApp/`));
});
Expand Down
39 changes: 11 additions & 28 deletions src/m365/app/commands/app-open.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { z } from 'zod';
import { cli } from '../../../cli/cli.js';
import { Logger } from '../../../cli/Logger.js';
import GlobalOptions from '../../../GlobalOptions.js';
import { settingsNames } from '../../../settingsNames.js';
import { browserUtil } from '../../../utils/browserUtil.js';
import AppCommand from '../../base/AppCommand.js';
import AppCommand, { appCommandOptions } from '../../base/AppCommand.js';
import commands from '../commands.js';

const options = appCommandOptions
.extend({
preview: z.boolean().optional().default(false)
})
.strict();
type Options = z.infer<typeof options>;

interface CommandArgs {
options: Options;
}

interface Options extends GlobalOptions {
appId?: string;
preview?: boolean;
}

class AppOpenCommand extends AppCommand {
public get name(): string {
return commands.OPEN;
Expand All @@ -24,27 +26,8 @@ class AppOpenCommand extends AppCommand {
return 'Opens Microsoft Entra app in the Microsoft Entra ID portal';
}

constructor() {
super();

this.#initTelemetry();
this.#initOptions();
}

#initTelemetry(): void {
this.telemetry.push((args: CommandArgs) => {
Object.assign(this.telemetryProperties, {
appId: typeof args.options.appId !== 'undefined',
preview: typeof args.options.preview !== 'undefined'
});
});
}

#initOptions(): void {
this.options.unshift(
{ option: '--appId [appId]' },
{ option: '--preview' }
);
public get schema(): z.ZodTypeAny | undefined {
return options;
}

public async commandAction(logger: Logger, args: CommandArgs): Promise<void> {
Expand Down
Loading