diff --git a/packages/apps/dashboard/server/.env.example b/packages/apps/dashboard/server/.env.example index d8532b39e4..f3ac7f4f39 100644 --- a/packages/apps/dashboard/server/.env.example +++ b/packages/apps/dashboard/server/.env.example @@ -34,6 +34,3 @@ S3_BUCKET= #Web3 WEB3_ENV= RPC_URL_POLYGON= - -# e2e testing -E2E_TESTING_EMAIL_ADDRESS= diff --git a/packages/apps/dashboard/server/README.md b/packages/apps/dashboard/server/README.md index 83729419a3..efbadeb8a0 100644 --- a/packages/apps/dashboard/server/README.md +++ b/packages/apps/dashboard/server/README.md @@ -51,9 +51,6 @@ $ yarn run start:prod # unit tests $ yarn run test -# e2e tests -$ yarn run test:e2e - # test coverage $ yarn run test:cov ``` diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 0822378082..1b3bf5252c 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -16,8 +16,7 @@ "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json" + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand" }, "dependencies": { "@human-protocol/sdk": "*", diff --git a/packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts b/packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts deleted file mode 100644 index fbcd16506f..0000000000 --- a/packages/apps/dashboard/server/src/common/config/test-environment-config.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -import Joi from 'joi'; -import { ConfigService } from '@nestjs/config'; -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class TestEnvironmentConfigService { - constructor(private configService: ConfigService) {} - - /** - * The email address used for end-to-end (E2E) testing. - * Default: empty string - */ - get e2eTestingEmailAddress(): string { - return this.configService.get('E2E_TESTING_EMAIL_ADDRESS', ''); - } -} - -export const testEnvValidator = Joi.object({ - E2E_TESTING_EMAIL_ADDRESS: Joi.string().required(), -}); diff --git a/packages/apps/dashboard/server/test/app.e2e-spec.ts b/packages/apps/dashboard/server/test/app.e2e-spec.ts deleted file mode 100644 index 35f4ae9f85..0000000000 --- a/packages/apps/dashboard/server/test/app.e2e-spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import request from 'supertest'; -import { AppModule } from '../src/app.module'; -import { beforeAll, afterAll, describe, it, expect } from '@jest/globals'; -import { ConfigService } from '@nestjs/config'; -import { - TestEnvironmentConfigService, - testEnvValidator, -} from '../src/common/config/test-environment-config.service'; -import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { Cache } from 'cache-manager'; - -describe('Dashboard (e2e) tests', () => { - let app: INestApplication; - let configService: ConfigService; - let envConfigService: TestEnvironmentConfigService; - let cacheManager: Cache; - - beforeAll(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - configService = moduleFixture.get(ConfigService); - envConfigService = new TestEnvironmentConfigService(configService); - cacheManager = app.get(CACHE_MANAGER); - - const { error } = testEnvValidator.validate({ - E2E_TESTING_EMAIL_ADDRESS: envConfigService.e2eTestingEmailAddress, - }); - - if (error) { - throw new Error(`Test environment is not valid: ${error.message}`); - } - - await app.init(); - }); - - describe('Networks API', () => { - it('should successfully retrieve operating networks and validate chain IDs', async () => { - const response = await request(app.getHttpServer()) - .get('/networks/operating') - .expect(200); - - expect(Array.isArray(response.body)).toBe(true); - expect(response.body.every((id: any) => typeof id === 'number')).toBe( - true, - ); - }); - - it('should retrieve from cache when it exists', async () => { - const mockData = [1, 2, 3]; - await cacheManager.set('operating-networks', mockData); - - const response = await request(app.getHttpServer()) - .get('/networks/operating') - .expect(200); - - expect(response.body).toEqual(mockData); - }); - }); - - afterAll(async () => { - await app.close(); - }); -}); diff --git a/packages/apps/dashboard/server/test/jest-e2e.json b/packages/apps/dashboard/server/test/jest-e2e.json deleted file mode 100644 index d530a8f8d9..0000000000 --- a/packages/apps/dashboard/server/test/jest-e2e.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - }, - "transformIgnorePatterns": [ - "/node_modules/(?!(@nestjs/config|uuid)).+\\.js$" - ] -} diff --git a/packages/apps/fortune/exchange-oracle/server/README.md b/packages/apps/fortune/exchange-oracle/server/README.md index 92a7f6b570..3a4ce72618 100644 --- a/packages/apps/fortune/exchange-oracle/server/README.md +++ b/packages/apps/fortune/exchange-oracle/server/README.md @@ -90,9 +90,6 @@ $ yarn run start:debug # unit tests $ yarn run test -# e2e tests -$ yarn run test:e2e - # test coverage $ yarn run test:cov ``` diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 09b216cac0..99a18ac957 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -23,7 +23,6 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json", "setup:local": "ts-node ./test/setup.ts", "generate-env-doc": "ts-node scripts/generate-env-doc.ts" }, diff --git a/packages/apps/fortune/exchange-oracle/server/test/app.e2e-spec.ts b/packages/apps/fortune/exchange-oracle/server/test/app.e2e-spec.ts deleted file mode 100644 index 50cda62332..0000000000 --- a/packages/apps/fortune/exchange-oracle/server/test/app.e2e-spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); diff --git a/packages/apps/fortune/exchange-oracle/server/test/jest-e2e.json b/packages/apps/fortune/exchange-oracle/server/test/jest-e2e.json deleted file mode 100644 index e9d912f3e3..0000000000 --- a/packages/apps/fortune/exchange-oracle/server/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} diff --git a/packages/apps/fortune/recording-oracle/README.md b/packages/apps/fortune/recording-oracle/README.md index e8d16bd3c5..c84ac39290 100644 --- a/packages/apps/fortune/recording-oracle/README.md +++ b/packages/apps/fortune/recording-oracle/README.md @@ -60,9 +60,6 @@ $ yarn run start:debug # unit tests $ yarn run test -# e2e tests -$ yarn run test:e2e - # test coverage $ yarn run test:cov ``` diff --git a/packages/apps/fortune/recording-oracle/package.json b/packages/apps/fortune/recording-oracle/package.json index 6e0f294dfe..2dd1dc7c58 100644 --- a/packages/apps/fortune/recording-oracle/package.json +++ b/packages/apps/fortune/recording-oracle/package.json @@ -16,7 +16,6 @@ "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", - "test:e2e": "jest --config ./test/jest-e2e.json", "postgres": "docker compose up -d postgres", "docker": "docker compose up -d", "local": "docker compose down && (concurrently --hide 0 \"yarn docker\" \"yarn recording-oracle:dev\" )", diff --git a/packages/apps/fortune/recording-oracle/test/app.e2e-spec.ts b/packages/apps/fortune/recording-oracle/test/app.e2e-spec.ts deleted file mode 100644 index 50cda62332..0000000000 --- a/packages/apps/fortune/recording-oracle/test/app.e2e-spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); diff --git a/packages/apps/fortune/recording-oracle/test/jest-e2e.json b/packages/apps/fortune/recording-oracle/test/jest-e2e.json deleted file mode 100644 index e9d912f3e3..0000000000 --- a/packages/apps/fortune/recording-oracle/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} diff --git a/packages/apps/job-launcher/server/README.md b/packages/apps/job-launcher/server/README.md index c409c3f656..c9a5b013ca 100644 --- a/packages/apps/job-launcher/server/README.md +++ b/packages/apps/job-launcher/server/README.md @@ -88,9 +88,6 @@ $ yarn run start:debug # unit tests $ yarn run test -# e2e tests -$ yarn run test:e2e - # test coverage $ yarn run test:cov ``` diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index e6d7cdbccd..e9b7c083a0 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -25,7 +25,6 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "export POSTGRES_DATABASE=job-launcher POSTGRES_PASSWORD=qwerty POSTGRES_USER=default POSTGRES_HOST=0.0.0.0 NODE_ENV=test-e2e && docker compose up -d postgres && yarn migration:run && jest --config ./test/jest-e2e.json; testStatus=$?; docker rm -f postgres; exit $testStatus", "generate-env-doc": "ts-node scripts/generate-env-doc.ts" }, "dependencies": { diff --git a/packages/apps/job-launcher/server/src/app.module.ts b/packages/apps/job-launcher/server/src/app.module.ts index e6fbbcda18..322ef389d1 100644 --- a/packages/apps/job-launcher/server/src/app.module.ts +++ b/packages/apps/job-launcher/server/src/app.module.ts @@ -19,7 +19,6 @@ import { CronJobModule } from './modules/cron-job/cron-job.module'; import { SnakeCaseInterceptor } from './common/interceptors/snake-case'; import { WebhookModule } from './modules/webhook/webhook.module'; import { EnvConfigModule } from './common/config/config.module'; -import { E2E_TEST_ENV } from './common/constants'; import { ExceptionFilter } from './common/exceptions/exception.filter'; import { ScheduleModule } from '@nestjs/schedule'; import { StatisticModule } from './modules/statistic/statistic.module'; @@ -52,15 +51,10 @@ import { TransformEnumInterceptor } from './common/interceptors/transform-enum.i imports: [ ScheduleModule.forRoot(), ConfigModule.forRoot({ - ignoreEnvFile: process.env.NODE_ENV === E2E_TEST_ENV, - ...(process.env.NODE_ENV !== E2E_TEST_ENV && { - envFilePath: process.env.NODE_ENV - ? `.env.${process.env.NODE_ENV as string}` - : '.env', - }), - ...(process.env.NODE_ENV !== E2E_TEST_ENV && { - validationSchema: envValidator, - }), + envFilePath: process.env.NODE_ENV + ? `.env.${process.env.NODE_ENV as string}` + : '.env', + validationSchema: envValidator, }), DatabaseModule, HealthModule, diff --git a/packages/apps/job-launcher/server/src/common/constants/index.ts b/packages/apps/job-launcher/server/src/common/constants/index.ts index a34772c2bd..64c81444bd 100644 --- a/packages/apps/job-launcher/server/src/common/constants/index.ts +++ b/packages/apps/job-launcher/server/src/common/constants/index.ts @@ -67,6 +67,4 @@ export const HCAPTCHA_NOT_PRESENTED_LABEL = 'Not presented'; export const RESEND_EMAIL_VERIFICATION_PATH = '/auth/resend-email-verification'; export const LOGOUT_PATH = '/auth/logout'; -export const E2E_TEST_ENV = 'test-e2e'; - export const MUTEX_TIMEOUT = 2000; //ms diff --git a/packages/apps/job-launcher/server/test/e2e/app.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/app.e2e-spec.ts deleted file mode 100644 index f23cf97317..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/app.e2e-spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import request from 'supertest'; -import { AppModule } from '../../src/app.module'; -import setupE2eEnvironment from './env-setup'; -import { ChainId } from '@human-protocol/sdk'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; -import { - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../../test/constants'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeAll(async () => { - setupE2eEnvironment(); - }); - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(301) - .expect('Moved Permanently. Redirecting to /swagger'); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/auth-workflow.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/auth-workflow.e2e-spec.ts deleted file mode 100644 index 1c7065e852..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/auth-workflow.e2e-spec.ts +++ /dev/null @@ -1,145 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserRepository } from '../../src/modules/user/user.repository'; -import { TokenRepository } from '../../src/modules/auth/token.repository'; -import { TokenType } from '../../src/modules/auth/token.entity'; -import { UserStatus } from '../../src/common/enums/user'; -import setupE2eEnvironment from './env-setup'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; -import { ChainId } from '@human-protocol/sdk'; -import { - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; - -describe('AuthService E2E', () => { - let app: INestApplication; - let userRepository: UserRepository; - let tokenRepository: TokenRepository; - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - userRepository = moduleFixture.get(UserRepository); - tokenRepository = moduleFixture.get(TokenRepository); - }); - - afterAll(async () => { - await app.close(); - }); - - it.only('should test authentication workflow', async () => { - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - const password = 'Password1!'; - const hCaptchaToken = 'string'; - - // User Registration - const signUpResponse = await request(app.getHttpServer()) - .post('/auth/signup') - .send({ - email, - password, - h_captcha_token: hCaptchaToken, - }); - expect(signUpResponse.status).toBe(201); - - // Verify user registration - const userEntity = await userRepository.findByEmail(email); - expect(userEntity).toBeDefined(); - - // Email Verification - expect(userEntity!.status).toBe(UserStatus.PENDING); - - // Invalid verification - const invalidVerifyTokenResponse = await request(app.getHttpServer()) - .post(`/auth/email-verification`) - .send({ token: 123 }); - expect(invalidVerifyTokenResponse.status).toBe(400); - - const tokenEntity = await tokenRepository.findOneByUserIdAndType( - userEntity!.id, - TokenType.EMAIL, - ); - - // Valid verification - const verifyTokenResponse = await request(app.getHttpServer()) - .post(`/auth/email-verification`) - .send({ token: tokenEntity!.uuid }); - - expect(verifyTokenResponse.status).toBe(200); - - const updatedUserEntity = await userRepository.findByEmail(email); - expect(updatedUserEntity!.status).toBe(UserStatus.ACTIVE); - - // User Authentication - const signInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password, - h_captcha_token: hCaptchaToken, - }); - expect(signInResponse.status).toBe(200); - - const refreshedUserEntity = await userRepository.findByEmail(email); - const refreshTokenEntity = await tokenRepository.findOneByUserIdAndType( - refreshedUserEntity!.id, - TokenType.REFRESH, - ); - expect(refreshTokenEntity).toBeDefined(); - - // Invalid Authentication - const invalidSignInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password: 'Incorrect', - h_captcha_token: hCaptchaToken, - }); - expect(invalidSignInResponse.status).toBe(403); - - // Refresh Token - const refreshTokenResponse = await request(app.getHttpServer()) - .post('/auth/refresh') - .send({ refresh_token: refreshTokenEntity!.uuid }); // Add appropriate data if needed - - expect(refreshTokenResponse.status).toBe(200); - expect(refreshTokenResponse.body).toHaveProperty('access_token'); - expect(refreshTokenResponse.body).toHaveProperty('refresh_token'); - - const accessToken = refreshTokenResponse.body.access_token; - - // Resend Email Verification - const resendEmailVerificationResponse = await request(app.getHttpServer()) - .post('/auth/resend-email-verification') - .set('Authorization', `Bearer ${accessToken}`) - .send({ email }); - expect(resendEmailVerificationResponse.status).toBe(204); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/cvat-workflow.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/cvat-workflow.e2e-spec.ts deleted file mode 100644 index 1379c8389b..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/cvat-workflow.e2e-spec.ts +++ /dev/null @@ -1,549 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { HttpStatus, INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserStatus } from '../../src/common/enums/user'; -import { UserService } from '../../src/modules/user/user.service'; -import { UserEntity } from '../../src/modules/user/user.entity'; -import setupE2eEnvironment from './env-setup'; -import { - MOCK_CVAT_DATA, - MOCK_CVAT_GT, - MOCK_CVAT_LABELS, - MOCK_FILE_URL, - MOCK_REQUESTER_DESCRIPTION, - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; -import { JobRequestType, JobStatus } from '../../src/common/enums/job'; -import { ErrorJob } from '../../src/common/constants/errors'; -import { - Currency, - PaymentSource, - PaymentStatus, - PaymentType, - TokenId, -} from '../../src/common/enums/payment'; -import { PaymentEntity } from '../../src/modules/payment/payment.entity'; -import { PaymentRepository } from '../../src/modules/payment/payment.repository'; -import { JobRepository } from '../../src/modules/job/job.repository'; -import { AWSRegions, StorageProviders } from '../../src/common/enums/storage'; -import { ChainId } from '@human-protocol/sdk'; -import { StorageService } from '../../src/modules/storage/storage.service'; -import { delay, getFileNameFromURL } from './utils'; -import { PaymentService } from '../../src/modules/payment/payment.service'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; - -describe('CVAT E2E workflow', () => { - let app: INestApplication; - let paymentRepository: PaymentRepository; - let jobRepository: JobRepository; - let userService: UserService; - let storageService: StorageService; - let paymentService: PaymentService; - - let userEntity: UserEntity; - let accessToken: string; - let paidAmount = 0; - const initialBalance = 100; - - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - const paymentIntentId = crypto.randomBytes(16).toString('hex'); - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - paymentRepository = moduleFixture.get(PaymentRepository); - jobRepository = moduleFixture.get(JobRepository); - userService = moduleFixture.get(UserService); - storageService = moduleFixture.get(StorageService); - paymentService = moduleFixture.get(PaymentService); - - userEntity = await userService.create({ - email, - password: 'Password1!', - hCaptchaToken: 'string', - }); - - userEntity.status = UserStatus.ACTIVE; - await userEntity.save(); - - const signInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password: 'Password1!', - h_captcha_token: 'string', - }); - - accessToken = signInResponse.body.access_token; - - const newPaymentEntity = new PaymentEntity(); - Object.assign(newPaymentEntity, { - userId: userEntity.id, - source: PaymentSource.FIAT, - type: PaymentType.DEPOSIT, - amount: initialBalance, - currency: Currency.USD, - rate: 1, - transaction: paymentIntentId, - status: PaymentStatus.SUCCEEDED, - }); - await paymentRepository.createUnique(newPaymentEntity); - }); - - afterEach(async () => { - // Add a delay of 1 second between each test. Prevention: "429 Too Many Requests" - await delay(1000); - }); - - afterAll(async () => { - await app.close(); - }); - - it('should create an CVAT job with image boxes type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const groundTruthsData = MOCK_CVAT_GT; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(groundTruths.url), - }, - type: JobRequestType.IMAGE_BOXES, - fund_amount: 10, - }; - - const response = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(manifest.job_bounty).toBeDefined(); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an CVAT job with image points type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const groundTruthsData = MOCK_CVAT_GT; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(groundTruths.url), - }, - type: JobRequestType.IMAGE_POINTS, - fund_amount: 10, - }; - - const response = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(manifest.job_bounty).toBeDefined(); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an CVAT job with image boxes from points type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const datasetData = MOCK_CVAT_DATA; - - const dataset = await storageService.uploadJsonLikeData(datasetData); - - const groundTruthsData = MOCK_CVAT_GT; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - points: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(dataset.url), - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(groundTruths.url), - }, - type: JobRequestType.IMAGE_BOXES_FROM_POINTS, - fund_amount: 10, - }; - - const response = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(manifest.job_bounty).toBeDefined(); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should handle when data does not exist while creating a CVAT job with image boxes from points type', async () => { - const groundTruthsData = MOCK_CVAT_GT; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(groundTruths.url), - }, - type: JobRequestType.IMAGE_BOXES_FROM_POINTS, - fund_amount: 10, - }; - - const invalidCreateJobResponse = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(409); - - expect(invalidCreateJobResponse.status).toBe(HttpStatus.CONFLICT); - expect(invalidCreateJobResponse.body.message).toBe(ErrorJob.DataNotExist); - }); - - it('should create an CVAT job with image skeletons from boxes type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const datasetData = MOCK_CVAT_DATA; - - const dataset = await storageService.uploadJsonLikeData(datasetData); - - const groundTruthsData = MOCK_CVAT_GT; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - boxes: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(dataset.url), - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(groundTruths.url), - }, - type: JobRequestType.IMAGE_SKELETONS_FROM_BOXES, - fund_amount: 10, - }; - - const response = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(manifest.job_bounty).toBeDefined(); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should handle when data does not exist while creating a CVAT job with image skeletons from boxes type', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const groundTruthsData = MOCK_CVAT_GT; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: getFileNameFromURL(groundTruths.url), - }, - type: JobRequestType.IMAGE_BOXES_FROM_POINTS, - fund_amount: 10, - }; - - const invalidCreateJobResponse = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(409); - - expect(invalidCreateJobResponse.status).toBe(HttpStatus.CONFLICT); - expect(invalidCreateJobResponse.body.message).toBe(ErrorJob.DataNotExist); - }); - - it('should handle not enough funds error', async () => { - const cvatDto = { - chain_id: ChainId.LOCALHOST, - data: { - dataset: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - }, - labels: MOCK_CVAT_LABELS, - requester_description: MOCK_REQUESTER_DESCRIPTION, - user_guide: MOCK_FILE_URL, - min_quality: 0.8, - ground_truth: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: MOCK_FILE_URL, - }, - type: JobRequestType.IMAGE_BOXES, - fund_amount: 100000000, - }; - - const invalidCreateJobResponse = await request(app.getHttpServer()) - .post('/job/cvat') - .set('Authorization', `Bearer ${accessToken}`) - .send(cvatDto) - .expect(400); - - expect(invalidCreateJobResponse.status).toBe(HttpStatus.BAD_REQUEST); - expect(invalidCreateJobResponse.body.message).toBe(ErrorJob.NotEnoughFunds); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/env-setup.ts b/packages/apps/job-launcher/server/test/e2e/env-setup.ts deleted file mode 100644 index 8dec352553..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/env-setup.ts +++ /dev/null @@ -1,69 +0,0 @@ -export default function setupE2eEnvironment() { - process.env.NODE_ENV = 'test-e2e'; - process.env.S3_ACCESS_KEY = 'value'; - - process.env.POSTGRES_DATABASE = 'job-launcher'; - process.env.POSTGRES_PASSWORD = 'qwerty'; - process.env.POSTGRES_USER = 'default'; - process.env.POSTGRES_HOST = '0.0.0.0'; - - process.env.SESSION_SECRET = 'test'; - process.env.POSTGRES_HOST = '0.0.0.0'; - process.env.POSTGRES_USER = 'default'; - process.env.POSTGRES_PASSWORD = 'qwerty'; - process.env.POSTGRES_DATABASE = 'job-launcher'; - process.env.POSTGRES_PORT = '5432'; - process.env.POSTGRES_SSL = 'false'; - - process.env.WEB3_ENV = 'localhost'; - process.env.WEB3_PRIVATE_KEY = - '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d'; - process.env.GAS_PRICE_MULTIPLIER = '1'; - process.env.PGP_ENCRYPT = 'false'; - process.env.FORTUNE_EXCHANGE_ORACLE_ADDRESS = - '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC'; - process.env.FORTUNE_RECORDING_ORACLE_ADDRESS = - '0x90F79bf6EB2c4f870365E785982E1f101E93b906'; - process.env.CVAT_EXCHANGE_ORACLE_ADDRESS = - '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC'; - process.env.CVAT_RECORDING_ORACLE_ADDRESS = - '0x90F79bf6EB2c4f870365E785982E1f101E93b906'; - process.env.REPUTATION_ORACLE_ADDRESS = - '0x90F79bf6EB2c4f870365E785982E1f101E93b906'; - process.env.HCAPTCHA_RECORDING_ORACLE_URI = 'a'; - process.env.HCAPTCHA_REPUTATION_ORACLE_URI = 'a'; - process.env.HCAPTCHA_ORACLE_ADDRESS = 'a'; - process.env.HCAPTCHA_SITE_KEY = 'a'; - - process.env.HASH_SECRET = 'a328af3fc1dad15342cc3d68936008fa'; - process.env.JWT_PRIVATE_KEY = `-----BEGIN EC PARAMETERS----- -BggqhkjOPQMBBw== ------END EC PARAMETERS----- ------BEGIN EC PRIVATE KEY----- -MHcCAQEEID2jVcOtjupW4yqNTz70nvmt1GSvqET5G7lpC0Gp31LFoAoGCCqGSM49 -AwEHoUQDQgAEUznVCoagfRCuMA3TfG51xWShNrMJt86lkzfAep9bfBxbaCBbUhJ1 -s9+9eeLMG/nUMAaGxWeOwJ92L/KvzN6RFw== ------END EC PRIVATE KEY-----`; - - process.env.JWT_PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUznVCoagfRCuMA3TfG51xWShNrMJ -t86lkzfAep9bfBxbaCBbUhJ1s9+9eeLMG/nUMAaGxWeOwJ92L/KvzN6RFw== ------END PUBLIC KEY-----`; - process.env.JWT_ACCESS_TOKEN_EXPIRES_IN = '600'; - process.env.JWT_REFRESH_TOKEN_EXPIRES_IN = '1d'; - - process.env.S3_ENDPOINT = 'localhost'; - process.env.S3_PORT = '9000'; - process.env.S3_ACCESS_KEY = 'access-key'; - process.env.S3_SECRET_KEY = 'secret-key'; - process.env.S3_BUCKET = 'bucket'; - process.env.S3_USE_SSL = 'false'; - - process.env.STRIPE_API_VERSION = '2022-11-15'; - process.env.STRIPE_APP_NAME = 'Staging Launcher Server'; - process.env.STRIPE_APP_VERSION = '1.0.0'; - process.env.STRIPE_APP_INFO_URL = - 'https://github.com/humanprotocol/human-protocol/tree/main/packages/apps/job-launcher/server'; - - process.env.SENDGRID_API_KEY = 'sendgrid-disabled'; -} diff --git a/packages/apps/job-launcher/server/test/e2e/fiat-account-deposit-workflow.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/fiat-account-deposit-workflow.e2e-spec.ts deleted file mode 100644 index 07dafa08b3..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/fiat-account-deposit-workflow.e2e-spec.ts +++ /dev/null @@ -1,112 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserStatus } from '../../src/common/enums/user'; -import { UserService } from '../../src/modules/user/user.service'; -import { UserEntity } from '../../src/modules/user/user.entity'; -import setupE2eEnvironment from './env-setup'; -import { - Currency, - PaymentSource, - PaymentStatus, - PaymentType, -} from '../../src/common/enums/payment'; -import { PaymentRepository } from '../../src/modules/payment/payment.repository'; -import { ChainId } from '@human-protocol/sdk'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; -import { - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; - -describe('Fiat account deposit E2E workflow', () => { - let app: INestApplication; - let paymentRepository: PaymentRepository; - let userService: UserService; - - let userEntity: UserEntity; - let accessToken: string; - - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - paymentRepository = moduleFixture.get(PaymentRepository); - userService = moduleFixture.get(UserService); - - userEntity = await userService.create({ - email, - password: 'Password1!', - hCaptchaToken: 'string', - }); - - userEntity.status = UserStatus.ACTIVE; - await userEntity.save(); - - const signInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password: 'Password1!', - h_captcha_token: 'string', - }); - - accessToken = signInResponse.body.access_token; - }); - - afterAll(async () => { - await app.close(); - }); - - it('should create a fiat payment successfully', async () => { - const payemntFiatDto = { - amount: 10, - currency: Currency.USD, - }; - - const response = await request(app.getHttpServer()) - .post('/payment/fiat') - .set('Authorization', `Bearer ${accessToken}`) - .send(payemntFiatDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.PENDING, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.DEPOSIT); - expect(paymentEntities[0].source).toBe(PaymentSource.FIAT); - expect(paymentEntities[0].currency).toBe(Currency.USD); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/fortune-workflow.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/fortune-workflow.e2e-spec.ts deleted file mode 100644 index 0f40299e65..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/fortune-workflow.e2e-spec.ts +++ /dev/null @@ -1,197 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { HttpStatus, INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserStatus } from '../../src/common/enums/user'; -import { UserService } from '../../src/modules/user/user.service'; -import { UserEntity } from '../../src/modules/user/user.entity'; -import setupE2eEnvironment from './env-setup'; -import { JobRequestType, JobStatus } from '../../src/common/enums/job'; -import { ChainId } from '@human-protocol/sdk'; -import { ErrorJob } from '../../src/common/constants/errors'; -import { - Currency, - PaymentSource, - PaymentStatus, - PaymentType, - TokenId, -} from '../../src/common/enums/payment'; -import { PaymentEntity } from '../../src/modules/payment/payment.entity'; -import { PaymentRepository } from '../../src/modules/payment/payment.repository'; -import { JobRepository } from '../../src/modules/job/job.repository'; -import { StorageService } from '../../src/modules/storage/storage.service'; -import { delay } from './utils'; -import { PaymentService } from '../../src/modules/payment/payment.service'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; -import { - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; - -describe('Fortune E2E workflow', () => { - let app: INestApplication; - let paymentRepository: PaymentRepository; - let jobRepository: JobRepository; - let userService: UserService; - let paymentService: PaymentService; - let storageService: StorageService; - - let userEntity: UserEntity; - let accessToken: string; - const initialBalance = 100; - - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - const paymentIntentId = crypto.randomBytes(16).toString('hex'); - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - paymentRepository = moduleFixture.get(PaymentRepository); - jobRepository = moduleFixture.get(JobRepository); - userService = moduleFixture.get(UserService); - paymentService = moduleFixture.get(PaymentService); - storageService = moduleFixture.get(StorageService); - - userEntity = await userService.create({ - email, - password: 'Password1!', - hCaptchaToken: 'string', - }); - - userEntity.status = UserStatus.ACTIVE; - await userEntity.save(); - - const signInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password: 'Password1!', - h_captcha_token: 'string', - }); - - accessToken = signInResponse.body.access_token; - - const newPaymentEntity = new PaymentEntity(); - Object.assign(newPaymentEntity, { - userId: userEntity.id, - source: PaymentSource.FIAT, - type: PaymentType.DEPOSIT, - amount: initialBalance, - currency: Currency.USD, - rate: 1, - transaction: paymentIntentId, - status: PaymentStatus.SUCCEEDED, - }); - await paymentRepository.createUnique(newPaymentEntity); - }); - - afterEach(async () => { - // Add a delay of 1 second between each test. Prevention: "429 Too Many Requests" - await delay(1000); - }); - - afterAll(async () => { - await app.close(); - }); - - it('should create a Fortune job successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance); - - const createJobDto = { - chain_id: ChainId.LOCALHOST, - requester_title: 'Write an odd number', - requester_description: 'Prime number', - submissions_required: 10, - fund_amount: 10, // USD - }; - - const response = await request(app.getHttpServer()) - .post('/job/fortune') - .set('Authorization', `Bearer ${accessToken}`) - .send(createJobDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - expect(manifest).toMatchObject({ - chainId: ChainId.LOCALHOST, - fundAmount: expect.any(Number), - requestType: JobRequestType.FORTUNE, - requesterDescription: createJobDto.requester_description, - requesterTitle: createJobDto.requester_title, - submissionsRequired: createJobDto.submissions_required, - }); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - const paidAmount = paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should handle not enough funds error', async () => { - const createJobDto = { - chain_id: ChainId.LOCALHOST, - requester_title: 'Write an odd number', - requester_description: 'Prime number', - submissions_required: 10, - fund_amount: 100000000, // USD - }; - - const invalidQuickLaunchResponse = await request(app.getHttpServer()) - .post('/job/fortune') - .set('Authorization', `Bearer ${accessToken}`) - .send(createJobDto) - .expect(400); - - expect(invalidQuickLaunchResponse.status).toBe(HttpStatus.BAD_REQUEST); - expect(invalidQuickLaunchResponse.body.message).toBe( - ErrorJob.NotEnoughFunds, - ); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/hcaptcha-workflow.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/hcaptcha-workflow.e2e-spec.ts deleted file mode 100644 index 7e93c5ccae..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/hcaptcha-workflow.e2e-spec.ts +++ /dev/null @@ -1,572 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { HttpStatus, INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserStatus } from '../../src/common/enums/user'; -import { UserService } from '../../src/modules/user/user.service'; -import { UserEntity } from '../../src/modules/user/user.entity'; -import setupE2eEnvironment from './env-setup'; -import { - MOCK_BUCKET_FILES, - MOCK_FILE_URL, - MOCK_PRIVATE_KEY, - MOCK_REQUESTER_DESCRIPTION, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; -import { JobCaptchaShapeType, JobStatus } from '../../src/common/enums/job'; -import { ErrorJob } from '../../src/common/constants/errors'; -import { - Currency, - PaymentSource, - PaymentStatus, - PaymentType, - TokenId, -} from '../../src/common/enums/payment'; -import { PaymentEntity } from '../../src/modules/payment/payment.entity'; -import { PaymentRepository } from '../../src/modules/payment/payment.repository'; -import { JobRepository } from '../../src/modules/job/job.repository'; -import { AWSRegions, StorageProviders } from '../../src/common/enums/storage'; -import { ChainId } from '@human-protocol/sdk'; -import { StorageService } from '../../src/modules/storage/storage.service'; -import { delay } from './utils'; -import { PaymentService } from '../../src/modules/payment/payment.service'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; - -describe.skip('hCaptcha E2E workflow', () => { - let app: INestApplication; - let paymentRepository: PaymentRepository; - let jobRepository: JobRepository; - let userService: UserService; - let storageService: StorageService; - let paymentService: PaymentService; - - let userEntity: UserEntity; - let accessToken: string; - let paidAmount = 0; - const initialBalance = 100; - - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - const paymentIntentId = crypto.randomBytes(16).toString('hex'); - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - paymentRepository = moduleFixture.get(PaymentRepository); - jobRepository = moduleFixture.get(JobRepository); - userService = moduleFixture.get(UserService); - storageService = moduleFixture.get(StorageService); - paymentService = moduleFixture.get(PaymentService); - - userEntity = await userService.create({ - email, - password: 'Password1!', - hCaptchaToken: 'string', - }); - - userEntity.status = UserStatus.ACTIVE; - await userEntity.save(); - - const signInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password: 'Password1!', - h_captcha_token: 'string', - }); - - accessToken = signInResponse.body.access_token; - - const newPaymentEntity = new PaymentEntity(); - Object.assign(newPaymentEntity, { - userId: userEntity.id, - source: PaymentSource.FIAT, - type: PaymentType.DEPOSIT, - amount: 100, - currency: Currency.USD, - rate: 1, - transaction: paymentIntentId, - status: PaymentStatus.SUCCEEDED, - }); - await paymentRepository.createUnique(newPaymentEntity); - }); - - afterEach(async () => { - // Add a delay of 1 second between each test. Prevention: "429 Too Many Requests" - await delay(1000); - }); - - afterAll(async () => { - await app.close(); - }); - - it('should create an hCaptcha job with comparison type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - accuracy_target: 0.9, - completion_date: new Date(), - min_requests: 1, - max_requests: 10, - annotations: { - type_of_job: JobCaptchaShapeType.COMPARISON, - labeling_prompt: MOCK_REQUESTER_DESCRIPTION, - ground_truths: MOCK_FILE_URL, - example_images: MOCK_BUCKET_FILES, - task_bid_price: 0.5, - }, - advanced: {}, - }; - - const response = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(manifest).toBeDefined(); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an hCaptcha job with categorization type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const groundTruthsData = { - 'image_name_1.jpg': [['Dog']], - 'image_name_2.jpg': [['Cat']], - }; - - const groundTruths = - await storageService.uploadJsonLikeData(groundTruthsData); - - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - accuracy_target: 0.9, - completion_date: new Date(), - min_requests: 1, - max_requests: 10, - annotations: { - type_of_job: JobCaptchaShapeType.CATEGORIZATION, - labeling_prompt: MOCK_REQUESTER_DESCRIPTION, - ground_truths: groundTruths.url, - example_images: MOCK_BUCKET_FILES, - task_bid_price: 0.5, - }, - advanced: {}, - }; - - const response = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(jobEntity!.manifestUrl).toBeDefined(); - expect(manifest.requester_restricted_answer_set).toMatchObject({ - Dog: { answer_example_uri: 'image_name_1.jpg', en: 'Dog' }, - Cat: { answer_example_uri: 'image_name_2.jpg', en: 'Cat' }, - }); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an hCaptcha job with polygon type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - accuracy_target: 0.9, - completion_date: new Date(), - min_requests: 1, - max_requests: 10, - annotations: { - type_of_job: JobCaptchaShapeType.POLYGON, - label: 'Label', - labeling_prompt: MOCK_REQUESTER_DESCRIPTION, - ground_truths: MOCK_FILE_URL, - example_images: MOCK_BUCKET_FILES, - task_bid_price: 0.5, - }, - advanced: {}, - }; - - const response = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(jobEntity!.manifestUrl).toBeDefined(); - expect(manifest.requester_restricted_answer_set).toMatchObject({ - Label: { en: 'Label' }, - }); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an hCaptcha job with point type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - accuracy_target: 0.9, - completion_date: new Date(), - min_requests: 1, - max_requests: 10, - annotations: { - type_of_job: JobCaptchaShapeType.POINT, - label: 'Label', - labeling_prompt: MOCK_REQUESTER_DESCRIPTION, - ground_truths: MOCK_FILE_URL, - example_images: MOCK_BUCKET_FILES, - task_bid_price: 0.5, - }, - advanced: {}, - }; - - const response = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(jobEntity!.manifestUrl).toBeDefined(); - expect(manifest.requester_restricted_answer_set).toMatchObject({ - Label: { en: 'Label' }, - }); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an hCaptcha job with bounding box type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - accuracy_target: 0.9, - completion_date: new Date(), - min_requests: 1, - max_requests: 10, - annotations: { - type_of_job: JobCaptchaShapeType.BOUNDING_BOX, - label: 'Label', - labeling_prompt: MOCK_REQUESTER_DESCRIPTION, - ground_truths: MOCK_FILE_URL, - example_images: MOCK_BUCKET_FILES, - task_bid_price: 0.5, - }, - advanced: {}, - }; - - const response = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(jobEntity!.manifestUrl).toBeDefined(); - expect(manifest.requester_restricted_answer_set).toMatchObject({ - Label: { en: 'Label' }, - }); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should create an hCaptcha job with immo type successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance + paidAmount); - - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucket_name: 'bucket', - path: '', - }, - accuracy_target: 0.9, - completion_date: new Date(), - min_requests: 1, - max_requests: 10, - annotations: { - type_of_job: JobCaptchaShapeType.IMMO, - label: 'Label', - labeling_prompt: MOCK_REQUESTER_DESCRIPTION, - ground_truths: MOCK_FILE_URL, - example_images: MOCK_BUCKET_FILES, - task_bid_price: 0.5, - }, - advanced: {}, - }; - - const response = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - expect(jobEntity!.manifestUrl).toBeDefined(); - - const manifest = (await storageService.downloadJsonLikeData( - jobEntity!.manifestUrl, - )) as any; - - expect(jobEntity!.manifestUrl).toBeDefined(); - expect(manifest.requester_restricted_answer_set).toMatchObject({ - Label: { en: 'Label' }, - }); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - paidAmount += paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should handle not enough funds error', async () => { - const hCaptchaDto = { - chain_id: ChainId.LOCALHOST, - data: { - provider: StorageProviders.LOCAL, - region: AWSRegions.EU_CENTRAL_1, - bucketName: 'bucket', - path: '', - }, - accuracyTarget: 0.9, - minRequests: 1, - maxRequests: 10, - annotations: { - typeOfJob: JobCaptchaShapeType.COMPARISON, - labelingPrompt: MOCK_REQUESTER_DESCRIPTION, - groundTruths: MOCK_FILE_URL, - exampleImages: MOCK_BUCKET_FILES, - taskBidPrice: 100, - }, - completionDate: new Date(), - advanced: {}, - }; - - const invalidQuickLaunchResponse = await request(app.getHttpServer()) - .post('/job/hCaptcha') - .set('Authorization', `Bearer ${accessToken}`) - .send(hCaptchaDto) - .expect(400); - - expect(invalidQuickLaunchResponse.status).toBe(HttpStatus.BAD_REQUEST); - expect(invalidQuickLaunchResponse.body.message).toBe( - ErrorJob.NotEnoughFunds, - ); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/quick-launch-workflow.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/quick-launch-workflow.e2e-spec.ts deleted file mode 100644 index 5fce5d6f55..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/quick-launch-workflow.e2e-spec.ts +++ /dev/null @@ -1,196 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { HttpStatus, INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserStatus } from '../../src/common/enums/user'; -import { UserService } from '../../src/modules/user/user.service'; -import { UserEntity } from '../../src/modules/user/user.entity'; -import setupE2eEnvironment from './env-setup'; -import { MOCK_FILE_HASH, MOCK_FILE_URL } from '../../test/constants'; -import { JobRequestType, JobStatus } from '../../src/common/enums/job'; -import { ChainId } from '@human-protocol/sdk'; -import { ErrorJob } from '../../src/common/constants/errors'; -import { - Currency, - PaymentSource, - PaymentStatus, - PaymentType, - TokenId, -} from '../../src/common/enums/payment'; -import { PaymentEntity } from '../../src/modules/payment/payment.entity'; -import { PaymentRepository } from '../../src/modules/payment/payment.repository'; -import { JobRepository } from '../../src/modules/job/job.repository'; -import { PaymentService } from '../../src/modules/payment/payment.service'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; -import { - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; - -describe('Quick launch E2E workflow', () => { - let app: INestApplication; - let paymentRepository: PaymentRepository; - let jobRepository: JobRepository; - let userService: UserService; - let paymentService: PaymentService; - - let userEntity: UserEntity; - let accessToken: string; - const initialBalance = 100; - - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - const paymentIntentId = crypto.randomBytes(16).toString('hex'); - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - paymentRepository = moduleFixture.get(PaymentRepository); - jobRepository = moduleFixture.get(JobRepository); - userService = moduleFixture.get(UserService); - paymentService = moduleFixture.get(PaymentService); - - userEntity = await userService.create({ - email, - password: 'Password1!', - hCaptchaToken: 'string', - }); - - userEntity.status = UserStatus.ACTIVE; - await userEntity.save(); - - const signInResponse = await request(app.getHttpServer()) - .post('/auth/signin') - .send({ - email, - password: 'Password1!', - h_captcha_token: 'string', - }); - - accessToken = signInResponse.body.access_token; - - const newPaymentEntity = new PaymentEntity(); - Object.assign(newPaymentEntity, { - userId: userEntity.id, - source: PaymentSource.FIAT, - type: PaymentType.DEPOSIT, - amount: initialBalance, - currency: Currency.USD, - rate: 1, - transaction: paymentIntentId, - status: PaymentStatus.SUCCEEDED, - }); - await paymentRepository.createUnique(newPaymentEntity); - }); - - afterAll(async () => { - await app.close(); - }); - - it('should create a job via quick launch successfully', async () => { - const balance_before = await paymentService.getUserBalance(userEntity.id); - expect(balance_before).toBe(initialBalance); - - const quickLaunchDto = { - chain_id: ChainId.LOCALHOST, - request_type: JobRequestType.HCAPTCHA, - manifest_url: MOCK_FILE_URL, - manifest_hash: MOCK_FILE_HASH, - fund_amount: 10, // HMT - }; - - const response = await request(app.getHttpServer()) - .post('/job/quick-launch') - .set('Authorization', `Bearer ${accessToken}`) - .send(quickLaunchDto) - .expect(201); - - expect(response.text).toBeDefined(); - expect(typeof response.text).toBe('string'); - - const jobEntity = await jobRepository.findOneByIdAndUserId( - Number(response.text), - userEntity.id, - ); - - expect(jobEntity).toBeDefined(); - expect(jobEntity!.status).toBe(JobStatus.PAID); - - const paymentEntities = await paymentRepository.findByUserAndStatus( - userEntity.id, - PaymentStatus.SUCCEEDED, - ); - - expect(paymentEntities[0]).toBeDefined(); - expect(paymentEntities[0].type).toBe(PaymentType.WITHDRAWAL); - expect(paymentEntities[0].currency).toBe(TokenId.HMT); - - const paidAmount = paymentEntities[0].rate * paymentEntities[0].amount; - const balance_after = await paymentService.getUserBalance(userEntity.id); - expect(balance_after).toBe(initialBalance + paidAmount); - }); - - it('should handle not enough funds error', async () => { - const quickLaunchData = { - chain_id: ChainId.LOCALHOST, - request_type: JobRequestType.HCAPTCHA, - manifest_url: MOCK_FILE_URL, - manifest_hash: MOCK_FILE_HASH, - fund_amount: 100000000, // HMT - }; - - const invalidQuickLaunchResponse = await request(app.getHttpServer()) - .post('/job/quick-launch') - .set('Authorization', `Bearer ${accessToken}`) - .send(quickLaunchData) - .expect(400); - - expect(invalidQuickLaunchResponse.status).toBe(HttpStatus.BAD_REQUEST); - expect(invalidQuickLaunchResponse.body.message).toBe( - ErrorJob.NotEnoughFunds, - ); - }); - - it('should handle manifest hash does not exist error', async () => { - const quickLaunchData = { - chain_id: ChainId.LOCALHOST, - request_type: JobRequestType.HCAPTCHA, - manifest_url: 'http://example.com', - fund_amount: 10, // HMT - }; - - const invalidQuickLaunchResponse = await request(app.getHttpServer()) - .post('/job/quick-launch') - .set('Authorization', `Bearer ${accessToken}`) - .send(quickLaunchData) - .expect(409); - - expect(invalidQuickLaunchResponse.status).toBe(HttpStatus.CONFLICT); - expect(invalidQuickLaunchResponse.body.message).toBe( - ErrorJob.ManifestHashNotExist, - ); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/restore-password.e2e-spec.ts b/packages/apps/job-launcher/server/test/e2e/restore-password.e2e-spec.ts deleted file mode 100644 index 3a72c7068a..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/restore-password.e2e-spec.ts +++ /dev/null @@ -1,198 +0,0 @@ -import request from 'supertest'; -import * as crypto from 'crypto'; -import { HttpStatus, INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AppModule } from '../../src/app.module'; -import { UserRepository } from '../../src/modules/user/user.repository'; -import { TokenRepository } from '../../src/modules/auth/token.repository'; -import { TokenEntity, TokenType } from '../../src/modules/auth/token.entity'; -import { UserStatus } from '../../src/common/enums/user'; -import { UserService } from '../../src/modules/user/user.service'; -import { UserEntity } from '../../src/modules/user/user.entity'; -import { ErrorAuth } from '../../src/common/constants/errors'; -import setupE2eEnvironment from './env-setup'; -import { NetworkConfigService } from '../../src/common/config/network-config.service'; -import { Web3ConfigService } from '../../src/common/config/web3-config.service'; -import { ChainId } from '@human-protocol/sdk'; -import { - MOCK_PRIVATE_KEY, - MOCK_WEB3_NODE_HOST, - MOCK_WEB3_RPC_URL, -} from '../constants'; - -describe('Restore password E2E workflow', () => { - let app: INestApplication; - let userRepository: UserRepository; - let tokenRepository: TokenRepository; - let userService: UserService; - - let userEntity: UserEntity; - let tokenEntity: TokenEntity; - - const email = `${crypto.randomBytes(16).toString('hex')}@hmt.ai`; - - beforeAll(async () => { - setupE2eEnvironment(); - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }) - .overrideProvider(NetworkConfigService) - .useValue({ - networks: [ - { - chainId: ChainId.LOCALHOST, - rpcUrl: MOCK_WEB3_RPC_URL, - }, - ], - }) - .overrideProvider(Web3ConfigService) - .useValue({ - privateKey: MOCK_PRIVATE_KEY, - env: MOCK_WEB3_NODE_HOST, - }) - .compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - userRepository = moduleFixture.get(UserRepository); - tokenRepository = moduleFixture.get(TokenRepository); - userService = moduleFixture.get(UserService); - - userEntity = await userService.create({ - email, - password: 'Password1!', - hCaptchaToken: 'string', - }); - - userEntity.status = UserStatus.ACTIVE; - await userEntity.save(); - - tokenEntity = new TokenEntity(); - tokenEntity.type = TokenType.EMAIL; - tokenEntity.user = userEntity; - const date = new Date(); - tokenEntity.expiresAt = new Date(date.getTime() + 100000); - - await tokenRepository.createUnique(tokenEntity); - }); - - afterAll(async () => { - await app.close(); - }); - - it('should restore password successfully', async () => { - // Call forgot password endpoint - await request(app.getHttpServer()) - .post('/auth/forgot-password') - .send({ email }) - .expect(HttpStatus.NO_CONTENT); - - // Ensure old token was deleted and a new token was created - const oldTokenExists = await tokenRepository.findOneByUuidAndType( - tokenEntity.uuid, - TokenType.PASSWORD, - ); - expect(oldTokenExists).toBeNull(); - - const newToken = await tokenRepository.findOneByUserIdAndType( - userEntity.id, - TokenType.PASSWORD, - ); - expect(newToken).toBeDefined(); - - // Call restore password endpoint - const restorePasswordData = { - password: 'NewPassword1!', - token: newToken!.uuid, - hCaptchaToken: 'string', - }; - await request(app.getHttpServer()) - .post('/auth/restore-password') - .send(restorePasswordData) - .expect(HttpStatus.NO_CONTENT); - - // Ensure password was updated - const updatedUser = await userRepository.findById(userEntity!.id); - expect(updatedUser!.password).not.toEqual(userEntity.password); - - userEntity = updatedUser!; - - // Ensure new token was deleted - const deletedToken = await tokenRepository.findOneByUuidAndType( - newToken!.uuid, - TokenType.PASSWORD, - ); - expect(deletedToken).toBeNull(); - }); - - it('should handle invalid token error', async () => { - // Call forgot password endpoint - await request(app.getHttpServer()) - .post('/auth/forgot-password') - .send({ email }) - .expect(HttpStatus.NO_CONTENT); - - // Delete the new token - await tokenRepository.delete(tokenEntity.id); - - // Call restore password endpoint with invalid token - const invalidToken = '00000000-0000-0000-0000-000000000000'; - const restorePasswordData = { - password: 'NewPassword2!', - token: invalidToken, - hCaptchaToken: 'string', - }; - - const invalidRestorePasswordResponse = await request(app.getHttpServer()) - .post('/auth/restore-password') - .send(restorePasswordData) - .expect(HttpStatus.FORBIDDEN); - - expect(invalidRestorePasswordResponse.status).toBe(HttpStatus.FORBIDDEN); - expect(invalidRestorePasswordResponse.body.message).toBe( - ErrorAuth.InvalidToken, - ); - - // Ensure password was not updated - const updatedUser = await userRepository.findById(userEntity.id); - expect(updatedUser!.password).toEqual(userEntity.password); - }); - - it('should handle token expired error', async () => { - // Call forgot password endpoint - await request(app.getHttpServer()) - .post('/auth/forgot-password') - .send({ email }) - .expect(HttpStatus.NO_CONTENT); - - // Expire the new token - const date = new Date(); - const expiredToken = await tokenRepository.findOneByUserIdAndType( - userEntity.id, - TokenType.PASSWORD, - ); - expiredToken!.expiresAt = new Date(date.getTime() - 100000); // Set token expiration in the past - await expiredToken!.save(); - - // Call restore password endpoint with expired token - const expiredTokenValue = expiredToken!.uuid; - const restorePasswordData = { - password: 'NewPassword2!', - token: expiredTokenValue, - hCaptchaToken: 'string', - }; - const invalidRestorePasswordResponse = await request(app.getHttpServer()) - .post('/auth/restore-password') - .send(restorePasswordData); - - expect(invalidRestorePasswordResponse.status).toBe(HttpStatus.FORBIDDEN); - expect(invalidRestorePasswordResponse.body.message).toBe( - ErrorAuth.TokenExpired, - ); - - // Ensure password was not updated - const updatedUser = await userRepository.findById(userEntity.id); - expect(updatedUser!.password).toEqual(userEntity.password); - }); -}); diff --git a/packages/apps/job-launcher/server/test/e2e/utils.ts b/packages/apps/job-launcher/server/test/e2e/utils.ts deleted file mode 100644 index 726393296c..0000000000 --- a/packages/apps/job-launcher/server/test/e2e/utils.ts +++ /dev/null @@ -1,8 +0,0 @@ -export async function delay(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -export function getFileNameFromURL(url: string): string { - const parts = url.split('/'); - return parts[parts.length - 1]; -} diff --git a/packages/apps/job-launcher/server/test/jest-e2e.json b/packages/apps/job-launcher/server/test/jest-e2e.json deleted file mode 100644 index e9d912f3e3..0000000000 --- a/packages/apps/job-launcher/server/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -}