diff --git a/.github/maintainers_guide.md b/.github/maintainers_guide.md index 69721b658..86a17c707 100644 --- a/.github/maintainers_guide.md +++ b/.github/maintainers_guide.md @@ -54,6 +54,7 @@ work for this project again in the future, `cd` into this project directory and run `source env_3.9.6/bin/activate` again. The last step is to install this project's dependencies and run all unit tests; to do so, you can run + ```bash $ ./scripts/run_validation.sh ``` @@ -61,6 +62,7 @@ $ ./scripts/run_validation.sh Also check out [how we configure GitHub Actions to install dependencies for this project for use in our continuous integration](https://github.com/slackapi/python-slack-sdk/blob/v3.17.0/.github/workflows/ci-build.yml#L28-L32). + ## Tasks ### Testing (Unit Tests) @@ -68,16 +70,19 @@ our continuous integration](https://github.com/slackapi/python-slack-sdk/blob/v3 When you make changes to this SDK, please write unit tests verifying if the changes work as you expected. You can easily run all the tests and formatting/linter with the below scripts. Run all the unit tests, code formatter, and code analyzer: + ```bash $ ./scripts/run_validation.sh ``` Run all the unit tests (no formatter nor code analyzer): + ```bash $ ./scripts/run_unit_tests.sh ``` Run a specific unit test: + ```bash $ ./scripts/run_unit_tests.sh tests/web/test_web_client.py ``` @@ -89,11 +94,13 @@ You can rely on GitHub Actions builds for running the tests on a variety of Pyth This project also has integration tests that verify the SDK works with the Slack API platform. As a preparation, you need to set [the required env variables](https://github.com/slackapi/python-slack-sdk/blob/main/integration_tests/env_variable_names.py) properly. You don't need to setup all of them if you just want to run some of the tests. Commonly, `SLACK_SDK_TEST_BOT_TOKEN` and `SLACK_SDK_TEST_USER_TOKEN` are used for running `WebClient` tests. Run all integration tests: + ```bash $ ./scripts/run_integration_tests.sh ``` Run a specific integration test: + ```bash $ ./scripts/run_integration_tests.sh integration_tests/web/test_async_web_client.py ``` @@ -104,12 +111,14 @@ The documentation is generated from the source and templates in the `docs-src` d gets committed to the repo in `docs` and also published to a GitHub Pages website. You can generate and preview the **SDK document pages** by running + ```bash $ ./scripts/docs.sh $ open docs/index.html ``` Similarly you can generate and preview the **API documents for `slack_sdk` package modules** by running + ```bash $ ./scripts/generate_api_docs.sh ``` @@ -118,46 +127,46 @@ $ ./scripts/generate_api_docs.sh 1. Create the commit for the release: -- Bump the version number in adherence to [Semantic Versioning](http://semver.org/) in `slack_sdk/version.py`. -- Build the docs with `./scripts/docs.sh` and then `./scripts/generate_api_docs.sh`. -- Create a branch for the release with `git checkout -b v2.5.0` -- Make a commit that includes the new version number: `git commit -m 'version 2.5.0'`. -- Open a PR and merge after receiving at least one approval from other maintainers. -- Create a git tag for the release. For example `git tag v2.5.0`. -- Push the tag up to github with `git push origin --tags` + - Bump the version number in adherence to [Semantic Versioning](http://semver.org/) in `slack_sdk/version.py`. + - Build the docs with `./scripts/docs.sh` and then `./scripts/generate_api_docs.sh`. + - Create a branch for the release with `git checkout -b v2.5.0` + - Make a commit that includes the new version number: `git commit -m 'version 2.5.0'`. + - Open a PR and merge after receiving at least one approval from other maintainers. + - Create a git tag for the release. For example `git tag v2.5.0`. + - Push the tag up to github with `git push origin --tags` 2. Distribute the release -- Use the latest stable Python runtime - - `python -m venv env` - - `python setup.py upload` -- Create a GitHub Release. You will select the commit with updated version number (e.g. `version 2.5.0`) to associate with the tag, and name the tag after this version (e.g. `v2.5.0`). This will also serve as a Changelog for the project. Add a description of changes to the Release. Mention Issue and PR #'s and @-mention contributors. + - Use the latest stable Python runtime + - `python -m venv env` + - `python setup.py upload` + - Create a GitHub Release. You will select the commit with updated version number (e.g. `version 2.5.0`) to associate with the tag, and name the tag after this version (e.g. `v2.5.0`). This will also serve as a Changelog for the project. Add a description of changes to the Release. Mention Issue and PR #'s and @-mention contributors. -```markdown -Refer to [v{version} milestone](https://github.com/slackapi/python-slack-sdk/milestone/{TODO}?closed=1) to know the complete list of the issues resolved by this release. + ```markdown + Refer to [v{version} milestone](https://github.com/slackapi/python-slack-sdk/milestone/{TODO}?closed=1) to know the complete list of the issues resolved by this release. -**Updates** + **Updates** -1. [WebClient] #111 Make an awesome change - Thanks @SlackHQ -1. [RTMClient] #222 Make an awesome change - Thanks @SlackAPI + 1. [WebClient] #111 Make an awesome change - Thanks @SlackHQ + 2. [RTMClient] #222 Make an awesome change - Thanks @SlackAPI -**All Changes** + **All Changes** -https://github.com/slackapi/python-slack-sdk/compare/{the previous release version tag}...{the release version tag} -``` + https://github.com/slackapi/python-slack-sdk/compare/{the previous release version tag}...{the release version tag} + ``` 3. (Slack Internal) Communicate the release internally -- Include a link to the GitHub release + - Include a link to the GitHub release 4. Make announcements -- #slack-api in dev4slack.slack.com -- #lang-python in community.slack.com + - #slack-api in dev4slack.slack.com + - #lang-python in community.slack.com 5. (Slack Internal) Tweet by @SlackAPI -- Not necessary for patch updates, might be needed for minor updates, definitely needed for major updates. Include a link to the GitHub release + - Not necessary for patch updates, might be needed for minor updates, definitely needed for major updates. Include a link to the GitHub release ## Workflow diff --git a/integration_tests/env_variable_names.py b/integration_tests/env_variable_names.py index 993cdaf4c..47deb1038 100644 --- a/integration_tests/env_variable_names.py +++ b/integration_tests/env_variable_names.py @@ -24,6 +24,7 @@ SLACK_SDK_TEST_GRID_IDP_USERGROUP_ID = "SLACK_SDK_TEST_GRID_IDP_USERGROUP_ID" SLACK_SDK_TEST_GRID_IDP_USERGROUP_ID_2 = "SLACK_SDK_TEST_GRID_IDP_USERGROUP_ID_2" SLACK_SDK_TEST_GRID_TEAM_ID = "SLACK_SDK_TEST_GRID_TEAM_ID" +SLACK_SDK_TEST_GRID_TEAM_ID_2 = "SLACK_SDK_TEST_GRID_TEAM_ID_2" SLACK_SDK_TEST_GRID_USER_ID = "SLACK_SDK_TEST_GRID_USER_ID" # The following user must be a full member, who is not a primary owner SLACK_SDK_TEST_GRID_USER_ID_ADMIN_AUTH = "SLACK_SDK_TEST_GRID_USER_ID_ADMIN_AUTH" diff --git a/integration_tests/web/test_admin_conversations_bulk.py b/integration_tests/web/test_admin_conversations_bulk.py new file mode 100644 index 000000000..1f99a6187 --- /dev/null +++ b/integration_tests/web/test_admin_conversations_bulk.py @@ -0,0 +1,150 @@ +import asyncio +import logging +import os +import time +import unittest + +from integration_tests.env_variable_names import ( + SLACK_SDK_TEST_GRID_ORG_ADMIN_USER_TOKEN, + SLACK_SDK_TEST_GRID_TEAM_ID_2, + SLACK_SDK_TEST_GRID_TEAM_ID, +) +from integration_tests.helpers import async_test +from slack_sdk.web import WebClient, SlackResponse +from slack_sdk.errors import SlackApiError +from slack_sdk.web.async_client import AsyncWebClient + + +class TestWebClient(unittest.TestCase): + """Runs integration tests with real Slack API""" + + def setUp(self): + self.logger = logging.getLogger(__name__) + self.org_admin_token = os.environ[SLACK_SDK_TEST_GRID_ORG_ADMIN_USER_TOKEN] + self.sync_client: WebClient = WebClient(token=self.org_admin_token) + self.async_client: AsyncWebClient = AsyncWebClient(token=self.org_admin_token) + + self.team_id = os.environ[SLACK_SDK_TEST_GRID_TEAM_ID] + self.team_id_2 = os.environ[SLACK_SDK_TEST_GRID_TEAM_ID_2] + self.channel_name = f"test-channel-{int(round(time.time() * 1000))}" + + def tearDown(self): + pass + + def test_sync_move(self): + client = self.sync_client + + conv_creation = client.admin_conversations_create( + is_private=False, + name=self.channel_name, + team_id=self.team_id, + ) + self.assertIsNotNone(conv_creation) + created_channel_id = conv_creation.data["channel_id"] + + self.assertIsNotNone( + _get_bulk_response( + client.admin_conversations_bulkMove, + channel_ids=[created_channel_id], + target_team_id=self.team_id_2, + ) + ) + + def test_sync(self): + client = self.sync_client + + conv_creation = client.admin_conversations_create( + is_private=False, + name=self.channel_name, + team_id=self.team_id, + ) + self.assertIsNotNone(conv_creation) + created_channel_id = conv_creation.data["channel_id"] + + self.assertIsNotNone( + _get_bulk_response( + client.admin_conversations_bulkArchive, + channel_ids=[created_channel_id], + ) + ) + + self.assertIsNotNone( + _get_bulk_response( + client.admin_conversations_bulkDelete, + channel_ids=[created_channel_id], + ) + ) + + @async_test + async def test_async_move(self): + + client = self.async_client + + conv_creation = await client.admin_conversations_create( + is_private=False, + name=self.channel_name, + team_id=self.team_id, + ) + self.assertIsNotNone(conv_creation) + created_channel_id = conv_creation.data["channel_id"] + + self.assertIsNotNone( + await _get_async_bulk_response( + client.admin_conversations_bulkMove, + channel_ids=[created_channel_id], + target_team_id=self.team_id_2, + ) + ) + + @async_test + async def test_async(self): + + client = self.async_client + + conv_creation = await client.admin_conversations_create( + is_private=False, + name=self.channel_name, + team_id=self.team_id, + ) + self.assertIsNotNone(conv_creation) + created_channel_id = conv_creation.data["channel_id"] + + self.assertIsNotNone( + await _get_async_bulk_response( + client.admin_conversations_bulkArchive, + channel_ids=[created_channel_id], + ) + ) + + self.assertIsNotNone( + await _get_async_bulk_response( + client.admin_conversations_bulkDelete, + channel_ids=[created_channel_id], + ) + ) + + +async def _get_async_bulk_response(method, **kwargs) -> SlackResponse: + while True: + try: + return await method(**kwargs) + except SlackApiError as e: + if not _action_in_progress(e.response): + raise e + await asyncio.sleep(3) + + +def _get_bulk_response(method, **kwargs) -> SlackResponse: + while True: + try: + return method(**kwargs) + except SlackApiError as e: + if not _action_in_progress(e.response): + raise e + time.sleep(3) + + +def _action_in_progress(response: SlackResponse) -> bool: + if response.data.get("error", "") == "action_already_in_progress": + return True + return False diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index 3daeb97c7..2da70c02f 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -803,6 +803,48 @@ async def admin_conversations_setCustomRetention( kwargs.update({"channel_id": channel_id, "duration_days": duration_days}) return await self.api_call("admin.conversations.setCustomRetention", params=kwargs) + async def admin_conversations_bulkArchive( + self, + *, + channel_ids: Union[Sequence[str], str], + **kwargs, + ) -> AsyncSlackResponse: + """Archive public or private channels in bulk. + https://api.slack.com/methods/admin.conversations.bulkArchive + """ + kwargs.update({"channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids}) + return await self.api_call("admin.conversations.bulkArchive", params=kwargs) + + async def admin_conversations_bulkDelete( + self, + *, + channel_ids: Union[Sequence[str], str], + **kwargs, + ) -> AsyncSlackResponse: + """Delete public or private channels in bulk. + https://slack.com/api/admin.conversations.bulkDelete + """ + kwargs.update({"channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids}) + return await self.api_call("admin.conversations.bulkDelete", params=kwargs) + + async def admin_conversations_bulkMove( + self, + *, + channel_ids: Union[Sequence[str], str], + target_team_id: str, + **kwargs, + ) -> AsyncSlackResponse: + """Move public or private channels in bulk. + https://api.slack.com/methods/admin.conversations.bulkMove + """ + kwargs.update( + { + "target_team_id": target_team_id, + "channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids, + } + ) + return await self.api_call("admin.conversations.bulkMove", params=kwargs) + async def admin_emoji_add( self, *, diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index e599aaea9..4d383c37a 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -794,6 +794,48 @@ def admin_conversations_setCustomRetention( kwargs.update({"channel_id": channel_id, "duration_days": duration_days}) return self.api_call("admin.conversations.setCustomRetention", params=kwargs) + def admin_conversations_bulkArchive( + self, + *, + channel_ids: Union[Sequence[str], str], + **kwargs, + ) -> SlackResponse: + """Archive public or private channels in bulk. + https://api.slack.com/methods/admin.conversations.bulkArchive + """ + kwargs.update({"channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids}) + return self.api_call("admin.conversations.bulkArchive", params=kwargs) + + def admin_conversations_bulkDelete( + self, + *, + channel_ids: Union[Sequence[str], str], + **kwargs, + ) -> SlackResponse: + """Delete public or private channels in bulk. + https://slack.com/api/admin.conversations.bulkDelete + """ + kwargs.update({"channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids}) + return self.api_call("admin.conversations.bulkDelete", params=kwargs) + + def admin_conversations_bulkMove( + self, + *, + channel_ids: Union[Sequence[str], str], + target_team_id: str, + **kwargs, + ) -> SlackResponse: + """Move public or private channels in bulk. + https://api.slack.com/methods/admin.conversations.bulkMove + """ + kwargs.update( + { + "target_team_id": target_team_id, + "channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids, + } + ) + return self.api_call("admin.conversations.bulkMove", params=kwargs) + def admin_emoji_add( self, *, diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index e5fc490af..2b9a37d5c 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -805,6 +805,48 @@ def admin_conversations_setCustomRetention( kwargs.update({"channel_id": channel_id, "duration_days": duration_days}) return self.api_call("admin.conversations.setCustomRetention", params=kwargs) + def admin_conversations_bulkArchive( + self, + *, + channel_ids: Union[Sequence[str], str], + **kwargs, + ) -> Union[Future, SlackResponse]: + """Archive public or private channels in bulk. + https://api.slack.com/methods/admin.conversations.bulkArchive + """ + kwargs.update({"channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids}) + return self.api_call("admin.conversations.bulkArchive", params=kwargs) + + def admin_conversations_bulkDelete( + self, + *, + channel_ids: Union[Sequence[str], str], + **kwargs, + ) -> Union[Future, SlackResponse]: + """Delete public or private channels in bulk. + https://slack.com/api/admin.conversations.bulkDelete + """ + kwargs.update({"channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids}) + return self.api_call("admin.conversations.bulkDelete", params=kwargs) + + def admin_conversations_bulkMove( + self, + *, + channel_ids: Union[Sequence[str], str], + target_team_id: str, + **kwargs, + ) -> Union[Future, SlackResponse]: + """Move public or private channels in bulk. + https://api.slack.com/methods/admin.conversations.bulkMove + """ + kwargs.update( + { + "target_team_id": target_team_id, + "channel_ids": ",".join(channel_ids) if isinstance(channel_ids, (list, tuple)) else channel_ids, + } + ) + return self.api_call("admin.conversations.bulkMove", params=kwargs) + def admin_emoji_add( self, *, diff --git a/tests/slack_sdk_async/web/test_web_client_coverage.py b/tests/slack_sdk_async/web/test_web_client_coverage.py index dfcf887f8..5829ffaaf 100644 --- a/tests/slack_sdk_async/web/test_web_client_coverage.py +++ b/tests/slack_sdk_async/web/test_web_client_coverage.py @@ -1,12 +1,12 @@ import os import unittest -import slack_sdk import slack_sdk.errors as e from slack_sdk.models.blocks import DividerBlock from slack_sdk.models.views import View from slack_sdk.web.async_client import AsyncWebClient from slack_sdk.web.legacy_client import LegacyWebClient +from slack_sdk.web import WebClient from tests.slack_sdk_async.helpers import async_test from tests.slack_sdk.web.mock_web_api_server import ( setup_mock_web_api_server, @@ -15,9 +15,9 @@ class TestWebClientCoverage(unittest.TestCase): - # 231 endpoints as of October 2, 2022 + # 234 endpoints as of December 8, 2022 # Can be fetched by running `var methodNames = [].slice.call(document.getElementsByClassName('apiReferenceFilterableList__listItemLink')).map(e => e.href.replace("https://api.slack.com/methods/", ""));console.log(methodNames.toString());console.log(methodNames.length);` on https://api.slack.com/methods - all_api_methods = "admin.analytics.getFile,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.convertToPrivate,admin.conversations.create,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,api.test,apps.connections.open,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,auth.revoke,auth.test,auth.teams.list,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,channels.create,channels.info,channels.invite,channels.mark,groups.create,groups.info,groups.invite,groups.mark,groups.open,im.list,im.mark,im.open,mpim.list,mpim.mark,mpim.open".split( + all_api_methods = "admin.analytics.getFile,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.create,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,api.test,apps.connections.open,apps.uninstall,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,auth.revoke,auth.test,auth.teams.list,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.comments.delete,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,channels.create,channels.info,channels.invite,channels.mark,groups.create,groups.info,groups.invite,groups.mark,groups.open,im.list,im.mark,im.open,mpim.list,mpim.mark,mpim.open".split( "," ) @@ -26,7 +26,7 @@ class TestWebClientCoverage(unittest.TestCase): def setUp(self): setup_mock_web_api_server(self) - self.client = slack_sdk.web.WebClient(token="xoxb-coverage", base_url="http://localhost:8888") + self.client = WebClient(token="xoxb-coverage", base_url="http://localhost:8888") self.legacy_client = LegacyWebClient(token="xoxb-coverage", base_url="http://localhost:8888") self.async_client = AsyncWebClient(token="xoxb-coverage", base_url="http://localhost:8888") @@ -871,6 +871,15 @@ async def run_method(self, method_name, method, async_method): elif method_name == "admin_conversations_setCustomRetention": self.api_methods_to_call.remove(method(channel_id="C123", duration_days=365)["method"]) await async_method(channel_id="C123", duration_days=365) + elif method_name == WebClient.admin_conversations_bulkArchive.__name__: + self.api_methods_to_call.remove(method(channel_ids=["C123", "C234"])["method"]) + await async_method(channel_ids=["C123", "C234"]) + elif method_name == WebClient.admin_conversations_bulkDelete.__name__: + self.api_methods_to_call.remove(method(channel_ids=["C123", "C234"])["method"]) + await async_method(channel_ids=["C123", "C234"]) + elif method_name == WebClient.admin_conversations_bulkMove.__name__: + self.api_methods_to_call.remove(method(channel_ids=["C123", "C234"], target_team_id="T123")["method"]) + await async_method(channel_ids=["C123", "C234"], target_team_id="T123") else: self.api_methods_to_call.remove(method(*{})["method"]) await async_method(*{})