Files
doormilxpress_astryx/tests/lib/hubForm.test.js

135 lines
5.8 KiB
JavaScript

import { validateHubForm } from '@/lib/hubForm';
/**
* A hub in this console is a BASE to a rider.
*
* The bug these tests exist to prevent is already in production data: of the 18
* hubs live today, one carries no address and no coordinates. Only `hubname`
* and `applocationid` were ever validated, so a base could be saved that the
* rider app can name but cannot route anyone to — Navigate does nothing without
* a pin, and a rider standing outside an industrial estate has nothing to read
* without an address.
*
* The backend hands six fields to the rider app for a base. Five of six is not
* "mostly there"; it is a rider with a parcel and no way to deliver it.
*/
const VALID = {
hubname: 'Coimbatore Gandhipuram Hub',
applocationid: 1,
address: '14 Avinashi Road, Peelamedu, Coimbatore',
pincode: '641004',
latitude: '11.0168',
longitude: '76.9558'
};
describe('validateHubForm', () => {
describe('a complete base', () => {
it('should accept a form carrying all six rider-facing fields', () => {
const { errors, isValid } = validateHubForm(VALID);
expect(errors).toEqual({});
expect(isValid).toBe(true);
});
it('should hand back coordinates already coerced, so the caller does not re-parse', () => {
const { values } = validateHubForm(VALID);
expect(values.latitude).toBe(11.0168);
expect(values.longitude).toBe(76.9558);
expect(values.applocationid).toBe(1);
});
it('should accept a southern or western hemisphere base', () => {
// Nothing in the range check may assume India.
expect(validateHubForm({ ...VALID, latitude: '-33.8688', longitude: '-70.6693' }).isValid).toBe(true);
});
});
describe('the fields that were never checked', () => {
it('should reject a base with no address, because the rider reads it at the gate', () => {
const { errors, isValid } = validateHubForm({ ...VALID, address: '' });
expect(isValid).toBe(false);
expect(errors.address).toBeTruthy();
});
it('should reject whitespace as an address', () => {
expect(validateHubForm({ ...VALID, address: ' ' }).errors.address).toBeTruthy();
});
it('should reject a base with no pincode', () => {
expect(validateHubForm({ ...VALID, pincode: '' }).errors.pincode).toBeTruthy();
});
it('should reject a base with no coordinates, because Navigate cannot work', () => {
const { errors, isValid } = validateHubForm({ ...VALID, latitude: '', longitude: '' });
expect(isValid).toBe(false);
expect(errors.latitude).toBeTruthy();
expect(errors.longitude).toBeTruthy();
});
it('should treat 0,0 as unset rather than as a location', () => {
// The previous code coerced an empty coordinate to 0 and sent it. 0,0 is
// in the Gulf of Guinea; it is always an unset value, never a base.
const { errors } = validateHubForm({ ...VALID, latitude: '0', longitude: '0' });
expect(errors.latitude).toBeTruthy();
expect(errors.longitude).toBeTruthy();
});
it('should reject a single missing coordinate, not just both', () => {
// Half a pin is no pin.
expect(validateHubForm({ ...VALID, latitude: '' }).isValid).toBe(false);
expect(validateHubForm({ ...VALID, longitude: '' }).isValid).toBe(false);
});
it('should reject coordinates outside the possible range', () => {
expect(validateHubForm({ ...VALID, latitude: '91' }).errors.latitude).toBeTruthy();
expect(validateHubForm({ ...VALID, latitude: '-91' }).errors.latitude).toBeTruthy();
expect(validateHubForm({ ...VALID, longitude: '181' }).errors.longitude).toBeTruthy();
expect(validateHubForm({ ...VALID, longitude: '-181' }).errors.longitude).toBeTruthy();
});
it('should reject a coordinate that is not a number at all', () => {
expect(validateHubForm({ ...VALID, latitude: 'near the flyover' }).errors.latitude).toBeTruthy();
});
it('should catch a swapped lat/lng pair for an Indian base', () => {
// 76.9 as a latitude is inside the Arctic Circle. The range check is the
// only thing standing between a transposed paste and a base in the sea.
expect(validateHubForm({ ...VALID, latitude: '76.9558', longitude: '11.0168' }).isValid).toBe(true);
// ...but a longitude beyond 90 in the latitude slot is caught outright.
expect(validateHubForm({ ...VALID, latitude: '176.9558' }).errors.latitude).toBeTruthy();
});
});
describe('the checks that already existed', () => {
it('should still require a name', () => {
expect(validateHubForm({ ...VALID, hubname: '' }).errors.hubname).toBeTruthy();
expect(validateHubForm({ ...VALID, hubname: ' ' }).errors.hubname).toBeTruthy();
});
it('should still require a numeric city id', () => {
expect(validateHubForm({ ...VALID, applocationid: '' }).errors.applocationid).toBeTruthy();
expect(validateHubForm({ ...VALID, applocationid: 'Coimbatore' }).errors.applocationid).toBeTruthy();
});
it('should accept city id 0, which is a valid id and not an absence', () => {
expect(validateHubForm({ ...VALID, applocationid: 0 }).errors.applocationid).toBeUndefined();
});
});
describe('robustness', () => {
it('should report every problem at once rather than one at a time', () => {
// An operator fixing a form field by field, submit by submit, is a worse
// experience than being told everything that is wrong.
const { errors } = validateHubForm({});
expect(Object.keys(errors).sort()).toEqual(
['address', 'applocationid', 'hubname', 'latitude', 'longitude', 'pincode'].sort()
);
});
it('should not throw on an empty or missing form', () => {
expect(() => validateHubForm()).not.toThrow();
expect(validateHubForm().isValid).toBe(false);
});
});
});