iachat/app/javascript/dashboard/composables/spec/useInboxSignatures.spec.js
Gabriel Jablonski 56c5609ca0
feat: add per-inbox signature management (#226)
* feat: add per-inbox signature management

- Introduced `InboxSignature` model to manage signatures specific to each inbox.
- Added API endpoints for fetching, creating, updating, and deleting inbox signatures.
- Updated UI components to support inbox-specific signatures, including overrides for signature position and separator.
- Implemented a new composable `useInboxSignatures` for managing inbox signatures in the frontend.
- Enhanced existing components to utilize inbox signatures, including the reply box and message signature settings.
- Added tests for the new inbox signatures functionality, ensuring proper behavior of the API and model validations.
- Updated translations for new UI elements related to inbox signatures.

* feat: implement inbox access validation and add related tests

* feat: enhance inbox signatures fetching and management logic
2026-02-26 19:53:03 -03:00

200 lines
5.6 KiB
JavaScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { useInboxSignatures } from '../useInboxSignatures';
const mockInboxSignaturesAPI = vi.hoisted(() => ({
getAll: vi.fn(),
get: vi.fn(),
upsert: vi.fn(),
delete: vi.fn(),
}));
vi.mock('dashboard/api/inboxSignatures', () => ({
default: mockInboxSignaturesAPI,
}));
vi.mock('dashboard/composables/store', () => ({
useStoreGetters: () => ({
getCurrentUser: {
value: {
message_signature: '<p>Global Signature</p>',
ui_settings: {
signature_position: 'bottom',
signature_separator: '--',
},
},
},
getCurrentAccountId: {
value: 1,
},
}),
}));
describe('useInboxSignatures', () => {
beforeEach(() => {
vi.clearAllMocks();
const { _resetForTesting } = useInboxSignatures();
_resetForTesting();
});
describe('fetchInboxSignatures', () => {
it('fetches and caches inbox signatures', async () => {
const mockData = [
{
inbox_id: 1,
message_signature: '<p>Inbox 1 Sig</p>',
signature_position: 'top',
signature_separator: 'blank',
},
{
inbox_id: 2,
message_signature: '<p>Inbox 2 Sig</p>',
signature_position: 'bottom',
signature_separator: '--',
},
];
mockInboxSignaturesAPI.getAll.mockResolvedValue({ data: mockData });
const { fetchInboxSignatures, inboxSignatures, hasFetched } =
useInboxSignatures();
await fetchInboxSignatures();
expect(mockInboxSignaturesAPI.getAll).toHaveBeenCalled();
expect(inboxSignatures.value[1].message_signature).toBe(
'<p>Inbox 1 Sig</p>'
);
expect(inboxSignatures.value[2].message_signature).toBe(
'<p>Inbox 2 Sig</p>'
);
expect(hasFetched.value).toBe(true);
});
});
describe('getSignatureForInbox', () => {
it('returns inbox-specific signature when available', async () => {
mockInboxSignaturesAPI.getAll.mockResolvedValue({
data: [
{
inbox_id: 1,
message_signature: '<p>Inbox 1 Sig</p>',
signature_position: 'top',
signature_separator: 'blank',
},
],
});
const { fetchInboxSignatures, getSignatureForInbox } =
useInboxSignatures();
await fetchInboxSignatures();
expect(getSignatureForInbox(1)).toBe('<p>Inbox 1 Sig</p>');
});
it('falls back to global signature when no inbox-specific override', async () => {
mockInboxSignaturesAPI.getAll.mockResolvedValue({ data: [] });
const { fetchInboxSignatures, getSignatureForInbox } =
useInboxSignatures();
await fetchInboxSignatures();
expect(getSignatureForInbox(999)).toBe('<p>Global Signature</p>');
});
});
describe('getSignatureSettingsForInbox', () => {
it('returns inbox-specific settings when available', async () => {
mockInboxSignaturesAPI.getAll.mockResolvedValue({
data: [
{
inbox_id: 1,
message_signature: '<p>Sig</p>',
signature_position: 'top',
signature_separator: 'blank',
},
],
});
const { fetchInboxSignatures, getSignatureSettingsForInbox } =
useInboxSignatures();
await fetchInboxSignatures();
const settings = getSignatureSettingsForInbox(1);
expect(settings.position).toBe('top');
expect(settings.separator).toBe('blank');
});
it('falls back to global user settings when no inbox-specific override', async () => {
mockInboxSignaturesAPI.getAll.mockResolvedValue({ data: [] });
const { fetchInboxSignatures, getSignatureSettingsForInbox } =
useInboxSignatures();
await fetchInboxSignatures();
const settings = getSignatureSettingsForInbox(999);
expect(settings.position).toBe('bottom');
expect(settings.separator).toBe('--');
});
});
describe('upsertInboxSignature', () => {
it('updates the cache after upserting', async () => {
mockInboxSignaturesAPI.getAll.mockResolvedValue({ data: [] });
mockInboxSignaturesAPI.upsert.mockResolvedValue({
data: {
inbox_id: 3,
message_signature: '<p>New Sig</p>',
signature_position: 'top',
signature_separator: 'blank',
},
});
const {
fetchInboxSignatures,
upsertInboxSignature,
getSignatureForInbox,
} = useInboxSignatures();
await fetchInboxSignatures();
await upsertInboxSignature(3, {
message_signature: '<p>New Sig</p>',
signature_position: 'top',
signature_separator: 'blank',
});
expect(getSignatureForInbox(3)).toBe('<p>New Sig</p>');
});
});
describe('deleteInboxSignature', () => {
it('removes from cache after deleting', async () => {
mockInboxSignaturesAPI.getAll.mockResolvedValue({
data: [
{
inbox_id: 1,
message_signature: '<p>Sig</p>',
signature_position: 'top',
signature_separator: 'blank',
},
],
});
mockInboxSignaturesAPI.delete.mockResolvedValue({});
const {
fetchInboxSignatures,
deleteInboxSignature,
hasInboxSignature,
getSignatureForInbox,
} = useInboxSignatures();
await fetchInboxSignatures();
expect(hasInboxSignature(1)).toBe(true);
await deleteInboxSignature(1);
expect(hasInboxSignature(1)).toBe(false);
// Falls back to global
expect(getSignatureForInbox(1)).toBe('<p>Global Signature</p>');
});
});
});