Repository: slackapi/python-slack-sdk (python)

Issue:
Add the method to check equality in Block Kit model classes
### Reproducible in:

#### The Slack SDK version

All versions

#### Steps to reproduce:

```python
from slack_sdk.models.blocks import DividerBlock
DividerBlock() == DividerBlock()
```

It happens with any pair of equivalent blocks.

### Expected result:

True

### Actual result:

False

### Suggested solution

Implementing `__eq__` in JsonObject.

```python
class JsonObject(BaseObject, metaclass=ABCMeta):
    ...
    def __eq__(self, other: Any) -> bool:
        if not isinstance(other, JsonObject):
            return NotImplemented
        return self.to_dict() == other.to_dict()
```

This would allow testing user functions that accept and/or return Slack SDK models.

Pull request:
Fix #1131 Add the method to check equality in Block Kit model classes
## Summary

Fixes #1131 

@seratch
Sorry for the delay.
I worked on the issue #1131.

I've confirmed the following.
- Passing Unit Tests
- Solving the problem in interactive mode

Thank you for checking!

### Category (place an `x` in each of the `[ ]`)

- [ ] **slack_sdk.web.WebClient (sync/async)** (Web API client)
- [ ] **slack_sdk.webhook.WebhookClient (sync/async)** (Incoming Webhook, response_url sender)
- [ ] **slack_sdk.socket_mode** (Socket Mode client)
- [ ] **slack_sdk.signature** (Request Signature Verifier)
- [ ] **slack_sdk.oauth** (OAuth Flow Utilities)
- [x] **slack_sdk.models** (UI component builders)
- [ ] **slack_sdk.scim** (SCIM API client)
- [ ] **slack_sdk.audit_logs** (Audit Logs API client)
- [ ] **slack_sdk.rtm_v2** (RTM client)
- [ ] `/docs-src` (Documents, have you run `./scripts/docs.sh`?)
- [ ] `/docs-src-v2` (Documents, have you run `./scripts/docs-v2.sh`?)
- [ ] `/tutorial` (PythOnBoardingBot tutorial)
- [x] `tests`/`integration_tests` (Automated tests for this library)

## Requirements (place an `x` in each `[ ]`)

- [x] I've read and understood the [Contributing Guidelines](https://github.com/slackapi/python-slack-sdk/blob/main/.github/contributing.md) and have done my best effort to follow them.
- [x] I've read and agree to the [Code of Conduct](https://slackhq.github.io/code-of-conduct).
- [x] I've run `python3 -m venv .venv && source .venv/bin/activate && ./scripts/run_validation.sh` after making the changes.


Patch:
diff --git a/slack_sdk/models/basic_objects.py b/slack_sdk/models/basic_objects.py
index 3223148..814ab95 100644
--- a/slack_sdk/models/basic_objects.py
+++ b/slack_sdk/models/basic_objects.py
@@ -87,6 +87,11 @@ class JsonObject(BaseObject, metaclass=ABCMeta):
         else:
             return self.__str__()
 
+    def __eq__(self, other: Any) -> bool:
+        if not isinstance(other, JsonObject):
+            return False
+        return self.to_dict() == other.to_dict()
+
 
 class JsonValidator:
     def __init__(self, message: str):


Test patch:
diff --git a/tests/slack_sdk/models/test_blocks.py b/tests/slack_sdk/models/test_blocks.py
index 4eadbd4..c79cfed 100644
--- a/tests/slack_sdk/models/test_blocks.py
+++ b/tests/slack_sdk/models/test_blocks.py
@@ -54,6 +54,11 @@ class BlockTests(unittest.TestCase):
             block.to_dict(),
         )
 
+    def test_eq(self):
+        self.assertEqual(Block(), Block())
+        self.assertEqual(Block(type="test"), Block(type="test"))
+        self.assertNotEqual(Block(type="test"), Block(type="another test"))
+
 
 # ----------------------------------------------
 # Section
diff --git a/tests/slack_sdk/models/test_elements.py b/tests/slack_sdk/models/test_elements.py
index 62d23cc..7ebb6b5 100644
--- a/tests/slack_sdk/models/test_elements.py
+++ b/tests/slack_sdk/models/test_elements.py
@@ -2,6 +2,7 @@ import unittest
 
 from slack_sdk.errors import SlackObjectFormationError
 from slack_sdk.models.blocks import (
+    BlockElement,
     ButtonElement,
     DatePickerElement,
     TimePickerElement,
@@ -29,6 +30,15 @@ from slack_sdk.models.blocks import (
 from . import STRING_3001_CHARS, STRING_301_CHARS
 
 
+class BlockElementTests(unittest.TestCase):
+    def test_eq(self):
+        self.assertEqual(BlockElement(), BlockElement())
+        self.assertEqual(BlockElement(type="test"), BlockElement(type="test"))
+        self.assertNotEqual(
+            BlockElement(type="test"), BlockElement(type="another test")
+        )
+
+
 # -------------------------------------------------
 # Interactive Elements
 # -------------------------------------------------
diff --git a/tests/slack_sdk/models/test_objects.py b/tests/slack_sdk/models/test_objects.py
index f04057e..b861a76 100644
--- a/tests/slack_sdk/models/test_objects.py
+++ b/tests/slack_sdk/models/test_objects.py
@@ -148,6 +148,14 @@ class JsonObjectTests(unittest.TestCase):
         )
         self.assertDictEqual(expected, nested.get_non_null_attributes())
 
+    def test_eq(self):
+        obj1 = SimpleJsonObject()
+        self.assertEqual(self.good_test_object, obj1)
+
+        obj2 = SimpleJsonObject()
+        obj2.test = "another"
+        self.assertNotEqual(self.good_test_object, obj2)
+
 
 class JsonValidatorTests(unittest.TestCase):
     def setUp(self) -> None:
diff --git a/tests/slack_sdk/models/test_views.py b/tests/slack_sdk/models/test_views.py
index 7980262..6803928 100644
--- a/tests/slack_sdk/models/test_views.py
+++ b/tests/slack_sdk/models/test_views.py
@@ -531,3 +531,15 @@ class ViewTests(unittest.TestCase):
     def test_load_home_tab_view_006(self):
         with open("tests/slack_sdk_fixture/view_home_006.json") as file:
             self.verify_loaded_view_object(file)
+
+    def test_eq(self):
+        input = {
+            "type": "modal",
+            "blocks": [DividerBlock()],
+        }
+        another_input = {
+            "type": "modal",
+            "blocks": [DividerBlock(), DividerBlock()],
+        }
+        self.assertEqual(View(**input), View(**input))
+        self.assertNotEqual(View(**input), View(**another_input))