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
4 changes: 4 additions & 0 deletions .github/prompts/create-new-list-command.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
mode: agent
---
Create a new command
29 changes: 29 additions & 0 deletions convert-validation-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import fs from 'fs';

const files = [
'src/m365/entra/commands/app/app-role-add.spec.ts',
'src/m365/entra/commands/app/app-role-list.spec.ts'
];

files.forEach(filePath => {
if (!fs.existsSync(filePath)) {
console.log(`File not found: ${filePath}`);
return;
}

let content = fs.readFileSync(filePath, 'utf-8');

// Replace validation test patterns
content = content.replace(
/const actual = await command\.validate\(\{ options: \{([^}]*)\} \}, commandInfo\);\s*assert\.notStrictEqual\(actual, true\);/g,
'const schema = command.getRefinedSchema(commandOptionsSchema as any);\n const actual = schema?.safeParse({$1});\n assert.strictEqual(actual?.success, false);'
);

content = content.replace(
/const actual = await command\.validate\(\{ options: \{([^}]*)\} \}, commandInfo\);\s*assert\.strictEqual\(actual, true\);/g,
'const schema = command.getRefinedSchema(commandOptionsSchema as any);\n const actual = schema?.safeParse({$1});\n assert.strictEqual(actual?.success, true);'
);

fs.writeFileSync(filePath, content);
console.log(`Conversion completed for ${filePath}`);
});
67 changes: 35 additions & 32 deletions src/m365/entra/commands/m365group/m365group-set.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Group } from '@microsoft/microsoft-graph-types';
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';
Expand Down Expand Up @@ -53,6 +54,7 @@ describe(commands.M365GROUP_SET, () => {
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
let commandOptionsSchema: z.ZodTypeAny;
let loggerLogToStderrSpy: sinon.SinonSpy;
const groupId = 'f3db5c2b-068f-480d-985b-ec78b9fa0e76';

Expand All @@ -70,6 +72,7 @@ describe(commands.M365GROUP_SET, () => {
};
}
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse()!;
});

beforeEach(() => {
Expand Down Expand Up @@ -671,94 +674,94 @@ describe(commands.M365GROUP_SET, () => {
});

it('fails validation if the id is not a valid GUID', async () => {
const actual = await command.validate({ options: { id: 'invalid', description: 'My awesome group' } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: 'invalid', description: 'My awesome group' });
assert.strictEqual(actual.success, false);
});

it('passes validation when the id is a valid GUID and displayName specified', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', newDisplayName: 'My group' } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', newDisplayName: 'My group' });
assert.strictEqual(actual.success, true);
});

it('passes validation when the id is a valid GUID and description specified', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', description: 'My awesome group' } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', description: 'My awesome group' });
assert.strictEqual(actual.success, true);
});

it('fails validation if no property to update is specified', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848' } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848' });
assert.strictEqual(actual.success, false);
});

it('fails validation if ownerIds contains invalid GUID', async () => {
const ownerIds = ['7167b488-1ffb-43f1-9547-35969469bada', 'foo'];
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', ownerIds: ownerIds.join(',') } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', ownerIds: ownerIds.join(',') });
assert.strictEqual(actual.success, false);
});

it('fails validation if ownerUserNames contains invalid user principal name', async () => {
const ownerUserNames = ['[email protected]', 'foo'];
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', ownerUserNames: ownerUserNames.join(',') } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', ownerUserNames: ownerUserNames.join(',') });
assert.strictEqual(actual.success, false);
});

it('fails validation if memberIds contains invalid GUID', async () => {
const memberIds = ['7167b488-1ffb-43f1-9547-35969469bada', 'foo'];
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', memberIds: memberIds.join(',') } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', memberIds: memberIds.join(',') });
assert.strictEqual(actual.success, false);
});

it('fails validation if memberUserNames contains invalid user principal name', async () => {
const memberUserNames = ['[email protected]', 'foo'];
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', memberUserNames: memberUserNames.join(',') } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', memberUserNames: memberUserNames.join(',') });
assert.strictEqual(actual.success, false);
});

it('passes validation if isPrivate is true', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', isPrivate: true } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', isPrivate: true });
assert.strictEqual(actual.success, true);
});

it('passes validation if isPrivate is false', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', isPrivate: false } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', isPrivate: false });
assert.strictEqual(actual.success, true);
});

it('passes validation when all required parameters are valid with ids', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', ownerIds: userIds.join(',') } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', ownerIds: userIds.join(',') });
assert.strictEqual(actual.success, true);
});

it('passes validation when all required parameters are valid with user names', async () => {
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', memberUserNames: userUpns.join(',') } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', memberUserNames: userUpns.join(',') });
assert.strictEqual(actual.success, true);
});

it('fails validation if logoPath points to a non-existent file', async () => {
sinon.stub(fs, 'existsSync').returns(false);
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', logoPath: 'invalid' } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', logoPath: 'invalid' });
assert.strictEqual(actual.success, false);
});

it('fails validation if logoPath points to a folder', async () => {
const stats = { ...fsStats, isDirectory: () => true };
sinon.stub(fs, 'existsSync').returns(true);
sinon.stub(fs, 'lstatSync').returns(stats);
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', logoPath: 'folder' } }, commandInfo);
assert.notStrictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', logoPath: 'folder' });
assert.strictEqual(actual.success, false);
});

it('passes validation if logoPath points to an existing file', async () => {
sinon.stub(fs, 'existsSync').returns(true);
sinon.stub(fs, 'lstatSync').returns(fsStats);
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', logoPath: 'folder' } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', logoPath: 'folder' });
assert.strictEqual(actual.success, true);
});

it('passes validation if all options are being set', async () => {
sinon.stub(fs, 'existsSync').returns(true);
sinon.stub(fs, 'lstatSync').returns(fsStats);
const actual = await command.validate({ options: { id: '28beab62-7540-4db1-a23f-29a6018a3848', newDisplayName: 'Title', description: 'Description', logoPath: 'logo.png', ownerIds: userIds.join(','), memberIds: userIds.join(','), isPrivate: false, allowExternalSenders: false, autoSubscribeNewMembers: false, hideFromAddressLists: false, hideFromOutlookClients: false } }, commandInfo);
assert.strictEqual(actual, true);
const actual = commandOptionsSchema.safeParse({ id: '28beab62-7540-4db1-a23f-29a6018a3848', newDisplayName: 'Title', description: 'Description', logoPath: 'logo.png', ownerIds: userIds.join(','), memberIds: userIds.join(','), isPrivate: false, allowExternalSenders: false, autoSubscribeNewMembers: false, hideFromAddressLists: false, hideFromOutlookClients: false });
assert.strictEqual(actual.success, true);
});
});
Loading
Loading