mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Fix unit Test
This commit is contained in:
@@ -1,27 +1,21 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { of, throwError, NEVER } from 'rxjs';
|
||||
import { RemissionStockService } from './remission-stock.service';
|
||||
import { StockService } from '@generated/swagger/inventory-api';
|
||||
import { ResponseArgsError } from '@isa/common/data-access';
|
||||
import { Stock, StockInfo } from '../models';
|
||||
|
||||
jest.mock('@generated/swagger/inventory-api', () => ({
|
||||
StockService: jest.fn(),
|
||||
}));
|
||||
|
||||
/**
|
||||
* Unit tests for RemissionStockService.
|
||||
* Tests the service's ability to fetch and cache stock information.
|
||||
* These tests are isolated and do not depend on each other.
|
||||
*
|
||||
* @group unit
|
||||
* @group services
|
||||
*/
|
||||
describe('RemissionStockService', () => {
|
||||
let service: RemissionStockService;
|
||||
let mockStockService: {
|
||||
StockCurrentStock: jest.Mock;
|
||||
StockInStock: jest.Mock;
|
||||
};
|
||||
let mockStockService: jest.Mocked<StockService>;
|
||||
|
||||
const mockStock: Stock = {
|
||||
id: 123,
|
||||
@@ -45,13 +39,11 @@ describe('RemissionStockService', () => {
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
// Clear all mocks before each test
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Create a fresh mock for each test to ensure isolation
|
||||
mockStockService = {
|
||||
StockCurrentStock: jest.fn(),
|
||||
StockInStock: jest.fn(),
|
||||
};
|
||||
} as unknown as jest.Mocked<StockService>;
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
@@ -60,9 +52,16 @@ describe('RemissionStockService', () => {
|
||||
],
|
||||
});
|
||||
|
||||
// Create a fresh service instance for each test
|
||||
service = TestBed.inject(RemissionStockService);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Clear all mocks after each test to prevent interference
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests for fetchAssignedStock method.
|
||||
* Verifies caching behavior and API interaction.
|
||||
@@ -70,7 +69,7 @@ describe('RemissionStockService', () => {
|
||||
describe('fetchAssignedStock', () => {
|
||||
it('should fetch stock from API', async () => {
|
||||
mockStockService.StockCurrentStock.mockReturnValue(
|
||||
of({ result: mockStock, error: null }),
|
||||
of({ result: mockStock, error: false }),
|
||||
);
|
||||
|
||||
const result = await service.fetchAssignedStock();
|
||||
@@ -80,7 +79,7 @@ describe('RemissionStockService', () => {
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns error', async () => {
|
||||
const errorResponse = { error: 'API Error', result: null };
|
||||
const errorResponse = { error: true, result: undefined };
|
||||
mockStockService.StockCurrentStock.mockReturnValue(of(errorResponse));
|
||||
|
||||
await expect(service.fetchAssignedStock()).rejects.toThrow(
|
||||
@@ -90,7 +89,7 @@ describe('RemissionStockService', () => {
|
||||
|
||||
it('should throw ResponseArgsError when API returns no result', async () => {
|
||||
mockStockService.StockCurrentStock.mockReturnValue(
|
||||
of({ error: null, result: null }),
|
||||
of({ error: false, result: undefined }),
|
||||
);
|
||||
|
||||
await expect(service.fetchAssignedStock()).rejects.toThrow(
|
||||
@@ -98,20 +97,24 @@ describe('RemissionStockService', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle abort signal', async () => {
|
||||
it('should handle abort signal by configuring the observable pipeline', async () => {
|
||||
// Arrange
|
||||
const abortController = new AbortController();
|
||||
const mockObservable = {
|
||||
pipe: jest.fn().mockReturnThis(),
|
||||
};
|
||||
mockStockService.StockCurrentStock.mockReturnValue(mockObservable);
|
||||
const pipeSpy = jest.fn().mockReturnValue(
|
||||
of({ result: mockStock, error: false }),
|
||||
);
|
||||
|
||||
mockStockService.StockCurrentStock.mockReturnValue({
|
||||
pipe: pipeSpy,
|
||||
} as any);
|
||||
|
||||
try {
|
||||
await service.fetchAssignedStock(abortController.signal);
|
||||
} catch {
|
||||
// Expected to fail since we're not properly mocking the observable
|
||||
}
|
||||
// Act
|
||||
const result = await service.fetchAssignedStock(abortController.signal);
|
||||
|
||||
expect(mockObservable.pipe).toHaveBeenCalled();
|
||||
// Assert
|
||||
expect(result).toEqual(mockStock);
|
||||
expect(pipeSpy).toHaveBeenCalled();
|
||||
expect(mockStockService.StockCurrentStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle API observable errors', async () => {
|
||||
@@ -132,19 +135,23 @@ describe('RemissionStockService', () => {
|
||||
describe('fetchStock', () => {
|
||||
/**
|
||||
* Valid test parameters for stock fetching.
|
||||
* Note: The schema expects 'stockId', not 'assignedStockId'
|
||||
*/
|
||||
const validParams = {
|
||||
assignedStockId: 123,
|
||||
stockId: 123,
|
||||
itemIds: [100, 101],
|
||||
};
|
||||
|
||||
it('should fetch stock info successfully', async () => {
|
||||
it('should fetch stock info successfully with stockId provided', async () => {
|
||||
// Arrange
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ result: mockStockInfo, error: null }),
|
||||
of({ result: mockStockInfo, error: false }),
|
||||
);
|
||||
|
||||
// Act
|
||||
const result = await service.fetchStock(validParams);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(mockStockInfo);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalledWith({
|
||||
stockId: 123,
|
||||
@@ -152,69 +159,118 @@ describe('RemissionStockService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns error', async () => {
|
||||
const errorResponse = { error: 'API Error', result: null };
|
||||
mockStockService.StockInStock.mockReturnValue(of(errorResponse));
|
||||
|
||||
await expect(service.fetchStock(validParams)).rejects.toThrow(
|
||||
ResponseArgsError,
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns no result', async () => {
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ error: null, result: null }),
|
||||
);
|
||||
|
||||
await expect(service.fetchStock(validParams)).rejects.toThrow(
|
||||
ResponseArgsError,
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle abort signal', async () => {
|
||||
const abortController = new AbortController();
|
||||
const mockObservable = {
|
||||
pipe: jest.fn().mockReturnThis(),
|
||||
};
|
||||
mockStockService.StockInStock.mockReturnValue(mockObservable);
|
||||
|
||||
try {
|
||||
await service.fetchStock(validParams, abortController.signal);
|
||||
} catch {
|
||||
// Expected to fail since we're not properly mocking the observable
|
||||
}
|
||||
|
||||
expect(mockObservable.pipe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should validate params with schema', async () => {
|
||||
// This will be validated by the schema
|
||||
const invalidParams = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
assignedStockId: 'invalid' as any, // Should be number
|
||||
it('should fetch assigned stock when stockId not provided', async () => {
|
||||
// Arrange
|
||||
const paramsWithoutStockId = {
|
||||
itemIds: [100, 101],
|
||||
};
|
||||
|
||||
mockStockService.StockCurrentStock.mockReturnValue(
|
||||
of({ result: mockStock, error: false }),
|
||||
);
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ result: mockStockInfo, error: null }),
|
||||
of({ result: mockStockInfo, error: false }),
|
||||
);
|
||||
|
||||
// The schema parsing should throw an error for invalid params
|
||||
// Act
|
||||
const result = await service.fetchStock(paramsWithoutStockId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(mockStockInfo);
|
||||
expect(mockStockService.StockCurrentStock).toHaveBeenCalled();
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalledWith({
|
||||
stockId: 123, // Should use the fetched assigned stock ID
|
||||
articleIds: [100, 101],
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns error', async () => {
|
||||
// Arrange
|
||||
const errorResponse = { error: true, result: undefined };
|
||||
mockStockService.StockInStock.mockReturnValue(of(errorResponse));
|
||||
|
||||
// Act & Assert
|
||||
await expect(service.fetchStock(validParams)).rejects.toThrow(
|
||||
ResponseArgsError,
|
||||
);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns no result', async () => {
|
||||
// Arrange
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ error: false, result: undefined }),
|
||||
);
|
||||
|
||||
// Act & Assert
|
||||
await expect(service.fetchStock(validParams)).rejects.toThrow(
|
||||
ResponseArgsError,
|
||||
);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle abort signal by configuring the observable pipeline', async () => {
|
||||
// Arrange
|
||||
const abortController = new AbortController();
|
||||
const pipeSpy = jest.fn().mockReturnValue(
|
||||
of({ result: mockStockInfo, error: false }),
|
||||
);
|
||||
|
||||
mockStockService.StockInStock.mockReturnValue({
|
||||
pipe: pipeSpy,
|
||||
} as any);
|
||||
|
||||
// Act
|
||||
const result = await service.fetchStock(validParams, abortController.signal);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(mockStockInfo);
|
||||
expect(pipeSpy).toHaveBeenCalled();
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should validate params with schema and reject invalid stockId type', async () => {
|
||||
// Arrange - This will be validated by the schema
|
||||
const invalidParams = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
stockId: 'invalid' as any, // Should be number
|
||||
itemIds: [100, 101],
|
||||
};
|
||||
|
||||
// Act & Assert - The schema parsing should throw an error for invalid params
|
||||
await expect(service.fetchStock(invalidParams)).rejects.toThrow();
|
||||
// Should not reach the API call
|
||||
expect(mockStockService.StockInStock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should validate params with schema and reject invalid itemIds type', async () => {
|
||||
// Arrange
|
||||
const invalidParams = {
|
||||
stockId: 123,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
itemIds: 'not-an-array' as any, // Should be array
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
await expect(service.fetchStock(invalidParams)).rejects.toThrow();
|
||||
expect(mockStockService.StockInStock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle empty itemIds array', async () => {
|
||||
// Arrange
|
||||
const paramsWithEmptyItems = {
|
||||
assignedStockId: 123,
|
||||
stockId: 123,
|
||||
itemIds: [],
|
||||
};
|
||||
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ result: [], error: null }),
|
||||
of({ result: [], error: false }),
|
||||
);
|
||||
|
||||
// Act
|
||||
const result = await service.fetchStock(paramsWithEmptyItems);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual([]);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalledWith({
|
||||
stockId: 123,
|
||||
@@ -223,23 +279,30 @@ describe('RemissionStockService', () => {
|
||||
});
|
||||
|
||||
it('should handle API observable errors', async () => {
|
||||
// Arrange
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
throwError(() => new Error('Network error')),
|
||||
);
|
||||
|
||||
// Act & Assert
|
||||
await expect(service.fetchStock(validParams)).rejects.toThrow(
|
||||
'Network error',
|
||||
);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return empty array when API returns empty result', async () => {
|
||||
// Arrange
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ result: [], error: null }),
|
||||
of({ result: [], error: false }),
|
||||
);
|
||||
|
||||
// Act
|
||||
const result = await service.fetchStock(validParams);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual([]);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user