Skip to content
Open
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,4 @@ docs/.env.production.local

docs/npm-debug.log*
docs/yarn-debug.log*
docs/yarn-error.log*
docs/yarn-error.log*.impeccable/
45 changes: 18 additions & 27 deletions src/m365/pp/commands/gateway/gateway-get.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ 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 './gateway-get.js';
import command, { options } from './gateway-get.js';
import { accessToken } from '../../../../utils/accessToken.js';

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

const gateway: any = {
id: "1f69e798-5852-4fdd-ab01-33bb14b6e934",
Expand All @@ -39,6 +40,7 @@ describe(commands.GATEWAY_GET, () => {
sinon.stub(accessToken, 'assertAccessTokenType').returns();
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -74,30 +76,19 @@ describe(commands.GATEWAY_GET, () => {
assert.notStrictEqual(command.description, null);
});

it("fails validation if the id is not valid", async () => {
const actual = await command.validate(
{
options: {
id: "3eb1a01b"
}
},
commandInfo
);

assert.notStrictEqual(actual, true);
it("fails validation if the id is not valid", () => {
const actual = commandOptionsSchema.safeParse({ id: "3eb1a01b" });
assert.strictEqual(actual.success, false);
});

it("passes validation if the id is valid", async () => {
const actual = await command.validate(
{
options: {
id: "1f69e798-5852-4fdd-ab01-33bb14b6e934"
}
},
commandInfo
);
it("passes validation if the id is valid", () => {
const actual = commandOptionsSchema.safeParse({ id: "1f69e798-5852-4fdd-ab01-33bb14b6e934" });
assert.strictEqual(actual.success, true);
});

assert.strictEqual(actual, true);
it("fails validation with unknown options", () => {
const actual = commandOptionsSchema.safeParse({ id: "1f69e798-5852-4fdd-ab01-33bb14b6e934", unknownOption: "value" });
assert.strictEqual(actual.success, false);
});

it("correctly handles error", async () => {
Expand All @@ -107,9 +98,9 @@ describe(commands.GATEWAY_GET, () => {

await assert.rejects(
command.action(logger, {
options: {
id: 'testid'
}
options: commandOptionsSchema.parse({
id: '1f69e798-5852-4fdd-ab01-33bb14b6e934'
})
}),
new CommandError("An error has occurred")
);
Expand All @@ -128,9 +119,9 @@ describe(commands.GATEWAY_GET, () => {
});

await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
id: "1f69e798-5852-4fdd-ab01-33bb14b6e934"
}
})
});
const call: sinon.SinonSpyCall = loggerLogSpy.lastCall;

Expand Down
37 changes: 17 additions & 20 deletions src/m365/pp/commands/gateway/gateway-get.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import { z } from 'zod';
import { Logger } from "../../../../cli/Logger.js";
import { CommandArgs } from "../../../../Command.js";
import { globalOptionsZod } from "../../../../Command.js";
import request from "../../../../request.js";
import { formatting } from "../../../../utils/formatting.js";
import { validation } from "../../../../utils/validation.js";
import PowerBICommand from "../../../base/PowerBICommand.js";
import commands from "../../commands.js";

export const options = z.strictObject({
...globalOptionsZod.shape,
id: z.string().refine(val => validation.isValidGuid(val), {
error: 'The value must be a valid GUID.'
}).alias('i')
});

declare type Options = z.infer<typeof options>;

interface CommandArgs {
options: Options;
}

class PpGatewayGetCommand extends PowerBICommand {
public get name(): string {
return commands.GATEWAY_GET;
Expand All @@ -15,25 +29,8 @@ class PpGatewayGetCommand extends PowerBICommand {
return "Get information about the specified gateway.";
}

constructor() {
super();
this.#initOptions();
this.#initValidators();
}

#initOptions(): void {
this.options.unshift({
option: "-i, --id <id>"
});
}

#initValidators(): void {
this.validators.push(async (args: CommandArgs) => {
if (!validation.isValidGuid(args.options.id as string)) {
return `${args.options.id} is not a valid GUID`;
}
return true;
});
public get schema(): z.ZodTypeAny | undefined {
return options;
}

public async commandAction(logger: Logger, args: CommandArgs): Promise<void> {
Expand Down
122 changes: 48 additions & 74 deletions src/m365/pp/commands/managementapp/managementapp-add.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ 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 './managementapp-add.js';
import { settingsNames } from '../../../../settingsNames.js';
import command, { options } from './managementapp-add.js';
import { accessToken } from '../../../../utils/accessToken.js';
import { entraApp } from '../../../../utils/entraApp.js';

Expand All @@ -21,6 +20,7 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
let commandOptionsSchema: typeof options;

before(() => {
sinon.stub(auth, 'restoreAuth').resolves();
Expand All @@ -30,6 +30,7 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
sinon.stub(accessToken, 'assertAccessTokenType').returns();
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

beforeEach(() => {
Expand Down Expand Up @@ -77,9 +78,9 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
sinon.stub(entraApp, 'getAppRegistrationByAppName').rejects(new Error(error));

await assert.rejects(command.action(logger, {
options: {
options: commandOptionsSchema.parse({
name: 'My app'
}
})
}), new CommandError(error));
});

Expand All @@ -88,107 +89,80 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
sinon.stub(entraApp, 'getAppRegistrationByAppName').rejects(new Error(error));

await assert.rejects(command.action(logger, {
options: {
options: commandOptionsSchema.parse({
name: 'My app'
}
})
}), new CommandError(error));
});

it('handles error when retrieving information about app through appId failed', async () => {
sinon.stub(request, 'get').rejects(new Error('An error has occurred'));

await assert.rejects(command.action(logger, {
options: {
options: commandOptionsSchema.parse({
objectId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f'
}
})
}), new CommandError(`An error has occurred`));
});

it('handles error when retrieving information about app through name failed', async () => {
sinon.stub(request, 'get').rejects(new Error('An error has occurred'));

await assert.rejects(command.action(logger, {
options: {
options: commandOptionsSchema.parse({
name: 'My app'
}
})
}), new CommandError(`An error has occurred`));
});

it('fails validation if appId and objectId specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', objectId: 'c75be2e1-0204-4f95-857d-51a37cf40be8' } }, commandInfo);
assert.notStrictEqual(actual, true);
it('fails validation if appId and objectId specified', () => {
const actual = commandOptionsSchema.safeParse({ appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', objectId: 'c75be2e1-0204-4f95-857d-51a37cf40be8' });
assert.strictEqual(actual.success, false);
});

it('fails validation if appId and name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' } }, commandInfo);
assert.notStrictEqual(actual, true);
it('fails validation if appId and name specified', () => {
const actual = commandOptionsSchema.safeParse({ appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' });
assert.strictEqual(actual.success, false);
});

it('fails validation if objectId and name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { objectId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' } }, commandInfo);
assert.notStrictEqual(actual, true);
it('fails validation if objectId and name specified', () => {
const actual = commandOptionsSchema.safeParse({ objectId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' });
assert.strictEqual(actual.success, false);
});

it('fails validation if neither appId, objectId, nor name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});
it('fails validation if neither appId, objectId, nor name specified', () => {
const actual = commandOptionsSchema.safeParse({});
assert.strictEqual(actual.success, false);
});

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

it('fails validation if the objectId is not a valid guid', async () => {
const actual = await command.validate({ options: { objectId: '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('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('passes validation if required options specified (appId)', () => {
const actual = commandOptionsSchema.safeParse({ appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f' });
assert.strictEqual(actual.success, true);
});

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

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

it('passes validation if required options specified (name)', async () => {
const actual = await command.validate({ options: { name: 'My app' } }, commandInfo);
assert.strictEqual(actual, true);
it('fails validation with unknown options', () => {
const actual = commandOptionsSchema.safeParse({ appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', unknownOption: 'value' });
assert.strictEqual(actual.success, false);
});

it('successfully registers app as managementapp when passing appId', async () => {
Expand All @@ -203,9 +177,9 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
});

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].applicationId, '9b1b1e42-794b-4c71-93ac-5ed92488b67f');
Expand All @@ -231,9 +205,9 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
});

await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
name: 'My Test App', debug: true
}
})
});
const call: sinon.SinonSpyCall = loggerLogSpy.lastCall;
assert.strictEqual(call.args[0].applicationId, '9b1b1e42-794b-4c71-93ac-5ed92488b67f');
Expand All @@ -259,9 +233,9 @@ describe(commands.MANAGEMENTAPP_ADD, () => {
});

await command.action(logger, {
options: {
options: commandOptionsSchema.parse({
objectId: '340a4aa3-1af6-43ac-87d8-189819003952', debug: true
}
})
});
const call: sinon.SinonSpyCall = loggerLogSpy.lastCall;
assert.strictEqual(call.args[0].applicationId, '9b1b1e42-794b-4c71-93ac-5ed92488b67f');
Expand Down
Loading
Loading