163 lines
4.8 KiB
TypeScript
163 lines
4.8 KiB
TypeScript
/**
|
|
* S3 Notifications integration tests.
|
|
*/
|
|
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
import {
|
|
S3Client,
|
|
CreateBucketCommand,
|
|
PutObjectCommand,
|
|
DeleteObjectCommand,
|
|
DeleteBucketCommand,
|
|
PutBucketNotificationConfigurationCommand,
|
|
GetBucketNotificationConfigurationCommand,
|
|
} from '@aws-sdk/client-s3';
|
|
import {
|
|
SQSClient,
|
|
CreateQueueCommand,
|
|
GetQueueAttributesCommand,
|
|
DeleteQueueCommand,
|
|
} from '@aws-sdk/client-sqs';
|
|
import { SNSClient, CreateTopicCommand, DeleteTopicCommand } from '@aws-sdk/client-sns';
|
|
import { makeClient, uniqueName } from './setup';
|
|
|
|
describe('S3 Notifications', () => {
|
|
let s3: S3Client;
|
|
let sqs: SQSClient;
|
|
let sns: SNSClient;
|
|
let bucketName: string;
|
|
let queueUrl: string;
|
|
let queueArn: string;
|
|
let topicArn: string;
|
|
|
|
beforeAll(async () => {
|
|
s3 = makeClient(S3Client, { forcePathStyle: true });
|
|
sqs = makeClient(SQSClient);
|
|
sns = makeClient(SNSClient);
|
|
|
|
bucketName = `notif-test-bucket-${uniqueName()}`;
|
|
|
|
// Create SQS queue
|
|
const queueResult = await sqs.send(
|
|
new CreateQueueCommand({ QueueName: `notif-queue-${uniqueName()}` })
|
|
);
|
|
queueUrl = queueResult.QueueUrl!;
|
|
const attrs = await sqs.send(
|
|
new GetQueueAttributesCommand({ QueueUrl: queueUrl, AttributeNames: ['QueueArn'] })
|
|
);
|
|
queueArn = attrs.Attributes!.QueueArn!;
|
|
|
|
// Create SNS topic
|
|
const topicResult = await sns.send(
|
|
new CreateTopicCommand({ Name: `notif-topic-${uniqueName()}` })
|
|
);
|
|
topicArn = topicResult.TopicArn!;
|
|
|
|
// Create S3 bucket
|
|
await s3.send(new CreateBucketCommand({ Bucket: bucketName }));
|
|
});
|
|
|
|
afterAll(async () => {
|
|
try {
|
|
await s3.send(new DeleteObjectCommand({ Bucket: bucketName, Key: 'test-object.txt' }));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
try {
|
|
await s3.send(new DeleteBucketCommand({ Bucket: bucketName }));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
try {
|
|
await sqs.send(new DeleteQueueCommand({ QueueUrl: queueUrl }));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
try {
|
|
await sns.send(new DeleteTopicCommand({ TopicArn: topicArn }));
|
|
} catch {
|
|
// ignore
|
|
}
|
|
});
|
|
|
|
it('should put bucket notification configuration', async () => {
|
|
await s3.send(
|
|
new PutBucketNotificationConfigurationCommand({
|
|
Bucket: bucketName,
|
|
NotificationConfiguration: {
|
|
QueueConfigurations: [
|
|
{
|
|
Id: 'sqs-filtered',
|
|
QueueArn: queueArn,
|
|
Events: ['s3:ObjectCreated:*'],
|
|
Filter: {
|
|
Key: {
|
|
FilterRules: [
|
|
{ Name: 'prefix', Value: 'incoming/' },
|
|
{ Name: 'suffix', Value: '.csv' },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
TopicConfigurations: [
|
|
{
|
|
Id: 'sns-filtered',
|
|
TopicArn: topicArn,
|
|
Events: ['s3:ObjectRemoved:*'],
|
|
Filter: {
|
|
Key: {
|
|
FilterRules: [
|
|
{ Name: 'prefix', Value: '' },
|
|
{ Name: 'suffix', Value: '.txt' },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should get bucket notification configuration', async () => {
|
|
const response = await s3.send(
|
|
new GetBucketNotificationConfigurationCommand({ Bucket: bucketName })
|
|
);
|
|
|
|
// Verify SQS configuration
|
|
const sqsConfig = response.QueueConfigurations?.find((c) => c.Id === 'sqs-filtered');
|
|
expect(sqsConfig).toBeTruthy();
|
|
expect(sqsConfig?.QueueArn).toBe(queueArn);
|
|
expect(sqsConfig?.Events).toContain('s3:ObjectCreated:*');
|
|
|
|
const sqsRules = sqsConfig?.Filter?.Key?.FilterRules || [];
|
|
expect(sqsRules.some((r) => r.Name === 'prefix' && r.Value === 'incoming/')).toBe(true);
|
|
expect(sqsRules.some((r) => r.Name === 'suffix' && r.Value === '.csv')).toBe(true);
|
|
|
|
// Verify SNS configuration
|
|
const snsConfig = response.TopicConfigurations?.find((c) => c.Id === 'sns-filtered');
|
|
expect(snsConfig).toBeTruthy();
|
|
expect(snsConfig?.TopicArn).toBe(topicArn);
|
|
expect(snsConfig?.Events).toContain('s3:ObjectRemoved:*');
|
|
|
|
const snsRules = snsConfig?.Filter?.Key?.FilterRules || [];
|
|
expect(snsRules.some((r) => r.Name === 'suffix' && r.Value === '.txt')).toBe(true);
|
|
});
|
|
|
|
it('should clear notification configuration', async () => {
|
|
await s3.send(
|
|
new PutBucketNotificationConfigurationCommand({
|
|
Bucket: bucketName,
|
|
NotificationConfiguration: {},
|
|
})
|
|
);
|
|
|
|
const response = await s3.send(
|
|
new GetBucketNotificationConfigurationCommand({ Bucket: bucketName })
|
|
);
|
|
expect(response.QueueConfigurations?.length || 0).toBe(0);
|
|
expect(response.TopicConfigurations?.length || 0).toBe(0);
|
|
});
|
|
});
|