Skip to content

Commit 2e02c39

Browse files
committed
Update slackBotFunction unit tests after implementing async events
1 parent 3b3a6ef commit 2e02c39

File tree

1 file changed

+120
-87
lines changed

1 file changed

+120
-87
lines changed

packages/slackBotFunction/tests/test_app.py

Lines changed: 120 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,30 @@ def mock_env():
1717
env_vars = {
1818
"SLACK_BOT_TOKEN_PARAMETER": "/test/bot-token",
1919
"SLACK_SIGNING_SECRET_PARAMETER": "/test/signing-secret",
20-
"SLACK_SLASH_COMMAND": "/ask-eps",
20+
"SLACK_DEDUPLICATION_TABLE": "test-dedup-table",
2121
"KNOWLEDGEBASE_ID": "test-kb-id",
2222
"RAG_MODEL_ID": "test-model-id",
2323
"AWS_REGION": "eu-west-2",
2424
"GUARD_RAIL_ID": "test-guard-id",
2525
"GUARD_RAIL_VERSION": "1",
26+
"AWS_LAMBDA_FUNCTION_NAME": "test-function",
2627
}
2728
with patch.dict(os.environ, env_vars):
2829
yield env_vars
2930

3031

3132
@pytest.fixture
32-
def mock_ssm_parameters():
33-
"""Mock SSM parameters"""
33+
def mock_dynamodb_table():
34+
"""Mock DynamoDB table"""
3435
with mock_aws():
35-
client = boto3.client("ssm", region_name="eu-west-2")
36-
client.put_parameter(
37-
Name="/test/bot-token",
38-
Value=json.dumps({"token": TEST_BOT_TOKEN}),
39-
Type="SecureString",
36+
dynamodb = boto3.resource("dynamodb", region_name="eu-west-2")
37+
table = dynamodb.create_table(
38+
TableName="test-dedup-table",
39+
KeySchema=[{"AttributeName": "eventId", "KeyType": "HASH"}],
40+
AttributeDefinitions=[{"AttributeName": "eventId", "AttributeType": "S"}],
41+
BillingMode="PAY_PER_REQUEST",
4042
)
41-
client.put_parameter(
42-
Name="/test/signing-secret",
43-
Value=json.dumps({"secret": TEST_SIGNING_SECRET}),
44-
Type="SecureString",
45-
)
46-
yield
43+
yield table
4744

4845

4946
@pytest.fixture
@@ -57,174 +54,210 @@ def lambda_context():
5754

5855
@patch("slack_bolt.App")
5956
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
60-
def test_log_request(mock_get_parameter, mock_app, mock_env):
57+
@patch("boto3.resource")
58+
def test_log_request(mock_boto_resource, mock_get_parameter, mock_app, mock_env):
6159
"""Test middleware function behavior"""
6260
mock_get_parameter.side_effect = [
6361
json.dumps({"token": "test-token"}),
6462
json.dumps({"secret": "test-secret"}),
6563
]
64+
mock_boto_resource.return_value.Table.return_value = Mock()
6665

6766
if "app" in sys.modules:
6867
del sys.modules["app"]
6968

70-
# Create a simple test function that mimics the middleware behavior
71-
def test_log_request(slack_logger, body, next):
72-
# This simulates what the actual middleware does
73-
return next()
74-
75-
slack_logger = Mock()
76-
body = {"text": "test query"}
77-
next_func = Mock()
78-
next_func.return_value = "next_result"
79-
80-
# Call the test function
81-
result = test_log_request(slack_logger, body, next_func)
69+
# Test that the middleware function exists and can be imported
70+
from app import log_request
8271

83-
# Verify next was called and result is correct
84-
next_func.assert_called_once()
85-
assert result == "next_result"
72+
assert callable(log_request)
8673

8774

8875
@patch("slack_bolt.App")
8976
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
90-
def test_respond_to_slack_within_3_seconds(mock_get_parameter, mock_app, mock_env):
91-
"""Test Slack acknowledgment function"""
77+
@patch("boto3.resource")
78+
def test_is_duplicate_event(mock_boto_resource, mock_get_parameter, mock_app, mock_env):
79+
"""Test duplicate event detection"""
9280
mock_get_parameter.side_effect = [
9381
json.dumps({"token": "test-token"}),
9482
json.dumps({"secret": "test-secret"}),
9583
]
84+
mock_table = Mock()
85+
mock_boto_resource.return_value.Table.return_value = mock_table
86+
mock_table.get_item.return_value = {"Item": {"eventId": "test-event"}}
9687

9788
if "app" in sys.modules:
9889
del sys.modules["app"]
9990

100-
from app import respond_to_slack_within_3_seconds
91+
from app import is_duplicate_event
92+
93+
result = is_duplicate_event("test-event")
94+
assert result is True
95+
96+
97+
@patch("slack_bolt.App")
98+
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
99+
@patch("boto3.resource")
100+
@patch("time.time")
101+
def test_mark_event_processed(mock_time, mock_boto_resource, mock_get_parameter, mock_app, mock_env):
102+
"""Test marking event as processed"""
103+
mock_get_parameter.side_effect = [
104+
json.dumps({"token": "test-token"}),
105+
json.dumps({"secret": "test-secret"}),
106+
]
107+
mock_table = Mock()
108+
mock_boto_resource.return_value.Table.return_value = mock_table
109+
mock_time.return_value = 1000
101110

102-
body = {"text": "test query"}
103-
ack = Mock()
111+
if "app" in sys.modules:
112+
del sys.modules["app"]
104113

105-
respond_to_slack_within_3_seconds(body, ack)
114+
from app import mark_event_processed
106115

107-
ack.assert_called_once_with("\n/ask-eps - Processing Request: test query")
116+
mark_event_processed("test-event")
117+
mock_table.put_item.assert_called_once_with(Item={"eventId": "test-event", "ttl": 4600, "timestamp": 1000})
108118

109119

110120
@patch("slack_bolt.App")
111121
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
112-
def test_respond_to_slack_within_3_seconds_error(mock_get_parameter, mock_app, mock_env):
113-
"""Test Slack acknowledgment error handling"""
122+
@patch("boto3.resource")
123+
@patch("boto3.client")
124+
def test_get_bedrock_knowledgebase_response(
125+
mock_boto_client, mock_boto_resource, mock_get_parameter, mock_app, mock_env
126+
):
127+
"""Test Bedrock knowledge base integration"""
114128
mock_get_parameter.side_effect = [
115129
json.dumps({"token": "test-token"}),
116130
json.dumps({"secret": "test-secret"}),
117131
]
132+
mock_boto_resource.return_value.Table.return_value = Mock()
133+
134+
mock_client = Mock()
135+
mock_boto_client.return_value = mock_client
136+
mock_client.retrieve_and_generate.return_value = {"output": {"text": "bedrock response"}}
118137

119138
if "app" in sys.modules:
120139
del sys.modules["app"]
121140

122-
from app import respond_to_slack_within_3_seconds
123-
124-
body = {} # Missing 'text' key
125-
ack = Mock()
141+
from app import get_bedrock_knowledgebase_response
126142

127-
respond_to_slack_within_3_seconds(body, ack)
143+
result = get_bedrock_knowledgebase_response("test query")
128144

129-
ack.assert_called_once_with("/ask-eps - Sorry an error occurred. Please try again later.")
145+
mock_boto_client.assert_called_once_with(service_name="bedrock-agent-runtime", region_name="eu-west-2")
146+
mock_client.retrieve_and_generate.assert_called_once()
147+
assert result["output"]["text"] == "bedrock response"
130148

131149

132150
@patch("slack_bolt.App")
133151
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
134-
def test_process_command_request(mock_get_parameter, mock_app, mock_env):
135-
"""Test command processing function"""
152+
@patch("boto3.resource")
153+
def test_handler_normal_event(mock_boto_resource, mock_get_parameter, mock_app, mock_env, lambda_context):
154+
"""Test Lambda handler function for normal Slack events"""
136155
mock_get_parameter.side_effect = [
137156
json.dumps({"token": "test-token"}),
138157
json.dumps({"secret": "test-secret"}),
139158
]
159+
mock_boto_resource.return_value.Table.return_value = Mock()
140160

141161
if "app" in sys.modules:
142162
del sys.modules["app"]
143163

144-
with patch("app.get_bedrock_knowledgebase_response") as mock_bedrock:
145-
mock_bedrock.return_value = {"output": {"text": "test response"}}
146-
from app import process_command_request
164+
with patch("app.SlackRequestHandler") as mock_handler_class:
165+
mock_handler = Mock()
166+
mock_handler_class.return_value = mock_handler
167+
mock_handler.handle.return_value = {"statusCode": 200}
147168

148-
body = {"text": "test query"}
149-
respond = Mock()
169+
from app import handler
150170

151-
process_command_request(respond, body)
171+
event = {"body": "test event"}
172+
result = handler(event, lambda_context)
152173

153-
mock_bedrock.assert_called_once_with("test query")
154-
respond.assert_called_once_with("\n/ask-eps - Response: test response\n")
174+
mock_handler.handle.assert_called_once_with(event, lambda_context)
175+
assert result["statusCode"] == 200
155176

156177

157178
@patch("slack_bolt.App")
158179
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
159-
def test_process_command_request_exception(mock_get_parameter, mock_app, mock_env):
160-
"""Test process_command_request exception handling"""
180+
@patch("boto3.resource")
181+
def test_handler_async_processing(mock_boto_resource, mock_get_parameter, mock_app, mock_env, lambda_context):
182+
"""Test Lambda handler function for async processing"""
161183
mock_get_parameter.side_effect = [
162184
json.dumps({"token": "test-token"}),
163185
json.dumps({"secret": "test-secret"}),
164186
]
187+
mock_boto_resource.return_value.Table.return_value = Mock()
165188

166189
if "app" in sys.modules:
167190
del sys.modules["app"]
168191

169-
with patch("app.get_bedrock_knowledgebase_response") as mock_bedrock:
170-
mock_bedrock.side_effect = Exception("Bedrock error")
171-
from app import process_command_request
172-
173-
body = {"text": "test query"}
174-
respond = Mock()
192+
with patch("app.process_async_slack_event") as mock_process:
193+
from app import handler
175194

176-
process_command_request(respond, body)
195+
event = {"async_processing": True, "slack_event": {"test": "data"}}
196+
result = handler(event, lambda_context)
177197

178-
respond.assert_called_once_with("/ask-eps - Sorry an error occurred. Please try again later.")
198+
mock_process.assert_called_once_with({"test": "data"})
199+
assert result["statusCode"] == 200
179200

180201

181202
@patch("slack_bolt.App")
182203
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
204+
@patch("boto3.resource")
183205
@patch("boto3.client")
184-
def test_get_bedrock_knowledgebase_response(mock_boto_client, mock_get_parameter, mock_app, mock_env):
185-
"""Test Bedrock knowledge base integration"""
206+
def test_trigger_async_processing(mock_boto_client, mock_boto_resource, mock_get_parameter, mock_app, mock_env):
207+
"""Test triggering async processing"""
186208
mock_get_parameter.side_effect = [
187209
json.dumps({"token": "test-token"}),
188210
json.dumps({"secret": "test-secret"}),
189211
]
190-
191-
mock_client = Mock()
192-
mock_boto_client.return_value = mock_client
193-
mock_client.retrieve_and_generate.return_value = {"output": {"text": "bedrock response"}}
212+
mock_boto_resource.return_value.Table.return_value = Mock()
213+
mock_lambda_client = Mock()
214+
mock_boto_client.return_value = mock_lambda_client
194215

195216
if "app" in sys.modules:
196217
del sys.modules["app"]
197218

198-
from app import get_bedrock_knowledgebase_response
219+
from app import trigger_async_processing
199220

200-
result = get_bedrock_knowledgebase_response("test query")
221+
event_data = {"test": "data"}
222+
trigger_async_processing(event_data)
201223

202-
mock_boto_client.assert_called_once_with(service_name="bedrock-agent-runtime", region_name="eu-west-2")
203-
mock_client.retrieve_and_generate.assert_called_once()
204-
assert result["output"]["text"] == "bedrock response"
224+
mock_boto_client.assert_called_once_with("lambda")
225+
mock_lambda_client.invoke.assert_called_once()
205226

206227

207228
@patch("slack_bolt.App")
208229
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
209-
def test_handler(mock_get_parameter, mock_app, mock_env, lambda_context):
210-
"""Test Lambda handler function"""
230+
@patch("boto3.resource")
231+
def test_handle_app_mention(mock_boto_resource, mock_get_parameter, mock_app, mock_env):
232+
"""Test app mention handler exists and is callable"""
211233
mock_get_parameter.side_effect = [
212234
json.dumps({"token": "test-token"}),
213235
json.dumps({"secret": "test-secret"}),
214236
]
237+
mock_boto_resource.return_value.Table.return_value = Mock()
215238

216239
if "app" in sys.modules:
217240
del sys.modules["app"]
218241

219-
with patch("app.SlackRequestHandler") as mock_handler_class:
220-
mock_handler = Mock()
221-
mock_handler_class.return_value = mock_handler
222-
mock_handler.handle.return_value = {"statusCode": 200}
242+
from app import handle_app_mention
223243

224-
from app import handler
244+
assert callable(handle_app_mention)
225245

226-
event = {"body": "test event"}
227-
result = handler(event, lambda_context)
228246

229-
mock_handler.handle.assert_called_once_with(event, lambda_context)
230-
assert result["statusCode"] == 200
247+
@patch("slack_bolt.App")
248+
@patch("aws_lambda_powertools.utilities.parameters.get_parameter")
249+
@patch("boto3.resource")
250+
def test_handle_direct_message(mock_boto_resource, mock_get_parameter, mock_app, mock_env):
251+
"""Test direct message handler exists and is callable"""
252+
mock_get_parameter.side_effect = [
253+
json.dumps({"token": "test-token"}),
254+
json.dumps({"secret": "test-secret"}),
255+
]
256+
mock_boto_resource.return_value.Table.return_value = Mock()
257+
258+
if "app" in sys.modules:
259+
del sys.modules["app"]
260+
261+
from app import handle_direct_message
262+
263+
assert callable(handle_direct_message)

0 commit comments

Comments
 (0)