|
@@ -1,4 +1,5 @@
|
|
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
|
|
|
+import { provideRouter } from '@angular/router';
|
|
|
import { AdminSessionService } from '../admin-session.service';
|
|
import { AdminSessionService } from '../admin-session.service';
|
|
|
import { OperationsService } from '../operations.service';
|
|
import { OperationsService } from '../operations.service';
|
|
|
import { AdminDashboardComponent } from './admin-dashboard.component';
|
|
import { AdminDashboardComponent } from './admin-dashboard.component';
|
|
@@ -13,7 +14,12 @@ describe('AdminDashboardComponent', () => {
|
|
|
sessions = jasmine.createSpyObj<AdminSessionService>('AdminSessionService', ['applyIdentity']);
|
|
sessions = jasmine.createSpyObj<AdminSessionService>('AdminSessionService', ['applyIdentity']);
|
|
|
operations.dashboard.and.resolveTo({
|
|
operations.dashboard.and.resolveTo({
|
|
|
identity: { objectId: 'admin-1', username: 'ops', displayName: '运营经理', roles: ['admin', 'ops-manager'], isSuperAdmin: false, operationsRole: 'ops-manager' },
|
|
identity: { objectId: 'admin-1', username: 'ops', displayName: '运营经理', roles: ['admin', 'ops-manager'], isSuperAdmin: false, operationsRole: 'ops-manager' },
|
|
|
- date: '2026-08-20', metrics: [], alerts: [], scheduleTrend: {
|
|
|
|
|
|
|
+ date: '2026-08-20', metrics: [
|
|
|
|
|
+ { key: 'members', label: '在学会员', value: 27, hint: '当前有正式学习任务', route: '/admin/members', tone: 'blue' },
|
|
|
|
|
+ { key: 'today', label: '今日课程', value: 37, hint: '今天计划进行的课程', route: '/admin/schedule', tone: 'amber' },
|
|
|
|
|
+ { key: 'coaches', label: '在岗陪练', value: 39, hint: '实时业务账号', route: '/admin/coaches', tone: 'green' },
|
|
|
|
|
+ { key: 'pay', label: '本月预估工资', value: 120, hint: '按有效上课记录估算', route: '/admin/payroll', tone: 'rose' }
|
|
|
|
|
+ ], alerts: [], scheduleTrend: {
|
|
|
period: 'week', periodLabel: '近 7 天', dateFrom: '2026-08-14', dateTo: '2026-08-20',
|
|
period: 'week', periodLabel: '近 7 天', dateFrom: '2026-08-14', dateTo: '2026-08-20',
|
|
|
points: Array.from({ length: 7 }, (_, index) => ({ key: `2026-08-${14 + index}`, label: `8月${14 + index}日`, shortLabel: `周${index}`, courseCount: index + 1, studentCount: index, completedCount: index, isToday: index === 6 })),
|
|
points: Array.from({ length: 7 }, (_, index) => ({ key: `2026-08-${14 + index}`, label: `8月${14 + index}日`, shortLabel: `周${index}`, courseCount: index + 1, studentCount: index, completedCount: index, isToday: index === 6 })),
|
|
|
todayCourseCount: 7, todayStudentCount: 6, totalCourseCount: 28, totalStudentCount: 12, maxValue: 7,
|
|
todayCourseCount: 7, todayStudentCount: 6, totalCourseCount: 28, totalStudentCount: 12, maxValue: 7,
|
|
@@ -27,6 +33,7 @@ describe('AdminDashboardComponent', () => {
|
|
|
refreshedAt: '2026-08-20T04:00:00.000Z', liveSourceAvailable: true, liveSourceMessage: ''
|
|
refreshedAt: '2026-08-20T04:00:00.000Z', liveSourceAvailable: true, liveSourceMessage: ''
|
|
|
});
|
|
});
|
|
|
await TestBed.configureTestingModule({ imports: [AdminDashboardComponent], providers: [
|
|
await TestBed.configureTestingModule({ imports: [AdminDashboardComponent], providers: [
|
|
|
|
|
+ provideRouter([]),
|
|
|
{ provide: OperationsService, useValue: operations },
|
|
{ provide: OperationsService, useValue: operations },
|
|
|
{ provide: AdminSessionService, useValue: sessions }
|
|
{ provide: AdminSessionService, useValue: sessions }
|
|
|
] }).compileComponents();
|
|
] }).compileComponents();
|
|
@@ -49,4 +56,17 @@ describe('AdminDashboardComponent', () => {
|
|
|
expect(fixture.componentInstance.trend()?.period).toBe('month');
|
|
expect(fixture.componentInstance.trend()?.period).toBe('month');
|
|
|
expect(fixture.componentInstance.chartLine('courseCount')).toContain(',');
|
|
expect(fixture.componentInstance.chartLine('courseCount')).toContain(',');
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ it('merges daily course data into the trend and keeps only coach and pay overview links', async () => {
|
|
|
|
|
+ fixture.detectChanges();
|
|
|
|
|
+ await fixture.whenStable();
|
|
|
|
|
+ fixture.detectChanges();
|
|
|
|
|
+ const element: HTMLElement = fixture.nativeElement;
|
|
|
|
|
+ expect(element.querySelector('.metric-grid')).toBeNull();
|
|
|
|
|
+ expect(element.querySelector('.trend-stat.coaches')?.textContent).toContain('39');
|
|
|
|
|
+ expect(element.querySelector('.trend-stat.pay')?.textContent).toContain('120');
|
|
|
|
|
+ expect(element.querySelector('.trend-stat.courses')?.textContent).toContain('7');
|
|
|
|
|
+ expect(element.querySelector('.trend-stat.students')?.textContent).toContain('6');
|
|
|
|
|
+ expect(element.querySelectorAll('.trend-stat')).toHaveSize(4);
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|