feat: enhance tests with router, HTTP client, and animations support
This commit is contained in:
Generated
+23
@@ -8,6 +8,7 @@
|
||||
"name": "mobile-store",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@angular/animations": "v20-lts",
|
||||
"@angular/common": "v20-lts",
|
||||
"@angular/compiler": "v20-lts",
|
||||
"@angular/core": "v20-lts",
|
||||
@@ -681,6 +682,20 @@
|
||||
"typescript": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/animations": {
|
||||
"version": "20.3.26",
|
||||
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.3.26.tgz",
|
||||
"integrity": "sha512-hfNrX19v8xs/usNkELSqc6q5IwBfS2GGW8sQ4OMpxAmLZDJwaLUxkj48t8VYhUFezsIfzR+sDEi6ZQBOaMIYug==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": "20.3.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build": {
|
||||
"version": "20.3.32",
|
||||
"resolved": "https://registry.npmjs.org/@angular/build/-/build-20.3.32.tgz",
|
||||
@@ -10824,6 +10839,14 @@
|
||||
"@angular-eslint/bundled-angular-compiler": "21.0.1"
|
||||
}
|
||||
},
|
||||
"@angular/animations": {
|
||||
"version": "20.3.26",
|
||||
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.3.26.tgz",
|
||||
"integrity": "sha512-hfNrX19v8xs/usNkELSqc6q5IwBfS2GGW8sQ4OMpxAmLZDJwaLUxkj48t8VYhUFezsIfzR+sDEi6ZQBOaMIYug==",
|
||||
"requires": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"@angular/build": {
|
||||
"version": "20.3.32",
|
||||
"resolved": "https://registry.npmjs.org/@angular/build/-/build-20.3.32.tgz",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "v20-lts",
|
||||
"@angular/common": "v20-lts",
|
||||
"@angular/compiler": "v20-lts",
|
||||
"@angular/core": "v20-lts",
|
||||
|
||||
+13
-2
@@ -1,10 +1,21 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { App } from './app';
|
||||
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [App],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
provideNoopAnimations(),
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
@@ -14,10 +25,10 @@ describe('App', () => {
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
it('should render the header', () => {
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, mobile-store');
|
||||
expect(compiled.querySelector('app-header')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,70 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { ProductActions } from './product-actions';
|
||||
import { ProductOptions } from '../../../core/models/product.model';
|
||||
import {environment} from '../../../../environments/environment';
|
||||
|
||||
describe('ProductActions', () => {
|
||||
let component: ProductActions;
|
||||
let fixture: ComponentFixture<ProductActions>;
|
||||
let httpMock: HttpTestingController;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductActions]
|
||||
})
|
||||
.compileComponents();
|
||||
const options: ProductOptions = {
|
||||
colors: [
|
||||
{ code: 1, name: 'Negro' },
|
||||
{ code: 2, name: 'Blanco' }
|
||||
],
|
||||
storages: [
|
||||
{ code: 10, name: '16GB' },
|
||||
{ code: 20, name: '32GB' }
|
||||
]
|
||||
};
|
||||
|
||||
fixture = TestBed.createComponent(ProductActions);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProductActions],
|
||||
providers: [provideHttpClient(), provideHttpClientTesting(), provideNoopAnimations()]
|
||||
});
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it('preselect the first color and storage option', () => {
|
||||
const fixture = TestBed.createComponent(ProductActions);
|
||||
fixture.componentRef.setInput('productId', '1');
|
||||
fixture.componentRef.setInput('options', options);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.selectedColorCode()).toBe(1);
|
||||
expect(fixture.componentInstance.selectedStorageCode()).toBe(10);
|
||||
});
|
||||
|
||||
it('add the product to the cart with the current selection and emit added', async () => {
|
||||
const fixture = TestBed.createComponent(ProductActions);
|
||||
fixture.componentRef.setInput('productId', '1');
|
||||
fixture.componentRef.setInput('options', options);
|
||||
fixture.detectChanges();
|
||||
|
||||
let addedEmitted = false;
|
||||
fixture.componentInstance.added.subscribe(() => (addedEmitted = true));
|
||||
|
||||
fixture.componentInstance.selectedColorCode.set(2);
|
||||
fixture.componentInstance.selectedStorageCode.set(20);
|
||||
|
||||
const promise = fixture.componentInstance.onAddToCart();
|
||||
|
||||
const req = httpMock.expectOne(`${environment.apiBaseUrl}/cart`);
|
||||
expect(req.request.body).toEqual({ id: '1', colorCode: 2, storageCode: 20 });
|
||||
req.flush({ count: 1 });
|
||||
|
||||
await promise;
|
||||
|
||||
expect(addedEmitted).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,64 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProductDescription } from './product-description';
|
||||
import { ProductDetail } from '../../../core/models/product.model';
|
||||
|
||||
describe('ProductDescription', () => {
|
||||
let component: ProductDescription;
|
||||
let fixture: ComponentFixture<ProductDescription>;
|
||||
const product: ProductDetail = {
|
||||
id: '1',
|
||||
brand: 'Acer',
|
||||
model: 'Iconia Talk S',
|
||||
price: '170',
|
||||
imgUrl: 'a.jpg',
|
||||
cpu: 'Quad-core',
|
||||
ram: '2 GB RAM',
|
||||
displayResolution: '7.0 inches',
|
||||
displaySize: '720 x 1280 pixels',
|
||||
primaryCamera: ['13 MP'],
|
||||
secondaryCmera: ['2 MP'],
|
||||
dimentions: '191.7 x 101 x 9.4 mm',
|
||||
weight: '260',
|
||||
options: { colors: [], storages: [] }
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductDescription]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProductDescription);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({ imports: [ProductDescription] });
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('Show rows with the fields present, omitting the missing ones.', () => {
|
||||
const fixture = TestBed.createComponent(ProductDescription);
|
||||
fixture.componentRef.setInput('product', product);
|
||||
fixture.detectChanges();
|
||||
|
||||
const text: string = fixture.nativeElement.textContent;
|
||||
expect(text).toContain('Brand');
|
||||
expect(text).toContain('Acer');
|
||||
expect(text).toContain('CPU');
|
||||
// Campo ausente (os) no debe generar una fila.
|
||||
expect(text).not.toContain('OS');
|
||||
});
|
||||
|
||||
it('label displayResolution/displaySize according to their actual content (API names swapped)', () => {
|
||||
const fixture = TestBed.createComponent(ProductDescription);
|
||||
fixture.componentRef.setInput('product', product);
|
||||
fixture.detectChanges();
|
||||
|
||||
const rows = fixture.componentInstance.rows();
|
||||
const tamano = rows.find((r) => r.label === 'Screen size');
|
||||
const resolucion = rows.find((r) => r.label === 'Resolution');
|
||||
|
||||
expect(tamano?.value).toBe('7.0 inches');
|
||||
expect(resolucion?.value).toBe('720 x 1280 pixels');
|
||||
});
|
||||
|
||||
it('Combine primaryCamera and secondaryCamera into a single camera row.', () => {
|
||||
const fixture = TestBed.createComponent(ProductDescription);
|
||||
fixture.componentRef.setInput('product', product);
|
||||
fixture.detectChanges();
|
||||
|
||||
const rows = fixture.componentInstance.rows();
|
||||
const camaras = rows.find((r) => r.label === 'Cameras');
|
||||
|
||||
expect(camaras?.value).toBe('13 MP, 2 MP');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,70 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { ProductDetail } from './product-detail';
|
||||
import { ProductDetail as ProductDetailModel } from '../../core/models/product.model';
|
||||
import {environment} from '../../../environments/environment';
|
||||
|
||||
describe('ProductDetail', () => {
|
||||
let component: ProductDetail;
|
||||
let fixture: ComponentFixture<ProductDetail>;
|
||||
let httpMock: HttpTestingController;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductDetail]
|
||||
})
|
||||
.compileComponents();
|
||||
const detail: ProductDetailModel = {
|
||||
id: '1',
|
||||
brand: 'Acer',
|
||||
model: 'Iconia Talk S',
|
||||
price: '170',
|
||||
imgUrl: 'a.jpg',
|
||||
options: { colors: [{ code: 1, name: 'Negro' }], storages: [{ code: 1, name: '16GB' }] }
|
||||
};
|
||||
|
||||
fixture = TestBed.createComponent(ProductDetail);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProductDetail],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
provideNoopAnimations()
|
||||
]
|
||||
});
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it('loads and show the product detail using the id', async () => {
|
||||
const fixture = TestBed.createComponent(ProductDetail);
|
||||
fixture.componentRef.setInput('id', '1');
|
||||
fixture.detectChanges();
|
||||
|
||||
httpMock.expectOne(`${environment.apiBaseUrl}/product/1`).flush(detail);
|
||||
await fixture.whenStable();
|
||||
fixture.detectChanges();
|
||||
|
||||
const text: string = fixture.nativeElement.textContent;
|
||||
expect(text).toContain('Acer');
|
||||
expect(text).toContain('Iconia Talk S');
|
||||
expect(fixture.nativeElement.querySelector('app-product-actions')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('it shows an error message if API call fails', async () => {
|
||||
const fixture = TestBed.createComponent(ProductDetail);
|
||||
fixture.componentRef.setInput('id', '1');
|
||||
fixture.detectChanges();
|
||||
|
||||
httpMock
|
||||
.expectOne(`${environment.apiBaseUrl}/product/1`)
|
||||
.flush('error', { status: 404, statusText: 'Not Found' });
|
||||
await fixture.whenStable();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.error()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProductImage } from './product-image';
|
||||
|
||||
describe('ProductImage', () => {
|
||||
let component: ProductImage;
|
||||
let fixture: ComponentFixture<ProductImage>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductImage]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProductImage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({ imports: [ProductImage] });
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('it renders the image with proper src and alt', () => {
|
||||
const fixture = TestBed.createComponent(ProductImage);
|
||||
fixture.componentRef.setInput('imgUrl', 'https://example.com/a.jpg');
|
||||
fixture.componentRef.setInput('alt', 'Acer Iconia');
|
||||
fixture.detectChanges();
|
||||
|
||||
const img: HTMLImageElement = fixture.nativeElement.querySelector('img');
|
||||
expect(img.src).toBe('https://example.com/a.jpg');
|
||||
expect(img.alt).toBe('Acer Iconia');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,46 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { ProductItem } from './product-item';
|
||||
import { Product } from '../../../core/models/product.model';
|
||||
|
||||
describe('ProductItem', () => {
|
||||
let component: ProductItem;
|
||||
let fixture: ComponentFixture<ProductItem>;
|
||||
const product: Product = {
|
||||
id: '1',
|
||||
brand: 'Acer',
|
||||
model: 'Iconia Talk S',
|
||||
price: '170',
|
||||
imgUrl: 'https://example.com/a.jpg'
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductItem]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProductItem);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProductItem],
|
||||
providers: [provideNoopAnimations()]
|
||||
});
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('it shows brand, model and product price', () => {
|
||||
const fixture = TestBed.createComponent(ProductItem);
|
||||
fixture.componentRef.setInput('product', product);
|
||||
fixture.detectChanges();
|
||||
|
||||
const text: string = fixture.nativeElement.textContent;
|
||||
expect(text).toContain('Acer');
|
||||
expect(text).toContain('Iconia Talk S');
|
||||
expect(text).toContain('170');
|
||||
});
|
||||
|
||||
it('it emits productSelected with the product when clicking on it', () => {
|
||||
const fixture = TestBed.createComponent(ProductItem);
|
||||
fixture.componentRef.setInput('product', product);
|
||||
fixture.detectChanges();
|
||||
|
||||
let selected: Product | undefined;
|
||||
fixture.componentInstance.productSelected.subscribe((p) => (selected = p));
|
||||
|
||||
fixture.nativeElement.querySelector('mat-card').click();
|
||||
|
||||
expect(selected).toEqual(product);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,159 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideRouter, Router } from '@angular/router';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { ProductList } from './product-list';
|
||||
import { Product } from '../../core/models/product.model';
|
||||
import {environment} from '../../../environments/environment';
|
||||
|
||||
describe('ProductList', () => {
|
||||
let component: ProductList;
|
||||
let fixture: ComponentFixture<ProductList>;
|
||||
let httpMock: HttpTestingController;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductList]
|
||||
})
|
||||
.compileComponents();
|
||||
const products: Product[] = [
|
||||
{ id: '1', brand: 'Acer', model: 'Iconia Talk S', price: '170', imgUrl: 'a.jpg' },
|
||||
{ id: '2', brand: 'Samsung', model: 'Galaxy S9', price: '300', imgUrl: 'b.jpg' }
|
||||
];
|
||||
|
||||
fixture = TestBed.createComponent(ProductList);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
/** Genera `count` productos únicos, útil para probar la paginación del scroll infinito. */
|
||||
function buildProducts(count: number): Product[] {
|
||||
return Array.from({ length: count }, (_, i) => ({
|
||||
id: `${i + 1}`,
|
||||
brand: i % 2 === 0 ? 'Acer' : 'Samsung',
|
||||
model: `Model ${i + 1}`,
|
||||
price: '100',
|
||||
imgUrl: `img${i + 1}.jpg`
|
||||
}));
|
||||
}
|
||||
|
||||
/** Fabrica un Event mínimo con las propiedades de scroll que lee onScroll(). */
|
||||
function makeScrollEvent(scrollTop: number, clientHeight: number, scrollHeight: number): Event {
|
||||
return { target: { scrollTop, clientHeight, scrollHeight } } as unknown as Event;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProductList],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
provideNoopAnimations()
|
||||
]
|
||||
});
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
async function createAndLoad(mockProducts: Product[] = products) {
|
||||
const fixture = TestBed.createComponent(ProductList);
|
||||
Object.assign(fixture.nativeElement.style, {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '400px'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
httpMock.expectOne(`${environment.apiBaseUrl}/product`).flush(mockProducts);
|
||||
await fixture.whenStable();
|
||||
fixture.detectChanges();
|
||||
return fixture;
|
||||
}
|
||||
|
||||
it('loads and shows all producst when load', async () => {
|
||||
const fixture = await createAndLoad();
|
||||
|
||||
expect(fixture.componentInstance.filteredProducts().length).toBe(2);
|
||||
expect(fixture.nativeElement.querySelectorAll('app-product-item').length).toBe(2);
|
||||
});
|
||||
|
||||
it('filtering in live time', async () => {
|
||||
const fixture = await createAndLoad();
|
||||
|
||||
fixture.componentInstance.onSearchTermChange('Samsung');
|
||||
fixture.detectChanges();
|
||||
|
||||
const filtered = fixture.componentInstance.filteredProducts();
|
||||
expect(filtered.length).toBe(1);
|
||||
expect(filtered[0].brand).toBe('Samsung');
|
||||
});
|
||||
|
||||
it('goes to detail view', async () => {
|
||||
const fixture = await createAndLoad();
|
||||
const router = TestBed.inject(Router);
|
||||
const navigateSpy = spyOn(router, 'navigate');
|
||||
|
||||
fixture.componentInstance.onSelectProduct(products[0]);
|
||||
|
||||
expect(navigateSpy).toHaveBeenCalledWith(['/product', '1']);
|
||||
});
|
||||
|
||||
it('Error message when api fails', async () => {
|
||||
const fixture = TestBed.createComponent(ProductList);
|
||||
fixture.detectChanges();
|
||||
httpMock
|
||||
.expectOne(`${environment.apiBaseUrl}/product`)
|
||||
.flush('error', { status: 500, statusText: 'Server Error' });
|
||||
await fixture.whenStable();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.error()).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('infinite scroll', () => {
|
||||
it('Only 20 products when too much products', async () => {
|
||||
const fixture = await createAndLoad(buildProducts(45));
|
||||
|
||||
expect(fixture.componentInstance.visibleProducts().length).toBe(20);
|
||||
expect(fixture.componentInstance.hasMore()).toBeTrue();
|
||||
expect(fixture.nativeElement.querySelectorAll('app-product-item').length).toBe(20);
|
||||
});
|
||||
|
||||
it('loads when close to last element edge', async () => {
|
||||
const fixture = await createAndLoad(buildProducts(45));
|
||||
|
||||
// scrollTop + clientHeight a menos de 200px del final -> carga más.
|
||||
fixture.componentInstance.onScroll(makeScrollEvent(1000, 500, 1650));
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.visibleProducts().length).toBe(40);
|
||||
});
|
||||
|
||||
it('It does not load more items if it is not close to the limit boundary', async () => {
|
||||
const fixture = await createAndLoad(buildProducts(45));
|
||||
|
||||
fixture.componentInstance.onScroll(makeScrollEvent(0, 500, 3000));
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.visibleProducts().length).toBe(20);
|
||||
});
|
||||
|
||||
it('It does not exceed the total number of filtered products when revealing more batches.', async () => {
|
||||
const fixture = await createAndLoad(buildProducts(25));
|
||||
|
||||
fixture.componentInstance.onScroll(makeScrollEvent(1000, 500, 1650));
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.visibleProducts().length).toBe(25);
|
||||
expect(fixture.componentInstance.hasMore()).toBeFalse();
|
||||
});
|
||||
|
||||
it('Reset pagination to 20 when the search term changes.', async () => {
|
||||
const fixture = await createAndLoad(buildProducts(45));
|
||||
|
||||
fixture.componentInstance.onScroll(makeScrollEvent(1000, 500, 1650));
|
||||
fixture.detectChanges();
|
||||
expect(fixture.componentInstance.visibleProducts().length).toBe(40);
|
||||
|
||||
fixture.componentInstance.onSearchTermChange('acer');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.visibleProducts().length).toBe(20);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { ProductSearch } from './product-search';
|
||||
|
||||
describe('ProductSearch', () => {
|
||||
let component: ProductSearch;
|
||||
let fixture: ComponentFixture<ProductSearch>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProductSearch]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProductSearch);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ProductSearch],
|
||||
providers: [provideNoopAnimations()]
|
||||
});
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
it('emits searchChange with the inserted text', () => {
|
||||
const fixture = TestBed.createComponent(ProductSearch);
|
||||
fixture.detectChanges();
|
||||
|
||||
const emitted: string[] = [];
|
||||
fixture.componentInstance.searchChange.subscribe((value) => emitted.push(value));
|
||||
|
||||
const input: HTMLInputElement = fixture.nativeElement.querySelector('input');
|
||||
input.value = 'Samsung';
|
||||
input.dispatchEvent(new Event('input'));
|
||||
|
||||
expect(emitted).toEqual(['Samsung']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,23 +1,58 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { provideNoopAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import { Header } from './header';
|
||||
import { CartService } from '../../core/services/cart.service';
|
||||
import {environment} from '../../../environments/environment';
|
||||
|
||||
describe('Header', () => {
|
||||
let component: Header;
|
||||
let fixture: ComponentFixture<Header>;
|
||||
let httpMock: HttpTestingController;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Header]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Header);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [Header],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
provideNoopAnimations()
|
||||
]
|
||||
});
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it('successfully created', () => {
|
||||
const fixture = TestBed.createComponent(Header);
|
||||
expect(fixture.componentInstance).toBeTruthy();
|
||||
});
|
||||
|
||||
it('it shows home and cart icon', () => {
|
||||
const fixture = TestBed.createComponent(Header);
|
||||
fixture.detectChanges();
|
||||
const compiled: HTMLElement = fixture.nativeElement;
|
||||
|
||||
expect(compiled.querySelector('.app-header__brand')).toBeTruthy();
|
||||
expect(compiled.querySelector('button[aria-label="Cart"]')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('it shows the counter in the cart', async () => {
|
||||
const fixture = TestBed.createComponent(Header);
|
||||
const cartService = TestBed.inject(CartService);
|
||||
|
||||
const promise = cartService.addToCart({ id: '1', colorCode: 1, storageCode: 1 });
|
||||
httpMock.expectOne(`${environment.apiBaseUrl}/cart`).flush({ count: 7 });
|
||||
await promise;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.componentInstance.cartCount()).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user