| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- import { fakeAsync, TestBed, tick } from '@angular/core/testing';
- import { of, Subject } from 'rxjs';
- import { ApiService } from './api.service';
- import { LiveDataRefreshService, LiveVersions } from './live-data-refresh.service';
- import { SessionService } from './session.service';
- describe('LiveDataRefreshService', () => {
- let changes: Subject<{ source: 'local' | 'broadcast'; changedAt: string }>;
- let post: jasmine.Spy;
- let loggedIn: boolean;
- beforeEach(() => {
- changes = new Subject();
- post = jasmine.createSpy('post');
- loggedIn = true;
- TestBed.configureTestingModule({
- providers: [
- LiveDataRefreshService,
- { provide: ApiService, useValue: { post, dataChanges$: changes } },
- { provide: SessionService, useValue: { isLoggedIn: () => loggedIn } },
- ],
- });
- });
- it('refreshes full data only after a five-second version change', fakeAsync(() => {
- post.and.returnValues(
- of(envelope('learning=v1')),
- of(envelope('learning=v2')),
- );
- const refresh = jasmine.createSpy('refresh');
- const stop = TestBed.inject(LiveDataRefreshService).watch({
- scopes: ['learning'],
- studentId: () => 42,
- onRefresh: refresh,
- });
- expect(post).toHaveBeenCalledTimes(1);
- expect(refresh).not.toHaveBeenCalled();
- tick(5_000);
- expect(post).toHaveBeenCalledTimes(2);
- expect(refresh).toHaveBeenCalledOnceWith('version');
- stop();
- }));
- it('refreshes immediately after a local or another-tab write', () => {
- post.and.returnValue(of(envelope('review=v1')));
- const refresh = jasmine.createSpy('refresh');
- const stop = TestBed.inject(LiveDataRefreshService).watch({
- scopes: ['review'],
- studentId: () => 42,
- onRefresh: refresh,
- });
- changes.next({ source: 'local', changedAt: new Date().toISOString() });
- changes.next({ source: 'broadcast', changedAt: new Date().toISOString() });
- expect(refresh.calls.allArgs()).toEqual([['local-write'], ['broadcast']]);
- stop();
- });
- it('stops checking after logout', fakeAsync(() => {
- post.and.returnValue(of(envelope('learning=v1')));
- const stop = TestBed.inject(LiveDataRefreshService).watch({
- scopes: ['learning'],
- studentId: () => 42,
- onRefresh: () => undefined,
- });
- expect(post).toHaveBeenCalledTimes(1);
- loggedIn = false;
- tick(10_000);
- expect(post).toHaveBeenCalledTimes(1);
- stop();
- }));
- });
- function envelope(version: string): { retcode: number; result: LiveVersions } {
- return {
- retcode: 0,
- result: {
- version,
- scopeVersions: { learning: version, review: version },
- refreshedAt: '2026-09-25T00:00:00.000Z',
- syncStatus: { state: 'current', lagSeconds: 0, pending: 0 },
- },
- };
- }
|