Skip to content

Commit

Permalink
feat(file-uploader): added base for s3 testing (#256)
Browse files Browse the repository at this point in the history
* feat(file-uploader): added base for s3 testing

* feat: added s3Storage logger
  • Loading branch information
slaveeks authored May 18, 2024
1 parent 6e7fb71 commit 93a0530
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 3 deletions.
1 change: 1 addition & 0 deletions app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ logging:
metricsServer: info
appServer: info
database: info
s3Storage: info

s3:
accessKeyId: 'secret'
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@testcontainers/localstack": "^10.9.0",
"@types/jsonwebtoken": "^9.0.2",
"@types/node": "^20.2.3",
"@types/pg": "^8.10.2",
Expand Down
2 changes: 2 additions & 0 deletions src/infrastructure/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export const LoggingConfig = z.object({
metricsServer: LoggingLevel,
appServer: LoggingLevel,
database: LoggingLevel,
s3Storage: LoggingLevel,
});

export type LoggingConfig = z.infer<typeof LoggingConfig>;
Expand Down Expand Up @@ -159,6 +160,7 @@ const defaultConfig: AppConfig = {
metricsServer: 'info',
appServer: 'info',
database: 'info',
s3Storage: 'info',
},
database: {
dsn: 'postgres://user:pass@postgres/codex-notes',
Expand Down
28 changes: 28 additions & 0 deletions src/repository/storage/s3/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { getLogger } from '@infrastructure/logging/index.js';
import S3 from 'aws-sdk/clients/s3.js';
import type { Buffer } from 'buffer';

const s3StorageLogger = getLogger('s3Storage');

/**
* Class to handle S3 bucket operations
*/
Expand Down Expand Up @@ -55,6 +58,8 @@ export class S3Storage {

return response.Location;
} catch (error) {
s3StorageLogger.error(error);

return null;
}
}
Expand All @@ -76,6 +81,29 @@ export class S3Storage {

return response.Body as Buffer;
} catch (error) {
s3StorageLogger.error(error);

return null;
}
}

/**
* Method to create bucket in object storage, return its location
*
* @param name - bucket name
*/
public async createBucket(name: string): Promise<string | null> {
const createBucketManager = this.s3.createBucket({
Bucket: name,
});

try {
const response = await createBucketManager.promise();

return response.Location as string;
} catch (error) {
s3StorageLogger.error(error);

return null;
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/tests/utils/s3-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { S3Storage } from '@repository/storage/s3/index.js';

/**
* Bucket are needed to be created
*/
const Buckets = [
'test',
'note-attachment',
];

/**
* Class with methods to create buckets in storage or creating mock data in it
*/
export default class S3Helpers {
private s3: S3Storage;

/**
* Constructor for s3 helpers
*
* @param s3 - s3 client instance
*/
constructor(s3: S3Storage) {
this.s3 = s3;
}
/**
* Create buckets in s3 storage for testing
*/
public async createBuckets(): Promise<void> {
for (const bucket of Buckets) {
await this.s3.createBucket(bucket);
}
}
}
16 changes: 16 additions & 0 deletions src/tests/utils/setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import path from 'path';
import type { StartedPostgreSqlContainer } from '@testcontainers/postgresql';
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import type { StartedLocalStackContainer } from '@testcontainers/localstack';
import { LocalstackContainer } from '@testcontainers/localstack';

import { initORM, init as initRepositories } from '@repository/index.js';
import { init as initDomainServices } from '@domain/index.js';
Expand All @@ -12,6 +14,8 @@ import { beforeAll, afterAll } from 'vitest';
import type Api from '@presentation/api.interface.js';

import DatabaseHelpers from './database-helpers.js';
import { S3Storage } from '@repository/storage/s3/index.js';
import S3Helpers from './s3-helpers.js';

/**
* Tests setup maximum duration.
Expand Down Expand Up @@ -41,6 +45,12 @@ declare global {
*/
/* eslint-disable-next-line no-var */
var db: DatabaseHelpers;

/**
* S3Helpers class that contains methods for work with s3
*/
/* eslint-disable-next-line no-var */
var s3: S3Helpers;
}

/**
Expand All @@ -49,12 +59,16 @@ declare global {
const migrationsPath = path.join(process.cwd(), 'migrations', 'tenant');

let postgresContainer: StartedPostgreSqlContainer | undefined;
let localstackContainer: StartedLocalStackContainer | undefined;

beforeAll(async () => {
postgresContainer = await new PostgreSqlContainer()
.withUsername('postgres')
.start();

localstackContainer = await new LocalstackContainer().start();

const s3 = new S3Storage('test', 'test', 'us-east-1', localstackContainer.getConnectionUri());
const orm = await initORM({ dsn: postgresContainer.getConnectionUri() });
const repositories = await initRepositories(orm, config.s3);
const domainServices = initDomainServices(repositories, config);
Expand All @@ -71,9 +85,11 @@ beforeAll(async () => {
};

global.db = new DatabaseHelpers(orm);
global.s3 = new S3Helpers(s3);
}, TIMEOUT);

afterAll(async () => {
await postgresContainer?.stop();
await localstackContainer?.stop();
delete global.api;
});
Loading

0 comments on commit 93a0530

Please sign in to comment.