From d72a691bb88c18e519725c3048cdb083faeecb72 Mon Sep 17 00:00:00 2001 From: Pavlo Strunkin Date: Wed, 25 Dec 2024 15:40:10 +0200 Subject: [PATCH 1/3] Static service refactored to support different implementations --- .env | 8 ++++ .vscode/settings.json | 3 +- src/compare/compare.module.ts | 2 + src/compare/compare.service.spec.ts | 5 ++- .../looks-same/looks-same.service.spec.ts | 2 +- .../libs/looks-same/looks-same.service.ts | 6 +-- src/compare/libs/odiff/odiff.service.spec.ts | 2 +- src/compare/libs/odiff/odiff.service.ts | 18 ++++++--- .../pixelmatch/pixelmatch.service.spec.ts | 2 +- .../libs/pixelmatch/pixelmatch.service.ts | 8 ++-- src/main.ts | 21 +++++----- src/shared/shared.module.ts | 5 +-- src/static/aws/s3.service.ts | 39 +++++++++++++++++++ src/static/hdd/constants.ts | 1 + .../hdd/hdd.service.ts} | 19 +++++---- src/static/static.factory.ts | 25 ++++++++++++ src/static/static.interface.ts | 7 ++++ src/static/static.module.ts | 11 ++++++ .../static/static.service.spec.ts | 3 +- src/static/static.service.ts | 26 +++++++++++++ src/static/utils.ts | 3 ++ src/test-runs/test-runs.module.ts | 3 +- src/test-runs/test-runs.service.spec.ts | 2 +- src/test-runs/test-runs.service.ts | 8 ++-- src/test-variations/test-variations.module.ts | 3 +- .../test-variations.service.spec.ts | 2 +- .../test-variations.service.ts | 4 +- 27 files changed, 187 insertions(+), 51 deletions(-) create mode 100644 src/static/aws/s3.service.ts create mode 100644 src/static/hdd/constants.ts rename src/{shared/static/static.service.ts => static/hdd/hdd.service.ts} (74%) create mode 100644 src/static/static.factory.ts create mode 100644 src/static/static.interface.ts create mode 100644 src/static/static.module.ts rename src/{shared => }/static/static.service.spec.ts (88%) create mode 100644 src/static/static.service.ts create mode 100644 src/static/utils.ts diff --git a/.env b/.env index a959b16e..87008d7f 100644 --- a/.env +++ b/.env @@ -12,6 +12,14 @@ POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_DB=vrt_db_dev +# static +STATIC_SERVICE=hdd # hdd | s3 - hdd as default if not provided + +# AWS_ACCESS_KEY_ID= +# AWS_SECRET_ACCESS_KEY= +# AWS_REGION= +# AWS_S3_BUCKET_NAME= + # optional #HTTPS_KEY_PATH='./secrets/ssl.key' #HTTPS_CERT_PATH='./secrets/ssl.cert' diff --git a/.vscode/settings.json b/.vscode/settings.json index 88c6e3a4..8d0b5421 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,6 @@ "**/.git/objects/**": true, "**/.git/subtree-cache/**": true, "**/.hg/store/**": true - } + }, + "jest.runMode":"on-demand" } \ No newline at end of file diff --git a/src/compare/compare.module.ts b/src/compare/compare.module.ts index a4a0197e..c4c622c8 100644 --- a/src/compare/compare.module.ts +++ b/src/compare/compare.module.ts @@ -3,9 +3,11 @@ import { CompareService } from './compare.service'; import { LookSameService } from './libs/looks-same/looks-same.service'; import { OdiffService } from './libs/odiff/odiff.service'; import { PixelmatchService } from './libs/pixelmatch/pixelmatch.service'; +import { StaticModule } from '../static/static.module'; @Module({ providers: [CompareService, PixelmatchService, LookSameService, OdiffService], + imports: [StaticModule], exports: [CompareService], }) export class CompareModule {} diff --git a/src/compare/compare.service.spec.ts b/src/compare/compare.service.spec.ts index 51491d11..3c04db9f 100644 --- a/src/compare/compare.service.spec.ts +++ b/src/compare/compare.service.spec.ts @@ -1,17 +1,18 @@ import { Test, TestingModule } from '@nestjs/testing'; import { PrismaService } from '../prisma/prisma.service'; -import { StaticService } from '../shared/static/static.service'; import { CompareService } from './compare.service'; import { LookSameService } from './libs/looks-same/looks-same.service'; import { OdiffService } from './libs/odiff/odiff.service'; import { PixelmatchService } from './libs/pixelmatch/pixelmatch.service'; +import { StaticModule } from '../static/static.module'; describe('CompareService', () => { let service: CompareService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [CompareService, OdiffService, PixelmatchService, LookSameService, StaticService, PrismaService], + providers: [CompareService, OdiffService, PixelmatchService, LookSameService, PrismaService], + imports: [StaticModule], }).compile(); service = module.get(CompareService); diff --git a/src/compare/libs/looks-same/looks-same.service.spec.ts b/src/compare/libs/looks-same/looks-same.service.spec.ts index dd182349..505ceb3e 100644 --- a/src/compare/libs/looks-same/looks-same.service.spec.ts +++ b/src/compare/libs/looks-same/looks-same.service.spec.ts @@ -1,7 +1,7 @@ import { TestingModule, Test } from '@nestjs/testing'; import { TestStatus } from '@prisma/client'; import { PNG } from 'pngjs'; -import { StaticService } from '../../../shared/static/static.service'; +import { StaticService } from '../../../static/static.service'; import { DIFF_DIMENSION_RESULT, EQUAL_RESULT, NO_BASELINE_RESULT } from '../consts'; import { DEFAULT_CONFIG, LookSameService } from './looks-same.service'; import { LooksSameConfig } from './looks-same.types'; diff --git a/src/compare/libs/looks-same/looks-same.service.ts b/src/compare/libs/looks-same/looks-same.service.ts index 67798dcf..30beb3e9 100644 --- a/src/compare/libs/looks-same/looks-same.service.ts +++ b/src/compare/libs/looks-same/looks-same.service.ts @@ -1,7 +1,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { TestStatus } from '@prisma/client'; import { PNG } from 'pngjs'; -import { StaticService } from '../../../shared/static/static.service'; +import { StaticService } from '../../../static/static.service'; import { DiffResult } from '../../../test-runs/diffResult'; import { applyIgnoreAreas, parseConfig } from '../../utils'; import { ImageComparator } from '../image-comparator.interface'; @@ -32,8 +32,8 @@ export class LookSameService implements ImageComparator { ...NO_BASELINE_RESULT, }; - const baseline = this.staticService.getImage(data.baseline); - const image = this.staticService.getImage(data.image); + const baseline = await this.staticService.getImage(data.baseline); + const image = await this.staticService.getImage(data.image); if (!baseline) { return NO_BASELINE_RESULT; diff --git a/src/compare/libs/odiff/odiff.service.spec.ts b/src/compare/libs/odiff/odiff.service.spec.ts index 64be30e2..6906ca3c 100644 --- a/src/compare/libs/odiff/odiff.service.spec.ts +++ b/src/compare/libs/odiff/odiff.service.spec.ts @@ -1,7 +1,7 @@ import { TestingModule, Test } from '@nestjs/testing'; import { TestStatus } from '@prisma/client'; import { IgnoreAreaDto } from 'src/test-runs/dto/ignore-area.dto'; -import { StaticService } from '../../../shared/static/static.service'; +import { StaticService } from '../../../static/static.service'; import { DIFF_DIMENSION_RESULT, NO_BASELINE_RESULT } from '../consts'; import { OdiffService, DEFAULT_CONFIG, ignoreAreaToRegionMapper } from './odiff.service'; import { OdiffConfig, OdiffIgnoreRegions } from './odiff.types'; diff --git a/src/compare/libs/odiff/odiff.service.ts b/src/compare/libs/odiff/odiff.service.ts index 7c60d9df..40aa23fa 100644 --- a/src/compare/libs/odiff/odiff.service.ts +++ b/src/compare/libs/odiff/odiff.service.ts @@ -1,6 +1,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { TestStatus } from '@prisma/client'; -import { StaticService } from '../../../shared/static/static.service'; +import { StaticService } from '../../../static/static.service'; import { DiffResult } from '../../../test-runs/diffResult'; import { parseConfig } from '../../utils'; import { ImageComparator } from '../image-comparator.interface'; @@ -9,6 +9,8 @@ import { DIFF_DIMENSION_RESULT, NO_BASELINE_RESULT } from '../consts'; import { compare } from 'odiff-bin'; import { IgnoreAreaDto } from 'src/test-runs/dto/ignore-area.dto'; import { OdiffConfig, OdiffIgnoreRegions, OdiffResult } from './odiff.types'; +import { HddService } from 'src/static/hdd/hdd.service'; +import { isHddStaticServiceConfigured } from '../../../static/utils'; export const DEFAULT_CONFIG: OdiffConfig = { outputDiffMask: true, @@ -20,8 +22,14 @@ export const DEFAULT_CONFIG: OdiffConfig = { @Injectable() export class OdiffService implements ImageComparator { private readonly logger: Logger = new Logger(OdiffService.name); + private readonly hddService: HddService; - constructor(private staticService: StaticService) {} + constructor(private staticService: StaticService) { + if (!isHddStaticServiceConfigured()) { + throw new Error('OdiffService can only be used with HddService'); + } + this.hddService = this.staticService as unknown as HddService; + } parseConfig(configJson: string): OdiffConfig { return parseConfig(configJson, DEFAULT_CONFIG, this.logger); @@ -37,10 +45,10 @@ export class OdiffService implements ImageComparator { } // compare - const diff = this.staticService.generateNewImage('diff'); + const diff = this.hddService.generateNewImage('diff'); const compareResult = (await compare( - this.staticService.getImagePath(data.baseline), - this.staticService.getImagePath(data.image), + this.hddService.getImagePath(data.baseline), + this.hddService.getImagePath(data.image), diff.imagePath, { ...config, diff --git a/src/compare/libs/pixelmatch/pixelmatch.service.spec.ts b/src/compare/libs/pixelmatch/pixelmatch.service.spec.ts index cdb82fc4..c458f82e 100644 --- a/src/compare/libs/pixelmatch/pixelmatch.service.spec.ts +++ b/src/compare/libs/pixelmatch/pixelmatch.service.spec.ts @@ -3,7 +3,7 @@ import { TestStatus } from '@prisma/client'; import Pixelmatch from 'pixelmatch'; import { PNG } from 'pngjs'; import { mocked } from 'jest-mock'; -import { StaticService } from '../../../shared/static/static.service'; +import { StaticService } from '../../../static/static.service'; import { DIFF_DIMENSION_RESULT, EQUAL_RESULT, NO_BASELINE_RESULT } from '../consts'; import { DEFAULT_CONFIG, PixelmatchService } from './pixelmatch.service'; import { PixelmatchConfig } from './pixelmatch.types'; diff --git a/src/compare/libs/pixelmatch/pixelmatch.service.ts b/src/compare/libs/pixelmatch/pixelmatch.service.ts index a74c5f21..0f39912b 100644 --- a/src/compare/libs/pixelmatch/pixelmatch.service.ts +++ b/src/compare/libs/pixelmatch/pixelmatch.service.ts @@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { TestStatus } from '@prisma/client'; import Pixelmatch from 'pixelmatch'; import { PNG } from 'pngjs'; -import { StaticService } from '../../../shared/static/static.service'; +import { StaticService } from '../../../static/static.service'; import { DiffResult } from '../../../test-runs/diffResult'; import { scaleImageToSize, applyIgnoreAreas, parseConfig } from '../../utils'; import { DIFF_DIMENSION_RESULT, EQUAL_RESULT, NO_BASELINE_RESULT } from '../consts'; @@ -27,8 +27,8 @@ export class PixelmatchService implements ImageComparator { ...NO_BASELINE_RESULT, }; - const baseline = this.staticService.getImage(data.baseline); - const image = this.staticService.getImage(data.image); + const baseline = await this.staticService.getImage(data.baseline); + const image = await this.staticService.getImage(data.image); if (!baseline) { return NO_BASELINE_RESULT; @@ -68,7 +68,7 @@ export class PixelmatchService implements ImageComparator { if (result.diffPercent > data.diffTollerancePercent) { // save diff if (data.saveDiffAsFile) { - result.diffName = this.staticService.saveImage('diff', PNG.sync.write(diff)); + result.diffName = await this.staticService.saveImage('diff', PNG.sync.write(diff)); } result.status = TestStatus.unresolved; } else { diff --git a/src/main.ts b/src/main.ts index 410cdcb0..977e7923 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,8 +6,9 @@ import { join } from 'path'; import * as bodyParser from 'body-parser'; import { readFileSync, existsSync } from 'fs'; import { HttpsOptions } from '@nestjs/common/interfaces/external/https-options.interface'; -import { IMAGE_PATH } from './shared/static/static.service'; import { NestExpressApplication } from '@nestjs/platform-express'; +import { HDD_IMAGE_PATH } from './static/hdd/constants'; +import { isHddStaticServiceConfigured } from './static/utils'; function getHttpsOptions(): HttpsOptions | null { const keyPath = './secrets/ssl.key'; @@ -34,14 +35,16 @@ async function bootstrap() { app.use(bodyParser.json({ limit: process.env.BODY_PARSER_JSON_LIMIT })); } - // serve images - app.useStaticAssets(join(process.cwd(), IMAGE_PATH), { - maxAge: 31536000, - // allow cors - setHeaders: (res) => { - res.set('Access-Control-Allow-Origin', '*'); - }, - }); + // serve images only if hdd configuration + if (isHddStaticServiceConfigured()) { + app.useStaticAssets(join(process.cwd(), HDD_IMAGE_PATH), { + maxAge: 31536000, + // allow cors + setHeaders: (res) => { + res.set('Access-Control-Allow-Origin', '*'); + }, + }); + } await app.listen(process.env.APP_PORT || 3000); } diff --git a/src/shared/shared.module.ts b/src/shared/shared.module.ts index 6a82bd87..8e6f7e89 100644 --- a/src/shared/shared.module.ts +++ b/src/shared/shared.module.ts @@ -1,5 +1,4 @@ import { forwardRef, Global, Module } from '@nestjs/common'; -import { StaticService } from './static/static.service'; import { EventsGateway } from '../shared/events/events.gateway'; import { PrismaService } from '../prisma/prisma.service'; import { TasksService } from './tasks/tasks.service'; @@ -7,8 +6,8 @@ import { TestVariationsModule } from '../test-variations/test-variations.module' @Global() @Module({ - providers: [StaticService, EventsGateway, PrismaService, TasksService], - exports: [StaticService, EventsGateway, PrismaService], + providers: [EventsGateway, PrismaService, TasksService], + exports: [EventsGateway, PrismaService], imports: [forwardRef(() => TestVariationsModule)], controllers: [], }) diff --git a/src/static/aws/s3.service.ts b/src/static/aws/s3.service.ts new file mode 100644 index 00000000..b00ba672 --- /dev/null +++ b/src/static/aws/s3.service.ts @@ -0,0 +1,39 @@ +import { PNGWithMetadata } from 'pngjs'; +import { Logger } from '@nestjs/common'; +import { Static } from '../static.interface'; +// import { S3Client } from '@aws-sdk/client-s3'; + +export class AWSS3Service implements Static { + private readonly logger: Logger = new Logger(AWSS3Service.name); + // private readonly AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID; + // private readonly AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY; + // private readonly AWS_REGION = process.env.AWS_REGION; + // private readonly AWS_S3_BUCKET_NAME = process.env.AWS_S3_BUCKET_NAME; + + // private s3Client: S3Client; + + constructor() { + // this.s3Client = new S3Client({ + // credentials: { + // accessKeyId: this.AWS_ACCESS_KEY_ID, + // secretAccessKey: this.AWS_SECRET_ACCESS_KEY, + // }, + // region: this.AWS_REGION, + // }); + this.logger.log('AWS S3 service is being used for file storage.'); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + saveImage(type: 'screenshot' | 'diff' | 'baseline', imageBuffer: Buffer): Promise { + throw new Error('Method not implemented.'); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getImage(fileName: string): Promise { + throw new Error('Method not implemented.'); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + deleteImage(imageName: string): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/src/static/hdd/constants.ts b/src/static/hdd/constants.ts new file mode 100644 index 00000000..3bb90b2e --- /dev/null +++ b/src/static/hdd/constants.ts @@ -0,0 +1 @@ +export const HDD_IMAGE_PATH = 'imageUploads/'; diff --git a/src/shared/static/static.service.ts b/src/static/hdd/hdd.service.ts similarity index 74% rename from src/shared/static/static.service.ts rename to src/static/hdd/hdd.service.ts index 717aac31..d9de82f9 100644 --- a/src/shared/static/static.service.ts +++ b/src/static/hdd/hdd.service.ts @@ -1,13 +1,12 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Logger } from '@nestjs/common'; import path from 'path'; import { writeFileSync, readFileSync, unlink, mkdirSync, existsSync } from 'fs'; import { PNG, PNGWithMetadata } from 'pngjs'; +import { Static } from '../static.interface'; +import { HDD_IMAGE_PATH } from './constants'; -export const IMAGE_PATH = 'imageUploads/'; - -@Injectable() -export class StaticService { - private readonly logger: Logger = new Logger(StaticService.name); +export class HddService implements Static { + private readonly logger: Logger = new Logger(HddService.name); generateNewImage(type: 'screenshot' | 'diff' | 'baseline'): { imageName: string; imagePath: string } { const imageName = `${Date.now()}.${type}.png`; @@ -18,11 +17,11 @@ export class StaticService { } getImagePath(imageName: string): string { - this.ensureDirectoryExistence(IMAGE_PATH); - return path.resolve(IMAGE_PATH, imageName); + this.ensureDirectoryExistence(HDD_IMAGE_PATH); + return path.resolve(HDD_IMAGE_PATH, imageName); } - saveImage(type: 'screenshot' | 'diff' | 'baseline', imageBuffer: Buffer): string { + async saveImage(type: 'screenshot' | 'diff' | 'baseline', imageBuffer: Buffer): Promise { try { new PNG().parse(imageBuffer); } catch (ex) { @@ -34,7 +33,7 @@ export class StaticService { return imageName; } - getImage(imageName: string): PNGWithMetadata { + async getImage(imageName: string): Promise { if (!imageName) return; try { return PNG.sync.read(readFileSync(this.getImagePath(imageName))); diff --git a/src/static/static.factory.ts b/src/static/static.factory.ts new file mode 100644 index 00000000..852e10f1 --- /dev/null +++ b/src/static/static.factory.ts @@ -0,0 +1,25 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { Static } from './static.interface'; +import { HddService } from './hdd/hdd.service'; +import { AWSS3Service } from './aws/s3.service'; + +@Injectable() +export class StaticFactoryService { + private readonly logger: Logger = new Logger(StaticFactoryService.name); + + constructor(private configService: ConfigService) {} + + getStaticService(): Static { + const serviceType = this.configService.get('STATIC_SERVICE', 'hdd'); + switch (serviceType) { + case 's3': + this.logger.debug('static service type: S3'); + return new AWSS3Service(); + case 'hdd': + default: + this.logger.debug('static service type: HDD'); + return new HddService(); + } + } +} diff --git a/src/static/static.interface.ts b/src/static/static.interface.ts new file mode 100644 index 00000000..07ee4746 --- /dev/null +++ b/src/static/static.interface.ts @@ -0,0 +1,7 @@ +import { PNGWithMetadata } from 'pngjs'; + +export interface Static { + saveImage(type: 'screenshot' | 'diff' | 'baseline', imageBuffer: Buffer): Promise; + getImage(fileName: string): Promise; + deleteImage(imageName: string): Promise; +} diff --git a/src/static/static.module.ts b/src/static/static.module.ts new file mode 100644 index 00000000..6e69e888 --- /dev/null +++ b/src/static/static.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { StaticService } from './static.service'; +import { StaticFactoryService } from './static.factory'; + +@Module({ + imports: [ConfigModule], + providers: [StaticService, StaticFactoryService], + exports: [StaticService], +}) +export class StaticModule {} diff --git a/src/shared/static/static.service.spec.ts b/src/static/static.service.spec.ts similarity index 88% rename from src/shared/static/static.service.spec.ts rename to src/static/static.service.spec.ts index 67d90bbf..a3963cb7 100644 --- a/src/shared/static/static.service.spec.ts +++ b/src/static/static.service.spec.ts @@ -1,6 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { StaticService } from './static.service'; import { ConfigService } from '@nestjs/config'; +import { StaticModule } from './static.module'; describe('StaticService', () => { let service: StaticService; @@ -8,12 +9,12 @@ describe('StaticService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - StaticService, { provide: ConfigService, useValue: {}, }, ], + imports: [StaticModule], }).compile(); service = module.get(StaticService); diff --git a/src/static/static.service.ts b/src/static/static.service.ts new file mode 100644 index 00000000..309e7259 --- /dev/null +++ b/src/static/static.service.ts @@ -0,0 +1,26 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { PNGWithMetadata } from 'pngjs'; +import { StaticFactoryService } from './static.factory'; +import { Static } from './static.interface'; + +@Injectable() +export class StaticService { + private readonly logger: Logger = new Logger(StaticService.name); + private readonly staticService: Static; + + constructor(private staticFactoryService: StaticFactoryService) { + this.staticService = this.staticFactoryService.getStaticService(); + } + + async saveImage(type: 'screenshot' | 'diff' | 'baseline', imageBuffer: Buffer): Promise { + return this.staticService.saveImage(type, imageBuffer); + } + + async getImage(imageName: string): Promise { + return this.staticService.getImage(imageName); + } + + async deleteImage(imageName: string): Promise { + return this.staticService.deleteImage(imageName); + } +} diff --git a/src/static/utils.ts b/src/static/utils.ts new file mode 100644 index 00000000..2366c6e9 --- /dev/null +++ b/src/static/utils.ts @@ -0,0 +1,3 @@ +export function isHddStaticServiceConfigured() { + return !process.env.STATIC_SERVICE || process.env.STATIC_SERVICE === 'hdd'; +} diff --git a/src/test-runs/test-runs.module.ts b/src/test-runs/test-runs.module.ts index f25d5852..d869c252 100644 --- a/src/test-runs/test-runs.module.ts +++ b/src/test-runs/test-runs.module.ts @@ -5,9 +5,10 @@ import { PrismaService } from '../prisma/prisma.service'; import { TestRunsController } from './test-runs.controller'; import { TestVariationsModule } from '../test-variations/test-variations.module'; import { CompareModule } from '../compare/compare.module'; +import { StaticModule } from '../static/static.module'; @Module({ - imports: [SharedModule, forwardRef(() => TestVariationsModule), CompareModule], + imports: [SharedModule, forwardRef(() => TestVariationsModule), CompareModule, StaticModule], providers: [TestRunsService, PrismaService], controllers: [TestRunsController], exports: [TestRunsService], diff --git a/src/test-runs/test-runs.service.spec.ts b/src/test-runs/test-runs.service.spec.ts index c6cc96c8..ae3c8991 100644 --- a/src/test-runs/test-runs.service.spec.ts +++ b/src/test-runs/test-runs.service.spec.ts @@ -2,7 +2,7 @@ import { mocked } from 'jest-mock'; import { Test, TestingModule } from '@nestjs/testing'; import { TestRunsService } from './test-runs.service'; import { PrismaService } from '../prisma/prisma.service'; -import { StaticService } from '../shared/static/static.service'; +import { StaticService } from '../static/static.service'; import { TestStatus, TestRun, TestVariation } from '@prisma/client'; import { CreateTestRequestDto } from './dto/create-test-request.dto'; import { TestRunResultDto } from './dto/testRunResult.dto'; diff --git a/src/test-runs/test-runs.service.ts b/src/test-runs/test-runs.service.ts index efebd903..40e7a254 100644 --- a/src/test-runs/test-runs.service.ts +++ b/src/test-runs/test-runs.service.ts @@ -2,7 +2,7 @@ import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common'; import { PNG } from 'pngjs'; import { CreateTestRequestDto } from './dto/create-test-request.dto'; import { IgnoreAreaDto } from './dto/ignore-area.dto'; -import { StaticService } from '../shared/static/static.service'; +import { StaticService } from '../static/static.service'; import { PrismaService } from '../prisma/prisma.service'; import { Baseline, Prisma, TestRun, TestStatus, TestVariation } from '@prisma/client'; import { DiffResult } from './diffResult'; @@ -103,8 +103,8 @@ export class TestRunsService { } // save new baseline - const baseline = this.staticService.getImage(testRun.imageName); - const baselineName = this.staticService.saveImage('baseline', PNG.sync.write(baseline)); + const baseline = await this.staticService.getImage(testRun.imageName); + const baselineName = await this.staticService.saveImage('baseline', PNG.sync.write(baseline)); if (testRun.baselineBranchName !== testRun.branchName && !merge && !autoApprove) { // replace main branch with feature branch test variation @@ -206,7 +206,7 @@ export class TestRunsService { imageBuffer: Buffer; }): Promise { // save image - const imageName = this.staticService.saveImage('screenshot', imageBuffer); + const imageName = await this.staticService.saveImage('screenshot', imageBuffer); const testRun = await this.prismaService.testRun.create({ data: { diff --git a/src/test-variations/test-variations.module.ts b/src/test-variations/test-variations.module.ts index 4cc64701..6628c4e8 100644 --- a/src/test-variations/test-variations.module.ts +++ b/src/test-variations/test-variations.module.ts @@ -4,9 +4,10 @@ import { TestVariationsController } from './test-variations.controller'; import { PrismaService } from '../prisma/prisma.service'; import { TestRunsModule } from '../test-runs/test-runs.module'; import { BuildsModule } from '../builds/builds.module'; +import { StaticModule } from '../static/static.module'; @Module({ - imports: [forwardRef(() => TestRunsModule), forwardRef(() => BuildsModule)], + imports: [forwardRef(() => TestRunsModule), forwardRef(() => BuildsModule), StaticModule], providers: [TestVariationsService, PrismaService], controllers: [TestVariationsController], exports: [TestVariationsService], diff --git a/src/test-variations/test-variations.service.spec.ts b/src/test-variations/test-variations.service.spec.ts index 97a1e1b7..28d4a8e0 100644 --- a/src/test-variations/test-variations.service.spec.ts +++ b/src/test-variations/test-variations.service.spec.ts @@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { TestVariationsService } from './test-variations.service'; import { PrismaService } from '../prisma/prisma.service'; import { CreateTestRequestDto } from '../test-runs/dto/create-test-request.dto'; -import { StaticService } from '../shared/static/static.service'; +import { StaticService } from '../static/static.service'; import { TestVariation, Baseline, Project, Build } from '@prisma/client'; import { PNG } from 'pngjs'; import { BuildsService } from '../builds/builds.service'; diff --git a/src/test-variations/test-variations.service.ts b/src/test-variations/test-variations.service.ts index b711fb1b..3767588d 100644 --- a/src/test-variations/test-variations.service.ts +++ b/src/test-variations/test-variations.service.ts @@ -1,7 +1,7 @@ import { Injectable, Inject, forwardRef, Logger } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { TestVariation, Baseline, Build, TestRun, User } from '@prisma/client'; -import { StaticService } from '../shared/static/static.service'; +import { StaticService } from '../static/static.service'; import { BuildsService } from '../builds/builds.service'; import { TestRunsService } from '../test-runs/test-runs.service'; import { PNG } from 'pngjs'; @@ -183,7 +183,7 @@ export class TestVariationsService { // compare source to destination branch variations for (const sourceBranchTestVariation of testVariations) { - const baseline = this.staticService.getImage(sourceBranchTestVariation.baselineName); + const baseline = await this.staticService.getImage(sourceBranchTestVariation.baselineName); if (baseline) { // get destination branch request const createTestRequestDto: CreateTestRequestDto = { From 829c03f18cef2005f879f3462ddeadf97a7070a0 Mon Sep 17 00:00:00 2001 From: Pavlo Strunkin Date: Wed, 25 Dec 2024 16:29:11 +0200 Subject: [PATCH 2/3] fix --- package-lock.json | 20 -------------------- package.json | 1 - 2 files changed, 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6c20ab1d..33737757 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,6 @@ "@nestjs/testing": "^10.2.5", "@types/bcryptjs": "^2.4.4", "@types/cache-manager": "^3.4.3", - "@types/cron": "^2.4.0", "@types/express": "^4.17.17", "@types/jest": "^29.5.5", "@types/lodash": "^4.14.198", @@ -2377,16 +2376,6 @@ "@types/node": "*" } }, - "node_modules/@types/cron": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.4.0.tgz", - "integrity": "sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==", - "deprecated": "This is a stub types definition. cron provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "cron": "*" - } - }, "node_modules/@types/eslint": { "version": "8.44.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", @@ -12734,15 +12723,6 @@ "@types/node": "*" } }, - "@types/cron": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.4.0.tgz", - "integrity": "sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==", - "dev": true, - "requires": { - "cron": "*" - } - }, "@types/eslint": { "version": "8.44.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", diff --git a/package.json b/package.json index a4849e17..4f03ffc3 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "@nestjs/testing": "^10.2.5", "@types/bcryptjs": "^2.4.4", "@types/cache-manager": "^3.4.3", - "@types/cron": "^2.4.0", "@types/express": "^4.17.17", "@types/jest": "^29.5.5", "@types/lodash": "^4.14.198", From caecaa0b6ee9fbab2fb51c1dddf0c32f2d3e48f2 Mon Sep 17 00:00:00 2001 From: Pavlo Strunkin Date: Wed, 25 Dec 2024 16:50:34 +0200 Subject: [PATCH 3/3] Create static.factory.spec.ts --- src/static/static.factory.spec.ts | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/static/static.factory.spec.ts diff --git a/src/static/static.factory.spec.ts b/src/static/static.factory.spec.ts new file mode 100644 index 00000000..545dfab8 --- /dev/null +++ b/src/static/static.factory.spec.ts @@ -0,0 +1,49 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ConfigService } from '@nestjs/config'; +import { StaticFactoryService } from './static.factory'; +import { HddService } from './hdd/hdd.service'; +import { AWSS3Service } from './aws/s3.service'; + +describe('StaticFactoryService', () => { + let service: StaticFactoryService; + let configService: ConfigService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + StaticFactoryService, + { + provide: ConfigService, + useValue: { + get: jest.fn(), + }, + }, + ], + }).compile(); + + service = module.get(StaticFactoryService); + configService = module.get(ConfigService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + it('should return HddService when STATIC_SERVICE is hdd', () => { + jest.spyOn(configService, 'get').mockReturnValue('hdd'); + const result = service.getStaticService(); + expect(result).toBeInstanceOf(HddService); + }); + + it('should return AWSS3Service when STATIC_SERVICE is s3', () => { + jest.spyOn(configService, 'get').mockReturnValue('s3'); + const result = service.getStaticService(); + expect(result).toBeInstanceOf(AWSS3Service); + }); + + it('should return HddService by default when STATIC_SERVICE is not set', () => { + jest.spyOn(configService, 'get').mockReturnValue(undefined); + const result = service.getStaticService(); + expect(result).toBeInstanceOf(HddService); + }); +});