Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhances teams cache remove to support the new client #6381

Closed
wants to merge 2 commits into from
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
11 changes: 10 additions & 1 deletion docs/docs/cmd/teams/cache/cache-remove.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ m365 teams cache remove [options]
## Options

```md definition-list
`-c, --client`
: Teams client to target. Possible values are: `new` or `classic`. Default value is `new`.

`-f, --force`
: Don't prompt for confirmation
```
Expand Down Expand Up @@ -43,12 +46,18 @@ The command works only on Windows and macOS. If you run it on a different operat

## Examples

Removes the Microsoft Teams client cache
Removes the Microsoft Teams client cache for the new client.

```sh
m365 teams cache remove
```

Removes the Microsoft Teams client cache for the classic client.

```sh
m365 teams cache remove --client classic
```

## Response

The command won't return a response on success.
Expand Down
12 changes: 12 additions & 0 deletions docs/docs/v10-upgrade-guidance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,18 @@ Please update your scripts not to use the `overwrite` option.

## Teams

### Enhanced `teams cache remove` command

We enhanced the [teams cache remove](./cmd/teams/cache/cache-remove.mdx) command to support the removal of the cache from the new Teams client. We also made it so that by default, the command will remove the cache for the `new` client.

To still support the old client, we have added the option `--client`, in which you can specify `classic` as value to remove the cache of the old Teams client.

#### What action do I need to take?

Add the `--client` option to your scripts to specify which client's cache you want to remove. Otherwise, upon the release of v10, it will attempt to remove the cache from the new client.

## Teams

### Removes duplicate property from 'teams tab list' command.

For the [teams tab list](./cmd/teams/tab/tab-list.mdx) command we removed the `teamsAppTabId` from the command output as it was a duplicate of the `teamsApp/id` property.
Expand Down
150 changes: 139 additions & 11 deletions src/m365/teams/commands/cache/cache-remove.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import command from './cache-remove.js';
import os, { homedir } from 'os';

describe(commands.CACHE_REMOVE, () => {
const processOutput = `ProcessId
Expand All @@ -20,6 +21,7 @@ describe(commands.CACHE_REMOVE, () => {
11352`;
let log: string[];
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;

before(() => {
Expand All @@ -45,6 +47,7 @@ describe(commands.CACHE_REMOVE, () => {
log.push(msg);
}
};
loggerLogSpy = sinon.spy(logger, 'log');

sinon.stub(cli, 'promptForConfirmation').resolves(true);
});
Expand Down Expand Up @@ -84,6 +87,16 @@ describe(commands.CACHE_REMOVE, () => {
assert(confirmationStub.calledOnce);
});

it('fails validation if client is not a valid client option', async () => {
sinon.stub(process, 'platform').value('win32');
const actual = await command.validate({
options: {
client: 'invalid'
}
}, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if called from docker container.', async () => {
sinon.stub(process, 'platform').value('win32');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': 'docker' });
Expand Down Expand Up @@ -114,7 +127,7 @@ describe(commands.CACHE_REMOVE, () => {
assert.strictEqual(actual, true);
});

it('fails to remove teams cache when exec fails randomly when killing teams.exe process', async () => {
it('fails to remove teams cache when exec fails randomly when killing teams.exe process using classic client', async () => {
sinon.stub(process, 'platform').value('win32');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(fs, 'existsSync').returns(true);
Expand All @@ -125,10 +138,10 @@ describe(commands.CACHE_REMOVE, () => {
}
throw 'Invalid request';
});
await assert.rejects(command.action(logger, { options: { force: true } } as any), new CommandError('random error'));
await assert.rejects(command.action(logger, { options: { client: 'classic', force: true } } as any), new CommandError('random error'));
});

it('fails to remove teams cache when exec fails randomly when removing cache folder', async () => {
it('fails to remove teams cache when exec fails randomly when removing cache folder using classic client', async () => {
sinon.stub(process, 'platform').value('win32');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '', APPDATA: 'C:\\Users\\Administrator\\AppData\\Roaming' });
sinon.stub(process, 'kill' as any).returns(null);
Expand All @@ -143,10 +156,41 @@ describe(commands.CACHE_REMOVE, () => {
}
throw 'Invalid request';
});
await assert.rejects(command.action(logger, { options: { force: true } } as any), new CommandError('random error'));
await assert.rejects(command.action(logger, { options: { client: 'classic', force: true } } as any), new CommandError('random error'));
});

it('shows error message when exec fails when removing the teams cache folder on mac os', async () => {
const deleteError = {
code: 1,
killed: false,
signal: null,
cmd: 'rm -r "/Users/John/Library/Group Containers/UBF8T346G9.com.microsoft.teams"',
stdout: '',
stderr: 'rm: /Users/John/Library/Group Containers/UBF8T346G9.com.microsoft.teams: Operation not permitted\\n'
};

sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(process, 'kill' as any).returns(null);
sinon.stub(fs, 'existsSync').returns(true);

sinon.stub(command, 'exec' as any).callsFake(async (opts) => {
if (opts === `ps ax | grep MacOS/MSTeams -m 1 | grep -v grep | awk '{ print $1 }'`) {
return {};
}
if (opts === `rm -r "${homedir}/Library/Group Containers/UBF8T346G9.com.microsoft.teams"`) {
return;
}
if (opts === `rm -r "${homedir}/Library/Containers/com.microsoft.teams2"`) {
throw deleteError;
}
throw 'Invalid request';
});
await command.action(logger, { options: { force: true } } as any);
assert(loggerLogSpy.calledWith('Deleting the folder failed. Please have a look at the following URL to delete the folders manually: https://answers.microsoft.com/en-us/msteams/forum/all/clearing-cache-on-microsoft-teams/35876f6b-eb1a-4b77-bed1-02ce3277091f'));
});

it('removes Teams cache from macOs platform without prompting.', async () => {
it('removes Teams cache from macOs platform without prompting using classic client', async () => {
sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(command, 'exec' as any).returns({ stdout: '' });
Expand All @@ -156,13 +200,14 @@ describe(commands.CACHE_REMOVE, () => {
await command.action(logger, {
options: {
force: true,
verbose: true
verbose: true,
client: 'classic'
}
});
assert(true);
});

it('removes teams cache when teams is currently not active', async () => {
it('removes teams cache when teams is currently not active using the classic client', async () => {
sinon.stub(process, 'platform').value('win32');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '', APPDATA: 'C:\\Users\\Administrator\\AppData\\Roaming' });
sinon.stub(process, 'kill' as any).returns(null);
Expand All @@ -180,13 +225,14 @@ describe(commands.CACHE_REMOVE, () => {
await command.action(logger, {
options: {
force: true,
verbose: true
verbose: true,
client: 'classic'
}
});
assert(true);
});

it('removes Teams cache from win32 platform without prompting.', async () => {
it('removes Teams cache from win32 platform without prompting using the classic client', async () => {
sinon.stub(process, 'platform').value('win32');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '', APPDATA: 'C:\\Users\\Administrator\\AppData\\Roaming' });
sinon.stub(process, 'kill' as any).returns(null);
Expand All @@ -200,6 +246,30 @@ describe(commands.CACHE_REMOVE, () => {
throw 'Invalid request';
});
sinon.stub(fs, 'existsSync').returns(true);
await command.action(logger, {
options: {
force: true,
verbose: true,
client: 'classic'
}
});
assert(true);
});

it('removes Teams cache from win32 platform without prompting using the new client', async () => {
sinon.stub(process, 'platform').value('win32');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '', APPDATA: 'C:\\Users\\Administrator\\AppData\\Roaming', LOCALAPPDATA: 'C:\\Users\\Administrator\\AppData\\Local' });
sinon.stub(process, 'kill' as any).returns(null);
sinon.stub(command, 'exec' as any).callsFake(async (opts) => {
if (opts === 'wmic process where caption="ms-teams.exe" get ProcessId') {
return { stdout: processOutput };
}
if (opts === 'rmdir /s /q "C:\\Users\\Administrator\\AppData\\Local\\Packages\\MSTeams_8wekyb3d8bbwe\\LocalCache\\Microsoft\\MSTeams"') {
return;
}
throw 'Invalid request';
});
sinon.stub(fs, 'existsSync').returns(true);
await command.action(logger, {
options: {
force: true,
Expand All @@ -209,7 +279,7 @@ describe(commands.CACHE_REMOVE, () => {
assert(true);
});

it('removes Teams cache from darwin platform with prompting.', async () => {
it('removes Teams cache from darwin platform with prompting using the classic client', async () => {
sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(command, 'exec' as any).returns({ stdout: 'pid' });
Expand All @@ -218,12 +288,70 @@ describe(commands.CACHE_REMOVE, () => {

await command.action(logger, {
options: {
debug: true
debug: true,
client: 'classic'
}
});
assert(true);
});

it('removes Teams cache from darwin platform with prompting', async () => {
sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(command, 'exec' as any).returns({ stdout: '1111' });
sinon.stub(process, 'kill' as any).returns(null);
sinon.stub(fs, 'existsSync').returns(true);

await command.action(logger, {
options: {
debug: true,
client: 'new'
}
});
assert(true);
});

it('removes teams cache when teams is currently not running on macOS', async () => {
sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(process, 'kill' as any).returns(null);
sinon.stub(command, 'exec' as any).callsFake(async (opts) => {
if (opts === `ps ax | grep MacOS/MSTeams -m 1 | grep -v grep | awk '{ print $1 }'`) {
return {};
}
if (opts === `rm -r "${os.homedir()}/Library/Group Containers/UBF8T346G9.com.microsoft.teams"`) {
return;
}
if (opts === `rm -r "${os.homedir()}/Library/Containers/com.microsoft.teams2"`) {
return;
}
throw 'Invalid request';
});
sinon.stub(fs, 'existsSync').returns(true);

await command.action(logger, {
options: {
force: true,
verbose: true,
client: 'new'
}
});
assert(true);
});


it('aborts cache clearing when no cache folder is found using the classic client', async () => {
sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
sinon.stub(fs, 'existsSync').returns(false);
await command.action(logger, {
options: {
verbose: true,
client: 'classic'
}
});
});

it('aborts cache clearing when no cache folder is found', async () => {
sinon.stub(process, 'platform').value('darwin');
sinon.stub(process, 'env').value({ 'CLIMICROSOFT365_ENV': '' });
Expand Down
Loading