2026-05-18 15:24:57 +03:00
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
|
|
import { mount } from '@vue/test-utils';
|
|
|
|
|
|
import { createVuetify } from 'vuetify';
|
|
|
|
|
|
import { setActivePinia, createPinia } from 'pinia';
|
|
|
|
|
|
import DealDetailBody from '../../resources/js/components/deals/DealDetailBody.vue';
|
|
|
|
|
|
import type { MockDeal } from '../../resources/js/composables/mockDeals';
|
|
|
|
|
|
|
|
|
|
|
|
const vuetify = createVuetify();
|
|
|
|
|
|
|
|
|
|
|
|
function makeDeal(overrides: Partial<MockDeal> = {}): MockDeal {
|
|
|
|
|
|
return {
|
2026-06-17 05:17:12 +03:00
|
|
|
|
id: 1,
|
|
|
|
|
|
name: '+79991234567',
|
|
|
|
|
|
phone: '+79991234567',
|
|
|
|
|
|
statusSlug: 'new',
|
|
|
|
|
|
project: 'p',
|
|
|
|
|
|
manager: { initials: 'AD', name: 'Admin' },
|
|
|
|
|
|
cost: 0,
|
2026-05-18 15:24:57 +03:00
|
|
|
|
receivedMinutesAgo: 1,
|
2026-06-17 05:17:12 +03:00
|
|
|
|
projectSignalType: 'site',
|
|
|
|
|
|
projectSignalIdentifier: 'krk-finance.ru',
|
|
|
|
|
|
projectSmsKeyword: null,
|
|
|
|
|
|
projectSmsSenders: null,
|
2026-05-18 15:24:57 +03:00
|
|
|
|
...overrides,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
describe('DealDetailBody — Тип и Источник (18.05.2026 ux)', () => {
|
|
|
|
|
|
it('site: показывает Тип «Сайт» и Источник = signal_identifier', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
|
|
|
|
|
props: { deal: makeDeal() },
|
|
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('Сайт');
|
|
|
|
|
|
expect(w.text()).toContain('krk-finance.ru');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('call: Тип «Звонок» и Источник = телефонный номер', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
2026-06-17 05:17:12 +03:00
|
|
|
|
props: {
|
|
|
|
|
|
deal: makeDeal({
|
|
|
|
|
|
projectSignalType: 'call',
|
|
|
|
|
|
projectSignalIdentifier: '79992223344',
|
|
|
|
|
|
}),
|
|
|
|
|
|
},
|
2026-05-18 15:24:57 +03:00
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('Звонок');
|
|
|
|
|
|
expect(w.text()).toContain('79992223344');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('sms с keyword: Источник = «sender (KEYWORD)»', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
2026-06-17 05:17:12 +03:00
|
|
|
|
props: {
|
|
|
|
|
|
deal: makeDeal({
|
|
|
|
|
|
projectSignalType: 'sms',
|
|
|
|
|
|
projectSignalIdentifier: null,
|
|
|
|
|
|
projectSmsSenders: ['MTS', 'BEELINE'],
|
|
|
|
|
|
projectSmsKeyword: 'КРЕДИТ',
|
|
|
|
|
|
}),
|
|
|
|
|
|
},
|
2026-05-18 15:24:57 +03:00
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('СМС');
|
|
|
|
|
|
expect(w.text()).toContain('MTS (КРЕДИТ)');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('sms без keyword: Источник = только sender', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
2026-06-17 05:17:12 +03:00
|
|
|
|
props: {
|
|
|
|
|
|
deal: makeDeal({
|
|
|
|
|
|
projectSignalType: 'sms',
|
|
|
|
|
|
projectSignalIdentifier: null,
|
|
|
|
|
|
projectSmsSenders: ['MTS'],
|
|
|
|
|
|
projectSmsKeyword: null,
|
|
|
|
|
|
}),
|
|
|
|
|
|
},
|
2026-05-18 15:24:57 +03:00
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('СМС');
|
|
|
|
|
|
expect(w.text()).toContain('MTS');
|
|
|
|
|
|
// Никаких пустых скобок
|
|
|
|
|
|
expect(w.text()).not.toMatch(/\(\s*\)/);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('не отображает «Менеджер»', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
|
|
|
|
|
props: { deal: makeDeal() },
|
|
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).not.toContain('Менеджер');
|
|
|
|
|
|
expect(w.text()).not.toContain('Не назначен');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2026-06-17 12:40:49 +03:00
|
|
|
|
|
|
|
|
|
|
describe('DealDetailBody — Город (F1)', () => {
|
|
|
|
|
|
it('показывает подпись «Город» и значение city', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
|
|
|
|
|
props: { deal: makeDeal({ city: 'Москва' }) },
|
|
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('Город');
|
|
|
|
|
|
expect(w.text()).toContain('Москва');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('при пустом city показывает «Город» и прочерк', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
|
|
|
|
|
props: { deal: makeDeal({ city: null }) },
|
|
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('Город');
|
|
|
|
|
|
expect(w.text()).toContain('—');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2026-06-17 13:30:46 +03:00
|
|
|
|
|
|
|
|
|
|
describe('DealDetailBody — Стоимость лида (F2)', () => {
|
|
|
|
|
|
it('показывает списанную сумму при costKopecks (rub)', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
|
|
|
|
|
props: { deal: makeDeal({ costKopecks: 50000 }) },
|
|
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('Стоимость лида');
|
|
|
|
|
|
expect(w.text()).toContain('500');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('показывает прочерк, а не «0 ₽», при отсутствии списания (costKopecks null)', () => {
|
|
|
|
|
|
setActivePinia(createPinia());
|
|
|
|
|
|
const w = mount(DealDetailBody, {
|
|
|
|
|
|
props: { deal: makeDeal({ costKopecks: null }) },
|
|
|
|
|
|
global: { plugins: [vuetify] },
|
|
|
|
|
|
});
|
|
|
|
|
|
expect(w.text()).toContain('Стоимость лида');
|
|
|
|
|
|
expect(w.text()).not.toContain('0 ₽');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|