Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Allow using <RadioButtonGroup> / <CheckboxGroup> in <Blocks> #197

Merged
merged 6 commits into from
Oct 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Changed

- Allow using `<RadioButtonGroup>` and `<CheckboxGroup>` in message container `<Blocks>` ([#196](https://github.com/speee/jsx-slack/issues/196), [#197](https://github.com/speee/jsx-slack/pull/197))
- Upgrade dependent packages to the latest version ([#191](https://github.com/speee/jsx-slack/pull/191), [#198](https://github.com/speee/jsx-slack/pull/198))

## v2.4.0 - 2020-07-30
Expand Down
8 changes: 4 additions & 4 deletions docs/block-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,9 @@ An easy way to let the user selecting any date is using `<DatePicker>` component
- `title`/ `hint` (optional): Specify a helpful text appears under the element.
- `required` (optional): A boolean prop to specify whether any value must be filled when user confirms modal.

### <a name="checkbox-group" id="checkbox-group"></a> [`<CheckboxGroup>`: Checkbox group](https://api.slack.com/reference/block-kit/block-elements#checkboxes) (Only for modal and home tab)
### <a name="checkbox-group" id="checkbox-group"></a> [`<CheckboxGroup>`: Checkbox group](https://api.slack.com/reference/block-kit/block-elements#checkboxes)

A container for grouping checkboxes. _This component is only for [`<Modal>`](block-containers.md#modal) and [`<Home>`](block-containers.md#home) container. It cannot use in [`<Blocks>`](block-containers.md#blocks) container for messaging._
A container for grouping checkboxes.

```jsx
<Home>
Expand Down Expand Up @@ -547,9 +547,9 @@ A below checkbox is meaning exactly the same as an example shown earlier.
</Checkbox>
```

### <a name="radio-button-group" id="radio-button-group"></a> [`<RadioButtonGroup>`: Radio button group](https://api.slack.com/reference/block-kit/block-elements#radio) (Only for modal and home tab)
### <a name="radio-button-group" id="radio-button-group"></a> [`<RadioButtonGroup>`: Radio button group](https://api.slack.com/reference/block-kit/block-elements#radio)

A container for grouping radio buttons. _This component is only for [`<Modal>`](block-containers.md#modal) and [`<Home>`](block-containers.md#home) container. It cannot use in [`<Blocks>`](block-containers.md#blocks) container for messaging._
A container for grouping radio buttons.

```jsx
<Home>
Expand Down
4 changes: 2 additions & 2 deletions docs/jsx-components-for-block-kit.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
- [**`<Overflow>`**: Overflow menu](block-elements.md#overflow)
- [**`<OverflowItem>`**: Menu item in overflow menu](block-elements.md#overflow-item)
- [**`<DatePicker>`**: Select date from calendar](block-elements.md#date-picker)
- [**`<CheckboxGroup>`**: Checkbox group](block-elements.md#checkbox-group) (Only for modal and home tab)
- [**`<CheckboxGroup>`**: Checkbox group](block-elements.md#checkbox-group)
- [**`<Checkbox>`**: Checkbox](block-elements.md#checkbox)
- [**`<RadioButtonGroup>`**: Radio button group](block-elements.md#radio-button-group) (Only for modal and home tab)
- [**`<RadioButtonGroup>`**: Radio button group](block-elements.md#radio-button-group)
- [**`<RadioButton>`**: Radio button](block-elements.md#radio-button)

### **[Composition objects](block-elements.md#composition-objects)**
Expand Down
11 changes: 2 additions & 9 deletions src/block-kit/container/Blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import {
generateSectionValidator,
} from './utils'

// Message block cannot use "radio_buttons" and "checkboxes"
const blockTypeFilter = (t) => t !== 'radio_buttons' && t !== 'checkboxes'

/**
* The basic container component for Slack Block Kit suited to
* {@link https://api.slack.com/surfaces/messages|messages}.
Expand Down Expand Up @@ -48,18 +45,14 @@ const blockTypeFilter = (t) => t !== 'radio_buttons' && t !== 'checkboxes'
export const Blocks = generateBlocksContainer({
name: 'Blocks',
availableBlockTypes: {
actions: generateActionsValidator(
availableActionTypes.filter(blockTypeFilter)
),
actions: generateActionsValidator([...availableActionTypes]),
call: true,
context: true,
divider: true,
file: true,
header: true,
image: true,
section: generateSectionValidator(
availableSectionAccessoryTypes.filter(blockTypeFilter)
),
section: generateSectionValidator(availableSectionAccessoryTypes),
},
aliases: {
header: Header,
Expand Down
3 changes: 0 additions & 3 deletions src/block-kit/elements/CheckboxGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ type CheckboxGroupProps = InputComponentProps<CheckboxGroupBaseProps>
*
* Provide the container to choose multiple options supplied by `<Checkbox>`.
*
* _This component is available only in `<Modal>` and `<Home>` container, and
* cannot use in `<Blocks>` container for messaging._
*
* @example
* ```jsx
* <Modal title="Quick survey">
Expand Down
3 changes: 0 additions & 3 deletions src/block-kit/elements/RadioButtonGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ type RadioButtonGroupProps = InputComponentProps<RadioButtonGroupBaseProps>
* Provide the container to choose one of the options supplied by
* `<RadioButton>`.
*
* _This component is available only in `<Modal>` and `<Home>` container, and
* cannot use in `<Blocks>` container for messaging._
*
* @example
* ```jsx
* <Home>
Expand Down
4 changes: 2 additions & 2 deletions src/block-kit/layout/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ const actionTypeValidators: Record<string, (action: Action) => void> = {
* - `<ChannelsSelect>` _(Single-select only)_
* - `<Overflow>`
* - `<DatePicker>`
* - `<CheckboxGroup>` _(Only for `<Modal>` and `<Home>` container)_
* - `<RadioButtonGroup>` _(Only for `<Modal>` and `<Home>` container)_
* - `<CheckboxGroup>`
* - `<RadioButtonGroup>`
*
* @return The partial JSON for `actions` layout block
*/
Expand Down
4 changes: 2 additions & 2 deletions src/block-kit/layout/Section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ export const Field = createComponent<FieldProps, MrkdwnElement>(
* - `<ChannelsSelect>`
* - `<Overflow>`
* - `<DatePicker>`
* - `<CheckboxGroup>` _(Only for `<Modal>` and `<Home>` container)_
* - `<RadioButtonGroup>` _(Only for `<Modal>` and `<Home>` container)_
* - `<CheckboxGroup>`
* - `<RadioButtonGroup>`
*
* ### Fields
*
Expand Down
80 changes: 13 additions & 67 deletions test/block-kit/block-elements/interactive-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ describe('Interactive components', () => {

expect(
JSXSlack(
<Home>
<Blocks>
<Actions blockId="actions">
<RadioButtonGroup actionId="radio-buttons" value="second">
<RadioButton value="first" description="The first option">
Expand All @@ -1140,8 +1140,8 @@ describe('Interactive components', () => {
<RadioButton value="third">3rd</RadioButton>
</RadioButtonGroup>
</Actions>
</Home>
).blocks
</Blocks>
)
).toStrictEqual([action(radioButtonAction)])

// `checked` state prop, `confirm` prop and HTML-compatible props in <Modal>
Expand Down Expand Up @@ -1178,15 +1178,15 @@ describe('Interactive components', () => {

it('outputs radio button group in section block', () => {
const [section]: SectionBlock[] = JSXSlack(
<Home>
<Blocks>
<Section>
test
<RadioButtonGroup>
<RadioButton value="a">A</RadioButton>
</RadioButtonGroup>
</Section>
</Home>
).blocks
</Blocks>
)

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
expect(section.accessory!.type).toBe('radio_buttons')
Expand Down Expand Up @@ -1270,33 +1270,6 @@ describe('Interactive components', () => {
</RadioButtonGroup>
)).toThrow(/must contain/i)
})

it('throws error when using <RadioButtonGroup> within <Blocks> container', () => {
expect(() =>
JSXSlack(
<Blocks>
<Section>
test
<RadioButtonGroup>
<RadioButton value="a">A</RadioButton>
</RadioButtonGroup>
</Section>
</Blocks>
)
).toThrow(/incompatible/i)

expect(() =>
JSXSlack(
<Blocks>
<Actions>
<RadioButtonGroup>
<RadioButton value="a">A</RadioButton>
</RadioButtonGroup>
</Actions>
</Blocks>
)
).toThrow(/incompatible/i)
})
})

describe('<CheckboxGroup>', () => {
Expand Down Expand Up @@ -1428,15 +1401,15 @@ describe('Interactive components', () => {

it('outputs checkbox group in section block', () => {
const [section]: SectionBlock[] = JSXSlack(
<Home>
<Blocks>
<Section>
test
<CheckboxGroup>
<Checkbox value="a">A</Checkbox>
</CheckboxGroup>
</Section>
</Home>
).blocks
</Blocks>
)

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
expect(section.accessory!.type).toBe('checkboxes')
Expand All @@ -1445,52 +1418,25 @@ describe('Interactive components', () => {
it('throws error when <CheckboxGroup> has not contained <Checkbox>', () => {
expect(() =>
JSXSlack(
<Home>
<Blocks>
<Actions>
<CheckboxGroup>{}</CheckboxGroup>
</Actions>
</Home>
)
).toThrow(/must contain/i)

expect(() =>
JSXSlack(
<Home>
<Actions>
<CheckboxGroup>
<Option value="wtf">I&apos;m not checkbox</Option>
</CheckboxGroup>
</Actions>
</Home>
)
).toThrow(/must contain/i)
})

it('throws error when using <CheckboxGroup> within <Blocks> container', () => {
expect(() =>
JSXSlack(
<Blocks>
<Section>
test
<CheckboxGroup>
<Checkbox value="a">A</Checkbox>
</CheckboxGroup>
</Section>
</Blocks>
)
).toThrow(/incompatible/i)
).toThrow(/must contain/i)

expect(() =>
JSXSlack(
<Blocks>
<Actions>
<CheckboxGroup>
<Checkbox value="a">A</Checkbox>
<Option value="wtf">I&apos;m not checkbox</Option>
</CheckboxGroup>
</Actions>
</Blocks>
)
).toThrow(/incompatible/i)
).toThrow(/must contain/i)
})

it('prefers description prop of <Checkbox> rather than the content in <small> element', () => {
Expand Down
71 changes: 45 additions & 26 deletions test/block-kit/container-components.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @jsx JSXSlack.h */
import { PlainTextElement, View } from '@slack/types'
import {
Actions,
Blocks,
Call,
Escape,
Expand All @@ -22,34 +23,52 @@ describe('Container components', () => {

describe('<Blocks>', () => {
it('throws error when <Blocks> has unexpected element', () => {
expect(() =>
JSXSlack(
<Blocks>
<b>unexpected</b>
</Blocks>
)
).toThrow()

expect(() =>
JSXSlack(
<Blocks>
<Escape>unexpected</Escape>
</Blocks>
)
).toThrow()
expect(() => (
<Blocks>
<b>unexpected</b>
</Blocks>
)).toThrow()

expect(() => (
<Blocks>
<Escape>unexpected</Escape>
</Blocks>
)).toThrow()

// <Input> block cannot use in message
expect(() =>
JSXSlack(
<Blocks>
<Input label="Select">
<Select>
<Option value="test">test</Option>
</Select>
</Input>
</Blocks>
)
).toThrow()
expect(() => (
<Blocks>
<Input label="Select">
<Select>
<Option value="test">test</Option>
</Select>
</Input>
</Blocks>
)).toThrow()

// Incompatible accessory for section block
expect(() => (
<Blocks>
{
{
type: 'section',
accessory: { type: 'incompatible' },
} as any
}
</Blocks>
)).toThrow(/incompatible/)

// Incompatible interactive element for actions block
expect(() => (
<Blocks>
{
{
type: 'actions',
elements: [{ type: 'incompatible' }],
} as any
}
</Blocks>
)).toThrow(/incompatible/)
})

it('ignores invalid literal values to keep compatibillity with v1', () => {
Expand Down