updates on the admin and zone things and minor changes
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
import React from 'react';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { configure, render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
|
||||
// The page renders the client list and the city query before anything can be
|
||||
// found. Under the full suite (66 files at once) the first render here was
|
||||
// regularly slower than the 1 s default, failing "shows Edit and Delete on
|
||||
// each row" on timing alone.
|
||||
configure({ asyncUtilTimeout: 5000 });
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
@@ -35,9 +41,35 @@ jest.mock('@/api/doormile/notify', () => ({
|
||||
let mockAuth = { user: { email: 'admin@doormile.com', role: 'admin', tenantid: null }, isClient: false };
|
||||
jest.mock('@/lib/AuthContext', () => ({ useAuth: () => mockAuth }));
|
||||
|
||||
// The real address search calls the geocoding service. This stand-in is a text
|
||||
// box plus a "Pick" button that selects a fixed place, the way picking a
|
||||
// suggestion does.
|
||||
const mockPickedPlace = {
|
||||
formatted_address: '14 DB Road, RS Puram, Coimbatore',
|
||||
latitude: 11.009,
|
||||
longitude: 76.95,
|
||||
city: 'Coimbatore',
|
||||
postcode: '641002',
|
||||
address_components: [{ types: ['administrative_area_level_1'], long_name: 'Tamil Nadu' }],
|
||||
};
|
||||
jest.mock('@/components/doormile/AddressAutocomplete', () => ({
|
||||
__esModule: true,
|
||||
default: ({ id, label, value, onChange, onPlaceSelected }) => (
|
||||
<div>
|
||||
<label htmlFor={id}>{label}</label>
|
||||
<input id={id} value={value} onChange={(e) => onChange(e.target.value)} />
|
||||
<button type="button" onClick={() => onPlaceSelected(mockPickedPlace)}>
|
||||
Pick {label}
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
import * as api from '@/api/doormile';
|
||||
import ClientOnboarding from '@/pages/doormile/clients/ClientOnboarding';
|
||||
import { canOnboardClients, generateClientPassword, onboardingUnavailableMessage, validateOnboarding } from '@/lib/clientOnboarding';
|
||||
import {
|
||||
addressFromPlace, canOnboardClients, generateClientPassword, onboardingUnavailableMessage, validateAddress, validateOnboarding,
|
||||
} from '@/lib/clientOnboarding';
|
||||
|
||||
const CITIES = [
|
||||
{ applocationid: 1, applocationname: 'Coimbatore', status: 'Active' },
|
||||
@@ -67,6 +99,7 @@ const fillValidForm = async () => {
|
||||
fill('Operating city', '1');
|
||||
fireEvent.change(document.getElementById('onboard-password'), { target: { value: 's3cure-pass' } });
|
||||
fill('Confirm password', 's3cure-pass');
|
||||
fireEvent.click(screen.getAllByRole('button', { name: 'Pick Client address' })[0]);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -99,6 +132,24 @@ describe('Edit and Delete on a client login', () => {
|
||||
await waitFor(() => expect(api.updateOnboardedClient).toHaveBeenCalledWith(31, { phone: '9123456780', status: 'Inactive' }));
|
||||
});
|
||||
|
||||
it('adds an address for a client that has none, as one location object', async () => {
|
||||
renderPage();
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Edit Older Client' }));
|
||||
await screen.findByRole('dialog');
|
||||
expect(screen.getByText(/No address on file yet/)).toBeInTheDocument();
|
||||
const picks = screen.getAllByRole('button', { name: 'Pick Client address' });
|
||||
fireEvent.click(picks[picks.length - 1]); // the dialog's address box
|
||||
fireEvent.click(screen.getByRole('button', { name: /Save changes/ }));
|
||||
await waitFor(() =>
|
||||
expect(api.updateOnboardedClient).toHaveBeenCalledWith(31, {
|
||||
location: {
|
||||
address: '14 DB Road, RS Puram, Coimbatore', city: 'Coimbatore', state: 'Tamil Nadu',
|
||||
pincode: '641002', latitude: 11.009, longitude: 76.95,
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('resets the password only when one is entered, and checks its length', async () => {
|
||||
renderPage();
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Edit Older Client' }));
|
||||
@@ -171,6 +222,12 @@ describe('Client onboarding page', () => {
|
||||
password: 's3cure-pass',
|
||||
applocationid: 1,
|
||||
requiredeliveryotp: false,
|
||||
address: '14 DB Road, RS Puram, Coimbatore',
|
||||
city: 'Coimbatore',
|
||||
state: 'Tamil Nadu',
|
||||
pincode: '641002',
|
||||
latitude: 11.009,
|
||||
longitude: 76.95,
|
||||
});
|
||||
expect(screen.getByRole('status')).toHaveTextContent('ops@acme.example');
|
||||
expect(screen.getByRole('status')).toHaveTextContent('only time the password is shown');
|
||||
@@ -198,6 +255,32 @@ describe('Client onboarding page', () => {
|
||||
expect(api.onboardClient).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('needs an address with a map location before calling the server', async () => {
|
||||
renderPage();
|
||||
await screen.findByRole('option', { name: 'Coimbatore' });
|
||||
fill('Company name', 'Acme Foods');
|
||||
fill('Contact person', 'Priya Raman');
|
||||
fill('Mobile number', '9876543210');
|
||||
fill('Login email', 'ops@acme.example');
|
||||
fill('Operating city', '1');
|
||||
fireEvent.change(document.getElementById('onboard-password'), { target: { value: 's3cure-pass' } });
|
||||
fill('Confirm password', 's3cure-pass');
|
||||
// Typed, never picked: no map location.
|
||||
fireEvent.change(document.getElementById('onboard-address'), { target: { value: '14 DB Road, RS Puram' } });
|
||||
fill('Pincode', '641002');
|
||||
fireEvent.click(screen.getByRole('button', { name: /Onboard client/ }));
|
||||
expect(await screen.findByText('Pick the address from the suggestions so it has a map location')).toBeInTheDocument();
|
||||
expect(api.onboardClient).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows each client address in the list', async () => {
|
||||
api.getOnboardedClients.mockResolvedValue([
|
||||
{ authid: 32, tenantid: 13, tenantname: 'With Address', primarycontact: '9000000001', status: 'Active', loginemail: 'b@x.example', address: '5 Avinashi Road', pincode: '641004' },
|
||||
]);
|
||||
renderPage();
|
||||
expect(await screen.findByText('5 Avinashi Road · 641004')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('puts a server conflict under the field it is about', async () => {
|
||||
api.onboardClient.mockRejectedValue({ response: { status: 409, data: { success: false, message: 'this email already has a console login' } } });
|
||||
renderPage();
|
||||
@@ -277,6 +360,7 @@ describe('client onboarding helpers', () => {
|
||||
expect(pw).toMatch(/[a-z]/i);
|
||||
const errors = validateOnboarding({
|
||||
companyname: 'Acme', contactname: 'Priya', email: 'a@b.co', phone: '9876543210', applocationid: 1, password: pw, confirm: pw,
|
||||
address: '14 DB Road, RS Puram', pincode: '641002', latitude: 11.009, longitude: 76.95,
|
||||
});
|
||||
expect(errors).toEqual({});
|
||||
}
|
||||
@@ -296,4 +380,32 @@ describe('client onboarding helpers', () => {
|
||||
expect(validateOnboarding({ ...base, password: 'a@b.co', confirm: 'a@b.co' }).password).toBeTruthy();
|
||||
expect(validateOnboarding({ ...base, password: 'short', confirm: 'short' }).password).toBeTruthy();
|
||||
});
|
||||
|
||||
it('checks the address like the server does', () => {
|
||||
const ok = { address: '14 DB Road, RS Puram', pincode: '641002', latitude: 11.009, longitude: 76.95 };
|
||||
expect(validateAddress(ok)).toEqual({});
|
||||
expect(validateAddress({ ...ok, address: 'abc' }).address).toMatch(/Enter the client/);
|
||||
expect(validateAddress({ ...ok, pincode: '64100' }).pincode).toBeTruthy();
|
||||
expect(validateAddress({ ...ok, pincode: '041002' }).pincode).toBeTruthy();
|
||||
expect(validateAddress({ ...ok, latitude: '', longitude: '' }).address).toMatch(/Pick the address/);
|
||||
expect(validateAddress({ ...ok, latitude: 76.95, longitude: 11.0 }).address).toMatch(/Pick the address/); // swapped
|
||||
});
|
||||
|
||||
it('reads a picked place from either shape', () => {
|
||||
expect(addressFromPlace({ formatted_address: 'X Road', latitude: 11, longitude: 77, city: 'Coimbatore', postcode: '641 002' }))
|
||||
.toEqual({ address: 'X Road', city: 'Coimbatore', pincode: '641002', latitude: 11, longitude: 77 });
|
||||
const google = {
|
||||
name: 'Y Street',
|
||||
geometry: { location: { lat: () => 12.9, lng: () => 77.6 } },
|
||||
address_components: [
|
||||
{ types: ['locality'], long_name: 'Bengaluru' },
|
||||
{ types: ['administrative_area_level_1'], long_name: 'Karnataka' },
|
||||
{ types: ['postal_code'], long_name: '560034' },
|
||||
],
|
||||
};
|
||||
expect(addressFromPlace(google)).toEqual({
|
||||
address: 'Y Street', city: 'Bengaluru', state: 'Karnataka', pincode: '560034', latitude: 12.9, longitude: 77.6,
|
||||
});
|
||||
expect(addressFromPlace(null)).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user