b34b0dd7d6
Validators (Pushes and Pull Requests) / UI & Storage Validation (pull_request) Failing after 12s
Validators (Pushes and Pull Requests) / Database & Schema Validation (pull_request) Successful in 13s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (pull_request) Failing after 28s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / CI Workflow Lint (pull_request) Failing after 10s
Validators (Pushes and Pull Requests) / Security & Secrets (pull_request) Successful in 12s
Validators (Pushes and Pull Requests) / Notify PR Results (pull_request) Successful in 2s
Frontend CI Pipeline / ci-frontend-8-steps (pull_request) Failing after 2m50s
380 lines
12 KiB
TypeScript
380 lines
12 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { mount } from '@vue/test-utils'
|
|
import StockTransferField from './StockTransferField.vue'
|
|
|
|
describe('StockTransferField (Domain Field)', () => {
|
|
const defaultProps = {
|
|
modelValue: null
|
|
}
|
|
|
|
describe('Rendering', () => {
|
|
it('renders from warehouse dropdown', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('From Warehouse')
|
|
expect(wrapper.text()).toContain('Main Warehouse')
|
|
})
|
|
|
|
it('renders to warehouse dropdown', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('To Warehouse')
|
|
})
|
|
|
|
it('renders product SKU input', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Product SKU')
|
|
})
|
|
|
|
it('renders quantity input', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Quantity')
|
|
})
|
|
|
|
it('renders transfer unit dropdown', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Unit')
|
|
expect(wrapper.text()).toContain('Pieces (PCS)')
|
|
expect(wrapper.text()).toContain('PALLET')
|
|
})
|
|
|
|
it('renders reason dropdown', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Reason')
|
|
})
|
|
|
|
it('renders priority dropdown', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Priority')
|
|
})
|
|
|
|
it('renders notes textarea', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Notes')
|
|
})
|
|
})
|
|
|
|
describe('Warehouse Validation', () => {
|
|
it('requires from warehouse', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = ''
|
|
wrapper.vm.validateFromWarehouse()
|
|
|
|
expect(wrapper.vm.fromError).not.toBeNull()
|
|
expect(wrapper.vm.fromError).toContain('Source warehouse')
|
|
})
|
|
|
|
it('requires to warehouse', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.toWarehouse = ''
|
|
wrapper.vm.validateToWarehouse()
|
|
|
|
expect(wrapper.vm.toError).not.toBeNull()
|
|
expect(wrapper.vm.toError).toContain('Destination warehouse')
|
|
})
|
|
|
|
it('prevents same warehouse for source and destination', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-001'
|
|
wrapper.vm.validateFromWarehouse()
|
|
|
|
expect(wrapper.vm.fromError).not.toBeNull()
|
|
expect(wrapper.vm.fromError).toContain('cannot be the same')
|
|
})
|
|
|
|
it('accepts different warehouses', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.validateFromWarehouse()
|
|
wrapper.vm.validateToWarehouse()
|
|
|
|
expect(wrapper.vm.fromError).toBeNull()
|
|
expect(wrapper.vm.toError).toBeNull()
|
|
})
|
|
|
|
it('supports 4 warehouses', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Main Warehouse')
|
|
expect(wrapper.text()).toContain('Regional Center')
|
|
expect(wrapper.text()).toContain('Distribution Hub')
|
|
expect(wrapper.text()).toContain('Express Depot')
|
|
})
|
|
})
|
|
|
|
describe('SKU Validation', () => {
|
|
it('requires SKU', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.productSku = ''
|
|
wrapper.vm.validateSku()
|
|
|
|
expect(wrapper.vm.skuError).not.toBeNull()
|
|
expect(wrapper.vm.skuError).toContain('required')
|
|
})
|
|
|
|
it('validates minimum length', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.productSku = 'SK'
|
|
wrapper.vm.validateSku()
|
|
|
|
expect(wrapper.vm.skuError).not.toBeNull()
|
|
expect(wrapper.vm.skuError).toContain('at least 3 characters')
|
|
})
|
|
|
|
it('accepts valid SKU', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.productSku = 'SKU-12345'
|
|
wrapper.vm.validateSku()
|
|
|
|
expect(wrapper.vm.skuError).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('Quantity Validation', () => {
|
|
it('requires quantity', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.quantity = 0
|
|
wrapper.vm.validateQuantity()
|
|
|
|
expect(wrapper.vm.quantityError).not.toBeNull()
|
|
expect(wrapper.vm.quantityError).toContain('greater than 0')
|
|
})
|
|
|
|
it('validates whole number', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.quantity = 10.5
|
|
wrapper.vm.validateQuantity()
|
|
|
|
expect(wrapper.vm.quantityError).not.toBeNull()
|
|
expect(wrapper.vm.quantityError).toContain('whole number')
|
|
})
|
|
|
|
it('accepts valid quantity', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.quantity = 100
|
|
wrapper.vm.validateQuantity()
|
|
|
|
expect(wrapper.vm.quantityError).toBeNull()
|
|
})
|
|
|
|
it('accepts large quantities', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.quantity = 10000
|
|
wrapper.vm.validateQuantity()
|
|
|
|
expect(wrapper.vm.quantityError).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('Completion Status', () => {
|
|
it('requires all mandatory fields', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-123'
|
|
wrapper.vm.transfer.quantity = 100
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.vm.isComplete).toBe(true)
|
|
})
|
|
|
|
it('is not complete when from warehouse missing', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-123'
|
|
wrapper.vm.transfer.quantity = 100
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.vm.isComplete).toBe(false)
|
|
})
|
|
|
|
it('is not complete when quantity is 0', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-123'
|
|
wrapper.vm.transfer.quantity = 0
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.vm.isComplete).toBe(false)
|
|
})
|
|
|
|
it('shows success alert when complete', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-123'
|
|
wrapper.vm.transfer.quantity = 50
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.text()).toContain('Stock transfer is configured')
|
|
})
|
|
})
|
|
|
|
describe('Optional Fields', () => {
|
|
it('allows reason selection', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('STOCK_REBALANCE')
|
|
expect(wrapper.text()).toContain('CUSTOMER_REQUEST')
|
|
})
|
|
|
|
it('allows priority selection', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Normal')
|
|
expect(wrapper.text()).toContain('High')
|
|
expect(wrapper.text()).toContain('Urgent')
|
|
})
|
|
|
|
it('allows transit days input', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.transitDays = 3
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.vm.transfer.transitDays).toBe(3)
|
|
})
|
|
|
|
it('allows notes input', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.notes = 'Special handling required'
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.vm.transfer.notes).toBe('Special handling required')
|
|
})
|
|
})
|
|
|
|
describe('Transfer Summary Display', () => {
|
|
it('shows summary when complete', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-12345'
|
|
wrapper.vm.transfer.quantity = 100
|
|
wrapper.vm.transfer.unit = 'PCS'
|
|
wrapper.vm.transfer.reason = 'STOCK_REBALANCE'
|
|
wrapper.vm.transfer.priority = 'NORMAL'
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.text()).toContain('100 PCS')
|
|
expect(wrapper.text()).toContain('SKU-12345')
|
|
expect(wrapper.text()).toContain('Main Warehouse')
|
|
expect(wrapper.text()).toContain('Regional Center')
|
|
})
|
|
|
|
it('displays priority badge', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-123'
|
|
wrapper.vm.transfer.quantity = 50
|
|
wrapper.vm.transfer.priority = 'URGENT'
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.text()).toContain('URGENT')
|
|
})
|
|
})
|
|
|
|
describe('Props Updates', () => {
|
|
it('loads transfer from modelValue prop', () => {
|
|
const props = {
|
|
modelValue: {
|
|
fromWarehouse: 'WH-002',
|
|
toWarehouse: 'WH-003',
|
|
productSku: 'SKU-99999',
|
|
quantity: 500,
|
|
unit: 'KG',
|
|
reason: 'QUALITY_ISSUE',
|
|
transitDays: 5,
|
|
priority: 'HIGH',
|
|
notes: 'Return for inspection'
|
|
}
|
|
}
|
|
|
|
const wrapper = mount(StockTransferField, { props })
|
|
|
|
expect(wrapper.vm.transfer.fromWarehouse).toBe('WH-002')
|
|
expect(wrapper.vm.transfer.quantity).toBe(500)
|
|
expect(wrapper.vm.transfer.unit).toBe('KG')
|
|
expect(wrapper.vm.transfer.notes).toBe('Return for inspection')
|
|
})
|
|
})
|
|
|
|
describe('Event Emission', () => {
|
|
it('emits update:modelValue when complete', async () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
wrapper.vm.transfer.fromWarehouse = 'WH-001'
|
|
wrapper.vm.transfer.toWarehouse = 'WH-002'
|
|
wrapper.vm.transfer.productSku = 'SKU-123'
|
|
wrapper.vm.transfer.quantity = 100
|
|
wrapper.vm.transfer.unit = 'BOX'
|
|
wrapper.vm.transfer.priority = 'HIGH'
|
|
await wrapper.vm.$nextTick()
|
|
wrapper.vm.emitUpdate()
|
|
|
|
const emitted = wrapper.emitted('update:modelValue')
|
|
expect(emitted).toBeTruthy()
|
|
expect(emitted[0][0].quantity).toBe(100)
|
|
expect(emitted[0][0].unit).toBe('BOX')
|
|
expect(emitted[0][0].priority).toBe('HIGH')
|
|
})
|
|
})
|
|
|
|
describe('Accessibility', () => {
|
|
it('shows required indicators', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
const labels = wrapper.findAll('label')
|
|
const requiredLabels = labels.filter((l) => l.text().includes('*'))
|
|
|
|
expect(requiredLabels.length).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('shows unit options', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.text()).toContain('Kilogram (KG)')
|
|
expect(wrapper.text()).toContain('Liter (L)')
|
|
})
|
|
})
|
|
|
|
describe('Warehouse Name Formatting', () => {
|
|
it('formats warehouse names correctly', () => {
|
|
const wrapper = mount(StockTransferField, { props: defaultProps })
|
|
|
|
expect(wrapper.vm.getWarehouseName('WH-001')).toBe('Main Warehouse')
|
|
expect(wrapper.vm.getWarehouseName('WH-002')).toBe('Regional Center')
|
|
expect(wrapper.vm.getWarehouseName('WH-003')).toBe('Distribution Hub')
|
|
expect(wrapper.vm.getWarehouseName('WH-004')).toBe('Express Depot')
|
|
})
|
|
})
|
|
})
|