Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(tdd-test) Initial commit #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions backend/src/test/tests-smg.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { addCandidate } from '../application/services/candidateService';
import { Candidate } from '../domain/models/Candidate';
import { validateCandidateData } from '../application/validator';
import { Education } from '../domain/models/Education';
import { WorkExperience } from '../domain/models/WorkExperience';
import { Resume } from '../domain/models/Resume';

jest.mock('../domain/models/Candidate');
jest.mock('../application/validator');
jest.mock('../domain/models/Education');
jest.mock('../domain/models/WorkExperience');
jest.mock('../domain/models/Resume');

describe('addCandidate', () => {
const candidateData = {
name: 'John Doe',
email: '[email protected]',
educations: [{ degree: 'B.Sc', institution: 'University' }],
workExperiences: [{ company: 'Company', role: 'Developer' }],
cv: { fileName: 'resume.pdf', fileContent: '...' }
};

beforeEach(() => {
jest.clearAllMocks();
});

it('should throw an error if validation fails', async () => {
(validateCandidateData as jest.Mock).mockImplementation(() => {
throw new Error('Validation Error');
});

await expect(addCandidate(candidateData)).rejects.toThrow('Validation Error');
});

it('should save candidate and related data successfully', async () => {
// Mock validateCandidateData to resolve successfully


const result = await addCandidate(candidateData);

expect(Candidate.prototype.save).toHaveBeenCalled();
expect(Education.prototype.save).toHaveBeenCalled();
expect(WorkExperience.prototype.save).toHaveBeenCalled();
expect(Resume.prototype.save).toHaveBeenCalled();
});

it('should throw an error if unique constraint fails', async () => {
(Candidate.prototype.save as jest.Mock).mockImplementation(() => {
const error = new Error('Unique constraint failed');
(error as any).code = 'P2002';
throw error;
});

await expect(addCandidate(candidateData)).rejects.toThrow('The email already exists in the database');
});

it('should throw a general error', async () => {
(Candidate.prototype.save as jest.Mock).mockImplementation(() => {
throw new Error('General Error');
});

await expect(addCandidate(candidateData)).rejects.toThrow('General Error');
});

it('should handle empty education and work experience arrays', async () => {
const candidateDataWithoutEducationAndExperience = {
...candidateData,
educations: [],
workExperiences: []
};

(validateCandidateData as jest.Mock).mockImplementation(() => true);

const savedCandidate = { id: '123', ...candidateDataWithoutEducationAndExperience, education: [], workExperience: [], resumes: [] };
(Candidate.prototype.save as jest.Mock).mockResolvedValue(savedCandidate);

const savedResume = { id: '101', ...candidateData.cv };
(Resume.prototype.save as jest.Mock).mockResolvedValue(savedResume);

const result = await addCandidate(candidateDataWithoutEducationAndExperience);

expect(result).toEqual(savedCandidate);
expect(Candidate.prototype.save).toHaveBeenCalled();
expect(Education.prototype.save).not.toHaveBeenCalled();
expect(WorkExperience.prototype.save).not.toHaveBeenCalled();
expect(Resume.prototype.save).toHaveBeenCalled();
});

it('should handle missing CV', async () => {
const candidateDataWithoutCV = {
...candidateData,
cv: null
};

(validateCandidateData as jest.Mock).mockImplementation(() => true);

const savedCandidate = { id: '123', ...candidateDataWithoutCV, education: [], workExperience: [], resumes: [] };
(Candidate.prototype.save as jest.Mock).mockResolvedValue(savedCandidate);

const savedEducation = { id: '456', ...candidateData.educations[0] };
(Education.prototype.save as jest.Mock).mockResolvedValue(savedEducation);

const savedExperience = { id: '789', ...candidateData.workExperiences[0] };
(WorkExperience.prototype.save as jest.Mock).mockResolvedValue(savedExperience);

const result = await addCandidate(candidateDataWithoutCV);

expect(result).toEqual(savedCandidate);
expect(Candidate.prototype.save).toHaveBeenCalled();
expect(Education.prototype.save).toHaveBeenCalled();
expect(WorkExperience.prototype.save).toHaveBeenCalled();
expect(Resume.prototype.save).not.toHaveBeenCalled();
});
});
96 changes: 96 additions & 0 deletions prompts/smg-promtps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Prompt 1
@workspace /tests
Hi copilot! Today I need you as my expert assistant in TypeScript and Jest! I need to create all the unit tests possible for my application. Please explain each test and how to launch them. Note that this is a TypeScript file, so follow best practices for this technology.

# Prompt 2
Most of the test cases are working, but only one is failing. Could you fix it?

# Prompt 3
The test continues failing due to the error:
**TypeError**: Cannot read properties of undefined (reading 'push')

# Prompt 4
Lets review the first test failing.
addCandidate › should handle missing CV
Has the following output
```
TypeError: Cannot read properties of undefined (reading 'push')

42 | resumeModel.candidateId = candidateId;
43 | await resumeModel.save();
> 44 | candidate.resumes.push(resumeModel);
| ^
45 | }
46 | return savedCandidate;
47 | } catch (error: any) {

at src/application/services/candidateService.ts:44:31
at step (src/application/services/candidateService.ts:33:23)
at Object.next (src/application/services/candidateService.ts:14:53)
at fulfilled (src/application/services/candidateService.ts:5:58)
```
# Response
Copilot suggest me change code to initialize arrays to empty but it **is not a right solution**.
Adding here the response because **/backend/src/application/services/candidateService.ts** was modified.
```
import { Candidate } from '../../domain/models/Candidate';
import { validateCandidateData } from '../validator';
import { Education } from '../../domain/models/Education';
import { WorkExperience } from '../../domain/models/WorkExperience';
import { Resume } from '../../domain/models/Resume';

export const addCandidate = async (candidateData: any) => {
try {
validateCandidateData(candidateData); // Validar los datos del candidato
} catch (error: any) {
throw new Error(error);
}

const candidate = new Candidate(candidateData); // Crear una instancia del modelo Candidate
candidate.education = [];
candidate.workExperience = [];
candidate.resumes = [];

try {
const savedCandidate = await candidate.save(); // Guardar el candidato en la base de datos
const candidateId = savedCandidate.id; // Obtener el ID del candidato guardado

// Guardar la educación del candidato
if (candidateData.educations) {
for (const education of candidateData.educations) {
const educationModel = new Education(education);
educationModel.candidateId = candidateId;
await educationModel.save();
candidate.education.push(educationModel);
}
}

// Guardar la experiencia laboral del candidato
if (candidateData.workExperiences) {
for (const experience of candidateData.workExperiences) {
const experienceModel = new WorkExperience(experience);
experienceModel.candidateId = candidateId;
await experienceModel.save();
candidate.workExperience.push(experienceModel);
}
}

// Guardar los archivos de CV
if (candidateData.cv && Object.keys(candidateData.cv).length > 0) {
const resumeModel = new Resume(candidateData.cv);
resumeModel.candidateId = candidateId;
await resumeModel.save();
candidate.resumes.push(resumeModel);
}
return savedCandidate;
} catch (error: any) {
if (error.code === 'P2002') {
// Unique constraint failed on the fields: (`email`)
throw new Error('The email already exists in the database');
} else {
throw error;
}
}
};
```