Skip to content

Commit ad9d338

Browse files
committed
CCM-14482: Fix component tests
1 parent 6505c80 commit ad9d338

12 files changed

Lines changed: 74 additions & 45 deletions

File tree

infrastructure/terraform/components/dl/cloudwatch_event_rule_mesh_inbox_message_downloaded.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ resource "aws_cloudwatch_event_target" "pdm_uploader_target" {
2626
event_bus_name = aws_cloudwatch_event_bus.main.name
2727
}
2828

29-
resource "aws_cloudwatch_event_target" "mesh_cknowledge_target" {
29+
resource "aws_cloudwatch_event_target" "mesh_acknowledge_target" {
3030
rule = aws_cloudwatch_event_rule.mesh_inbox_message_downloaded.name
3131
arn = module.sqs_mesh_acknowledge.sqs_queue_arn
3232
target_id = "mesh_acknowledge_target"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
resource "aws_cloudwatch_event_rule" "mesh_inbox_message_invalid" {
2+
name = "${local.csi}-mesh-inbox-message-invalid"
3+
description = "MESH inbox message invalid event rule"
4+
event_bus_name = aws_cloudwatch_event_bus.main.name
5+
6+
event_pattern = jsonencode({
7+
"detail" : {
8+
"type" : [
9+
"uk.nhs.notify.digital.letters.mesh.inbox.message.invalid.v1"
10+
],
11+
}
12+
})
13+
}
14+
15+
resource "aws_cloudwatch_event_target" "mesh_acknowledge_invalid_target" {
16+
rule = aws_cloudwatch_event_rule.mesh_inbox_message_invalid.name
17+
arn = module.sqs_mesh_acknowledge.sqs_queue_arn
18+
target_id = "mesh_acknowledge_invalid_target"
19+
event_bus_name = aws_cloudwatch_event_bus.main.name
20+
}

infrastructure/terraform/components/dl/module_sqs_mesh_acknowledge.tf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ data "aws_iam_policy_document" "sqs_mesh_acknowledge" {
3535
condition {
3636
test = "ArnLike"
3737
variable = "aws:SourceArn"
38-
values = [aws_cloudwatch_event_rule.mesh_inbox_message_downloaded.arn]
38+
39+
values = [
40+
aws_cloudwatch_event_rule.mesh_inbox_message_downloaded.arn,
41+
aws_cloudwatch_event_rule.mesh_inbox_message_invalid.arn,
42+
]
3943
}
4044
}
4145
}

infrastructure/terraform/components/dl/s3_object_failure_codes.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
resource "aws_s3_object" "failure_codes" {
22
bucket = module.s3bucket_reporting.bucket
33
key = "reference-data/failure_codes/failure_codes.csv"
4-
source = "${path.module}/data/failure_codes.csv"
4+
source = "${path.module}/../../../../utils/py-utils/dl_utils/failure_codes.csv"
55
content_type = "text/csv"
6-
etag = filemd5("${path.module}/data/failure_codes.csv")
6+
etag = filemd5("${path.module}/../../../../utils/py-utils/dl_utils/failure_codes.csv")
77

88
tags = merge(
99
local.default_tags,

lambdas/mesh-acknowledge/mesh_acknowledge/__tests__/test_acknowledger.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ def test_negative_acknowledge_message_sends_correct_message_without_reference(
166166
mailbox_id,
167167
expected_body,
168168
workflow_id=NOTIFY_ACK_WORKFLOW_ID,
169-
local_id=None,
170169
subject=NACK_SUBJECT
171170
)
172171

lambdas/mesh-acknowledge/mesh_acknowledge/__tests__/test_message_processor.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"""
44
from unittest.mock import Mock, patch
55
from uuid import uuid4
6-
76
import pytest
87
from digital_letters_events import MESHInboxMessageDownloaded, MESHInboxMessageInvalid
98
from mesh_acknowledge.message_processor import MessageProcessor
@@ -74,13 +73,15 @@ def downloaded_event_fixture():
7473

7574
@pytest.fixture(name='valid_sqs_message')
7675
def create_valid_sqs_message():
77-
"""Create a valid SQS message with one record"""
76+
"""Create a valid SQS message with one downloaded event record"""
77+
event_id = str(uuid4())
78+
import json
7879
return {
7980
'Records': [
8081
{
8182
'messageId': 'sqs-msg-123',
8283
'eventSource': 'aws:sqs',
83-
'body': 'detail": { }',
84+
'body': json.dumps({'detail': create_downloaded_event_dict(event_id)}),
8485
}
8586
]
8687
}
@@ -153,11 +154,11 @@ def test_process_message_multiple_records(
153154
message = {
154155
'Records': [
155156
{'messageId': 'msg-1', 'eventSource': 'aws:sqs',
156-
'body': '{"detail": {}}'},
157+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'},
157158
{'messageId': 'msg-2', 'eventSource': 'aws:sqs',
158-
'body': '{"detail": {}}'},
159+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'},
159160
{'messageId': 'msg-3', 'eventSource': 'aws:sqs',
160-
'body': '{"detail": {}}'}
161+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'}
161162
]
162163
}
163164

@@ -191,11 +192,11 @@ def test_process_message_partial_failures(
191192
message = {
192193
'Records': [
193194
{'messageId': 'msg-1', 'eventSource': 'aws:sqs',
194-
'body': '{"detail": {}}'},
195+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'},
195196
{'messageId': 'msg-2', 'eventSource': 'aws:sqs',
196-
'body': '{"detail": {}}'},
197+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'},
197198
{'messageId': 'msg-3', 'eventSource': 'aws:sqs',
198-
'body': '{"detail": {}}'}
199+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'}
199200
]
200201
}
201202

@@ -222,11 +223,11 @@ def test_process_message_all_failures(
222223
'Records': [
223224
{
224225
'messageId': 'msg-1', 'eventSource': 'aws:sqs',
225-
'body': '{"detail": {}}'
226+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'
226227
},
227228
{
228229
'messageId': 'msg-2', 'eventSource': 'aws:sqs',
229-
'body': '{"detail": {}}'
230+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'
230231
}
231232
]
232233
}
@@ -444,11 +445,11 @@ def test_process_message_logs_summary(
444445
message = {
445446
'Records': [
446447
{'messageId': 'msg-1', 'eventSource': 'aws:sqs',
447-
'body': '{"detail": {}}'},
448+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'},
448449
{'messageId': 'msg-2', 'eventSource': 'aws:sqs',
449-
'body': '{"detail": {}}'},
450+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'},
450451
{'messageId': 'msg-3', 'eventSource': 'aws:sqs',
451-
'body': '{"detail": {}}'}
452+
'body': '{"detail": {"type": "uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1"}}'}
452453
]
453454
}
454455

@@ -468,8 +469,8 @@ def invalid_event_fixture():
468469
return MESHInboxMessageInvalid(**create_invalid_event_dict(event_id))
469470

470471

471-
@pytest.fixture(name='valid_invalid_sqs_message')
472-
def create_valid_invalid_sqs_message():
472+
@pytest.fixture(name='invalid_sqs_message')
473+
def create_invalid_sqs_message():
473474
"""Create a valid SQS message containing a MESHInboxMessageInvalid record"""
474475
event_id = str(uuid4())
475476
return {
@@ -501,7 +502,7 @@ def test_process_invalid_event_success(
501502
mock_sender_lookup,
502503
mock_event_publisher,
503504
mock_logger,
504-
valid_invalid_sqs_message,
505+
invalid_sqs_message,
505506
invalid_event: MESHInboxMessageInvalid
506507
):
507508
"""Test successful processing of a MESHInboxMessageInvalid SQS record"""
@@ -511,12 +512,12 @@ def test_process_invalid_event_success(
511512
mock_sender_lookup.get_mailbox_id.return_value = mesh_mailbox_id
512513
mock_acknowledger.negative_acknowledge_message.return_value = "NACK123"
513514

514-
result = message_processor.process_message(valid_invalid_sqs_message)
515+
result = message_processor.process_message(invalid_sqs_message)
515516

516517
assert result == []
517518

518519
mock_parse_invalid.assert_called_once_with(
519-
valid_invalid_sqs_message['Records'][0],
520+
invalid_sqs_message['Records'][0],
520521
mock_logger
521522
)
522523
mock_sender_lookup.get_mailbox_id.assert_called_once_with(
@@ -545,14 +546,14 @@ def test_process_invalid_event_unknown_sender_returns_failure(
545546
message_processor,
546547
mock_sender_lookup,
547548
mock_acknowledger,
548-
valid_invalid_sqs_message,
549+
invalid_sqs_message,
549550
invalid_event: MESHInboxMessageInvalid
550551
):
551552
"""Test that an unknown senderId causes a batch failure for invalid events"""
552553
mock_parse_invalid.return_value = invalid_event
553554
mock_sender_lookup.get_mailbox_id.return_value = None
554555

555-
result = message_processor.process_message(valid_invalid_sqs_message)
556+
result = message_processor.process_message(invalid_sqs_message)
556557

557558
assert len(result) == 1
558559
assert result[0] == {"itemIdentifier": "sqs-msg-invalid-123"}
@@ -569,15 +570,15 @@ def test_process_invalid_event_nack_error_returns_failure(
569570
message_processor,
570571
mock_sender_lookup,
571572
mock_acknowledger,
572-
valid_invalid_sqs_message,
573+
invalid_sqs_message,
573574
invalid_event: MESHInboxMessageInvalid
574575
):
575576
"""Test that a NACK send failure causes a batch failure"""
576577
mock_parse_invalid.return_value = invalid_event
577578
mock_sender_lookup.get_mailbox_id.return_value = "MAILBOX001"
578579
mock_acknowledger.negative_acknowledge_message.side_effect = RuntimeError("NACK failed")
579580

580-
result = message_processor.process_message(valid_invalid_sqs_message)
581+
result = message_processor.process_message(invalid_sqs_message)
581582

582583
assert len(result) == 1
583584
assert result[0] == {"itemIdentifier": "sqs-msg-invalid-123"}
@@ -594,7 +595,7 @@ def test_process_invalid_event_publish_error_sends_to_dlq(
594595
mock_sender_lookup,
595596
mock_acknowledger,
596597
mock_dlq,
597-
valid_invalid_sqs_message,
598+
invalid_sqs_message,
598599
invalid_event: MESHInboxMessageInvalid
599600
):
600601
"""
@@ -605,11 +606,11 @@ def test_process_invalid_event_publish_error_sends_to_dlq(
605606
mock_acknowledger.negative_acknowledge_message.return_value = "NACK123"
606607
mock_publish_nack.side_effect = Exception("Publish failed")
607608

608-
result = message_processor.process_message(valid_invalid_sqs_message)
609+
result = message_processor.process_message(invalid_sqs_message)
609610

610611
assert result == []
611612
mock_dlq.send_to_queue.assert_called_once_with(
612-
record=valid_invalid_sqs_message['Records'][0],
613+
record=invalid_sqs_message['Records'][0],
613614
reason="Failed to publish negative acknowledged event"
614615
)
615616

@@ -623,7 +624,7 @@ def test_process_invalid_event_dlq_error_returns_failure(
623624
mock_sender_lookup,
624625
mock_acknowledger,
625626
mock_dlq,
626-
valid_invalid_sqs_message,
627+
invalid_sqs_message,
627628
invalid_event: MESHInboxMessageInvalid
628629
):
629630
"""Test that if both publish and DLQ fail, the record is returned as a batch failure"""
@@ -633,7 +634,7 @@ def test_process_invalid_event_dlq_error_returns_failure(
633634
mock_publish_nack.side_effect = Exception("Publish failed")
634635
mock_dlq.send_to_queue.side_effect = Exception("DLQ send failed")
635636

636-
result = message_processor.process_message(valid_invalid_sqs_message)
637+
result = message_processor.process_message(invalid_sqs_message)
637638

638639
assert len(result) == 1
639640
assert result[0] == {"itemIdentifier": "sqs-msg-invalid-123"}

lambdas/mesh-acknowledge/mesh_acknowledge/acknowledger.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ def negative_acknowledge_message(self,
117117
mailbox_id,
118118
message_body,
119119
workflow_id=NOTIFY_ACK_WORKFLOW_ID,
120-
local_id=message_reference,
121-
subject=NACK_SUBJECT
120+
subject=NACK_SUBJECT,
121+
**({'local_id': message_reference} if message_reference is not None else {})
122122
)
123123
self.__log.info(
124124
"Sent negative acknowledgement for MESH message",

lambdas/mesh-acknowledge/mesh_acknowledge/message_processor.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
events and sends MESH acknowledgements or negative acknowledgements for each.
44
"""
55
from typing import Dict, Any, List
6+
import json
67
from dl_utils import EventPublisher, SenderLookup
78
from .acknowledger import MeshAcknowledger
89
from .dlq import Dlq
@@ -13,6 +14,9 @@
1314
publish_negative_acknowledged_event,
1415
)
1516

17+
_DOWNLOADED_EVENT_TYPE = 'uk.nhs.notify.digital.letters.mesh.inbox.message.downloaded.v1'
18+
_INVALID_EVENT_TYPE = 'uk.nhs.notify.digital.letters.mesh.inbox.message.invalid.v1'
19+
1620
class MessageProcessor:
1721
"""Processes SQS messages and sends MESH acknowledgments."""
1822

@@ -55,10 +59,12 @@ def process_message(self, message: Dict[str, Any]) -> List[Dict[str, str]]:
5559
try:
5660
event_type = self.__get_event_type(record)
5761

58-
if event_type == 'uk.nhs.notify.digital.letters.mesh.inbox.message.invalid.v1':
62+
if event_type == _INVALID_EVENT_TYPE:
5963
acknowledgement_message_id = self.__process_invalid_record(record)
60-
else:
64+
elif event_type == _DOWNLOADED_EVENT_TYPE:
6165
acknowledgement_message_id = self.__process_downloaded_record(record)
66+
else:
67+
raise ValueError(f"Unknown event type: '{event_type}'")
6268

6369
self.__log.info("Acknowledged message ID",
6470
message_id=message_id,
@@ -82,7 +88,6 @@ def process_message(self, message: Dict[str, Any]) -> List[Dict[str, str]]:
8288

8389
def __get_event_type(self, record: Dict[str, Any]) -> str:
8490
"""Extract the CloudEvents type field from an SQS record body."""
85-
import json
8691
try:
8792
body = json.loads(record.get('body', '{}'))
8893
return body.get('detail', {}).get('type', '')

tests/playwright/digital-letters-component-tests/mesh-acknowledge.component.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ test.describe('Digital Letters - Mesh Acknowledger', () => {
179179
});
180180

181181
test('should send MESH negative acknowledgement and publish message acknowledged event following message invalid event', async () => {
182-
test.setTimeout(120_000);
182+
test.setTimeout(160_000);
183183

184184
const letterId = uuidv4();
185185
const meshMessageId = `${Date.now()}_TEST_${uuidv4().slice(0, 8)}`;
@@ -229,7 +229,7 @@ test.describe('Digital Letters - Mesh Acknowledger', () => {
229229
);
230230
sentMeshMessageId = eventDetail.data.sentMeshMessageId;
231231
expect(sentMeshMessageId).toBeTruthy();
232-
});
232+
}, 120_000);
233233

234234
// Verify MESH negative acknowledgement message was sent.
235235
await expectToPassEventually(async () => {
@@ -247,6 +247,6 @@ test.describe('Digital Letters - Mesh Acknowledger', () => {
247247
expect(messageBody.meshMessageId).toEqual(meshMessageId);
248248
expect(messageBody.failureCode).toEqual(failureCode);
249249
expect(messageBody.requestId).toEqual(`${senderId}_`);
250-
});
250+
}, 30);
251251
});
252252
});
File renamed without changes.

0 commit comments

Comments
 (0)