From 0e69510a56deec5032504f7a1699a8b1887364c9 Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Tue, 21 Apr 2026 19:18:35 -0600 Subject: [PATCH] Fix #130: Incorrect validation of initial_options for OptionGroup entries. The `initial_option` [field](https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#fields) of a `StaticSelect` should single option even when the menu contains `OptionGroup`s. This PR fixes the validator and fixes the broken tests that let the old validator pass. The fix also applies to the validation of `MultiStaticSelect` and the tests of that are fixes as well. --- blockkit/core.py | 9 ++++++++- tests/test_core.py | 40 ++++++++-------------------------------- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/blockkit/core.py b/blockkit/core.py index e504715..48da2f2 100644 --- a/blockkit/core.py +++ b/blockkit/core.py @@ -244,7 +244,14 @@ def validate(self, component: "Component") -> None: if not isinstance(source_value, list | tuple | set): source_value = [source_value] - if not set(source_value).issubset(set(target_value)): + flattened_target = [] + for item in target_value: + if isinstance(item, OptionGroup): + flattened_target.extend(item._get_field_value("options") or []) + else: + flattened_target.append(item) + + if not set(source_value).issubset(set(flattened_target)): raise ComponentValidationError( component, f"'{self.source_field}' has items that aren't " diff --git a/tests/test_core.py b/tests/test_core.py index 5227f67..27224be 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1120,16 +1120,8 @@ def test_builds_option_groups(self): ], "initial_options": [ { - "label": { - "type": "plain_text", - "text": "Group 1", - }, - "options": [ - { - "text": {"type": "plain_text", "text": "Option 1"}, - "value": "option_1", - } - ], + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "option_1", }, ], } @@ -1144,9 +1136,7 @@ def test_builds_option_groups(self): ), ], initial_options=[ - OptionGroup( - label="Group 1", options=[Option(text="Option 1", value="option_1")] - ) + Option(text="Option 1", value="option_1") ], ).build() assert got == want @@ -1165,9 +1155,7 @@ def test_builds_option_groups(self): ), ) .add_initial_option( - OptionGroup( - label="Group 1", options=[Option(text="Option 1", value="option_1")] - ) + Option(text="Option 1", value="option_1") ) .build() ) @@ -1933,16 +1921,8 @@ def test_builds_option_groups(self): }, ], "initial_option": { - "label": { - "type": "plain_text", - "text": "Group 1", - }, - "options": [ - { - "text": {"type": "plain_text", "text": "Option 1"}, - "value": "option_1", - } - ], + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "option_1", }, } got = StaticSelect( @@ -1955,9 +1935,7 @@ def test_builds_option_groups(self): label="Group 2", options=[Option(text="Option 2", value="option_2")] ), ], - initial_option=OptionGroup( - label="Group 1", options=[Option(text="Option 1", value="option_1")] - ), + initial_option=Option(text="Option 1", value="option_1"), ).build() assert got == want @@ -1975,9 +1953,7 @@ def test_builds_option_groups(self): ), ) .initial_option( - OptionGroup( - label="Group 1", options=[Option(text="Option 1", value="option_1")] - ) + Option(text="Option 1", value="option_1") ) .build() )