first commit
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
import { signal } from '@angular/core';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AuthStore } from '../../../core/auth/auth-store';
|
||||
import { TeamStore } from '../../../core/team/team-store';
|
||||
import { TransactionsApi } from '../../../core/team/transactions-api';
|
||||
import { Cashbox } from './cashbox';
|
||||
|
||||
describe('Cashbox', () => {
|
||||
const team = {
|
||||
id: 5,
|
||||
name: 'Team A',
|
||||
alias: 'team-a',
|
||||
balance: 120,
|
||||
players: [
|
||||
{
|
||||
id: 1,
|
||||
firstName: 'Alex',
|
||||
lastName: 'Muster',
|
||||
balance: -12,
|
||||
active: true,
|
||||
teamRole: { id: 2, name: 'scnd_treasurer' },
|
||||
user: { id: 42, email: 'alex@example.com', firstName: 'Alex', lastName: 'Muster' },
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
firstName: 'Bea',
|
||||
lastName: 'Test',
|
||||
balance: 5,
|
||||
active: true,
|
||||
teamRole: { id: 1, name: 'player' },
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
firstName: 'Chris',
|
||||
lastName: 'Drittel',
|
||||
balance: 0,
|
||||
active: true,
|
||||
teamRole: { id: 1, name: 'player' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const activities = [
|
||||
{
|
||||
id: 9,
|
||||
date: '2026-07-31T10:00:00.000Z',
|
||||
amount: 12,
|
||||
type: 'fine',
|
||||
note: 'Training',
|
||||
playerName: 'Bea Test',
|
||||
isTeamWalletTransaction: false,
|
||||
},
|
||||
];
|
||||
|
||||
async function setup(roleId = 2, confirm = true) {
|
||||
const createPlayerTransactions = vi.fn(() => of([]));
|
||||
const createTeamWalletTransaction = vi.fn(() => of(activities[0]));
|
||||
const reverseTransaction = vi.fn(() => of(activities[0]));
|
||||
const loadTeamTransactions = vi.fn(() => of(activities));
|
||||
const refreshTeam = vi.fn();
|
||||
const dialog = {
|
||||
open: vi.fn(() => ({ afterClosed: () => of(confirm) })),
|
||||
};
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Cashbox],
|
||||
providers: [
|
||||
{
|
||||
provide: AuthStore,
|
||||
useValue: {
|
||||
currentUser: signal({
|
||||
id: 42,
|
||||
email: 'alex@example.com',
|
||||
firstName: 'Alex',
|
||||
lastName: 'Muster',
|
||||
role: { id: roleId === 99 ? 1 : 2 },
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: TeamStore,
|
||||
useValue: { team: signal(team), loading: signal(false), refreshTeam },
|
||||
},
|
||||
{
|
||||
provide: TransactionsApi,
|
||||
useValue: {
|
||||
loadTeamTransactions,
|
||||
createPlayerTransactions,
|
||||
createTeamWalletTransaction,
|
||||
reverseTransaction,
|
||||
},
|
||||
},
|
||||
{ provide: MatDialog, useValue: dialog },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
if (roleId === 1) {
|
||||
team.players[0].teamRole.id = 1;
|
||||
} else {
|
||||
team.players[0].teamRole.id = 2;
|
||||
}
|
||||
|
||||
const fixture = TestBed.createComponent(Cashbox);
|
||||
fixture.detectChanges();
|
||||
return {
|
||||
fixture,
|
||||
component: fixture.componentInstance,
|
||||
createPlayerTransactions,
|
||||
reverseTransaction,
|
||||
dialog,
|
||||
refreshTeam,
|
||||
};
|
||||
}
|
||||
|
||||
it('shows the activity feed and booking controls to a treasurer', async () => {
|
||||
const { fixture } = await setup();
|
||||
|
||||
expect(fixture.nativeElement.textContent).toContain('Bea Test');
|
||||
expect(fixture.nativeElement.textContent).toContain('-12,00');
|
||||
expect(fixture.nativeElement.querySelector('[data-testid="player-booking"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('submits cent-preserving split transactions for selected players', async () => {
|
||||
const { component, createPlayerTransactions, refreshTeam } = await setup();
|
||||
component['playerForm'].setValue({
|
||||
playerIds: [1, 2, 3],
|
||||
amount: 10,
|
||||
type: 11,
|
||||
note: 'Training',
|
||||
date: '2026-07-31',
|
||||
total: true,
|
||||
});
|
||||
|
||||
component['submitPlayerBooking']();
|
||||
|
||||
expect(createPlayerTransactions).toHaveBeenCalledWith([
|
||||
expect.objectContaining({ playerId: 1, amount: 3.34, type: 11 }),
|
||||
expect.objectContaining({ playerId: 2, amount: 3.33, type: 11 }),
|
||||
expect.objectContaining({ playerId: 3, amount: 3.33, type: 11 }),
|
||||
]);
|
||||
expect(refreshTeam).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('asks for confirmation before booking a high amount', async () => {
|
||||
const { component, createPlayerTransactions, dialog } = await setup(2, false);
|
||||
component['playerForm'].setValue({
|
||||
playerIds: [1],
|
||||
amount: 300,
|
||||
type: 11,
|
||||
note: '',
|
||||
date: '2026-07-31',
|
||||
total: false,
|
||||
});
|
||||
|
||||
component['submitPlayerBooking']();
|
||||
|
||||
expect(dialog.open).toHaveBeenCalled();
|
||||
expect(createPlayerTransactions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not show mutation controls to a regular member', async () => {
|
||||
const { fixture } = await setup(1);
|
||||
|
||||
expect(fixture.nativeElement.querySelector('[data-testid="player-booking"]')).toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('[data-testid="reverse-booking"]')).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user