135 lines
5.8 KiB
JavaScript
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);
|
|
});
|
|
});
|
|
});
|