From f89a27320f8a12d144d52e928475dd1464d7e433 Mon Sep 17 00:00:00 2001 From: Gabriel De Los Rios Date: Sun, 22 Feb 2026 23:33:08 -0300 Subject: [PATCH] feat(products): add resolvers --- src/app/resolvers/product-resolver.spec.ts | 58 +++++++++++++++++++++ src/app/resolvers/product-resolver.ts | 25 +++++++++ src/app/resolvers/products-resolver.spec.ts | 48 +++++++++++++++++ src/app/resolvers/products-resolver.ts | 17 ++++++ 4 files changed, 148 insertions(+) create mode 100644 src/app/resolvers/product-resolver.spec.ts create mode 100644 src/app/resolvers/product-resolver.ts create mode 100644 src/app/resolvers/products-resolver.spec.ts create mode 100644 src/app/resolvers/products-resolver.ts diff --git a/src/app/resolvers/product-resolver.spec.ts b/src/app/resolvers/product-resolver.spec.ts new file mode 100644 index 0000000..d00976c --- /dev/null +++ b/src/app/resolvers/product-resolver.spec.ts @@ -0,0 +1,58 @@ +import { TestBed } from '@angular/core/testing'; +import { provideRouter, RedirectCommand, ResolveFn, Router } from '@angular/router'; + +import { productResolver } from './product-resolver'; +import { Product } from '../models/Product'; +import { ProductDAO } from '../dao/ProductDAO'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-mock', + template: ``, + styles: ``, +}) +class MockComponent {} + +describe('productResolver', () => { + const executeResolver: ResolveFn = (...resolverParameters) => + TestBed.runInInjectionContext(() => productResolver(...resolverParameters)); + + let productDAO: Partial; + let router: Router; + + let PRODUCT_MOCK: Product; + beforeEach(() => { + productDAO = { + findBy: vi.fn().mockResolvedValue([]), + }; + + PRODUCT_MOCK = new Product('mock','mock','',1); + + TestBed.configureTestingModule({ + providers: [ + provideRouter([ + { path: 'mock/:id', component: MockComponent, resolve: { product: productResolver } }, + { path: 'settings/products', component: MockComponent }, + ]), + { provide: ProductDAO, useValue: productDAO }, + ], + }); + + router = TestBed.inject(Router); + }); + + it('should be created', () => { + expect(executeResolver).toBeTruthy(); + }); + + it('should navigate back to settings for not found ids', async () => { + await router.navigate(['mock', '99']); + expect(router.url).toEqual('/settings/products'); + }); + + it('should complete navigation for found ids', async () => { + productDAO.findBy = vi.fn().mockResolvedValue([PRODUCT_MOCK]); + await router.navigate(['mock', String(PRODUCT_MOCK.id)]); + expect(router.url).toEqual(`/mock/${PRODUCT_MOCK.id}`); + }); +}); diff --git a/src/app/resolvers/product-resolver.ts b/src/app/resolvers/product-resolver.ts new file mode 100644 index 0000000..43629af --- /dev/null +++ b/src/app/resolvers/product-resolver.ts @@ -0,0 +1,25 @@ +import { inject } from '@angular/core'; +import { RedirectCommand, ResolveFn, Router } from '@angular/router'; +import { ProductDAO } from '../dao/ProductDAO'; +import { Product } from '../models/Product'; + +export const productResolver: ResolveFn = async (route, _) => { + const productDAO = inject(ProductDAO); + const router = inject(Router); + const chainID = (<{ id: string }>route.params).id; + let product: Product; + + try { + const results = await productDAO.findBy({ id: Number(chainID) }); + if (!results[0]) { + throw new Error('The search for chain on edit did not find any match'); + } + product = results[0]; + } catch (e) { + console.error(e); + return new RedirectCommand(router.parseUrl('settings/products'), { + skipLocationChange: true, + }); + } + return product; +}; diff --git a/src/app/resolvers/products-resolver.spec.ts b/src/app/resolvers/products-resolver.spec.ts new file mode 100644 index 0000000..9d8630b --- /dev/null +++ b/src/app/resolvers/products-resolver.spec.ts @@ -0,0 +1,48 @@ +import { TestBed } from '@angular/core/testing'; +import { provideRouter, ResolveFn, Router } from '@angular/router'; + +import { productsResolver } from './products-resolver'; +import { Product } from '../models/Product'; +import { ProductDAO } from '../dao/ProductDAO'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-mock', + template: ``, + styles: ``, +}) +class MockComponent {} + +describe('productsResolver', () => { + const executeResolver: ResolveFn = (...resolverParameters) => + TestBed.runInInjectionContext(() => productsResolver(...resolverParameters)); + + let productDAO: Partial; + let router: Router; + + beforeEach(() => { + productDAO = { + findAll: vi.fn().mockResolvedValue([]), + }; + + TestBed.configureTestingModule({ + providers: [ + provideRouter([ + { path: 'products', component: MockComponent, resolve: { products: productsResolver } }, + ]), + { provide: ProductDAO, useValue: productDAO }, + ], + }); + + router = TestBed.inject(Router); + }); + + it('should be created', () => { + expect(executeResolver).toBeTruthy(); + }); + + it('should call productDAO findAll method', async () => { + await router.navigate(['products']); + expect(productDAO.findAll).toHaveBeenCalled(); + }); +}); diff --git a/src/app/resolvers/products-resolver.ts b/src/app/resolvers/products-resolver.ts new file mode 100644 index 0000000..57f4536 --- /dev/null +++ b/src/app/resolvers/products-resolver.ts @@ -0,0 +1,17 @@ +import { ResolveFn } from '@angular/router'; +import { ProductDAO } from '../dao/ProductDAO'; +import { inject } from '@angular/core'; +import { Product } from '../models/Product'; + +export const productsResolver: ResolveFn = async (route, state) => { + const productDAO = inject(ProductDAO); + let products: Product[] = []; + + try { + products = await productDAO.findAll() + } catch(e) { + console.error(e); + //TODO: report error + } + return products; +};