85 lines
3.2 KiB
TypeScript
85 lines
3.2 KiB
TypeScript
import { mount } from '@vue/test-utils';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { createVuetify } from 'vuetify';
|
|
import TenantActivityPane from '../../resources/js/components/admin/tenant-detail/TenantActivityPane.vue';
|
|
import type { TenantActivityItem, TenantAliveness } from '../../resources/js/composables/mockTenantDetail';
|
|
|
|
const vuetify = createVuetify();
|
|
|
|
const aliveness: TenantAliveness = {
|
|
state: 'cooling',
|
|
lastLoginAt: '2026-08-06T03:23:12+00:00',
|
|
daysSinceLogin: 6,
|
|
lastLoginIp: '5.166.40.65',
|
|
lastLoginUserAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0 Safari/537.36',
|
|
days: [{ date: '2026-08-06', visits: 1 }],
|
|
visits30d: 2,
|
|
activeDays30d: 2,
|
|
actions30d: 2,
|
|
failedLogins30d: 4,
|
|
};
|
|
|
|
const items: TenantActivityItem[] = [
|
|
{
|
|
id: 'ops-1',
|
|
at: '2026-08-05T07:34:48+00:00',
|
|
kind: 'project',
|
|
event: 'project.created',
|
|
actor: 'client@example.test',
|
|
subject: 'Окна ЕКБ',
|
|
amountRub: null,
|
|
bulkCount: 0,
|
|
},
|
|
];
|
|
|
|
function mountPane(props = {}) {
|
|
return mount(TenantActivityPane, {
|
|
global: { plugins: [vuetify] },
|
|
props: { aliveness, items, hasMore: false, ...props },
|
|
});
|
|
}
|
|
|
|
describe('панель «Активность»', () => {
|
|
it('показывает вердикт и устройство последнего входа', () => {
|
|
const text = mountPane().text();
|
|
expect(text).toContain('Не заходил 6 дней');
|
|
expect(text).toContain('Windows/Chrome');
|
|
expect(text).toContain('5.166.40.65');
|
|
});
|
|
|
|
it('показывает четыре счётчика', () => {
|
|
const text = mountPane().text();
|
|
expect(text).toContain('Визитов за 30 дней');
|
|
expect(text).toContain('Дней с визитами');
|
|
expect(text).toContain('Действий');
|
|
expect(text).toContain('Не смог войти');
|
|
});
|
|
|
|
it('красит «не смог войти», когда попытки были', () => {
|
|
const wrapper = mountPane();
|
|
expect(wrapper.find('[data-testid="failed-logins"]').classes()).toContain('text-error');
|
|
});
|
|
|
|
it('строит полоску ровно на 90 суток', () => {
|
|
expect(mountPane().findAll('[data-testid="strip-day"]')).toHaveLength(90);
|
|
});
|
|
|
|
it('пишет дела человеческой фразой', () => {
|
|
expect(mountPane().text()).toContain('создал проект «Окна ЕКБ»');
|
|
});
|
|
|
|
it('честно говорит, когда дел не было', () => {
|
|
expect(mountPane({ items: [] }).text()).toContain('Ничего не менял');
|
|
});
|
|
|
|
it('просит следующую страницу по кнопке', async () => {
|
|
const wrapper = mountPane({ hasMore: true });
|
|
await wrapper.find('[data-testid="load-more"]').trigger('click');
|
|
expect(wrapper.emitted('load-more')).toHaveLength(1);
|
|
});
|
|
|
|
it('прячет кнопку, когда больше нечего грузить', () => {
|
|
expect(mountPane({ hasMore: false }).find('[data-testid="load-more"]').exists()).toBe(false);
|
|
});
|
|
});
|