Files
ISA-Frontend/libs/core/navigation/src/lib/navigation-state.service.spec.ts
Lorenz Hilpert 596ae1da1b Merged PR 1969: Reward Shopping Cart Implementation with Navigation State Management and Shipping Address Integration
1. Reward Shopping Cart Implementation
  - New shopping cart with quantity control and availability checking
  - Responsive shopping cart item component with improved CSS styling
  - Shipping address integration in cart
  - Customer reward card and billing/shipping address components

  2. Navigation State Management Library (@isa/core/navigation)
  - New library with type-safe navigation context service (373 lines)
  - Navigation state service (287 lines) for temporary state between routes
  - Comprehensive test coverage (668 + 227 lines of tests)
  - Documentation (792 lines in README.md)
  - Replaces query parameters for passing temporary navigation context

  3. CRM Shipping Address Services
  - New ShippingAddressService with fetching and validation
  - CustomerShippingAddressResource and CustomerShippingAddressesResource
  - Zod schemas for data validation

  4. Additional Improvements
  - Enhanced searchbox accessibility with ARIA support
  - Availability data access rework for better fetching/mapping
  - Storybook tooltip variant support
  - Vitest JUnit and Cobertura reporting configuration

Related work items: #5382, #5383, #5384
2025-10-15 14:59:34 +00:00

228 lines
7.5 KiB
TypeScript

import { TestBed } from '@angular/core/testing';
import { Location } from '@angular/common';
import { Router } from '@angular/router';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { NavigationStateService } from './navigation-state.service';
import { NavigationContextService } from './navigation-context.service';
import { ReturnUrlContext } from './navigation-context.types';
describe('NavigationStateService', () => {
let service: NavigationStateService;
let locationMock: { getState: ReturnType<typeof vi.fn> };
let routerMock: { navigate: ReturnType<typeof vi.fn> };
let contextServiceMock: {
setContext: ReturnType<typeof vi.fn>;
getContext: ReturnType<typeof vi.fn>;
getAndClearContext: ReturnType<typeof vi.fn>;
clearContext: ReturnType<typeof vi.fn>;
hasContext: ReturnType<typeof vi.fn>;
clearScope: ReturnType<typeof vi.fn>;
};
beforeEach(() => {
locationMock = {
getState: vi.fn(),
};
routerMock = {
navigate: vi.fn(),
};
contextServiceMock = {
setContext: vi.fn().mockResolvedValue(undefined),
getContext: vi.fn().mockResolvedValue(null),
getAndClearContext: vi.fn().mockResolvedValue(null),
clearContext: vi.fn().mockResolvedValue(false),
hasContext: vi.fn().mockResolvedValue(false),
clearScope: vi.fn().mockResolvedValue(0),
};
TestBed.configureTestingModule({
providers: [
NavigationStateService,
{ provide: Location, useValue: locationMock },
{ provide: Router, useValue: routerMock },
{ provide: NavigationContextService, useValue: contextServiceMock },
],
});
service = TestBed.inject(NavigationStateService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
// Context Preservation Methods Tests
describe('preserveContext', () => {
it('should call contextService.setContext with correct parameters', async () => {
const data: ReturnUrlContext = { returnUrl: '/test-page' };
const scopeKey = 'process-123';
await service.preserveContext(data, scopeKey);
expect(contextServiceMock.setContext).toHaveBeenCalledWith(data, scopeKey);
});
it('should work without scope key', async () => {
const data: ReturnUrlContext = { returnUrl: '/test-page' };
await service.preserveContext(data);
expect(contextServiceMock.setContext).toHaveBeenCalledWith(data, undefined);
});
});
describe('restoreContext', () => {
it('should call contextService.getContext with correct parameters', async () => {
const expectedData: ReturnUrlContext = { returnUrl: '/test-page' };
contextServiceMock.getContext.mockResolvedValue(expectedData);
const result = await service.restoreContext<ReturnUrlContext>('scope-123');
expect(contextServiceMock.getContext).toHaveBeenCalledWith('scope-123');
expect(result).toEqual(expectedData);
});
it('should return null when context not found', async () => {
contextServiceMock.getContext.mockResolvedValue(null);
const result = await service.restoreContext();
expect(result).toBeNull();
});
it('should work without parameters', async () => {
const expectedData: ReturnUrlContext = { returnUrl: '/test-page' };
contextServiceMock.getContext.mockResolvedValue(expectedData);
const result = await service.restoreContext<ReturnUrlContext>();
expect(contextServiceMock.getContext).toHaveBeenCalledWith(undefined);
expect(result).toEqual(expectedData);
});
});
describe('restoreAndClearContext', () => {
it('should call contextService.getAndClearContext with correct parameters', async () => {
const expectedData: ReturnUrlContext = { returnUrl: '/test-page' };
contextServiceMock.getAndClearContext.mockResolvedValue(expectedData);
const result = await service.restoreAndClearContext<ReturnUrlContext>('scope-123');
expect(contextServiceMock.getAndClearContext).toHaveBeenCalledWith('scope-123');
expect(result).toEqual(expectedData);
});
it('should return null when context not found', async () => {
contextServiceMock.getAndClearContext.mockResolvedValue(null);
const result = await service.restoreAndClearContext();
expect(result).toBeNull();
});
});
describe('clearPreservedContext', () => {
it('should call contextService.clearContext and return result', async () => {
contextServiceMock.clearContext.mockResolvedValue(true);
const result = await service.clearPreservedContext('scope-123');
expect(contextServiceMock.clearContext).toHaveBeenCalledWith('scope-123');
expect(result).toBe(true);
});
it('should return false when context not found', async () => {
contextServiceMock.clearContext.mockResolvedValue(false);
const result = await service.clearPreservedContext();
expect(result).toBe(false);
});
});
describe('hasPreservedContext', () => {
it('should call contextService.hasContext and return result', async () => {
contextServiceMock.hasContext.mockResolvedValue(true);
const result = await service.hasPreservedContext('scope-123');
expect(contextServiceMock.hasContext).toHaveBeenCalledWith('scope-123');
expect(result).toBe(true);
});
it('should return false when context not found', async () => {
contextServiceMock.hasContext.mockResolvedValue(false);
const result = await service.hasPreservedContext();
expect(result).toBe(false);
});
});
describe('navigateWithPreservedContext', () => {
it('should preserve context and navigate', async () => {
const data: ReturnUrlContext = { returnUrl: '/reward/cart', customerId: 123 };
const commands = ['/customer/search'];
const scopeKey = 'process-123';
routerMock.navigate.mockResolvedValue(true);
const result = await service.navigateWithPreservedContext(commands, data, scopeKey);
expect(contextServiceMock.setContext).toHaveBeenCalledWith(data, scopeKey);
expect(routerMock.navigate).toHaveBeenCalledWith(commands, {
state: data,
});
expect(result).toEqual({ success: true });
});
it('should merge navigation extras', async () => {
const data: ReturnUrlContext = { returnUrl: '/test' };
const commands = ['/page'];
const extras = { queryParams: { foo: 'bar' } };
routerMock.navigate.mockResolvedValue(true);
await service.navigateWithPreservedContext(commands, data, undefined, extras);
expect(routerMock.navigate).toHaveBeenCalledWith(commands, {
queryParams: { foo: 'bar' },
state: data,
});
});
it('should return false when navigation fails', async () => {
const data: ReturnUrlContext = { returnUrl: '/test' };
const commands = ['/page'];
routerMock.navigate.mockResolvedValue(false);
const result = await service.navigateWithPreservedContext(commands, data);
expect(result).toEqual({ success: false });
});
});
describe('clearScopeContexts', () => {
it('should call contextService.clearScope and return count', async () => {
contextServiceMock.clearScope.mockResolvedValue(3);
const result = await service.clearScopeContexts();
expect(contextServiceMock.clearScope).toHaveBeenCalled();
expect(result).toBe(3);
});
it('should return 0 when no contexts cleared', async () => {
contextServiceMock.clearScope.mockResolvedValue(0);
const result = await service.clearScopeContexts();
expect(result).toBe(0);
});
});
});