|
| 1 | +import { Server } from 'net'; |
| 2 | +import { HttpStatus, INestApplication } from '@nestjs/common'; |
| 3 | +import { Test, TestingModule } from '@nestjs/testing'; |
| 4 | +import * as request from 'supertest'; |
| 5 | +import { DataSource, Repository } from 'typeorm'; |
| 6 | +import { AppModule } from '../../app.module'; |
| 7 | +import { PromptCategoryEntity } from '../../domain/database'; |
| 8 | +import { VisibilityType } from '../../domain/prompt'; |
| 9 | +import { initAppWithDataBaseAndValidUser } from '../../utils/testUtils'; |
| 10 | +import { CreatePromptDto, PromptDto } from './dtos'; |
| 11 | + |
| 12 | +describe('Prompts', () => { |
| 13 | + let app: INestApplication<Server>; |
| 14 | + let dataSource: DataSource; |
| 15 | + |
| 16 | + beforeAll(async () => { |
| 17 | + const module: TestingModule = await Test.createTestingModule({ |
| 18 | + imports: [AppModule], |
| 19 | + }).compile(); |
| 20 | + |
| 21 | + const initialized = await initAppWithDataBaseAndValidUser(dataSource, module, app); |
| 22 | + dataSource = initialized.dataSource; |
| 23 | + app = initialized.app; |
| 24 | + await seedTestData(dataSource); |
| 25 | + }); |
| 26 | + |
| 27 | + afterAll(async () => { |
| 28 | + await dataSource.destroy(); |
| 29 | + await app.close(); |
| 30 | + }); |
| 31 | + |
| 32 | + it('should create a prompt without categories', async () => { |
| 33 | + const newPrompt: CreatePromptDto = { |
| 34 | + title: 'Test Prompt', |
| 35 | + description: 'A test prompt for e2e testing', |
| 36 | + content: 'This is the prompt content for testing purposes.', |
| 37 | + visibility: VisibilityType.PUBLIC, |
| 38 | + }; |
| 39 | + |
| 40 | + const response = await request(app.getHttpServer()).post('/prompt').send(newPrompt).expect(HttpStatus.CREATED); |
| 41 | + |
| 42 | + const typedBody = response.body as PromptDto; |
| 43 | + expect(typedBody.id).toBeDefined(); |
| 44 | + expect(typedBody.title).toBe(newPrompt.title); |
| 45 | + expect(typedBody.description).toBe(newPrompt.description); |
| 46 | + expect(typedBody.content).toBe(newPrompt.content); |
| 47 | + expect(typedBody.visibility).toBe(newPrompt.visibility); |
| 48 | + expect(typedBody.categories).toEqual([]); |
| 49 | + }); |
| 50 | + |
| 51 | + it('should create a prompt with categories', async () => { |
| 52 | + const newPrompt: CreatePromptDto = { |
| 53 | + title: 'Categorized Prompt', |
| 54 | + content: 'This prompt has categories.', |
| 55 | + visibility: VisibilityType.PRIVATE, |
| 56 | + categories: ['technical', 'creative'], |
| 57 | + }; |
| 58 | + |
| 59 | + const response = await request(app.getHttpServer()).post('/prompt').send(newPrompt).expect(HttpStatus.CREATED); |
| 60 | + |
| 61 | + const typedBody = response.body as PromptDto; |
| 62 | + expect(typedBody.id).toBeDefined(); |
| 63 | + expect(typedBody.title).toBe(newPrompt.title); |
| 64 | + expect(typedBody.content).toBe(newPrompt.content); |
| 65 | + expect(typedBody.visibility).toBe(newPrompt.visibility); |
| 66 | + expect(typedBody.categories).toHaveLength(2); |
| 67 | + expect(typedBody.categories).toEqual( |
| 68 | + expect.arrayContaining([expect.objectContaining({ label: 'technical' }), expect.objectContaining({ label: 'creative' })]), |
| 69 | + ); |
| 70 | + }); |
| 71 | + |
| 72 | + it('should create a prompt with only required fields', async () => { |
| 73 | + const newPrompt: CreatePromptDto = { |
| 74 | + title: 'Minimal Prompt', |
| 75 | + content: 'This is a minimal prompt with only required fields.', |
| 76 | + visibility: VisibilityType.PRIVATE, |
| 77 | + }; |
| 78 | + |
| 79 | + const response = await request(app.getHttpServer()).post('/prompt').send(newPrompt).expect(HttpStatus.CREATED); |
| 80 | + |
| 81 | + const typedBody = response.body as PromptDto; |
| 82 | + expect(typedBody.id).toBeDefined(); |
| 83 | + expect(typedBody.title).toBe(newPrompt.title); |
| 84 | + expect(typedBody.content).toBe(newPrompt.content); |
| 85 | + expect(typedBody.visibility).toBe(newPrompt.visibility); |
| 86 | + expect(typedBody.description).toBeUndefined(); |
| 87 | + expect(typedBody.rating).toBeUndefined(); |
| 88 | + expect(typedBody.categories).toEqual([]); |
| 89 | + }); |
| 90 | + |
| 91 | + it('should create a prompt with non-existent categories', async () => { |
| 92 | + const newPrompt: CreatePromptDto = { |
| 93 | + title: 'Prompt with Non-existent Categories', |
| 94 | + content: 'This prompt references categories that do not exist.', |
| 95 | + visibility: VisibilityType.PUBLIC, |
| 96 | + categories: ['nonexistent1', 'technical', 'nonexistent2'], |
| 97 | + }; |
| 98 | + |
| 99 | + const response = await request(app.getHttpServer()).post('/prompt').send(newPrompt).expect(HttpStatus.CREATED); |
| 100 | + |
| 101 | + const typedBody = response.body as PromptDto; |
| 102 | + expect(typedBody.categories).toHaveLength(1); // Only 'technical' exists |
| 103 | + expect(typedBody.categories).toEqual([expect.objectContaining({ label: 'technical' })]); |
| 104 | + }); |
| 105 | + |
| 106 | + it('should fail to create a prompt without required fields', async () => { |
| 107 | + const invalidPrompt = { |
| 108 | + description: 'Missing title and content', |
| 109 | + visibility: VisibilityType.PUBLIC, |
| 110 | + }; |
| 111 | + |
| 112 | + await request(app.getHttpServer()).post('/prompt').send(invalidPrompt).expect(HttpStatus.BAD_REQUEST); |
| 113 | + }); |
| 114 | + |
| 115 | + it('should fail to create a prompt with invalid visibility', async () => { |
| 116 | + const invalidPrompt = { |
| 117 | + title: 'Invalid Prompt', |
| 118 | + content: 'This prompt has invalid visibility.', |
| 119 | + visibility: 'invalid_visibility', |
| 120 | + }; |
| 121 | + |
| 122 | + await request(app.getHttpServer()).post('/prompt').send(invalidPrompt).expect(HttpStatus.BAD_REQUEST); |
| 123 | + }); |
| 124 | +}); |
| 125 | + |
| 126 | +async function seedTestData(dataSource: DataSource) { |
| 127 | + const promptCategoryRepository = dataSource.getRepository(PromptCategoryEntity); |
| 128 | + |
| 129 | + // Create test categories |
| 130 | + await createPromptCategory('technical', 'Technical prompts', promptCategoryRepository); |
| 131 | + await createPromptCategory('creative', 'Creative writing prompts', promptCategoryRepository); |
| 132 | + await createPromptCategory('business', 'Business and professional prompts', promptCategoryRepository); |
| 133 | +} |
| 134 | + |
| 135 | +async function createPromptCategory( |
| 136 | + label: string, |
| 137 | + description: string, |
| 138 | + promptCategoryRepository: Repository<PromptCategoryEntity>, |
| 139 | +): Promise<PromptCategoryEntity> { |
| 140 | + const categoryEntity = new PromptCategoryEntity(); |
| 141 | + categoryEntity.label = label; |
| 142 | + categoryEntity.description = description; |
| 143 | + categoryEntity.creationDate = new Date(); |
| 144 | + categoryEntity.visibility = VisibilityType.PUBLIC; |
| 145 | + return promptCategoryRepository.save(categoryEntity); |
| 146 | +} |
0 commit comments