Detail page now has a "Copy URL" button that copies the image's direct file URL to the clipboard. A toast service (BehaviorSubject-backed, auto-dismissing after 3s) confirms success or failure. ToastComponent is registered at the app root and available to all future features. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
|
|
import { Toast, ToastService } from './toast.service';
|
|
|
|
describe('ToastService', () => {
|
|
let service: ToastService;
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({});
|
|
service = TestBed.inject(ToastService);
|
|
});
|
|
|
|
it('show() emits a toast with correct message and type', (done) => {
|
|
service.current$.subscribe((toast) => {
|
|
if (toast) {
|
|
expect(toast.message).toBe('Hello!');
|
|
expect(toast.type).toBe('error');
|
|
done();
|
|
}
|
|
});
|
|
service.show('Hello!', 'error');
|
|
});
|
|
|
|
it('type defaults to success when not provided', (done) => {
|
|
service.current$.subscribe((toast) => {
|
|
if (toast) {
|
|
expect(toast.type).toBe('success');
|
|
done();
|
|
}
|
|
});
|
|
service.show('Default type');
|
|
});
|
|
|
|
it('current$ emits null after the duration elapses', fakeAsync(() => {
|
|
const emitted: (string | null)[] = [];
|
|
service.current$.subscribe((t: Toast | null) => emitted.push(t ? t.message : null));
|
|
service.show('Auto-dismiss', 'success', 500);
|
|
tick(500);
|
|
expect(emitted).toContain(null);
|
|
}));
|
|
|
|
it('calling show() again before timer fires replaces the active toast', fakeAsync(() => {
|
|
const messages: (string | null)[] = [];
|
|
service.current$.subscribe((t: Toast | null) => messages.push(t ? t.message : null));
|
|
service.show('First', 'success', 1000);
|
|
tick(200);
|
|
service.show('Second', 'success', 1000);
|
|
tick(0);
|
|
const nonNull = messages.filter((m) => m !== null);
|
|
expect(nonNull[nonNull.length - 1]).toBe('Second');
|
|
}));
|
|
});
|