├── .github
├── coverage-badge.svg
├── images
│ ├── blocks-with-header.png
│ ├── section-with-button.png
│ └── simple-text.png
└── workflows
│ ├── coverage.yml
│ ├── develop-branch.yml
│ ├── main-branch.yml
│ ├── pull-request.yml
│ └── test.yml
├── .gitignore
├── LICENSE
├── README.md
├── bin
├── run-tests
└── run-tests.bat
├── composer.json
├── composer.lock
├── config
└── slack.php
├── examples
├── README.md
├── blocks-with-header.md
├── section-with-button.md
└── simple-text.md
├── phpcs.xml
├── phpunit.xml
├── src
├── Channels
│ └── SlackNotificationChannel.php
├── Contracts
│ ├── Channels
│ │ └── SlackNotificationChannelContract.php
│ ├── Notifications
│ │ └── SlackApiNotificationContract.php
│ ├── PaginatorContract.php
│ ├── Services
│ │ ├── SlackCommandHandlerFactoryServiceContract.php
│ │ └── SlackCommandHandlerServiceContract.php
│ ├── SlackApiServiceContract.php
│ ├── SlackCommandHandlerContract.php
│ └── Support
│ │ └── LayoutBuilder
│ │ └── BuilderContract.php
├── Providers
│ └── SlackBotServiceProvider.php
├── Services
│ ├── SlackApiService.php
│ ├── SlackCommandHandlerFactoryService.php
│ └── SlackCommandHandlerService.php
└── Support
│ ├── LayoutBlocks
│ ├── Block.php
│ ├── Blocks
│ │ ├── ActionsBlock.php
│ │ ├── ContextBlock.php
│ │ ├── DividerBlock.php
│ │ ├── FileBlock.php
│ │ ├── HeaderBlock.php
│ │ ├── ImageBlock.php
│ │ ├── InputBlock.php
│ │ └── SectionBlock.php
│ ├── Composition
│ │ ├── ConfirmationDialogObject.php
│ │ ├── DispatchActionConfigurationObject.php
│ │ ├── FilterObject.php
│ │ ├── MarkdownObject.php
│ │ ├── OptionGroupObject.php
│ │ ├── OptionObject.php
│ │ └── TextObject.php
│ ├── CompositionObject.php
│ ├── Element.php
│ ├── Elements
│ │ ├── ButtonElement.php
│ │ ├── CheckboxesElement.php
│ │ ├── DatePickerElement.php
│ │ ├── ImageElement.php
│ │ ├── MultiSelect
│ │ │ ├── MultiSelect.php
│ │ │ ├── MultiSelectConversationElement.php
│ │ │ ├── MultiSelectExternalElement.php
│ │ │ ├── MultiSelectPublicChannelElement.php
│ │ │ ├── MultiSelectStaticElement.php
│ │ │ └── MultiSelectUserElement.php
│ │ ├── OverflowMenuElement.php
│ │ ├── PlainTextInputElement.php
│ │ ├── RadioButtonGroupElement.php
│ │ ├── SelectMenu
│ │ │ ├── SelectMenu.php
│ │ │ ├── SelectMenuConversationElement.php
│ │ │ ├── SelectMenuExternalElement.php
│ │ │ ├── SelectMenuPublicChannelElement.php
│ │ │ ├── SelectMenuStaticElement.php
│ │ │ └── SelectMenuUserElement.php
│ │ └── TimePickerElement.php
│ └── Traits
│ │ ├── Composition
│ │ └── WithFocusOnLoad.php
│ │ ├── Elements
│ │ ├── HasInitialOption.php
│ │ ├── WithConfirmationDialog.php
│ │ └── WithFilter.php
│ │ ├── HasActionId.php
│ │ ├── HasElements.php
│ │ ├── MergesArrays.php
│ │ └── MultiSelectElementCompatibility.php
│ ├── LayoutBuilder
│ └── Builder.php
│ ├── Paginator.php
│ ├── SlackCommandRequest.php
│ └── SlackOptionsBuilder.php
└── tests
├── TestCase.php
├── Traits
├── BasicMultiSelectTests.php
└── BasicSelectMenuTests.php
└── Unit
├── Channels
└── SlackNotificationChannelTest.php
├── Services
├── SlackApiServiceTest.php
├── SlackCommandHandlerFactoryServiceTest.php
└── SlackCommandHandlerServiceTest.php
└── Support
├── LayoutBlocks
├── Blocks
│ ├── ActionsBlockTest.php
│ ├── ContextBlockTest.php
│ ├── DividerBlockTest.php
│ ├── FileBlockTest.php
│ ├── HeaderBlockTest.php
│ ├── ImageBlockTest.php
│ ├── InputBlockTest.php
│ └── SectionBlockTest.php
├── Composition
│ ├── ConfirmationDialogObjectTest.php
│ ├── DispatchActionConfigurationObjectTest.php
│ ├── FilterObjectTest.php
│ ├── MarkdownObjectTest.php
│ ├── OptionGroupObjectTest.php
│ ├── OptionObjectTest.php
│ └── TextObjectTest.php
└── Elements
│ ├── ButtonElementTest.php
│ ├── CheckboxesElementTest.php
│ ├── DatePickerElementTest.php
│ ├── ImageElementTest.php
│ ├── MultiSelect
│ ├── MultiSelectConversationElementTest.php
│ ├── MultiSelectExternalElementTest.php
│ ├── MultiSelectPublicChannelElementTest.php
│ ├── MultiSelectStaticElementTest.php
│ └── MultiSelectUserElementTest.php
│ ├── OverflowMenuElementTest.php
│ ├── PlainTextInputElementTest.php
│ ├── RadioButtonGroupElementTest.php
│ ├── SelectMenu
│ ├── SelectMenuConversationElementTest.php
│ ├── SelectMenuExternalElementTest.php
│ ├── SelectMenuPublicChannelElementTest.php
│ ├── SelectMenuStaticElementTest.php
│ └── SelectMenuUserElementTest.php
│ └── TimePickerElementTest.php
├── LayoutBuilder
└── BuilderTest.php
├── PaginatorTest.php
└── SlackOptionsBuilderTest.php
/.github/coverage-badge.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/images/blocks-with-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nwilging/laravel-slack-bot/046f46e4cd896de75ec62b1b789c6de1962e3e9a/.github/images/blocks-with-header.png
--------------------------------------------------------------------------------
/.github/images/section-with-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nwilging/laravel-slack-bot/046f46e4cd896de75ec62b1b789c6de1962e3e9a/.github/images/section-with-button.png
--------------------------------------------------------------------------------
/.github/images/simple-text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nwilging/laravel-slack-bot/046f46e4cd896de75ec62b1b789c6de1962e3e9a/.github/images/simple-text.png
--------------------------------------------------------------------------------
/.github/workflows/coverage.yml:
--------------------------------------------------------------------------------
1 | name: Coverage
2 | on:
3 | workflow_call:
4 |
5 | jobs:
6 | run-coverage:
7 | name: Run Tests with Coverage
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout code
11 | uses: actions/checkout@v2
12 | with:
13 | fetch-depth: 0
14 | - name: Composer
15 | uses: php-actions/composer@v5
16 | with:
17 | php_extensions: xdebug
18 | - name: Run Tests
19 | env:
20 | XDEBUG_MODE: coverage
21 | run: vendor/bin/phpunit
22 | - name: Commit Coverage
23 | uses: timkrase/phpunit-coverage-badge@v1.2.0
24 | with:
25 | report: clover.xml
26 | report_type: clover
27 | coverage_badge_path: ./.github/coverage-badge.svg
28 | repo_token: ${{ secrets.GH_ACCESS_TOKEN }}
29 | push_badge: true
30 |
--------------------------------------------------------------------------------
/.github/workflows/develop-branch.yml:
--------------------------------------------------------------------------------
1 | name: Develop Branch
2 | on:
3 | push:
4 | branches:
5 | - develop
6 |
7 | jobs:
8 | run-tests:
9 | name: Tests
10 | uses: ./.github/workflows/test.yml
11 | run-coverage:
12 | name: Coverage
13 | uses: ./.github/workflows/coverage.yml
14 |
--------------------------------------------------------------------------------
/.github/workflows/main-branch.yml:
--------------------------------------------------------------------------------
1 | name: Main Branch
2 | on:
3 | push:
4 | branches:
5 | - main
6 |
7 | jobs:
8 | run-tests:
9 | name: Tests
10 | uses: ./.github/workflows/test.yml
11 | run-coverage:
12 | name: Coverage
13 | uses: ./.github/workflows/coverage.yml
14 |
--------------------------------------------------------------------------------
/.github/workflows/pull-request.yml:
--------------------------------------------------------------------------------
1 | name: Pull Request
2 | on:
3 | pull_request:
4 |
5 | jobs:
6 | test:
7 | name: Run Tests
8 | uses: ./.github/workflows/test.yml
9 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | workflow_call:
4 |
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | php: ["7.4", "8.0", "8.1"]
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 | - name: Composer
17 | uses: php-actions/composer@v5
18 | with:
19 | php_version: ${{ matrix.php }}
20 | - name: Run Tests
21 | run: vendor/bin/phpunit --no-coverage
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | .env
3 | .phpunit.result.cache
4 | tests/html-coverage
5 | clover.xml
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 nwilging
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bin/run-tests:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | vendor/bin/phpunit
4 |
--------------------------------------------------------------------------------
/bin/run-tests.bat:
--------------------------------------------------------------------------------
1 | vendor\bin\phpunit.bat
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nwilging/laravel-slack-bot",
3 | "description": "A robust Slack messaging integration for Laravel",
4 | "type": "library",
5 | "license": "MIT",
6 | "autoload": {
7 | "psr-4": {
8 | "Nwilging\\LaravelSlackBot\\": "src/",
9 | "Nwilging\\LaravelSlackBotTests\\": "tests/"
10 | }
11 | },
12 | "authors": [
13 | {
14 | "name": "Nicole Wilging",
15 | "email": "nicole@wilging.com"
16 | }
17 | ],
18 | "require": {
19 | "php": ">=7.4",
20 | "laravel/framework": ">=8",
21 | "guzzlehttp/guzzle": "^7.4"
22 | },
23 | "extra": {
24 | "laravel": {
25 | "providers": [
26 | "Nwilging\\LaravelSlackBot\\Providers\\SlackBotServiceProvider"
27 | ]
28 | }
29 | },
30 | "require-dev": {
31 | "phpunit/phpunit": "^9.5",
32 | "mockery/mockery": "^1.5",
33 | "squizlabs/php_codesniffer": "^3.6",
34 | "dealerinspire/laravel-coding-standard": "^2.0"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/config/slack.php:
--------------------------------------------------------------------------------
1 | env('SLACK_API_BOT_TOKEN'),
6 | 'api_url' => env('SLACK_API_URL', 'https://slack.com/api'),
7 | 'driver_name' => env('SLACK_API_DRIVER_NAME', 'slack'),
8 | 'signing_secret' => env('SLACK_API_SIGNING_SECRET'),
9 | ];
10 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | Examples of different types of messages and how to configure them in your
4 | Laravel notification.
5 |
6 | ---
7 |
8 | ### Simple Text
9 |
10 | 
11 |
12 | [Example](./simple-text.md)
13 |
14 | ### Blocks Message with Header
15 |
16 | 
17 |
18 | [Example](./blocks-with-header.md)
19 |
20 | ### Section with Button Accessory
21 |
22 | 
23 |
24 | [Example](./section-with-button.md)
25 |
--------------------------------------------------------------------------------
/examples/blocks-with-header.md:
--------------------------------------------------------------------------------
1 | # Blocks Message with Header
2 |
3 | 
4 |
5 | Code:
6 | ```phpt
7 | username('My Bot')
37 | ->iconEmoji(':smile:');
38 |
39 | $layoutBuilder = new Builder();
40 |
41 | $sectionBlock = new SectionBlock();
42 | $sectionBlock->withFields([
43 | $layoutBuilder->withPlainText('Some text in a section'),
44 | $layoutBuilder->withPlainText('More text!'),
45 | ]);
46 |
47 | $layoutBuilder
48 | ->header('Test Message')
49 | ->divider()
50 | ->addBlock($sectionBlock);
51 |
52 | return [
53 | 'contentType' => 'blocks',
54 | 'blocks' => $layoutBuilder->getBlocks(),
55 | 'channelId' => 'general',
56 | 'options' => $options->toArray(),
57 | ];
58 | }
59 | }
60 | ```
--------------------------------------------------------------------------------
/examples/section-with-button.md:
--------------------------------------------------------------------------------
1 | # Section with Button Accessory
2 |
3 | 
4 |
5 | Code:
6 | ```phpt
7 | username('My Bot')
38 | ->iconEmoji(':smile:');
39 |
40 | $layoutBuilder = new Builder();
41 |
42 | $sectionBlock = new SectionBlock();
43 | $sectionBlock->withFields([
44 | $layoutBuilder->withPlainText('Some text in a section'),
45 | ]);
46 |
47 | $accessoryButton = new ButtonElement($layoutBuilder->withPlainText('A Button'), 'actionId');
48 | $accessoryButton->primary();
49 |
50 | $sectionBlock->withAccessory($accessoryButton);
51 |
52 | $layoutBuilder
53 | ->header('Test Message')
54 | ->divider()
55 | ->addBlock($sectionBlock);
56 |
57 | return [
58 | 'contentType' => 'blocks',
59 | 'blocks' => $layoutBuilder->getBlocks(),
60 | 'channelId' => 'general',
61 | 'options' => $options->toArray(),
62 | ];
63 | }
64 | }
65 | ```
66 |
--------------------------------------------------------------------------------
/examples/simple-text.md:
--------------------------------------------------------------------------------
1 | # Simple Text Message
2 |
3 | 
4 |
5 | Code:
6 | ```phpt
7 | username('My Bot')
35 | ->iconEmoji(':smile:');
36 |
37 | return [
38 | 'contentType' => 'text',
39 | 'message' => 'This is a test message!',
40 | 'channelId' => 'general',
41 | 'options' => $options->toArray(),
42 | ];
43 | }
44 | }
45 | ```
46 |
--------------------------------------------------------------------------------
/phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The coding standard for PHP_CodeSniffer itself.
4 |
5 | src
6 | tests
7 |
8 | */src/Standards/*/Tests/*\.(inc|css|js)$
9 | */tests/Core/*/*\.(inc|css|js)$
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | ./tests/Unit
10 |
11 |
12 |
13 |
14 | ./src
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Channels/SlackNotificationChannel.php:
--------------------------------------------------------------------------------
1 | slackApiService = $slackApiService;
19 | }
20 |
21 | /**
22 | * @param Notifiable $notifiable
23 | * @param SlackApiNotificationContract $notification
24 | * @return void
25 | */
26 | public function send($notifiable, SlackApiNotificationContract $notification): void
27 | {
28 | $slackNotificationArray = $notification->toSlackArray($notifiable);
29 | switch ($slackNotificationArray['contentType']) {
30 | case 'text':
31 | $this->handleTextMessage($slackNotificationArray);
32 | break;
33 | case 'blocks':
34 | $this->handleBlocksMessage($slackNotificationArray);
35 | break;
36 | default:
37 | throw new \InvalidArgumentException(sprintf('%s is not a valid content type. Use `blocks` or `text`', $slackNotificationArray['contentType']));
38 | }
39 | }
40 |
41 | protected function handleBlocksMessage(array $slackNotificationArray): void
42 | {
43 | $blocks = $slackNotificationArray['blocks'];
44 | $options = $slackNotificationArray['options'] ?? [];
45 |
46 | $this->slackApiService->sendBlocksMessage($slackNotificationArray['channelId'], $blocks, $options);
47 | }
48 |
49 | protected function handleTextMessage(array $slackNotificationArray): void
50 | {
51 | $message = $slackNotificationArray['message'];
52 | $options = $slackNotificationArray['options'] ?? [];
53 |
54 | $this->slackApiService->sendTextMessage($slackNotificationArray['channelId'], $message, $options);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Contracts/Channels/SlackNotificationChannelContract.php:
--------------------------------------------------------------------------------
1 | mergeConfigFrom(__DIR__ . '/../../config/slack.php', 'slack');
28 | }
29 |
30 | public function register()
31 | {
32 | Notification::resolved(function (ChannelManager $channelManager): void {
33 | $driverName = $this->app->make(Config::class)->get('slack.driver_name');
34 | $channelManager->extend($driverName, function (): SlackNotificationChannelContract {
35 | return $this->app->make(SlackNotificationChannelContract::class);
36 | });
37 | });
38 |
39 | $this->app->bind(ClientInterface::class, Client::class);
40 | $this->app->bind(SlackApiServiceContract::class, SlackApiService::class);
41 |
42 | $this->app->when(SlackApiService::class)->needs('$botToken')->give(function (): string {
43 | return $this->app->make(Config::class)->get('slack.bot_token');
44 | });
45 |
46 | $this->app->when(SlackApiService::class)->needs('$apiUrl')->give(function (): string {
47 | return $this->app->make(Config::class)->get('slack.api_url');
48 | });
49 |
50 | $this->app->bind(BuilderContract::class, Builder::class);
51 |
52 | $this->app->bind(SlackNotificationChannelContract::class, SlackNotificationChannel::class);
53 |
54 | $this->app->singleton(SlackCommandHandlerFactoryServiceContract::class, SlackCommandHandlerFactoryService::class);
55 |
56 | $this->app->bind(SlackCommandHandlerServiceContract::class, SlackCommandHandlerService::class);
57 | $this->app->when(SlackCommandHandlerService::class)->needs('$signingSecret')->give(function (): string {
58 | return $this->app->make(Config::class)->get('slack.signing_secret');
59 | });
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Services/SlackCommandHandlerFactoryService.php:
--------------------------------------------------------------------------------
1 | laravel = $laravel;
19 | }
20 |
21 | public function register(string $slackCommandHandlerClass, string $slackSlashCommand): void
22 | {
23 | $this->commandHandlers[$slackSlashCommand] = $slackCommandHandlerClass;
24 | }
25 |
26 | public function getHandler(string $slackSlashCommand): SlackCommandHandlerContract
27 | {
28 | if (!array_key_exists($slackSlashCommand, $this->commandHandlers)) {
29 | throw new \InvalidArgumentException(sprintf('No handler found for command %s', $slackSlashCommand));
30 | }
31 |
32 | return $this->laravel->make($this->commandHandlers[$slackSlashCommand]);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Services/SlackCommandHandlerService.php:
--------------------------------------------------------------------------------
1 | handlerFactory = $handlerFactory;
22 | $this->signingSecret = $signingSecret;
23 | }
24 |
25 | public function handle(Request $request): Response
26 | {
27 | $data = ($request->isJson()) ? $request->json()->all() : $request->toArray();
28 | $this->validateSignature($request, $data);
29 |
30 | $command = $this->generateCommandRequest($data);
31 |
32 | $handler = $this->handlerFactory->getHandler($command->command);
33 | return $handler->handle($command);
34 | }
35 |
36 | protected function generateCommandRequest(array $data): SlackCommandRequest
37 | {
38 | $request = new SlackCommandRequest();
39 |
40 | $request->token = $data['token'];
41 | $request->teamId = $data['team_id'];
42 | $request->teamDomain = $data['team_domain'];
43 | $request->channelId = $data['channel_id'];
44 | $request->channelName = $data['channel_name'];
45 | $request->userId = $data['user_id'];
46 | $request->username = $data['user_name'];
47 | $request->command = ltrim($data['command'], '/');
48 | $request->commandArgs = explode(' ', $data['text'] ?? '');
49 | $request->apiAppId = $data['api_app_id'];
50 | $request->isEnterpriseInstall = ($data['is_enterprise_install'] === 'true');
51 | $request->responseUrl = $data['response_url'];
52 | $request->triggerId = $data['trigger_id'];
53 |
54 | return $request;
55 | }
56 |
57 | protected function validateSignature(Request $request, array $data): void
58 | {
59 | $timestamp = $request->header('X-Slack-Request-Timestamp');
60 | $slackSignature = $request->header('X-Slack-Signature');
61 | if (!$timestamp || !$slackSignature) {
62 | throw new UnauthorizedException();
63 | }
64 |
65 | $formattedRequestBody = implode('&', array_map(function (string $key) use ($data): string {
66 | return sprintf('%s=%s', urlencode($key), urlencode($data[$key] ?? ''));
67 | }, array_keys($data)));
68 |
69 | $signatureBase = sprintf('v0:%s:%s', $timestamp, $formattedRequestBody);
70 | $signature = sprintf('v0=%s', hash_hmac('sha256', $signatureBase, $this->signingSecret));
71 |
72 | if (!hash_equals($signature, $slackSignature)) {
73 | throw new UnauthorizedException();
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Block.php:
--------------------------------------------------------------------------------
1 | blockId = $blockId;
29 | }
30 |
31 | /**
32 | * The Slack-API compatible type of this block
33 | *
34 | * @return string
35 | */
36 | public abstract function getType(): string;
37 |
38 | /**
39 | * The Slack-API compatible array for this block
40 | *
41 | * @return array
42 | */
43 | public function toArray(): array
44 | {
45 | return array_filter([
46 | 'type' => $this->getType(),
47 | 'block_id' => $this->blockId,
48 | ]);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/ActionsBlock.php:
--------------------------------------------------------------------------------
1 | elements = $elements;
22 | }
23 |
24 | public function getType(): string
25 | {
26 | return static::TYPE_ACTIONS;
27 | }
28 |
29 | public function toArray(): array
30 | {
31 | return $this->toMergedArray([
32 | 'elements' => $this->elementsArray(),
33 | 'block_id' => $this->blockId,
34 | ]);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/ContextBlock.php:
--------------------------------------------------------------------------------
1 | textObjects = $textObjects;
35 | $this->elements = $elements;
36 | }
37 |
38 | public function getType(): string
39 | {
40 | return static::TYPE_CONTEXT;
41 | }
42 |
43 | public function toArray(): array
44 | {
45 | return $this->toMergedArray([
46 | 'elements' => array_merge($this->elementsArray(), array_map(function (TextObject $textObject): array {
47 | return $textObject->toArray();
48 | }, $this->textObjects)),
49 | 'block_id' => $this->blockId,
50 | ]);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/DividerBlock.php:
--------------------------------------------------------------------------------
1 | externalId = $externalId;
23 | }
24 |
25 | public function getType(): string
26 | {
27 | return static::TYPE_FILE;
28 | }
29 |
30 | public function toArray(): array
31 | {
32 | return $this->toMergedArray([
33 | 'external_id' => $this->externalId,
34 | /**
35 | * At the moment, source will always be remote for a remote file.
36 | * @see https://api.slack.com/reference/block-kit/blocks#file_fields
37 | */
38 | 'source' => 'remote',
39 | ]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/HeaderBlock.php:
--------------------------------------------------------------------------------
1 | textObject = $textObject;
24 | }
25 |
26 | public function getType(): string
27 | {
28 | return static::TYPE_HEADER;
29 | }
30 |
31 | public function toArray(): array
32 | {
33 | return $this->toMergedArray([
34 | 'text' => $this->textObject->toArray(),
35 | ]);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/ImageBlock.php:
--------------------------------------------------------------------------------
1 | imageUrl = $imageUrl;
29 | $this->altText = $altText;
30 | }
31 |
32 | /**
33 | * An optional title for the image. Maximum length for the text in this field is 2000 characters.
34 | *
35 | * @see https://api.slack.com/reference/block-kit/blocks#image_fields
36 | *
37 | * @param TextObject $textObject
38 | * @return $this
39 | */
40 | public function withTitle(TextObject $textObject): self
41 | {
42 | $this->title = $textObject;
43 | return $this;
44 | }
45 |
46 | public function getType(): string
47 | {
48 | return static::TYPE_IMAGE;
49 | }
50 |
51 | public function toArray(): array
52 | {
53 | return $this->toMergedArray([
54 | 'image_url' => $this->imageUrl,
55 | 'alt_text' => $this->altText,
56 | 'title' => ($this->title) ? $this->title->toArray() : null,
57 | ]);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/InputBlock.php:
--------------------------------------------------------------------------------
1 | label = $label;
34 | $this->element = $element;
35 | }
36 |
37 | public function dispatchAction(bool $dispatchAction = true): self
38 | {
39 | $this->dispatchAction = $dispatchAction;
40 | return $this;
41 | }
42 |
43 | public function withHint(TextObject $text): self
44 | {
45 | $this->hint = $text;
46 | return $this;
47 | }
48 |
49 | public function optional(bool $optional = true): self
50 | {
51 | $this->optional = $optional;
52 | return $this;
53 | }
54 |
55 | public function getType(): string
56 | {
57 | return static::TYPE_INPUT;
58 | }
59 |
60 | public function toArray(): array
61 | {
62 | return $this->toMergedArray([
63 | 'label' => $this->label->toArray(),
64 | 'element' => $this->element->toArray(),
65 | 'hint' => ($this->hint) ? $this->hint->toArray() : null,
66 | 'dispatch_action' => $this->dispatchAction,
67 | 'optional' => $this->optional,
68 | ]);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Blocks/SectionBlock.php:
--------------------------------------------------------------------------------
1 | text = $text;
45 | return $this;
46 | }
47 |
48 | /**
49 | * Required if no text is provided. An array of text objects.
50 | * Any text objects included with fields will be rendered in a compact format that allows for 2 columns of
51 | * side-by-side text. Maximum number of items is 10. Maximum length for the text in each item is 2000 characters.
52 | *
53 | * @see https://api.slack.com/reference/block-kit/blocks#section_fields
54 | *
55 | * @param TextObject[] $fields
56 | * @return $this
57 | */
58 | public function withFields(array $fields): self
59 | {
60 | $this->fields = $fields;
61 | return $this;
62 | }
63 |
64 | /**
65 | * A Block Element to add as an accessory to this section
66 | *
67 | * @see https://api.slack.com/reference/block-kit/blocks#section_fields
68 | *
69 | * @param Element $accessory
70 | * @return $this
71 | */
72 | public function withAccessory(Element $accessory): self
73 | {
74 | $this->accessory = $accessory;
75 | return $this;
76 | }
77 |
78 | public function getType(): string
79 | {
80 | return static::TYPE_SECTION;
81 | }
82 |
83 | public function toArray(): array
84 | {
85 | $data = [
86 | 'accessory' => ($this->accessory) ? $this->accessory->toArray() : null,
87 | ];
88 |
89 | if (!$this->fields) {
90 | $data['text'] = $this->text->toArray();
91 | } else {
92 | $data['fields'] = array_map(function (TextObject $textObject): array {
93 | return $textObject->toArray();
94 | }, $this->fields);
95 | }
96 |
97 | return $this->toMergedArray($data);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Composition/ConfirmationDialogObject.php:
--------------------------------------------------------------------------------
1 | title = $title;
30 | $this->text = $text;
31 | $this->confirmText = $confirmText;
32 | $this->denyText = $denyText;
33 | }
34 |
35 | /**
36 | * Defines the color scheme applied to the confirm button.
37 | * A value of primary will display the button with a green background on desktop, or blue text on mobile.
38 | *
39 | * @see https://api.slack.com/reference/block-kit/composition-objects#confirm__fields
40 | *
41 | * @return $this
42 | */
43 | public function confirmButtonPrimary(): self
44 | {
45 | $this->confirmButtonStyle = 'primary';
46 | return $this;
47 | }
48 |
49 | /**
50 | * Defines the color scheme applied to the confirm button.
51 | * A value of danger will display the button with a red background on desktop, or red text on mobile.
52 | *
53 | * @see https://api.slack.com/reference/block-kit/composition-objects#confirm__fields
54 | *
55 | * @return $this
56 | */
57 | public function confirmButtonDanger(): self
58 | {
59 | $this->confirmButtonStyle = 'danger';
60 | return $this;
61 | }
62 |
63 | public function toArray(): array
64 | {
65 | return $this->toMergedArray([
66 | 'title' => $this->title->toArray(),
67 | 'text' => $this->text->toArray(),
68 | 'confirm' => $this->confirmText->toArray(),
69 | 'deny' => $this->denyText->toArray(),
70 | 'style' => $this->confirmButtonStyle,
71 | ]);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Composition/DispatchActionConfigurationObject.php:
--------------------------------------------------------------------------------
1 | triggerActionsOn[] = 'on_enter_pressed';
33 | return $this;
34 | }
35 |
36 | /**
37 | * Payload is dispatched when a character is entered (or removed) in the input.
38 | *
39 | * @see https://api.slack.com/reference/block-kit/composition-objects#dispatch_action_config__fields
40 | *
41 | * @return $this
42 | */
43 | public function onCharacterEntered(): self
44 | {
45 | $this->triggerActionsOn[] = 'on_character_entered';
46 | return $this;
47 | }
48 |
49 | public function toArray(): array
50 | {
51 | return $this->toMergedArray([
52 | 'trigger_actions_on' => !empty($this->triggerActionsOn) ? $this->triggerActionsOn : null,
53 | ]);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Composition/FilterObject.php:
--------------------------------------------------------------------------------
1 | include = $include;
39 | return $this;
40 | }
41 |
42 | /**
43 | * Indicates whether to exclude external shared channels from conversation lists.
44 | *
45 | * @see https://api.slack.com/reference/block-kit/composition-objects#filter_conversations__fields
46 | *
47 | * @param bool $exclude
48 | * @return $this
49 | */
50 | public function excludeExternalSharedChannels(bool $exclude = true): self
51 | {
52 | $this->excludeExternalSharedChannels = $exclude;
53 | return $this;
54 | }
55 |
56 | /**
57 | * Indicates whether to exclude bot users from conversation lists.
58 | *
59 | * @see https://api.slack.com/reference/block-kit/composition-objects#filter_conversations__fields
60 | *
61 | * @param bool $exclude
62 | * @return $this
63 | */
64 | public function excludeBotUsers(bool $exclude = true): self
65 | {
66 | $this->excludeBotUsers = $exclude;
67 | return $this;
68 | }
69 |
70 | public function toArray(): array
71 | {
72 | return $this->toMergedArray([
73 | 'include' => $this->include,
74 | 'exclude_external_shared_channels' => $this->excludeExternalSharedChannels,
75 | 'exclude_bot_users' => $this->excludeBotUsers,
76 | ]);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Composition/MarkdownObject.php:
--------------------------------------------------------------------------------
1 | label = $label;
31 | $this->options = $options;
32 | }
33 |
34 | public function toArray(): array
35 | {
36 | return $this->toMergedArray([
37 | 'label' => $this->label->toArray(),
38 | 'options' => array_map(function (OptionObject $option): array {
39 | return $option->toArray();
40 | }, $this->options),
41 | ]);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Composition/OptionObject.php:
--------------------------------------------------------------------------------
1 | text = $text;
28 | $this->value = $value;
29 | }
30 |
31 | /**
32 | * A plain_text only text object that defines a line of descriptive text shown below the text field beside the
33 | * radio button. Maximum length for the text object within this field is 75 characters.
34 | *
35 | * @see https://api.slack.com/reference/block-kit/composition-objects#option__fields
36 | *
37 | * @param TextObject $textObject
38 | * @return $this
39 | */
40 | public function withDescription(TextObject $textObject): self
41 | {
42 | $this->description = $textObject;
43 | return $this;
44 | }
45 |
46 | /**
47 | * A URL to load in the user's browser when the option is clicked.
48 | * The url attribute is only available in overflow menus. Maximum length for this field is 3000 characters.
49 | *
50 | * @see https://api.slack.com/reference/block-kit/composition-objects#option__fields
51 | *
52 | * @param string $url
53 | * @return $this
54 | */
55 | public function withUrl(string $url): self
56 | {
57 | $this->url = $url;
58 | return $this;
59 | }
60 |
61 | public function toArray(): array
62 | {
63 | return $this->toMergedArray([
64 | 'text' => $this->text,
65 | 'value' => $this->value,
66 | 'description' => ($this->description) ? $this->description->toArray() : null,
67 | 'url' => $this->url,
68 | ]);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Composition/TextObject.php:
--------------------------------------------------------------------------------
1 | text = $text;
28 | }
29 |
30 | /**
31 | * Indicates whether emojis in a text field should be escaped into the colon emoji format.
32 | * This field is only usable when type is plain_text.
33 | *
34 | * @see https://api.slack.com/reference/block-kit/composition-objects#text__fields
35 | *
36 | * @return $this
37 | */
38 | public function escapeEmojis(): self
39 | {
40 | $this->emoji = true;
41 | return $this;
42 | }
43 |
44 | /**
45 | * When set to false (as is default) URLs will be auto-converted into links, conversation names will be link-ified,
46 | * and certain mentions will be automatically parsed. Using a value of true will skip any preprocessing of this
47 | * nature, although you can still include manual parsing strings.
48 | * This field is only usable when type is mrkdwn.
49 | *
50 | * @see https://api.slack.com/reference/block-kit/composition-objects#text__fields
51 | *
52 | * @return $this
53 | */
54 | public function verbatim(): self
55 | {
56 | if ($this->type !== 'mrkdwn') return $this;
57 |
58 | $this->verbatim = true;
59 | return $this;
60 | }
61 |
62 | public function toArray(): array
63 | {
64 | return $this->toMergedArray([
65 | 'type' => $this->type,
66 | 'text' => $this->text,
67 | 'emoji' => $this->emoji,
68 | 'verbatim' => $this->verbatim,
69 | ]);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/CompositionObject.php:
--------------------------------------------------------------------------------
1 | $this->getType(),
56 | ];
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/ButtonElement.php:
--------------------------------------------------------------------------------
1 | text = $text;
34 | $this->actionId = $actionId;
35 | }
36 |
37 | /**
38 | * Sets the button style to `primary`
39 | * @see https://api.slack.com/reference/block-kit/block-elements#button__fields
40 | *
41 | * @return $this
42 | */
43 | public function primary(): self
44 | {
45 | $this->style = 'primary';
46 | return $this;
47 | }
48 |
49 | /**
50 | * Sets the button style to `danger`
51 | *
52 | * @see https://api.slack.com/reference/block-kit/block-elements#button__fields
53 | *
54 | * @return $this
55 | */
56 | public function danger(): self
57 | {
58 | $this->style = 'danger';
59 | return $this;
60 | }
61 |
62 | public function getType(): string
63 | {
64 | return static::TYPE_BUTTON;
65 | }
66 |
67 | /**
68 | * A URL to load in the user's browser when the button is clicked.
69 | * Maximum length for this field is 3000 characters.
70 | *
71 | * @see https://api.slack.com/reference/block-kit/block-elements#button__fields
72 | *
73 | * @return $this
74 | */
75 | public function withUrl(string $url, ?string $value = null): self
76 | {
77 | $this->url = $url;
78 | $this->value = $value;
79 | return $this;
80 | }
81 |
82 | /**
83 | * A label for longer descriptive text about a button element.
84 | * This label will be read out by screen readers instead of the button text object.
85 | * Maximum length for this field is 75 characters.
86 | *
87 | * @see https://api.slack.com/reference/block-kit/block-elements#button__fields
88 | *
89 | * @return $this
90 | */
91 | public function withAccessibilityLabel(string $accessibilityLabel): self
92 | {
93 | $this->accessibilityLabel = $accessibilityLabel;
94 | return $this;
95 | }
96 |
97 | public function compatibleWith(): array
98 | {
99 | return [
100 | Block::TYPE_ACTIONS,
101 | Block::TYPE_SECTION,
102 | ];
103 | }
104 |
105 | public function toArray(): array
106 | {
107 | return $this->toMergedArray($this->mergeConfirmationDialog([
108 | 'text' => $this->text->toArray(),
109 | 'action_id' => $this->actionId,
110 | 'style' => $this->style,
111 | 'url' => $this->url,
112 | 'value' => $this->value,
113 | 'accessibility_label' => $this->accessibilityLabel,
114 | ]));
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/CheckboxesElement.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
40 | $this->options = $options;
41 | }
42 |
43 | /**
44 | * An array of option objects that exactly matches one or more of the options within options.
45 | * These options will be selected when the checkbox group initially loads.
46 | *
47 | * @see https://api.slack.com/reference/block-kit/block-elements#checkboxes__fields
48 | *
49 | * @param OptionObject[] $options
50 | * @return $this
51 | */
52 | public function withInitialOptions(array $options): self
53 | {
54 | $this->initialOptions = $options;
55 | return $this;
56 | }
57 |
58 | public function getType(): string
59 | {
60 | return static::TYPE_CHECKBOXES;
61 | }
62 |
63 | public function compatibleWith(): array
64 | {
65 | return [
66 | Block::TYPE_ACTIONS,
67 | Block::TYPE_SECTION,
68 | ];
69 | }
70 |
71 | public function toArray(): array
72 | {
73 | return $this->toMergedArray($this->mergeConfirmationDialog([
74 | 'action_id' => $this->actionId,
75 | 'options' => array_map(function (OptionObject $option): array {
76 | return $option->toArray();
77 | }, $this->options),
78 | 'initial_options' => ($this->initialOptions) ? array_map(function (OptionObject $option): array {
79 | return $option->toArray();
80 | }, $this->initialOptions) : null,
81 | 'focus_on_load' => $this->focusOnLoad,
82 | ]));
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/DatePickerElement.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
36 | $this->initialDate = $initialDate;
37 | }
38 |
39 | /**
40 | * A plain_text only text object that defines the placeholder text shown on the datepicker.
41 | * Maximum length for the text in this field is 150 characters.
42 | *
43 | * @see https://api.slack.com/reference/block-kit/block-elements#datepicker__fields
44 | *
45 | * @param TextObject $textObject
46 | * @return $this
47 | */
48 | public function withPlaceholder(TextObject $textObject): self
49 | {
50 | $this->placeholder = $textObject;
51 | return $this;
52 | }
53 |
54 | public function getType(): string
55 | {
56 | return static::TYPE_DATEPICKER;
57 | }
58 |
59 | public function compatibleWith(): array
60 | {
61 | return [
62 | Block::TYPE_SECTION,
63 | Block::TYPE_ACTIONS,
64 | ];
65 | }
66 |
67 | public function toArray(): array
68 | {
69 | return $this->toMergedArray($this->mergeConfirmationDialog([
70 | 'action_id' => $this->actionId,
71 | 'initial_date' => $this->initialDate,
72 | 'placeholder' => ($this->placeholder) ? $this->placeholder->toArray() : null,
73 | 'focus_on_load' => $this->focusOnLoad,
74 | ]));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/ImageElement.php:
--------------------------------------------------------------------------------
1 | imageUrl = $imageUrl;
25 | $this->altText = $altText;
26 | }
27 |
28 | public function getType(): string
29 | {
30 | return Element::TYPE_IMAGE;
31 | }
32 |
33 | public function compatibleWith(): array
34 | {
35 | return [
36 | Block::TYPE_SECTION,
37 | Block::TYPE_CONTEXT,
38 | ];
39 | }
40 |
41 | public function toArray(): array
42 | {
43 | return $this->toMergedArray([
44 | 'image_url' => $this->imageUrl,
45 | 'alt_text' => $this->altText,
46 | ]);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/MultiSelect/MultiSelect.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
26 | $this->placeholder = $placeholder;
27 | }
28 |
29 | public function maxSelectedItems(int $maxSelectedItems): self
30 | {
31 | $this->maxSelectedItems = $maxSelectedItems;
32 | return $this;
33 | }
34 |
35 | public function toArray(): array
36 | {
37 | return $this->mergeConfirmationDialog([
38 | 'type' => $this->getType(),
39 | 'action_id' => $this->actionId,
40 | 'placeholder' => $this->placeholder->toArray(),
41 | 'focus_on_load' => $this->focusOnLoad,
42 | 'max_selected_items' => $this->maxSelectedItems,
43 | ]);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectConversationElement.php:
--------------------------------------------------------------------------------
1 | defaultToCurrent = $defaultToCurrent;
40 | return $this;
41 | }
42 |
43 | /**
44 | * An array of one or more IDs of any valid conversations to be pre-selected when the menu loads.
45 | * If defaultToCurrent is also supplied, initial conversations will be ignored.
46 | *
47 | * @see https://api.slack.com/reference/block-kit/block-elements#conversation_multi_select__fields
48 | *
49 | * @param string[] $initialConversations
50 | * @return $this
51 | */
52 | public function withInitialConversations(array $initialConversations): self
53 | {
54 | $this->initialConversations = $initialConversations;
55 | return $this;
56 | }
57 |
58 | public function getType(): string
59 | {
60 | return static::TYPE_MULTI_SELECT_CONVERSATIONS;
61 | }
62 |
63 | public function compatibleWith(): array
64 | {
65 | return [
66 | Block::TYPE_SECTION,
67 | ];
68 | }
69 |
70 | public function toArray(): array
71 | {
72 | return $this->toMergedArray($this->mergeFilter([
73 | 'initial_conversations' => $this->initialConversations,
74 | 'default_to_current_conversation' => $this->defaultToCurrent,
75 | ]));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectExternalElement.php:
--------------------------------------------------------------------------------
1 | minQueryLength = $minQueryLength;
42 | return $this;
43 | }
44 |
45 | /**
46 | * An array of options that exactly match one or more of the options within options.
47 | * These options will be selected when the menu initially loads.
48 | *
49 | * @see https://api.slack.com/reference/block-kit/block-elements#external_multi_select__fields
50 | *
51 | * @param OptionObject[] $options
52 | * @return $this
53 | */
54 | public function withInitialOptions(array $options): self
55 | {
56 | $this->initialOptions = $options;
57 | return $this;
58 | }
59 |
60 | public function getType(): string
61 | {
62 | return Element::TYPE_MULTI_SELECT_EXTERNAL;
63 | }
64 |
65 | public function compatibleWith(): array
66 | {
67 | return [
68 | Block::TYPE_SECTION,
69 | ];
70 | }
71 |
72 | public function toArray(): array
73 | {
74 | return $this->toMergedArray([
75 | 'min_query_length' => $this->minQueryLength,
76 | 'initial_options' => ($this->initialOptions) ? array_map(function (OptionObject $option): array {
77 | return $option->toArray();
78 | }, $this->initialOptions) : null,
79 | ]);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectPublicChannelElement.php:
--------------------------------------------------------------------------------
1 | initialChannels = $initialChannels;
36 | return $this;
37 | }
38 |
39 | public function getType(): string
40 | {
41 | return static::TYPE_MULTI_SELECT_CHANNELS;
42 | }
43 |
44 | public function compatibleWith(): array
45 | {
46 | return [
47 | Block::TYPE_SECTION,
48 | ];
49 | }
50 |
51 | public function toArray(): array
52 | {
53 | return $this->toMergedArray([
54 | 'initial_channels' => $this->initialChannels,
55 | ]);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectStaticElement.php:
--------------------------------------------------------------------------------
1 | options = $options;
40 | }
41 |
42 | /**
43 | * An array of options that exactly match one or more of the options within options.
44 | * These options will be selected when the menu initially loads.
45 | *
46 | * @see https://api.slack.com/reference/block-kit/block-elements#static_multi_select__fields
47 | *
48 | * @param OptionObject[] $options
49 | * @return $this
50 | */
51 | public function withInitialOptions(array $options): self
52 | {
53 | $this->initialOptions = $options;
54 | return $this;
55 | }
56 |
57 | public function getType(): string
58 | {
59 | return static::TYPE_MULTI_SELECT_STATIC;
60 | }
61 |
62 | public function toArray(): array
63 | {
64 | return $this->toMergedArray([
65 | 'options' => array_map(function (OptionObject $option): array {
66 | return $option->toArray();
67 | }, $this->options),
68 | 'initial_options' => ($this->initialOptions) ? array_map(function (OptionObject $option): array {
69 | return $option->toArray();
70 | }, $this->initialOptions) : null,
71 | ]);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectUserElement.php:
--------------------------------------------------------------------------------
1 | initialUsers = $initialUsers;
36 | return $this;
37 | }
38 |
39 | public function getType(): string
40 | {
41 | return static::TYPE_MULTI_SELECT_USERS;
42 | }
43 |
44 | public function compatibleWith(): array
45 | {
46 | return [
47 | Block::TYPE_SECTION,
48 | ];
49 | }
50 |
51 | public function toArray(): array
52 | {
53 | return $this->toMergedArray([
54 | 'initial_users' => $this->initialUsers,
55 | ]);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/OverflowMenuElement.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
29 | $this->options = $options;
30 | }
31 |
32 | public function getType(): string
33 | {
34 | return static::TYPE_OVERFLOW_MENU;
35 | }
36 |
37 | public function compatibleWith(): array
38 | {
39 | return [
40 | Block::TYPE_SECTION,
41 | Block::TYPE_ACTIONS,
42 | ];
43 | }
44 |
45 | public function toArray(): array
46 | {
47 | return $this->toMergedArray($this->mergeConfirmationDialog([
48 | 'action_id' => $this->actionId,
49 | 'options' => array_map(function (OptionObject $option): array {
50 | return $option->toArray();
51 | }, $this->options),
52 | ]));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/PlainTextInputElement.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
34 | }
35 |
36 | /**
37 | * The initial value in the plain-text input when it is loaded.
38 | *
39 | * @see https://api.slack.com/reference/block-kit/block-elements#input__fields
40 | *
41 | * @param string $initialValue
42 | * @return $this
43 | */
44 | public function withInitialValue(string $initialValue): self
45 | {
46 | $this->initialValue = $initialValue;
47 | return $this;
48 | }
49 |
50 | /**
51 | * The minimum length of input that the user must provide. If the user provides less, they will receive an error.
52 | * Maximum value is 3000.
53 | *
54 | * @see https://api.slack.com/reference/block-kit/block-elements#input__fields
55 | *
56 | * @param int $minLength
57 | * @return $this
58 | */
59 | public function withMinLength(int $minLength): self
60 | {
61 | $this->minLength = $minLength;
62 | return $this;
63 | }
64 |
65 | /**
66 | * The maximum length of input that the user can provide. If the user provides more, they will receive an error.
67 | *
68 | * @see https://api.slack.com/reference/block-kit/block-elements#input__fields
69 | *
70 | * @param int $maxLength
71 | * @return $this
72 | */
73 | public function withMaxLength(int $maxLength): self
74 | {
75 | $this->maxLength = $maxLength;
76 | return $this;
77 | }
78 |
79 | /**
80 | * Indicates whether the input will be a single line (false) or a larger textarea (true). Defaults to false.
81 | *
82 | * @see https://api.slack.com/reference/block-kit/block-elements#input__fields
83 | *
84 | * @param bool $multiline
85 | * @return $this
86 | */
87 | public function multiline(bool $multiline = true): self
88 | {
89 | $this->multiline = $multiline;
90 | return $this;
91 | }
92 |
93 | public function getType(): string
94 | {
95 | return static::TYPE_PLAIN_TEXT_INPUT;
96 | }
97 |
98 | public function compatibleWith(): array
99 | {
100 | return [
101 | Block::TYPE_INPUT,
102 | ];
103 | }
104 |
105 | public function toArray(): array
106 | {
107 | return $this->toMergedArray([
108 | 'action_id' => $this->actionId,
109 | 'placeholder' => ($this->placeholder) ? $this->placeholder->toArray() : null,
110 | 'initial_value' => $this->initialValue,
111 | 'multiline' => $this->multiline,
112 | 'min_length' => $this->minLength,
113 | 'max_length' => $this->maxLength,
114 | 'focus_on_load' => $this->focusOnLoad,
115 | ]);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/RadioButtonGroupElement.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
36 | $this->options = $options;
37 | }
38 |
39 | /**
40 | * An option object that exactly matches one of the options within options.
41 | * This option will be selected when the radio button group initially loads.
42 | *
43 | * @see https://api.slack.com/reference/block-kit/block-elements#radio__fields
44 | *
45 | * @param OptionObject $option
46 | * @return $this
47 | */
48 | public function withInitialOption(OptionObject $option): self
49 | {
50 | $this->initialOption = $option;
51 | return $this;
52 | }
53 |
54 | public function getType(): string
55 | {
56 | return static::TYPE_RADIO_BUTTON_GROUP;
57 | }
58 |
59 | public function compatibleWith(): array
60 | {
61 | return [
62 | Block::TYPE_SECTION,
63 | Block::TYPE_ACTIONS,
64 | Block::TYPE_INPUT,
65 | ];
66 | }
67 |
68 | public function toArray(): array
69 | {
70 | return $this->toMergedArray($this->mergeConfirmationDialog([
71 | 'action_id' => $this->actionId,
72 | 'options' => array_map(function (OptionObject $option): array {
73 | return $option->toArray();
74 | }, $this->options),
75 | 'initial_option' => ($this->initialOption) ? $this->initialOption->toArray() : null,
76 | 'focus_on_load' => $this->focusOnLoad,
77 | ]));
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/SelectMenu/SelectMenu.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
23 | $this->placeholder = $placeholder;
24 | }
25 |
26 | public function compatibleWith(): array
27 | {
28 | return [
29 | Block::TYPE_SECTION,
30 | Block::TYPE_ACTIONS,
31 | Block::TYPE_INPUT,
32 | ];
33 | }
34 |
35 | public function toArray(): array
36 | {
37 | return $this->mergeConfirmationDialog([
38 | 'type' => $this->getType(),
39 | 'action_id' => $this->actionId,
40 | 'placeholder' => $this->placeholder->toArray(),
41 | 'focus_on_load' => $this->focusOnLoad,
42 | ]);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuConversationElement.php:
--------------------------------------------------------------------------------
1 | initialOptionKeyName = 'initial_conversation';
27 | }
28 |
29 | /**
30 | * Pre-populates the select menu with the conversation that the user was viewing when they opened
31 | * the modal, if available.
32 | *
33 | * @see https://api.slack.com/reference/block-kit/block-elements#conversation_select__fields
34 | *
35 | * @param bool $defaultToCurrent
36 | * @return $this
37 | */
38 | public function defaultToCurrent(bool $defaultToCurrent = true): self
39 | {
40 | $this->defaultToCurrent = $defaultToCurrent;
41 | return $this;
42 | }
43 |
44 | /**
45 | * This field only works with menus in input blocks in modals.
46 | * When set to true, the view_submission payload from the menu's parent view will contain a response_url.
47 | * This response_url can be used for message responses. The target conversation for the message will be
48 | * determined by the value of this select menu.
49 | *
50 | * @see https://api.slack.com/reference/block-kit/block-elements#conversation_select__fields
51 | *
52 | * @param bool $responseUrlEnabled
53 | * @return $this
54 | */
55 | public function withResponseUrlEnabled(bool $responseUrlEnabled = true): self
56 | {
57 | $this->responseUrlEnabled = $responseUrlEnabled;
58 | return $this;
59 | }
60 |
61 | public function getType(): string
62 | {
63 | return static::TYPE_SELECT_MENU_CONVERSATIONS;
64 | }
65 |
66 | public function toArray(): array
67 | {
68 | return $this->toMergedArray($this->mergeInitialOption($this->mergeFilter([
69 | 'default_to_current_conversation' => $this->defaultToCurrent,
70 | 'response_url_enabled' => $this->responseUrlEnabled,
71 | ])));
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuExternalElement.php:
--------------------------------------------------------------------------------
1 | minQueryLength = $length;
38 | return $this;
39 | }
40 |
41 | public function getType(): string
42 | {
43 | return static::TYPE_SELECT_MENU_EXTERNAL;
44 | }
45 |
46 | public function toArray(): array
47 | {
48 | return $this->toMergedArray($this->mergeInitialOption([
49 | 'min_query_length' => $this->minQueryLength,
50 | ]));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuPublicChannelElement.php:
--------------------------------------------------------------------------------
1 | initialOptionKeyName = 'initial_channel';
24 | }
25 |
26 | /**
27 | * This field only works with menus in input blocks in modals.
28 | * When set to true, the view_submission payload from the menu's parent view will contain a response_url.
29 | * This response_url can be used for message responses.
30 | * The target channel for the message will be determined by the value of this select menu.
31 | *
32 | * @see https://api.slack.com/reference/block-kit/block-elements#channel_select__fields
33 | *
34 | * @param bool $responseUrlEnabled
35 | * @return $this
36 | */
37 | public function withResponseUrlEnabled(bool $responseUrlEnabled = true): self
38 | {
39 | $this->responseUrlEnabled = $responseUrlEnabled;
40 | return $this;
41 | }
42 |
43 | public function getType(): string
44 | {
45 | return static::TYPE_SELECT_MENU_CHANNELS;
46 | }
47 |
48 | public function toArray(): array
49 | {
50 | return $this->toMergedArray($this->mergeInitialOption([
51 | 'response_url_enabled' => $this->responseUrlEnabled,
52 | ]));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuStaticElement.php:
--------------------------------------------------------------------------------
1 | options = $options;
33 | }
34 |
35 | public function getType(): string
36 | {
37 | return static::TYPE_SELECT_MENU_STATIC;
38 | }
39 |
40 | public function toArray(): array
41 | {
42 | return $this->toMergedArray($this->mergeInitialOption([
43 | 'options' => array_map(function (OptionObject $option): array {
44 | return $option->toArray();
45 | }, $this->options),
46 | ]));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuUserElement.php:
--------------------------------------------------------------------------------
1 | initialOptionKeyName = 'initial_user';
22 | }
23 |
24 | public function getType(): string
25 | {
26 | return static::TYPE_SELECT_MENU_USERS;
27 | }
28 |
29 | public function toArray(): array
30 | {
31 | return $this->toMergedArray($this->mergeInitialOption());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Elements/TimePickerElement.php:
--------------------------------------------------------------------------------
1 | actionId = $actionId;
29 | $this->placeholder = $placeholder;
30 | }
31 |
32 | /**
33 | * The initial time that is selected when the element is loaded.
34 | * This should be in the format HH:mm, where HH is the 24-hour format of an hour (00 to 23) and mm is minutes
35 | * with leading zeros (00 to 59), for example 22:25 for 10:25pm.
36 | *
37 | * @see https://api.slack.com/reference/block-kit/block-elements#timepicker__fields
38 | *
39 | * @param string $initialTime
40 | * @return $this
41 | */
42 | public function withInitialTime(string $initialTime): self
43 | {
44 | $this->initialTime = $initialTime;
45 | return $this;
46 | }
47 |
48 | public function getType(): string
49 | {
50 | return static::TYPE_TIME_PICKER;
51 | }
52 |
53 | public function compatibleWith(): array
54 | {
55 | return [
56 | Block::TYPE_SECTION,
57 | Block::TYPE_ACTIONS,
58 | Block::TYPE_INPUT,
59 | ];
60 | }
61 |
62 | public function toArray(): array
63 | {
64 | return $this->toMergedArray($this->mergeConfirmationDialog([
65 | 'action_id' => $this->actionId,
66 | 'placeholder' => $this->placeholder->toArray(),
67 | 'initial_time' => $this->initialTime,
68 | 'focus_on_load' => $this->focusOnLoad,
69 | ]));
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Traits/Composition/WithFocusOnLoad.php:
--------------------------------------------------------------------------------
1 | focusOnLoad = $focusOnLoad;
20 | return $this;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Traits/Elements/HasInitialOption.php:
--------------------------------------------------------------------------------
1 | initialOption = $initialOption;
25 | return $this;
26 | }
27 |
28 | protected function mergeInitialOption(array $toMergeWith = []): array
29 | {
30 | $formattedOption = null;
31 | if (is_string($this->initialOption)) {
32 | $formattedOption = $this->initialOption;
33 | } elseif ($this->initialOption instanceof Arrayable) {
34 | $formattedOption = $this->initialOption->toArray();
35 | }
36 |
37 | return array_merge($toMergeWith, [
38 | $this->initialOptionKeyName => $formattedOption,
39 | ]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Traits/Elements/WithConfirmationDialog.php:
--------------------------------------------------------------------------------
1 | confirmationDialog = $confirmationDialog;
23 | return $this;
24 | }
25 |
26 | protected function mergeConfirmationDialog(array $mergeWith): array
27 | {
28 | return array_merge($mergeWith, [
29 | 'confirm' => ($this->confirmationDialog) ? $this->confirmationDialog->toArray() : null,
30 | ]);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Traits/Elements/WithFilter.php:
--------------------------------------------------------------------------------
1 | filter = $filter;
23 | return $this;
24 | }
25 |
26 | protected function mergeFilter(array $mergeWith): array
27 | {
28 | return array_filter(array_merge($mergeWith, [
29 | 'filter' => ($this->filter) ? $this->filter->toArray() : null,
30 | ]));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Traits/HasActionId.php:
--------------------------------------------------------------------------------
1 | toArray();
19 | }, $this->elements);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Support/LayoutBlocks/Traits/MergesArrays.php:
--------------------------------------------------------------------------------
1 | blocks[] = $block;
24 | return $this;
25 | }
26 |
27 | public function header(string $text): self
28 | {
29 | $this->blocks[] = new HeaderBlock($this->withPlainText($text));
30 | return $this;
31 | }
32 |
33 | public function divider(): self
34 | {
35 | $this->blocks[] = new DividerBlock();
36 | return $this;
37 | }
38 |
39 | public function withPlainText(string $text): TextObject
40 | {
41 | return new TextObject($text);
42 | }
43 |
44 | public function withMarkdownText(string $text): MarkdownObject
45 | {
46 | return new MarkdownObject($text);
47 | }
48 |
49 | /**
50 | * @return Block[]
51 | */
52 | public function getBlocks(): array
53 | {
54 | return $this->blocks;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Support/Paginator.php:
--------------------------------------------------------------------------------
1 | items = $items;
17 | $this->nextCursor = $nextCursor;
18 | }
19 |
20 | public function hasMorePages(): bool
21 | {
22 | return !is_null($this->nextCursor);
23 | }
24 |
25 | public function nextCursor(): ?string
26 | {
27 | return $this->nextCursor;
28 | }
29 |
30 | public function toArray(): array
31 | {
32 | return [
33 | 'items' => $this->items,
34 | 'next_cursor' => $this->nextCursor,
35 | 'has_more_pages' => $this->hasMorePages(),
36 | ];
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Support/SlackCommandRequest.php:
--------------------------------------------------------------------------------
1 | options['username'] = $username;
15 | return $this;
16 | }
17 |
18 | public function iconUrl(string $url): self
19 | {
20 | if (empty($this->options['icon'])) {
21 | $this->options['icon'] = [];
22 | }
23 |
24 | $this->options['icon']['url'] = $url;
25 | return $this;
26 | }
27 |
28 | public function iconEmoji(string $emoji): self
29 | {
30 | if (empty($this->options['icon'])) {
31 | $this->options['icon'] = [];
32 | }
33 |
34 | $this->options['icon']['emoji'] = $emoji;
35 | return $this;
36 | }
37 |
38 | public function unfurlMedia(bool $unfurl = true): self
39 | {
40 | if (empty($this->options['unfurl'])) {
41 | $this->options['unfurl'] = [];
42 | }
43 |
44 | $this->options['unfurl']['media'] = $unfurl;
45 | return $this;
46 | }
47 |
48 | public function unfurlLinks(bool $unfurl = true): self
49 | {
50 | if (empty($this->options['unfurl'])) {
51 | $this->options['unfurl'] = [];
52 | }
53 |
54 | $this->options['unfurl']['links'] = $unfurl;
55 | return $this;
56 | }
57 |
58 | public function threadTs(string $ts): self
59 | {
60 | if (empty($this->options['thread'])) {
61 | $this->options['thread'] = [];
62 | }
63 |
64 | $this->options['thread']['ts'] = $ts;
65 | return $this;
66 | }
67 |
68 | public function threadReplySendToChannel(bool $sendToChannel = true): self
69 | {
70 | if (empty($this->options['thread'])) {
71 | $this->options['thread'] = [];
72 | }
73 |
74 | $this->options['thread']['send_to_channel'] = $sendToChannel;
75 | return $this;
76 | }
77 |
78 | public function linkNames(bool $linkNames = true): self
79 | {
80 | $this->options['link_names'] = $linkNames;
81 | return $this;
82 | }
83 |
84 | public function metadata(array $metadata): self
85 | {
86 | $this->options['metadata'] = $metadata;
87 | return $this;
88 | }
89 |
90 | public function parse(string $parse): self
91 | {
92 | $this->options['parse'] = $parse;
93 | return $this;
94 | }
95 |
96 | public function markdown(bool $markdown = true): self
97 | {
98 | $this->options['markdown'] = $markdown;
99 | return $this;
100 | }
101 |
102 | public function toArray(): array
103 | {
104 | return $this->options;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | addToAssertionCount($container->mockery_getExpectationCount());
15 | }
16 |
17 | \Mockery::close();
18 | }
19 |
20 | parent::tearDown();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Traits/BasicMultiSelectTests.php:
--------------------------------------------------------------------------------
1 | elementClass('action-id', \Mockery::mock(TextObject::class), ...$this->additionalSetupArgs);
22 | $this->assertEquals([
23 | Block::TYPE_SECTION,
24 | ], $element->compatibleWith());
25 | }
26 |
27 | public function testElementType()
28 | {
29 | /** @var Element $element */
30 | $element = new $this->elementClass('action-id', \Mockery::mock(TextObject::class), ...$this->additionalSetupArgs);
31 | $this->assertSame($this->expectedType, $element->getType());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/Traits/BasicSelectMenuTests.php:
--------------------------------------------------------------------------------
1 | elementClass('action-id', \Mockery::mock(TextObject::class), ...$this->additionalSetupArgs);
22 | $this->assertEquals([
23 | Block::TYPE_SECTION,
24 | Block::TYPE_ACTIONS,
25 | Block::TYPE_INPUT,
26 | ], $element->compatibleWith());
27 | }
28 |
29 | public function testElementType()
30 | {
31 | /** @var SelectMenu $element */
32 | $element = new $this->elementClass('action-id', \Mockery::mock(TextObject::class), ...$this->additionalSetupArgs);
33 | $this->assertSame($this->expectedType, $element->getType());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/Unit/Services/SlackCommandHandlerFactoryServiceTest.php:
--------------------------------------------------------------------------------
1 | laravel = \Mockery::mock(Application::class);
23 | $this->service = new SlackCommandHandlerFactoryService($this->laravel);
24 | }
25 |
26 | public function testRegisterAndGetHandlerSuccess()
27 | {
28 | $command = 'test';
29 | $handlerClass = 'App\\TestClass';
30 |
31 | $this->service->register($handlerClass, $command);
32 |
33 | $handlerMock = \Mockery::mock(SlackCommandHandlerContract::class);
34 | $this->laravel->shouldReceive('make')
35 | ->once()
36 | ->with($handlerClass)
37 | ->andReturn($handlerMock);
38 |
39 | $result = $this->service->getHandler($command);
40 | $this->assertSame($result, $handlerMock);
41 | }
42 |
43 | public function testRegisterAndGetHandlerFailsForMissingCommandHandler()
44 | {
45 | $this->expectException(\InvalidArgumentException::class);
46 | $this->expectExceptionMessage('No handler found for command invalid-command');
47 |
48 | $this->service->getHandler('invalid-command');
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/ActionsBlockTest.php:
--------------------------------------------------------------------------------
1 | 'val'];
16 | $element = \Mockery::mock(Element::class);
17 | $element->shouldReceive('toArray')->andReturn($expectedElementArray);
18 |
19 | $block = new ActionsBlock([$element], 'block-id');
20 | $this->assertSame(Block::TYPE_ACTIONS, $block->getType());
21 |
22 | $this->assertEquals([
23 | 'type' => Block::TYPE_ACTIONS,
24 | 'block_id' => 'block-id',
25 | 'elements' => [$expectedElementArray]
26 | ], $block->toArray());
27 | }
28 |
29 | public function testBlockNoBlockId()
30 | {
31 | $block = new ActionsBlock([]);
32 | $this->assertSame(Block::TYPE_ACTIONS, $block->getType());
33 |
34 | $this->assertEquals([
35 | 'type' => Block::TYPE_ACTIONS,
36 | ], $block->toArray());
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/ContextBlockTest.php:
--------------------------------------------------------------------------------
1 | 'val'];
17 | $expectedElementArray = ['key2' => 'val2'];
18 |
19 | $textBlockElement = \Mockery::mock(TextObject::class);
20 | $textBlockElement->shouldReceive('toArray')->andReturn($expectedTextElementArray);
21 |
22 | $element = \Mockery::mock(Element::class);
23 | $element->shouldReceive('toArray')->andReturn($expectedElementArray);
24 |
25 | $block = new ContextBlock([$textBlockElement], [$element], 'block-id');
26 | $this->assertSame(Block::TYPE_CONTEXT, $block->getType());
27 |
28 | $this->assertEquals([
29 | 'type' => Block::TYPE_CONTEXT,
30 | 'block_id' => 'block-id',
31 | 'elements' => [$expectedElementArray, $expectedTextElementArray]
32 | ], $block->toArray());
33 | }
34 |
35 | public function testBlockNoBlockId()
36 | {
37 | $block = new ContextBlock([], []);
38 | $this->assertSame(Block::TYPE_CONTEXT, $block->getType());
39 |
40 | $this->assertEquals([
41 | 'type' => Block::TYPE_CONTEXT,
42 | ], $block->toArray());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/DividerBlockTest.php:
--------------------------------------------------------------------------------
1 | assertSame(Block::TYPE_DIVIDER, $block->getType());
16 | $this->assertEquals([
17 | 'type' => Block::TYPE_DIVIDER,
18 | 'block_id' => 'block-id',
19 | ], $block->toArray());
20 | }
21 |
22 | public function testBlockNoBlockId()
23 | {
24 | $block = new DividerBlock();
25 | $this->assertSame(Block::TYPE_DIVIDER, $block->getType());
26 | $this->assertEquals([
27 | 'type' => Block::TYPE_DIVIDER,
28 | ], $block->toArray());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/FileBlockTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
20 | 'type' => Block::TYPE_FILE,
21 | 'external_id' => $externalId,
22 | 'block_id' => $blockId,
23 | 'source' => 'remote',
24 | ], $block->toArray());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/HeaderBlockTest.php:
--------------------------------------------------------------------------------
1 | 'val'];
16 |
17 | $textObject = \Mockery::mock(TextObject::class);
18 | $textObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
19 |
20 | $block = new HeaderBlock($textObject, 'block-id');
21 | $this->assertSame(Block::TYPE_HEADER, $block->getType());
22 | $this->assertEquals([
23 | 'type' => Block::TYPE_HEADER,
24 | 'block_id' => 'block-id',
25 | 'text' => $expectedTextObjectArray,
26 | ], $block->toArray());
27 | }
28 |
29 | public function testBlockNoBlockId()
30 | {
31 | $expectedTextObjectArray = ['key' => 'val'];
32 |
33 | $textObject = \Mockery::mock(TextObject::class);
34 | $textObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
35 |
36 | $block = new HeaderBlock($textObject);
37 | $this->assertSame(Block::TYPE_HEADER, $block->getType());
38 | $this->assertEquals([
39 | 'type' => Block::TYPE_HEADER,
40 | 'text' => $expectedTextObjectArray,
41 | ], $block->toArray());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/ImageBlockTest.php:
--------------------------------------------------------------------------------
1 | 'val'];
16 |
17 | $textObject = \Mockery::mock(TextObject::class);
18 | $textObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
19 |
20 | $block = new ImageBlock('https://example.com', 'test alt text', 'block-id');
21 | $this->assertSame(Block::TYPE_IMAGE, $block->getType());
22 | $this->assertEquals([
23 | 'type' => Block::TYPE_IMAGE,
24 | 'block_id' => 'block-id',
25 | 'image_url' => 'https://example.com',
26 | 'alt_text' => 'test alt text',
27 | ], $block->toArray());
28 | }
29 |
30 | public function testBlockNoBlockId()
31 | {
32 | $block = new ImageBlock('https://example.com', 'test alt text');
33 | $this->assertSame(Block::TYPE_IMAGE, $block->getType());
34 | $this->assertEquals([
35 | 'type' => Block::TYPE_IMAGE,
36 | 'image_url' => 'https://example.com',
37 | 'alt_text' => 'test alt text',
38 | ], $block->toArray());
39 | }
40 |
41 | public function testBlockWithTitle()
42 | {
43 | $expectedTextObjectArray = ['key' => 'val'];
44 |
45 | $textObject = \Mockery::mock(TextObject::class);
46 | $textObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
47 |
48 | $block = new ImageBlock('https://example.com', 'test alt text');
49 | $block->withTitle($textObject);
50 |
51 | $this->assertSame(Block::TYPE_IMAGE, $block->getType());
52 | $this->assertEquals([
53 | 'type' => Block::TYPE_IMAGE,
54 | 'image_url' => 'https://example.com',
55 | 'alt_text' => 'test alt text',
56 | 'title' => $expectedTextObjectArray,
57 | ], $block->toArray());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/InputBlockTest.php:
--------------------------------------------------------------------------------
1 | 'v1'];
16 | $expectedElementArray = ['k2' => 'v2'];
17 |
18 | $label = \Mockery::mock(TextObject::class);
19 | $element = \Mockery::mock(Element::class);
20 |
21 | $label->shouldReceive('toArray')->andReturn($expectedLabelArray);
22 | $element->shouldReceive('toArray')->andReturn($expectedElementArray);
23 |
24 | $block = new InputBlock($label, $element);
25 |
26 | $this->assertEquals([
27 | 'type' => Block::TYPE_INPUT,
28 | 'label' => $expectedLabelArray,
29 | 'element' => $expectedElementArray,
30 | ], $block->toArray());
31 | }
32 |
33 | public function testBlockWithOptions()
34 | {
35 | $expectedLabelArray = ['k1' => 'v1'];
36 | $expectedHintArray = ['k2' => 'v2'];
37 | $expectedElementArray = ['k3' => 'v3'];
38 |
39 | $label = \Mockery::mock(TextObject::class);
40 | $hint = \Mockery::mock(TextObject::class);
41 | $element = \Mockery::mock(Element::class);
42 |
43 | $label->shouldReceive('toArray')->andReturn($expectedLabelArray);
44 | $hint->shouldReceive('toArray')->andReturn($expectedHintArray);
45 | $element->shouldReceive('toArray')->andReturn($expectedElementArray);
46 |
47 | $block = new InputBlock($label, $element, 'block-id');
48 |
49 | $block->withHint($hint);
50 | $block->dispatchAction();
51 | $block->optional();
52 |
53 | $this->assertEquals([
54 | 'type' => Block::TYPE_INPUT,
55 | 'label' => $expectedLabelArray,
56 | 'element' => $expectedElementArray,
57 | 'block_id' => 'block-id',
58 | 'hint' => $expectedHintArray,
59 | 'dispatch_action' => true,
60 | 'optional' => true,
61 | ], $block->toArray());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Blocks/SectionBlockTest.php:
--------------------------------------------------------------------------------
1 | 'val'];
17 |
18 | $textObject = \Mockery::mock(TextObject::class);
19 | $textObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
20 |
21 | $block = new SectionBlock();
22 | $block->withText($textObject);
23 |
24 | $this->assertSame(Block::TYPE_SECTION, $block->getType());
25 | $this->assertEquals([
26 | 'type' => Block::TYPE_SECTION,
27 | 'text' => $expectedTextObjectArray,
28 | ], $block->toArray());
29 | }
30 |
31 | public function testBlockWithFields()
32 | {
33 | $expectedTextObject1Array = ['key' => 'val'];
34 | $expectedTextObject2Array = ['key' => 'val'];
35 | $expectedTextObject3Array = ['key' => 'val'];
36 |
37 | $textObject1 = \Mockery::mock(TextObject::class);
38 | $textObject1->shouldReceive('toArray')->andReturn($expectedTextObject1Array);
39 |
40 | $textObject2 = \Mockery::mock(TextObject::class);
41 | $textObject2->shouldReceive('toArray')->andReturn($expectedTextObject2Array);
42 |
43 | $textObject3 = \Mockery::mock(TextObject::class);
44 | $textObject3->shouldReceive('toArray')->andReturn($expectedTextObject3Array);
45 |
46 | $block = new SectionBlock();
47 | $block->withFields([$textObject1, $textObject2, $textObject3]);
48 |
49 | $this->assertSame(Block::TYPE_SECTION, $block->getType());
50 | $this->assertEquals([
51 | 'type' => Block::TYPE_SECTION,
52 | 'fields' => [$expectedTextObject1Array, $expectedTextObject2Array, $expectedTextObject3Array],
53 | ], $block->toArray());
54 | }
55 |
56 | public function testBlockWithAccessory()
57 | {
58 | $expectedTextObjectArray = ['key' => 'val'];
59 | $expectedElementArray = ['key2' => 'val2'];
60 |
61 | $textObject = \Mockery::mock(TextObject::class);
62 | $textObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
63 |
64 | $element = \Mockery::mock(Element::class);
65 | $element->shouldReceive('toArray')->andReturn($expectedElementArray);
66 |
67 | $block = new SectionBlock('block-id');
68 | $block->withText($textObject);
69 | $block->withAccessory($element);
70 |
71 | $this->assertSame(Block::TYPE_SECTION, $block->getType());
72 | $this->assertEquals([
73 | 'type' => Block::TYPE_SECTION,
74 | 'text' => $expectedTextObjectArray,
75 | 'accessory' => $expectedElementArray,
76 | 'block_id' => 'block-id',
77 | ], $block->toArray());
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/ConfirmationDialogObjectTest.php:
--------------------------------------------------------------------------------
1 | 'v1'];
15 | $expectedTextArray = ['k2' => 'v2'];
16 | $expectedConfirmArray = ['k3' => 'v3'];
17 | $expectedDenyArray = ['k4' => 'v4'];
18 |
19 | $title = \Mockery::mock(TextObject::class);
20 | $text = \Mockery::mock(TextObject::class);
21 | $confirm = \Mockery::mock(TextObject::class);
22 | $deny = \Mockery::mock(TextObject::class);
23 |
24 | $title->shouldReceive('toArray')->andReturn($expectedTitleArray);
25 | $text->shouldReceive('toArray')->andReturn($expectedTextArray);
26 | $confirm->shouldReceive('toArray')->andReturn($expectedConfirmArray);
27 | $deny->shouldReceive('toArray')->andReturn($expectedDenyArray);
28 |
29 | $object = new ConfirmationDialogObject($title, $text, $confirm, $deny);
30 |
31 | $this->assertEquals([
32 | 'title' => $expectedTitleArray,
33 | 'text' => $expectedTextArray,
34 | 'confirm' => $expectedConfirmArray,
35 | 'deny' => $expectedDenyArray,
36 | ], $object->toArray());
37 | }
38 |
39 | public function testObjectWithButtonPrimary()
40 | {
41 | $expectedTitleArray = ['k1' => 'v1'];
42 | $expectedTextArray = ['k2' => 'v2'];
43 | $expectedConfirmArray = ['k3' => 'v3'];
44 | $expectedDenyArray = ['k4' => 'v4'];
45 |
46 | $title = \Mockery::mock(TextObject::class);
47 | $text = \Mockery::mock(TextObject::class);
48 | $confirm = \Mockery::mock(TextObject::class);
49 | $deny = \Mockery::mock(TextObject::class);
50 |
51 | $title->shouldReceive('toArray')->andReturn($expectedTitleArray);
52 | $text->shouldReceive('toArray')->andReturn($expectedTextArray);
53 | $confirm->shouldReceive('toArray')->andReturn($expectedConfirmArray);
54 | $deny->shouldReceive('toArray')->andReturn($expectedDenyArray);
55 |
56 | $object = new ConfirmationDialogObject($title, $text, $confirm, $deny);
57 | $object->confirmButtonPrimary();
58 |
59 | $this->assertEquals([
60 | 'title' => $expectedTitleArray,
61 | 'text' => $expectedTextArray,
62 | 'confirm' => $expectedConfirmArray,
63 | 'deny' => $expectedDenyArray,
64 | 'style' => 'primary',
65 | ], $object->toArray());
66 | }
67 |
68 | public function testObjectWithButtonDanger()
69 | {
70 | $expectedTitleArray = ['k1' => 'v1'];
71 | $expectedTextArray = ['k2' => 'v2'];
72 | $expectedConfirmArray = ['k3' => 'v3'];
73 | $expectedDenyArray = ['k4' => 'v4'];
74 |
75 | $title = \Mockery::mock(TextObject::class);
76 | $text = \Mockery::mock(TextObject::class);
77 | $confirm = \Mockery::mock(TextObject::class);
78 | $deny = \Mockery::mock(TextObject::class);
79 |
80 | $title->shouldReceive('toArray')->andReturn($expectedTitleArray);
81 | $text->shouldReceive('toArray')->andReturn($expectedTextArray);
82 | $confirm->shouldReceive('toArray')->andReturn($expectedConfirmArray);
83 | $deny->shouldReceive('toArray')->andReturn($expectedDenyArray);
84 |
85 | $object = new ConfirmationDialogObject($title, $text, $confirm, $deny);
86 | $object->confirmButtonDanger();
87 |
88 | $this->assertEquals([
89 | 'title' => $expectedTitleArray,
90 | 'text' => $expectedTextArray,
91 | 'confirm' => $expectedConfirmArray,
92 | 'deny' => $expectedDenyArray,
93 | 'style' => 'danger',
94 | ], $object->toArray());
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/DispatchActionConfigurationObjectTest.php:
--------------------------------------------------------------------------------
1 | onEnterPressed();
17 | $object->onCharacterEntered();
18 |
19 | $this->assertEquals([
20 | 'trigger_actions_on' => $triggerActionsOn,
21 | ], $object->toArray());
22 | }
23 |
24 | public function testObjectNoTriggers()
25 | {
26 | $object = new DispatchActionConfigurationObject();
27 | $this->assertEquals([], $object->toArray());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/FilterObjectTest.php:
--------------------------------------------------------------------------------
1 | assertEmpty($object->toArray());
15 | }
16 |
17 | public function testObjectWithAllOptions()
18 | {
19 | $object = new FilterObject();
20 |
21 | $object->includeConversationTypes(['public', 'private']);
22 | $object->excludeExternalSharedChannels();
23 | $object->excludeBotUsers();
24 |
25 | $this->assertEquals([
26 | 'include' => ['public', 'private'],
27 | 'exclude_external_shared_channels' => true,
28 | 'exclude_bot_users' => true,
29 | ], $object->toArray());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/MarkdownObjectTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
17 | 'type' => 'mrkdwn',
18 | 'text' => 'test text',
19 | ], $object->toArray());
20 | }
21 |
22 | public function testObjectWithOptions()
23 | {
24 | $text = 'test text';
25 | $object = new MarkdownObject($text);
26 |
27 | $object->verbatim();
28 | $object->escapeEmojis();
29 |
30 | $this->assertEquals([
31 | 'type' => 'mrkdwn',
32 | 'text' => 'test text',
33 | 'emoji' => true,
34 | 'verbatim' => true,
35 | ], $object->toArray());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/OptionGroupObjectTest.php:
--------------------------------------------------------------------------------
1 | 'v1'];
16 | $expectedOption1Array = ['k2' => 'v2'];
17 | $expectedOption2Array = ['k3' => 'v3'];
18 |
19 | $label = \Mockery::mock(TextObject::class);
20 | $option1 = \Mockery::mock(OptionObject::class);
21 | $option2 = \Mockery::mock(OptionObject::class);
22 |
23 | $label->shouldReceive('toArray')->andReturn($expectedLabelArray);
24 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
25 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
26 |
27 | $object = new OptionGroupObject($label, [$option1, $option2]);
28 |
29 | $this->assertEquals([
30 | 'label' => $expectedLabelArray,
31 | 'options' => [$expectedOption1Array, $expectedOption2Array],
32 | ], $object->toArray());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/OptionObjectTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
20 | 'text' => $text,
21 | 'value' => $value,
22 | ], $option->toArray());
23 | }
24 |
25 | public function testObjectWithOptions()
26 | {
27 | $text = 'test text';
28 | $value = 'test value';
29 |
30 | $option = new OptionObject($text, $value);
31 |
32 | $expectedTextObjectArray = ['key' => 'value'];
33 |
34 | $descriptionTextObject = \Mockery::mock(TextObject::class);
35 | $descriptionTextObject->shouldReceive('toArray')->andReturn($expectedTextObjectArray);
36 |
37 | $option->withDescription($descriptionTextObject);
38 | $option->withUrl('https://example.com');
39 |
40 | $this->assertEquals([
41 | 'text' => $text,
42 | 'value' => $value,
43 | 'url' => 'https://example.com',
44 | 'description' => $expectedTextObjectArray,
45 | ], $option->toArray());
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Composition/TextObjectTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
17 | 'type' => 'plain_text',
18 | 'text' => 'test text',
19 | ], $object->toArray());
20 | }
21 |
22 | public function testObjectWithOptions()
23 | {
24 | $text = 'test text';
25 | $object = new TextObject($text);
26 |
27 | $object->verbatim();
28 | $object->escapeEmojis();
29 |
30 | $this->assertEquals([
31 | 'type' => 'plain_text',
32 | 'text' => 'test text',
33 | 'emoji' => true,
34 | ], $object->toArray());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/CheckboxesElementTest.php:
--------------------------------------------------------------------------------
1 | 'val'];
20 | $expectedOption2Array = ['key2' => 'val2'];
21 |
22 | $option1 = \Mockery::mock(OptionObject::class);
23 | $option2 = \Mockery::mock(OptionObject::class);
24 |
25 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
26 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
27 |
28 | $element = new CheckboxesElement($actionId, [$option1, $option2]);
29 |
30 | $this->assertEquals([
31 | 'type' => Element::TYPE_CHECKBOXES,
32 | 'action_id' => $actionId,
33 | 'options' => [
34 | $expectedOption1Array,
35 | $expectedOption2Array,
36 | ],
37 | ], $element->toArray());
38 | }
39 |
40 | public function testElementWithInitialOptions()
41 | {
42 | $actionId = 'action-id';
43 |
44 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
45 | $expectedOption1Array = ['key' => 'val'];
46 | $expectedOption2Array = ['key2' => 'val2'];
47 |
48 | $option1 = \Mockery::mock(OptionObject::class);
49 | $option2 = \Mockery::mock(OptionObject::class);
50 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
51 |
52 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
53 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
54 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
55 |
56 | $element = new CheckboxesElement($actionId, [$option1, $option2]);
57 |
58 | $element->withInitialOptions([$option1, $option2]);
59 | $element->withFocusOnLoad();
60 | $element->withConfirmationDialog($confirmationDialogObject);
61 |
62 | $this->assertEquals([
63 | 'type' => Element::TYPE_CHECKBOXES,
64 | 'action_id' => $actionId,
65 | 'options' => [
66 | $expectedOption1Array,
67 | $expectedOption2Array,
68 | ],
69 | 'initial_options' => [
70 | $expectedOption1Array,
71 | $expectedOption2Array,
72 | ],
73 | 'focus_on_load' => true,
74 | 'confirm' => $expectedConfirmationDialogArray,
75 | ], $element->toArray());
76 | }
77 |
78 | public function testCompatibleWith()
79 | {
80 | $element = new CheckboxesElement('', []);
81 | $this->assertSame([
82 | Block::TYPE_ACTIONS,
83 | Block::TYPE_SECTION,
84 | ], $element->compatibleWith());
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/DatePickerElementTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
22 | 'type' => Element::TYPE_DATEPICKER,
23 | 'action_id' => $actionId,
24 | ], $element->toArray());
25 | }
26 |
27 | public function testElementWithOptions()
28 | {
29 | $actionId = 'action-id';
30 | $initialDate = '2022-01-01';
31 |
32 | $element = new DatePickerElement($actionId, $initialDate);
33 |
34 | $expectedPlaceholderTextArray = ['key' => 'val'];
35 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
36 |
37 | $placeholderTextObject = \Mockery::mock(TextObject::class);
38 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
39 |
40 | $placeholderTextObject->shouldReceive('toArray')->andReturn($expectedPlaceholderTextArray);
41 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
42 |
43 | $element->withPlaceholder($placeholderTextObject);
44 | $element->withFocusOnLoad();
45 | $element->withConfirmationDialog($confirmationDialogObject);
46 |
47 | $this->assertEquals([
48 | 'type' => Element::TYPE_DATEPICKER,
49 | 'action_id' => $actionId,
50 | 'initial_date' => $initialDate,
51 | 'placeholder' => $expectedPlaceholderTextArray,
52 | 'focus_on_load' => true,
53 | 'confirm' => $expectedConfirmationDialogArray,
54 | ], $element->toArray());
55 | }
56 |
57 | public function testCompatibleWith()
58 | {
59 | $element = new DatePickerElement('');
60 | $this->assertSame([
61 | Block::TYPE_SECTION,
62 | Block::TYPE_ACTIONS,
63 | ], $element->compatibleWith());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/ImageElementTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
21 | 'type' => Element::TYPE_IMAGE,
22 | 'image_url' => $imageUrl,
23 | 'alt_text' => $altText,
24 | ], $element->toArray());
25 |
26 | $this->assertEquals([
27 | Block::TYPE_SECTION,
28 | Block::TYPE_CONTEXT,
29 | ], $element->compatibleWith());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectConversationElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = MultiSelectConversationElement::class;
23 | $this->expectedType = Element::TYPE_MULTI_SELECT_CONVERSATIONS;
24 | }
25 |
26 | public function testElement()
27 | {
28 | $expectedPlaceholderArray = ['key' => 'value'];
29 |
30 | $actionId = 'action-id';
31 | $placeholder = \Mockery::mock(TextObject::class);
32 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
33 |
34 | $element = new MultiSelectConversationElement($actionId, $placeholder);
35 |
36 | $this->assertEquals([
37 | 'type' => Element::TYPE_MULTI_SELECT_CONVERSATIONS,
38 | 'action_id' => $actionId,
39 | 'placeholder' => $expectedPlaceholderArray,
40 | ], $element->toArray());
41 | }
42 |
43 | public function testElementWithOptions()
44 | {
45 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
46 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
47 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
48 |
49 | $expectedFilterArray = ['filter' => 'value'];
50 | $filter = \Mockery::mock(FilterObject::class);
51 | $filter->shouldReceive('toArray')->andReturn($expectedFilterArray);
52 |
53 | $expectedPlaceholderArray = ['key' => 'value'];
54 |
55 | $actionId = 'action-id';
56 | $placeholder = \Mockery::mock(TextObject::class);
57 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
58 |
59 | $initialConversations = ['channel1', 'channel2'];
60 |
61 | $element = new MultiSelectConversationElement($actionId, $placeholder);
62 |
63 | $element->withInitialConversations($initialConversations);
64 | $element->maxSelectedItems(5);
65 | $element->withFocusOnLoad();
66 | $element->defaultToCurrent();
67 | $element->withConfirmationDialog($confirmationDialogObject);
68 | $element->withFilter($filter);
69 |
70 | $this->assertEquals([
71 | 'type' => Element::TYPE_MULTI_SELECT_CONVERSATIONS,
72 | 'action_id' => $actionId,
73 | 'placeholder' => $expectedPlaceholderArray,
74 | 'focus_on_load' => true,
75 | 'max_selected_items' => 5,
76 | 'initial_conversations' => $initialConversations,
77 | 'default_to_current_conversation' => true,
78 | 'confirm' => $expectedConfirmationDialogArray,
79 | 'filter' => $expectedFilterArray,
80 | ], $element->toArray());
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectExternalElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = MultiSelectExternalElement::class;
24 | $this->expectedType = Element::TYPE_MULTI_SELECT_EXTERNAL;
25 | }
26 |
27 | public function testElement()
28 | {
29 | $expectedPlaceholderArray = ['key' => 'val'];
30 |
31 | $actionId = 'action-id';
32 | $placeholder = \Mockery::mock(TextObject::class);
33 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
34 |
35 | $element = new MultiSelectExternalElement($actionId, $placeholder);
36 |
37 | $this->assertEquals([
38 | 'type' => Element::TYPE_MULTI_SELECT_EXTERNAL,
39 | 'action_id' => $actionId,
40 | 'placeholder' => $expectedPlaceholderArray,
41 | ], $element->toArray());
42 | }
43 |
44 | public function testElementWithOptions()
45 | {
46 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
47 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
48 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
49 |
50 | $expectedPlaceholderArray = ['key' => 'val'];
51 |
52 | $actionId = 'action-id';
53 | $placeholder = \Mockery::mock(TextObject::class);
54 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
55 |
56 | $expectedOption1Array = ['o1' => 'k1'];
57 | $expectedOption2Array = ['o2' => 'k2'];
58 |
59 | $option1 = \Mockery::mock(OptionObject::class);
60 | $option2 = \Mockery::mock(OptionObject::class);
61 |
62 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
63 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
64 |
65 | $element = new MultiSelectExternalElement($actionId, $placeholder);
66 |
67 | $element->withMinQueryLength(5);
68 | $element->withFocusOnLoad();
69 | $element->withInitialOptions([$option1, $option2]);
70 | $element->maxSelectedItems(1);
71 | $element->withConfirmationDialog($confirmationDialogObject);
72 |
73 | $this->assertEquals([
74 | 'type' => Element::TYPE_MULTI_SELECT_EXTERNAL,
75 | 'action_id' => $actionId,
76 | 'placeholder' => $expectedPlaceholderArray,
77 | 'initial_options' => [
78 | $expectedOption1Array,
79 | $expectedOption2Array,
80 | ],
81 | 'focus_on_load' => true,
82 | 'max_selected_items' => 1,
83 | 'min_query_length' => 5,
84 | 'confirm' => $expectedConfirmationDialogArray,
85 | ], $element->toArray());
86 | }
87 |
88 | public function testCompatibleWith()
89 | {
90 | $actionId = 'action-id';
91 | $element = new MultiSelectExternalElement($actionId, \Mockery::mock(TextObject::class));
92 |
93 | $this->assertSame([
94 | Block::TYPE_SECTION,
95 | ], $element->compatibleWith());
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectPublicChannelElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = MultiSelectPublicChannelElement::class;
23 | $this->expectedType = Element::TYPE_MULTI_SELECT_CHANNELS;
24 | }
25 |
26 | public function testElement()
27 | {
28 | $expectedPlaceholderArray = ['key' => 'value'];
29 |
30 | $actionId = 'action-id';
31 | $placeholder = \Mockery::mock(TextObject::class);
32 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
33 |
34 | $element = new MultiSelectPublicChannelElement($actionId, $placeholder);
35 |
36 | $this->assertEquals([
37 | 'type' => Element::TYPE_MULTI_SELECT_CHANNELS,
38 | 'action_id' => $actionId,
39 | 'placeholder' => $expectedPlaceholderArray,
40 | ], $element->toArray());
41 | }
42 |
43 | public function testElementWithOptions()
44 | {
45 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
46 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
47 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
48 |
49 | $expectedPlaceholderArray = ['key' => 'value'];
50 |
51 | $actionId = 'action-id';
52 | $placeholder = \Mockery::mock(TextObject::class);
53 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
54 |
55 | $initialChannels = ['channel1', 'channel2'];
56 |
57 | $element = new MultiSelectPublicChannelElement($actionId, $placeholder);
58 |
59 | $element->withInitialChannels($initialChannels);
60 | $element->maxSelectedItems(5);
61 | $element->withFocusOnLoad();
62 | $element->withConfirmationDialog($confirmationDialogObject);
63 |
64 | $this->assertEquals([
65 | 'type' => Element::TYPE_MULTI_SELECT_CHANNELS,
66 | 'action_id' => $actionId,
67 | 'placeholder' => $expectedPlaceholderArray,
68 | 'focus_on_load' => true,
69 | 'max_selected_items' => 5,
70 | 'initial_channels' => $initialChannels,
71 | 'confirm' => $expectedConfirmationDialogArray,
72 | ], $element->toArray());
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectStaticElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = MultiSelectStaticElement::class;
24 | $this->additionalSetupArgs = [[]];
25 | $this->expectedType = Element::TYPE_MULTI_SELECT_STATIC;
26 | }
27 |
28 | public function testElement()
29 | {
30 | $expectedPlaceholderArray = ['key' => 'val'];
31 |
32 | $actionId = 'action-id';
33 | $placeholder = \Mockery::mock(TextObject::class);
34 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
35 |
36 | $expectedOption1Array = ['o1' => 'k1'];
37 | $expectedOption2Array = ['o2' => 'k2'];
38 |
39 | $option1 = \Mockery::mock(OptionObject::class);
40 | $option2 = \Mockery::mock(OptionObject::class);
41 |
42 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
43 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
44 |
45 | $element = new MultiSelectStaticElement($actionId, $placeholder, [$option1, $option2]);
46 |
47 | $this->assertEquals([
48 | 'type' => Element::TYPE_MULTI_SELECT_STATIC,
49 | 'action_id' => $actionId,
50 | 'placeholder' => $expectedPlaceholderArray,
51 | 'options' => [
52 | $expectedOption1Array,
53 | $expectedOption2Array,
54 | ],
55 | ], $element->toArray());
56 | }
57 |
58 | public function testElementWithOptions()
59 | {
60 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
61 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
62 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
63 |
64 | $expectedPlaceholderArray = ['key' => 'val'];
65 |
66 | $actionId = 'action-id';
67 | $placeholder = \Mockery::mock(TextObject::class);
68 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
69 |
70 | $expectedOption1Array = ['o1' => 'k1'];
71 | $expectedOption2Array = ['o2' => 'k2'];
72 |
73 | $option1 = \Mockery::mock(OptionObject::class);
74 | $option2 = \Mockery::mock(OptionObject::class);
75 |
76 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
77 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
78 |
79 | $element = new MultiSelectStaticElement($actionId, $placeholder, [$option1, $option2]);
80 |
81 | $element->withFocusOnLoad();
82 | $element->withInitialOptions([$option1, $option2]);
83 | $element->maxSelectedItems(1);
84 | $element->withConfirmationDialog($confirmationDialogObject);
85 |
86 | $this->assertEquals([
87 | 'type' => Element::TYPE_MULTI_SELECT_STATIC,
88 | 'action_id' => $actionId,
89 | 'placeholder' => $expectedPlaceholderArray,
90 | 'options' => [
91 | $expectedOption1Array,
92 | $expectedOption2Array,
93 | ],
94 | 'initial_options' => [
95 | $expectedOption1Array,
96 | $expectedOption2Array,
97 | ],
98 | 'focus_on_load' => true,
99 | 'max_selected_items' => 1,
100 | 'confirm' => $expectedConfirmationDialogArray,
101 | ], $element->toArray());
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/MultiSelect/MultiSelectUserElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = MultiSelectUserElement::class;
22 | $this->expectedType = Element::TYPE_MULTI_SELECT_USERS;
23 | }
24 |
25 | public function testElement()
26 | {
27 | $expectedPlaceholderArray = ['key' => 'value'];
28 |
29 | $actionId = 'action-id';
30 | $placeholder = \Mockery::mock(TextObject::class);
31 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
32 |
33 | $element = new MultiSelectUserElement($actionId, $placeholder);
34 |
35 | $this->assertEquals([
36 | 'type' => Element::TYPE_MULTI_SELECT_USERS,
37 | 'action_id' => $actionId,
38 | 'placeholder' => $expectedPlaceholderArray,
39 | ], $element->toArray());
40 | }
41 |
42 | public function testElementWithOptions()
43 | {
44 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
45 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
46 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
47 |
48 | $expectedPlaceholderArray = ['key' => 'value'];
49 |
50 | $actionId = 'action-id';
51 | $placeholder = \Mockery::mock(TextObject::class);
52 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
53 |
54 | $initialUsers = ['user1', 'user2'];
55 |
56 | $element = new MultiSelectUserElement($actionId, $placeholder);
57 |
58 | $element->withInitialUsers($initialUsers);
59 | $element->maxSelectedItems(5);
60 | $element->withFocusOnLoad();
61 | $element->withConfirmationDialog($confirmationDialogObject);
62 |
63 | $this->assertEquals([
64 | 'type' => Element::TYPE_MULTI_SELECT_USERS,
65 | 'action_id' => $actionId,
66 | 'placeholder' => $expectedPlaceholderArray,
67 | 'focus_on_load' => true,
68 | 'max_selected_items' => 5,
69 | 'initial_users' => $initialUsers,
70 | 'confirm' => $expectedConfirmationDialogArray,
71 | ], $element->toArray());
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/OverflowMenuElementTest.php:
--------------------------------------------------------------------------------
1 | 'v1'];
18 | $expectedOption2Array = ['k2' => 'v2'];
19 |
20 | $option1 = \Mockery::mock(OptionObject::class);
21 | $option2 = \Mockery::mock(OptionObject::class);
22 |
23 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
24 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
25 |
26 | $actionId = 'action-id';
27 |
28 | $element = new OverflowMenuElement($actionId, [$option1, $option2]);
29 |
30 | $this->assertEquals([
31 | 'type' => Element::TYPE_OVERFLOW_MENU,
32 | 'action_id' => $actionId,
33 | 'options' => [$expectedOption1Array, $expectedOption2Array],
34 | ], $element->toArray());
35 |
36 | $this->assertEquals([
37 | Block::TYPE_SECTION,
38 | Block::TYPE_ACTIONS,
39 | ], $element->compatibleWith());
40 | }
41 |
42 | public function testElementWithOptions()
43 | {
44 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
45 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
46 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
47 |
48 | $expectedOption1Array = ['k1' => 'v1'];
49 | $expectedOption2Array = ['k2' => 'v2'];
50 |
51 | $option1 = \Mockery::mock(OptionObject::class);
52 | $option2 = \Mockery::mock(OptionObject::class);
53 |
54 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
55 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
56 |
57 | $actionId = 'action-id';
58 |
59 | $element = new OverflowMenuElement($actionId, [$option1, $option2]);
60 | $element->withConfirmationDialog($confirmationDialogObject);
61 |
62 | $this->assertEquals([
63 | 'type' => Element::TYPE_OVERFLOW_MENU,
64 | 'action_id' => $actionId,
65 | 'options' => [$expectedOption1Array, $expectedOption2Array],
66 | 'confirm' => $expectedConfirmationDialogArray,
67 | ], $element->toArray());
68 |
69 | $this->assertEquals([
70 | Block::TYPE_SECTION,
71 | Block::TYPE_ACTIONS,
72 | ], $element->compatibleWith());
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/PlainTextInputElementTest.php:
--------------------------------------------------------------------------------
1 | assertEquals([
21 | 'type' => Element::TYPE_PLAIN_TEXT_INPUT,
22 | 'action_id' => $actionId,
23 | ], $element->toArray());
24 | }
25 |
26 | public function testElementWithOptions()
27 | {
28 | $actionId = 'action-id';
29 |
30 | $element = new PlainTextInputElement($actionId);
31 |
32 | $expectedPlaceholderArray = ['key' => 'value'];
33 |
34 | $placeholder = \Mockery::mock(TextObject::class);
35 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
36 |
37 | $element->multiline();
38 | $element->withMinLength(1);
39 | $element->withMaxLength(10);
40 | $element->withInitialValue('initial value');
41 | $element->withFocusOnLoad();
42 |
43 | $this->assertEquals([
44 | 'type' => Element::TYPE_PLAIN_TEXT_INPUT,
45 | 'action_id' => $actionId,
46 | 'initial_value' => 'initial value',
47 | 'multiline' => true,
48 | 'min_length' => 1,
49 | 'max_length' => 10,
50 | 'focus_on_load' => true,
51 | ], $element->toArray());
52 | }
53 |
54 | public function testCompatibleWith()
55 | {
56 | $actionId = 'action-id';
57 | $element = new PlainTextInputElement($actionId);
58 |
59 | $this->assertEquals([
60 | Block::TYPE_INPUT,
61 | ], $element->compatibleWith());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/RadioButtonGroupElementTest.php:
--------------------------------------------------------------------------------
1 | 'v1'];
18 | $expectedOption2Array = ['k2' => 'v2'];
19 |
20 | $option1 = \Mockery::mock(OptionObject::class);
21 | $option2 = \Mockery::mock(OptionObject::class);
22 |
23 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
24 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
25 |
26 | $actionId = 'action-id';
27 |
28 | $element = new RadioButtonGroupElement($actionId, [$option1, $option2]);
29 |
30 | $this->assertEquals([
31 | 'type' => Element::TYPE_RADIO_BUTTON_GROUP,
32 | 'action_id' => $actionId,
33 | 'options' => [$expectedOption1Array, $expectedOption2Array],
34 | ], $element->toArray());
35 | }
36 |
37 | public function testElementWithOptions()
38 | {
39 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
40 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
41 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
42 |
43 | $expectedOption1Array = ['k1' => 'v1'];
44 | $expectedOption2Array = ['k2' => 'v2'];
45 |
46 | $option1 = \Mockery::mock(OptionObject::class);
47 | $option2 = \Mockery::mock(OptionObject::class);
48 |
49 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
50 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
51 |
52 | $actionId = 'action-id';
53 |
54 | $element = new RadioButtonGroupElement($actionId, [$option1, $option2]);
55 |
56 | $element->withInitialOption($option1);
57 | $element->withFocusOnLoad();
58 | $element->withConfirmationDialog($confirmationDialogObject);
59 |
60 | $this->assertEquals([
61 | 'type' => Element::TYPE_RADIO_BUTTON_GROUP,
62 | 'action_id' => $actionId,
63 | 'options' => [$expectedOption1Array, $expectedOption2Array],
64 | 'focus_on_load' => true,
65 | 'initial_option' => $expectedOption1Array,
66 | 'confirm' => $expectedConfirmationDialogArray,
67 | ], $element->toArray());
68 | }
69 |
70 | public function testCompatibleWith()
71 | {
72 | $actionId = 'action-id';
73 | $element = new RadioButtonGroupElement($actionId, []);
74 |
75 | $this->assertEquals([
76 | Block::TYPE_SECTION,
77 | Block::TYPE_ACTIONS,
78 | Block::TYPE_INPUT,
79 | ], $element->compatibleWith());
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuConversationElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = SelectMenuConversationElement::class;
23 | $this->expectedType = Element::TYPE_SELECT_MENU_CONVERSATIONS;
24 | }
25 |
26 | public function testElement()
27 | {
28 | $expectedPlaceholderArray = ['key' => 'value'];
29 |
30 | $placeholder = \Mockery::mock(TextObject::class);
31 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
32 |
33 | $actionId = 'action-id';
34 | $element = new SelectMenuConversationElement($actionId, $placeholder);
35 |
36 | $this->assertEquals([
37 | 'type' => Element::TYPE_SELECT_MENU_CONVERSATIONS,
38 | 'action_id' => $actionId,
39 | 'placeholder' => $expectedPlaceholderArray,
40 | ], $element->toArray());
41 | }
42 |
43 | public function testElementWithOptions()
44 | {
45 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
46 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
47 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
48 |
49 | $expectedFilterArray = ['filter' => 'value'];
50 | $filter = \Mockery::mock(FilterObject::class);
51 | $filter->shouldReceive('toArray')->andReturn($expectedFilterArray);
52 |
53 | $expectedPlaceholderArray = ['key' => 'value'];
54 |
55 | $placeholder = \Mockery::mock(TextObject::class);
56 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
57 |
58 | $actionId = 'action-id';
59 | $element = new SelectMenuConversationElement($actionId, $placeholder);
60 |
61 | $element->withInitialOption('general');
62 | $element->withFocusOnLoad();
63 | $element->withResponseUrlEnabled();
64 | $element->defaultToCurrent();
65 | $element->withConfirmationDialog($confirmationDialogObject);
66 | $element->withFilter($filter);
67 |
68 | $this->assertEquals([
69 | 'type' => Element::TYPE_SELECT_MENU_CONVERSATIONS,
70 | 'action_id' => $actionId,
71 | 'placeholder' => $expectedPlaceholderArray,
72 | 'initial_conversation' => 'general',
73 | 'focus_on_load' => true,
74 | 'response_url_enabled' => true,
75 | 'default_to_current_conversation' => true,
76 | 'confirm' => $expectedConfirmationDialogArray,
77 | 'filter' => $expectedFilterArray,
78 | ], $element->toArray());
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuExternalElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = SelectMenuExternalElement::class;
23 | $this->expectedType = Element::TYPE_SELECT_MENU_EXTERNAL;
24 | }
25 |
26 | public function testElement()
27 | {
28 | $expectedPlaceholderArray = ['key' => 'value'];
29 |
30 | $placeholder = \Mockery::mock(TextObject::class);
31 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
32 |
33 | $actionId = 'action-id';
34 | $element = new SelectMenuExternalElement($actionId, $placeholder);
35 |
36 | $this->assertEquals([
37 | 'type' => Element::TYPE_SELECT_MENU_EXTERNAL,
38 | 'action_id' => $actionId,
39 | 'placeholder' => $expectedPlaceholderArray,
40 | ], $element->toArray());
41 | }
42 |
43 | public function testElementWithOptions()
44 | {
45 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
46 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
47 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
48 |
49 | $expectedPlaceholderArray = ['key' => 'value'];
50 |
51 | $placeholder = \Mockery::mock(TextObject::class);
52 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
53 |
54 | $expectedOption1Array = ['k1' => 'v1'];
55 | $expectedOption2Array = ['k2' => 'v2'];
56 |
57 | $option1 = \Mockery::mock(OptionObject::class);
58 | $option2 = \Mockery::mock(OptionObject::class);
59 |
60 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
61 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
62 |
63 | $actionId = 'action-id';
64 | $element = new SelectMenuExternalElement($actionId, $placeholder);
65 |
66 | $element->withMinQueryLength(5);
67 | $element->withInitialOption($option1);
68 | $element->withFocusOnLoad();
69 | $element->withConfirmationDialog($confirmationDialogObject);
70 |
71 | $this->assertEquals([
72 | 'type' => Element::TYPE_SELECT_MENU_EXTERNAL,
73 | 'action_id' => $actionId,
74 | 'placeholder' => $expectedPlaceholderArray,
75 | 'initial_option' => $expectedOption1Array,
76 | 'focus_on_load' => true,
77 | 'min_query_length' => 5,
78 | 'confirm' => $expectedConfirmationDialogArray,
79 | ], $element->toArray());
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuPublicChannelElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = SelectMenuPublicChannelElement::class;
22 | $this->expectedType = Element::TYPE_SELECT_MENU_CHANNELS;
23 | }
24 |
25 | public function testElement()
26 | {
27 | $expectedPlaceholderArray = ['key' => 'value'];
28 |
29 | $placeholder = \Mockery::mock(TextObject::class);
30 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
31 |
32 | $actionId = 'action-id';
33 | $element = new SelectMenuPublicChannelElement($actionId, $placeholder);
34 |
35 | $this->assertEquals([
36 | 'type' => Element::TYPE_SELECT_MENU_CHANNELS,
37 | 'action_id' => $actionId,
38 | 'placeholder' => $expectedPlaceholderArray,
39 | ], $element->toArray());
40 | }
41 |
42 | public function testElementWithOptions()
43 | {
44 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
45 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
46 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
47 |
48 | $expectedPlaceholderArray = ['key' => 'value'];
49 |
50 | $placeholder = \Mockery::mock(TextObject::class);
51 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
52 |
53 | $actionId = 'action-id';
54 | $element = new SelectMenuPublicChannelElement($actionId, $placeholder);
55 |
56 | $element->withInitialOption('general');
57 | $element->withFocusOnLoad();
58 | $element->withResponseUrlEnabled();
59 | $element->withConfirmationDialog($confirmationDialogObject);
60 |
61 | $this->assertEquals([
62 | 'type' => Element::TYPE_SELECT_MENU_CHANNELS,
63 | 'action_id' => $actionId,
64 | 'placeholder' => $expectedPlaceholderArray,
65 | 'initial_channel' => 'general',
66 | 'focus_on_load' => true,
67 | 'response_url_enabled' => true,
68 | 'confirm' => $expectedConfirmationDialogArray,
69 | ], $element->toArray());
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuStaticElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = SelectMenuStaticElement::class;
23 | $this->expectedType = Element::TYPE_SELECT_MENU_STATIC;
24 | $this->additionalSetupArgs = [[]];
25 | }
26 |
27 | public function testElement()
28 | {
29 | $expectedPlaceholderArray = ['key' => 'value'];
30 |
31 | $placeholder = \Mockery::mock(TextObject::class);
32 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
33 |
34 | $expectedOption1Array = ['k1' => 'v1'];
35 | $expectedOption2Array = ['k2' => 'v2'];
36 |
37 | $option1 = \Mockery::mock(OptionObject::class);
38 | $option2 = \Mockery::mock(OptionObject::class);
39 |
40 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
41 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
42 |
43 | $actionId = 'action-id';
44 | $element = new SelectMenuStaticElement($actionId, $placeholder, [$option1, $option2]);
45 |
46 | $this->assertEquals([
47 | 'type' => Element::TYPE_SELECT_MENU_STATIC,
48 | 'action_id' => $actionId,
49 | 'placeholder' => $expectedPlaceholderArray,
50 | 'options' => [$expectedOption1Array, $expectedOption2Array],
51 | ], $element->toArray());
52 | }
53 |
54 | public function testElementWithOptions()
55 | {
56 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
57 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
58 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
59 |
60 | $expectedPlaceholderArray = ['key' => 'value'];
61 |
62 | $placeholder = \Mockery::mock(TextObject::class);
63 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
64 |
65 | $expectedOption1Array = ['k1' => 'v1'];
66 | $expectedOption2Array = ['k2' => 'v2'];
67 |
68 | $option1 = \Mockery::mock(OptionObject::class);
69 | $option2 = \Mockery::mock(OptionObject::class);
70 |
71 | $option1->shouldReceive('toArray')->andReturn($expectedOption1Array);
72 | $option2->shouldReceive('toArray')->andReturn($expectedOption2Array);
73 |
74 | $actionId = 'action-id';
75 | $element = new SelectMenuStaticElement($actionId, $placeholder, [$option1, $option2]);
76 |
77 | $element->withInitialOption($option1);
78 | $element->withFocusOnLoad();
79 | $element->withConfirmationDialog($confirmationDialogObject);
80 |
81 | $this->assertEquals([
82 | 'type' => Element::TYPE_SELECT_MENU_STATIC,
83 | 'action_id' => $actionId,
84 | 'placeholder' => $expectedPlaceholderArray,
85 | 'options' => [$expectedOption1Array, $expectedOption2Array],
86 | 'initial_option' => $expectedOption1Array,
87 | 'focus_on_load' => true,
88 | 'confirm' => $expectedConfirmationDialogArray,
89 | ], $element->toArray());
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/SelectMenu/SelectMenuUserElementTest.php:
--------------------------------------------------------------------------------
1 | elementClass = SelectMenuUserElement::class;
23 | $this->expectedType = Element::TYPE_SELECT_MENU_USERS;
24 | }
25 |
26 | public function testElement()
27 | {
28 | $expectedPlaceholderArray = ['key' => 'value'];
29 |
30 | $placeholder = \Mockery::mock(TextObject::class);
31 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
32 |
33 | $actionId = 'action-id';
34 | $element = new SelectMenuUserElement($actionId, $placeholder);
35 |
36 | $this->assertEquals([
37 | 'type' => Element::TYPE_SELECT_MENU_USERS,
38 | 'action_id' => $actionId,
39 | 'placeholder' => $expectedPlaceholderArray,
40 | ], $element->toArray());
41 | }
42 |
43 | public function testElementWithOptions()
44 | {
45 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
46 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
47 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
48 |
49 | $expectedPlaceholderArray = ['key' => 'value'];
50 |
51 | $placeholder = \Mockery::mock(TextObject::class);
52 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
53 |
54 | $actionId = 'action-id';
55 | $element = new SelectMenuUserElement($actionId, $placeholder);
56 |
57 | $element->withInitialOption('username');
58 | $element->withFocusOnLoad();
59 | $element->withConfirmationDialog($confirmationDialogObject);
60 |
61 | $this->assertEquals([
62 | 'type' => Element::TYPE_SELECT_MENU_USERS,
63 | 'action_id' => $actionId,
64 | 'placeholder' => $expectedPlaceholderArray,
65 | 'initial_user' => 'username',
66 | 'focus_on_load' => true,
67 | 'confirm' => $expectedConfirmationDialogArray,
68 | ], $element->toArray());
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBlocks/Elements/TimePickerElementTest.php:
--------------------------------------------------------------------------------
1 | 'value'];
18 |
19 | $placeholder = \Mockery::mock(TextObject::class);
20 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
21 |
22 | $actionId = 'action-id';
23 |
24 | $element = new TimePickerElement($actionId, $placeholder);
25 |
26 | $this->assertEquals([
27 | 'type' => Element::TYPE_TIME_PICKER,
28 | 'action_id' => $actionId,
29 | 'placeholder' => $expectedPlaceholderArray,
30 | ], $element->toArray());
31 | }
32 |
33 | public function testElementWithOptions()
34 | {
35 | $expectedConfirmationDialogArray = ['key2' => 'value2'];
36 | $confirmationDialogObject = \Mockery::mock(ConfirmationDialogObject::class);
37 | $confirmationDialogObject->shouldReceive('toArray')->andReturn($expectedConfirmationDialogArray);
38 |
39 | $expectedPlaceholderArray = ['key' => 'value'];
40 |
41 | $placeholder = \Mockery::mock(TextObject::class);
42 | $placeholder->shouldReceive('toArray')->andReturn($expectedPlaceholderArray);
43 |
44 | $actionId = 'action-id';
45 |
46 | $element = new TimePickerElement($actionId, $placeholder);
47 |
48 | $element->withFocusOnLoad();
49 | $element->withInitialTime('10:00:00');
50 | $element->withConfirmationDialog($confirmationDialogObject);
51 |
52 | $this->assertEquals([
53 | 'type' => Element::TYPE_TIME_PICKER,
54 | 'action_id' => $actionId,
55 | 'placeholder' => $expectedPlaceholderArray,
56 | 'focus_on_load' => true,
57 | 'initial_time' => '10:00:00',
58 | 'confirm' => $expectedConfirmationDialogArray,
59 | ], $element->toArray());
60 | }
61 |
62 | public function testCompatibleWith()
63 | {
64 | $element = new TimePickerElement('action-id', \Mockery::mock(TextObject::class));
65 | $this->assertEquals([
66 | Block::TYPE_SECTION,
67 | Block::TYPE_ACTIONS,
68 | Block::TYPE_INPUT,
69 | ], $element->compatibleWith());
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/Unit/Support/LayoutBuilder/BuilderTest.php:
--------------------------------------------------------------------------------
1 | withPlainText($text);
23 |
24 | $this->assertInstanceOf(TextObject::class, $result);
25 | $this->assertEquals([
26 | 'type' => 'plain_text',
27 | 'text' => $text,
28 | ], $result->toArray());
29 | }
30 |
31 | public function testWithMarkdownText()
32 | {
33 | $text = 'test text';
34 |
35 | $builder = new Builder();
36 | $result = $builder->withMarkdownText($text);
37 |
38 | $this->assertInstanceOf(MarkdownObject::class, $result);
39 | $this->assertEquals([
40 | 'type' => 'mrkdwn',
41 | 'text' => $text,
42 | ], $result->toArray());
43 | }
44 |
45 | public function testDivider()
46 | {
47 | $builder = new Builder();
48 | $builder->divider();
49 |
50 | $blocks = $builder->getBlocks();
51 | $this->assertCount(1, $blocks);
52 | $this->assertInstanceOf(DividerBlock::class, $blocks[0]);
53 | }
54 |
55 | public function testHeader()
56 | {
57 | $text = 'test header';
58 |
59 | $builder = new Builder();
60 | $builder->header($text);
61 |
62 | $blocks = $builder->getBlocks();
63 | $this->assertCount(1, $blocks);
64 | $this->assertInstanceOf(HeaderBlock::class, $blocks[0]);
65 | $this->assertEquals([
66 | 'type' => 'header',
67 | 'text' => [
68 | 'type' => 'plain_text',
69 | 'text' => $text,
70 | ],
71 | ], $blocks[0]->toArray());
72 | }
73 |
74 | public function testAddBlock()
75 | {
76 | $block1 = new ActionsBlock([]);
77 | $block2 = new DividerBlock();
78 | $block3 = new ContextBlock([], []);
79 |
80 | $builder = new Builder();
81 |
82 | $builder
83 | ->addBlock($block3)
84 | ->addBlock($block1)
85 | ->addBlock($block2);
86 |
87 | $blocks = $builder->getBlocks();
88 | $this->assertCount(3, $blocks);
89 |
90 | $first = $blocks[0];
91 | $second = $blocks[1];
92 | $third = $blocks[2];
93 |
94 | $this->assertSame($block3, $first);
95 | $this->assertSame($block1, $second);
96 | $this->assertSame($block2, $third);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/tests/Unit/Support/PaginatorTest.php:
--------------------------------------------------------------------------------
1 | assertFalse($paginator->hasMorePages());
17 | $this->assertNull($paginator->nextCursor());
18 | $this->assertEquals([
19 | 'items' => $items,
20 | 'next_cursor' => null,
21 | 'has_more_pages' => false,
22 | ], $paginator->toArray());
23 | }
24 |
25 | public function testWithMultiplePages()
26 | {
27 | $items = [1, 2, 3];
28 | $nextCursor = 'next-cursor';
29 |
30 | $paginator = new Paginator($items, $nextCursor);
31 |
32 | $this->assertTrue($paginator->hasMorePages());
33 | $this->assertSame($nextCursor, $paginator->nextCursor());
34 | $this->assertEquals([
35 | 'items' => $items,
36 | 'next_cursor' => $nextCursor,
37 | 'has_more_pages' => true,
38 | ], $paginator->toArray());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/Unit/Support/SlackOptionsBuilderTest.php:
--------------------------------------------------------------------------------
1 | assertEmpty($builder->toArray());
15 | }
16 |
17 | public function testAllOptions()
18 | {
19 | $builder = new SlackOptionsBuilder();
20 |
21 | $builder
22 | ->username('Test Bot')
23 | ->iconUrl('https://example.com')
24 | ->iconEmoji(':test:')
25 | ->unfurlMedia()
26 | ->unfurlLinks()
27 | ->threadTs('test-ts')
28 | ->threadReplySendToChannel()
29 | ->linkNames()
30 | ->metadata(['key' => 'val'])
31 | ->parse('test-parse')
32 | ->markdown();
33 |
34 | $this->assertEquals([
35 | 'username' => 'Test Bot',
36 | 'icon' => [
37 | 'url' => 'https://example.com',
38 | 'emoji' => ':test:',
39 | ],
40 | 'unfurl' => [
41 | 'media' => true,
42 | 'links' => true,
43 | ],
44 | 'thread' => [
45 | 'ts' => 'test-ts',
46 | 'send_to_channel' => true,
47 | ],
48 | 'link_names' => true,
49 | 'metadata' => ['key' => 'val'],
50 | 'parse' => 'test-parse',
51 | 'markdown' => true,
52 | ], $builder->toArray());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------