|
|
@@ -9,6 +9,7 @@ import { CourseCenterPageComponent } from '../features/course-center/course-cent
|
|
|
import { ApiService, ApiError } from './api.service';
|
|
|
import { SessionService } from './session.service';
|
|
|
import { PlatformService } from './platform.service';
|
|
|
+import { appointmentDate, beijingDate } from './appointment-time';
|
|
|
|
|
|
@Component({standalone:true,template:'课堂内容'}) class ClassroomStub {}
|
|
|
|
|
|
@@ -63,6 +64,56 @@ describe('appointment workflow screens',()=>{
|
|
|
(harness.routeNativeElement?.querySelector('.appointment-actions .primary-button') as HTMLButtonElement).click();
|
|
|
harness.fixture.detectChanges();expect(calls.filter(c=>c.action==='e_order_update_v2').length).toBe(1);expect(component.status()).toBe(10);
|
|
|
});
|
|
|
+ for (const time of ['00:01', '23:59']) {
|
|
|
+ it(`starts a same-day lesson scheduled at ${time} without new server capabilities`,async()=>{
|
|
|
+ order={...order,bxrq:beijingDate(),sdsd:time};delete order['allowedActions'];
|
|
|
+ const {harness,component}=await screen();
|
|
|
+ expect(component.can('start')).toBeTrue();expect(component.can('complete')).toBeFalse();
|
|
|
+ expect(harness.routeNativeElement?.textContent).toContain('可提前开始');
|
|
|
+ component.toggleUnit({NodeID:811});component.startOrContinue();await harness.fixture.whenStable();
|
|
|
+ expect(calls.filter(c=>c.action==='e_order_update_v2').length).toBe(1);
|
|
|
+ expect(TestBed.inject(Router).url).toContain('/pages/stu/stu_abc');
|
|
|
+ expect(student()).toEqual(jasmine.objectContaining({userId:20}));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ it('keeps all of today’s unfinished lessons out of the overdue filter and opens details immediately',async()=>{
|
|
|
+ order={...order,bxrq:beijingDate(),sdsd:'00:00'};
|
|
|
+ const {harness}=await screen('/pages/home/shop');
|
|
|
+ const center=harness.fixture.debugElement.query(By.directive(CourseCenterPageComponent)).componentInstance as CourseCenterPageComponent;
|
|
|
+ expect(center.statusText(order)).toBe('未开始');
|
|
|
+ expect(center.statusText({...order,bxrq:'2000-01-01'})).toBe('计划未完成');
|
|
|
+ expect(center.statusText({...order,dszt:10})).toBe('已开始');
|
|
|
+ center.open(order);await harness.fixture.whenStable();
|
|
|
+ expect(TestBed.inject(Router).url).toBe('/pages/shop/get_order?id=901');
|
|
|
+ expect(calls.some(c=>c.action==='user_get')).toBeFalse();
|
|
|
+ });
|
|
|
+ it('allows an already started legacy lesson to continue across midnight',async()=>{
|
|
|
+ order={...order,dszt:10,bxrq:'2000-01-01'};delete order['allowedActions'];
|
|
|
+ const {component}=await screen();expect(component.can('continue')).toBeTrue();expect(component.can('start')).toBeFalse();
|
|
|
+ });
|
|
|
+ for (const changes of [{bxrq:'2000-01-01'}, {bxrq:'2099-10-11'}, {pl:31}, {cancelled:true}, {GeneralID:902}]) {
|
|
|
+ it(`does not infer start permission for an ineligible legacy detail ${JSON.stringify(changes)}`,async()=>{
|
|
|
+ order={...order,bxrq:beijingDate(),...changes};delete order['allowedActions'];
|
|
|
+ const {component}=await screen();component.startOrContinue();
|
|
|
+ expect(component.can('start')).toBeFalse();expect(calls.some(c=>c.action==='e_order_update_v2')).toBeFalse();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ it('does not override an explicit server denial on today’s lesson',async()=>{
|
|
|
+ order={...order,bxrq:beijingDate(),allowedActions:[],blockedReason:'课时不足'};
|
|
|
+ const {component}=await screen();expect(component.can('start')).toBeFalse();
|
|
|
+ });
|
|
|
+ it('disables legacy start again when a background detail refresh fails',async()=>{
|
|
|
+ order={...order,bxrq:beijingDate()};delete order['allowedActions'];
|
|
|
+ const {component}=await screen();expect(component.can('start')).toBeTrue();
|
|
|
+ failDetail=true;component.load(true);expect(component.can('start')).toBeFalse();
|
|
|
+ });
|
|
|
+ it('uses Beijing midnight boundaries and accepts the legacy compact business date',()=>{
|
|
|
+ expect(beijingDate(Date.parse('2026-10-10T15:59:59Z'))).toBe('2026-10-10');
|
|
|
+ expect(beijingDate(Date.parse('2026-10-10T16:00:00Z'))).toBe('2026-10-11');
|
|
|
+ expect(beijingDate(Date.parse('2026-10-11T15:59:59Z'))).toBe('2026-10-11');
|
|
|
+ expect(beijingDate(Date.parse('2026-10-11T16:00:00Z'))).toBe('2026-10-12');
|
|
|
+ expect(appointmentDate({bxrq:'20261011'})).toBe('2026-10-11');
|
|
|
+ });
|
|
|
it('shows a persistent reason when vocabulary has not been selected, then enters the bound classroom',async()=>{
|
|
|
const {harness,component}=await screen();component.startOrContinue();harness.fixture.detectChanges();
|
|
|
expect(harness.routeNativeElement?.querySelector('[role="alert"]')?.textContent).toContain('选择');
|