feat: catalog read cache (api + user apps) and clearer Zarrin accounting errors
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -59,6 +59,17 @@ describe('wire format', () => {
|
||||
await expect(z.listCustomerGroups(s)).rejects.toThrow('دسترسی مجاز نیست');
|
||||
});
|
||||
|
||||
it('shows the server reason on a non-2xx reply, without the token', async () => {
|
||||
http.mockReturnValueOnce(reply('<html><body><h1>Server Error</h1><p>kind=listGorooheHesabha&token=SECRET failed</p></body></html>', 500));
|
||||
const err = await z.listCustomerGroups(s).catch((e) => e);
|
||||
expect(err.message).toContain('HTTP 500 — Server Error');
|
||||
expect(err.message).toContain('failed');
|
||||
expect(err.message).not.toContain('SECRET');
|
||||
|
||||
http.mockReturnValueOnce(reply({ state: false, msg: 'شناسه نامعتبر' }, 400));
|
||||
await expect(z.listCustomerGroups(s)).rejects.toThrow('HTTP 400 — شناسه نامعتبر');
|
||||
});
|
||||
|
||||
it('lists the different envelopes Zarrin uses', () => {
|
||||
const { listOf, fullJalali } = __zarrinInternals;
|
||||
expect(listOf({ data: [1] })).toEqual([1]);
|
||||
@@ -70,17 +81,76 @@ describe('wire format', () => {
|
||||
});
|
||||
|
||||
describe('customers', () => {
|
||||
it('pages with Get100Account and fills groups from listhesabha', async () => {
|
||||
const page = Array.from({ length: 100 }, (_, i) => ({ code: 81 + i, name: 'n', namKhanevadegi: `f${i}`, mobile: i === 0 ? '09121112233' : '' }));
|
||||
http
|
||||
.mockReturnValueOnce(reply({ state: true, msg: '', date: page }))
|
||||
.mockReturnValueOnce(reply({ data: [{ id: '81', nam: 'حسین اصغری', gorooh: 'مشتری (خریدار)', tell: '021', mobile: '09121112233', codeMeli: '' }] }));
|
||||
it('lists every account with its group from one listhesabha call', async () => {
|
||||
http.mockReturnValueOnce(
|
||||
reply({
|
||||
data: [
|
||||
{ id: '81', nam: 'حسین اصغری', gorooh: 'مشتری (خریدار)', tell: '021', mobile: '09121112233', codeMeli: '' },
|
||||
{ id: '82', nam: 'آرین یوسفی', gorooh: 'سازنده (تامین کننده)', tell: '', mobile: '', codeMeli: '' },
|
||||
],
|
||||
}),
|
||||
);
|
||||
const res = await z.listCustomers(s, null);
|
||||
expect(url(0).searchParams.get('id')).toBe('0');
|
||||
expect(url(1).searchParams.get('az')).toBe('81');
|
||||
expect(url(1).searchParams.get('ta')).toBe('180');
|
||||
expect(http).toHaveBeenCalledTimes(1);
|
||||
expect(url(0).searchParams.get('kind')).toBe('listhesabha');
|
||||
expect(url(0).searchParams.get('az')).toBe('1');
|
||||
expect(res.items).toHaveLength(2);
|
||||
expect(res.items[0]).toMatchObject({ code: '81', name: 'حسین اصغری', mobile: '09121112233', groupName: 'مشتری (خریدار)', phone: '021' });
|
||||
expect(res.next).toBe('181');
|
||||
expect(res.items[1].mobile).toBeNull();
|
||||
expect(res.next).toBeNull();
|
||||
});
|
||||
|
||||
it('finds by mobile with searchAccount, keeping exact matches only', async () => {
|
||||
http.mockReturnValueOnce(
|
||||
reply({
|
||||
state: true,
|
||||
msg: '',
|
||||
date: [
|
||||
{ code: 84, name: 'سعید', namKhanevadegi: 'رجایی', mobile: '09121995971' },
|
||||
{ code: 90, name: 'x', namKhanevadegi: 'y', mobile: '09121995972' },
|
||||
],
|
||||
}),
|
||||
);
|
||||
const found = await z.findCustomersByMobile(s, '09121995971');
|
||||
expect(url(0).searchParams.get('kind')).toBe('searchAccount');
|
||||
expect(found.map((c) => c.code)).toEqual(['84']);
|
||||
expect(found[0].name).toBe('سعید رجایی');
|
||||
});
|
||||
|
||||
it('falls back to listhesabha when searchAccount is missing (bare 400)', async () => {
|
||||
http
|
||||
.mockReturnValueOnce(reply('', 400))
|
||||
.mockReturnValueOnce(reply({ data: [{ id: '84', nam: 'رجایی * سعید', gorooh: 'مشتری (خریدار)', mobile: '09121995971' }, { id: '85', nam: 'z', mobile: '' }] }));
|
||||
const found = await z.findCustomersByMobile(s, '09121995971');
|
||||
expect(url(1).searchParams.get('kind')).toBe('listhesabha');
|
||||
expect(found.map((c) => c.code)).toEqual(['84']);
|
||||
});
|
||||
|
||||
it('does not hide other errors behind the fallback', async () => {
|
||||
http.mockReturnValueOnce(reply('', 500));
|
||||
await expect(z.findCustomersByMobile(s, '09121995971')).rejects.toThrow('HTTP 500');
|
||||
});
|
||||
|
||||
it('lists karsakhte groups with goroohSakhte when the installation has it', async () => {
|
||||
http.mockReturnValueOnce(reply({ state: true, detail: 'OK', data: [{ id: '26', name: 'النگو' }] }));
|
||||
expect(await z.listKarSakhteGroups!(s)).toEqual([{ id: '26', name: 'النگو' }]);
|
||||
expect(http).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('scans karsakhte groups with infogorooh when goroohSakhte is missing, skipping ids that fail', async () => {
|
||||
http.mockImplementation((req) => {
|
||||
const u = new URL(req.url);
|
||||
if (u.searchParams.get('kind') === 'goroohSakhte') return reply('', 400);
|
||||
const id = u.searchParams.get('id');
|
||||
if (id === '26') return reply({ data: [{ nam: 'النگو', code: 26 }] });
|
||||
if (id === '115') return reply({ data: [{ nam: 'سکه', code: 115 }] });
|
||||
if (id === '3') return reply('', 500);
|
||||
return reply('{\n "data": \n ]\n}');
|
||||
});
|
||||
expect(await z.listKarSakhteGroups!(s)).toEqual([
|
||||
{ id: '26', name: 'النگو' },
|
||||
{ id: '115', name: 'سکه' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps the account in its group on edit', async () => {
|
||||
|
||||
Reference in New Issue
Block a user