Typescript + Test + 驴GraphQL?
Adri谩n Ferrera Gonz谩lez
@afergon
adrian-afergon
Como testear una aplicaci贸n de manera simple
Si es un nuevo elemento
Si ya los elementos est谩n preparados
Si no conozco nada
import puppeteer from 'puppeteer';
describe('Display video', () => {
let browser: puppeteer.Browser;
let page: puppeteer.Page;
beforeEach(async () => {
browser = await puppeteer.launch({
headless: false,
});
page = await browser.newPage();
await page.emulate({
viewport: {
width: 500,
height: 2400,
},
userAgent: '',
});
await page.goto('http://localhost:3000/best-builds');
});
afterEach(async () => {
await browser.close();
});
it('should select a video and view details ', async () => {
await page.waitForSelector('[data-testid="video-item-1"]');
const button = await page.$('[data-testid="video-item-1"]');
if (button) {
await button.evaluate((element: Element) => element.click());
}
const html = await page.$eval('[data-testid="video-details-title-1"]', (e: any) => e.innerHTML);
expect(html).toBe('La amiga imaginaria y otros relatos de terror');
});
});
// Test
describe('Videos', () => {
it('should return the specified number of videos', async () => {
const expectedQuantity = 4;
const videosRepository: VideosRepository = new VideosRepository();
const foundVideos: Video[] = await videosRepository.getVideos(expectedQuantity);
expect(foundVideos.length).toBe(expectedQuantity);
});
});
// Component
export VideosRepository {
// ...
public getVideos(quantity: number): Promise<Video[]> {
return Promise.resolve(videos.slice(0, quantity));
}
}
Acceso a datos
C谩lculos y operaciones
Representaci贸n
Repository
Service
View
mapper
mapper
Repository
Service
View
1. Vamos a consumir los datos del servicio
Por lo que omitiremos la capa de presentaci贸n
Repository
Service
1. Vamos a consumir los datos del servicio
describe('Videos service', () => {
it('should retrive the requested videos', async () => {
const allVideos = [ /* ? */ ];
const videoService = new VideoService();
const foundVideos = await videoService.find();
expect(foundVideos).toBe(allVideos);
});
});
2. Identificamos las dependencias y las inyectamos
describe('Videos service', () => {
it('should retrive the requested videos', async () => {
const allVideos = [ terrorVideo, actionVideo ];
const videoRepository = new VideoRepository();
const videoService = new VideoService(videoRepository);
const foundVideos = await videoService.find();
expect(foundVideos).toBe(allVideos);
});
});
Repository
Service
3. Reemplazamos la llamada real por una propia
describe('Videos service', () => {
it('should retrive the requested videos', async () => {
const allVideos = [ terrorVideo, actionVideo ];
const videoRepository = new VideoRepository();
videoRepository.getVideos = jest.fn( () => Promise.resolve(allVideos) );
const videoService = new VideoService(videoRepository);
const foundVideos = await videoService.find();
expect(foundVideos).toBe(allVideos);
});
});
Repository
Service
export class VideoService {
constructor() {
this.videoRepository = new VideoRepository();
}
public async find(): Video[] {
return videoRepository.getVideos();
}
}
驴Entonces tengo que cambiar todas las llamadas?
Repository
Service
export class VideoService {
constructor(
private videoRepository = new VideoRepository()
) {}
public async find(): Video[] {
return videoRepository.getVideos();
}
}
No, solo le daremos un valor por defecto
Repository
Service