mirror of https://github.com/ghostfolio/ghostfolio
1 changed files with 0 additions and 170 deletions
@ -1,170 +0,0 @@ |
|||||
import { Clipboard } from '@angular/cdk/clipboard'; |
|
||||
import { Component, Input } from '@angular/core'; |
|
||||
import { |
|
||||
ComponentFixture, |
|
||||
TestBed, |
|
||||
fakeAsync, |
|
||||
flush, |
|
||||
tick |
|
||||
} from '@angular/core/testing'; |
|
||||
import '@angular/localize/init'; |
|
||||
import { MatSnackBar } from '@angular/material/snack-bar'; |
|
||||
import { By } from '@angular/platform-browser'; |
|
||||
|
|
||||
import type { GfValueComponent as GfValueComponentType } from './value.component'; |
|
||||
|
|
||||
@Component({ |
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
|
||||
selector: 'ion-icon', |
|
||||
standalone: true, |
|
||||
template: '' |
|
||||
}) |
|
||||
class MockIonIcon { |
|
||||
@Input() name = ''; |
|
||||
} |
|
||||
|
|
||||
jest.mock('@ionic/angular/standalone', () => ({ IonIcon: MockIonIcon })); |
|
||||
|
|
||||
const { GfValueComponent } = |
|
||||
require('./value.component') as typeof import('./value.component'); |
|
||||
|
|
||||
describe('GfValueComponent', () => { |
|
||||
let clipboard: { copy: jest.Mock }; |
|
||||
let fixture: ComponentFixture<GfValueComponentType>; |
|
||||
let snackBar: { dismiss: jest.Mock; open: jest.Mock }; |
|
||||
|
|
||||
const getCopyButton = () => |
|
||||
fixture.nativeElement.querySelector( |
|
||||
'button[aria-label]' |
|
||||
) as HTMLButtonElement; |
|
||||
|
|
||||
const getCopyIcon = () => |
|
||||
fixture.debugElement.query(By.directive(MockIonIcon)) |
|
||||
.componentInstance as MockIonIcon; |
|
||||
|
|
||||
beforeEach(async () => { |
|
||||
clipboard = { copy: jest.fn().mockReturnValue(true) }; |
|
||||
snackBar = { dismiss: jest.fn(), open: jest.fn() }; |
|
||||
|
|
||||
await TestBed.configureTestingModule({ |
|
||||
imports: [GfValueComponent], |
|
||||
providers: [ |
|
||||
{ provide: Clipboard, useValue: clipboard }, |
|
||||
{ provide: MatSnackBar, useValue: snackBar } |
|
||||
] |
|
||||
}).compileComponents(); |
|
||||
|
|
||||
fixture = TestBed.createComponent(GfValueComponent); |
|
||||
fixture.componentRef.setInput('enableCopyToClipboardButton', true); |
|
||||
fixture.componentRef.setInput('locale', 'en-US'); |
|
||||
fixture.componentRef.setInput('value', 42); |
|
||||
fixture.detectChanges(); |
|
||||
}); |
|
||||
|
|
||||
it('shows confirmation immediately after copying', () => { |
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(clipboard.copy).toHaveBeenCalledWith('42'); |
|
||||
expect(snackBar.open).toHaveBeenCalledTimes(1); |
|
||||
expect(snackBar.open).toHaveBeenCalledWith( |
|
||||
expect.any(String), |
|
||||
undefined, |
|
||||
expect.objectContaining({ politeness: 'polite' }) |
|
||||
); |
|
||||
expect(getCopyButton().title).toBe('Copied!'); |
|
||||
expect(getCopyIcon().name).toBe('checkmark-outline'); |
|
||||
}); |
|
||||
|
|
||||
it('does not show confirmation when copying fails', () => { |
|
||||
clipboard.copy.mockReturnValue(false); |
|
||||
|
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(getCopyButton().title).toBe('Copy to clipboard'); |
|
||||
expect(getCopyIcon().name).toBe('copy-outline'); |
|
||||
expect(snackBar.dismiss).toHaveBeenCalledTimes(1); |
|
||||
expect(snackBar.open).not.toHaveBeenCalled(); |
|
||||
}); |
|
||||
|
|
||||
it('clears active confirmation when a repeated copy fails', fakeAsync(() => { |
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
clipboard.copy.mockReturnValue(false); |
|
||||
|
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(clipboard.copy).toHaveBeenCalledTimes(2); |
|
||||
expect(snackBar.dismiss).toHaveBeenCalledTimes(1); |
|
||||
expect(snackBar.open).toHaveBeenCalledTimes(1); |
|
||||
expect(getCopyButton().title).toBe('Copy to clipboard'); |
|
||||
expect(getCopyIcon().name).toBe('copy-outline'); |
|
||||
|
|
||||
tick(2000); |
|
||||
|
|
||||
expect(getCopyButton().title).toBe('Copy to clipboard'); |
|
||||
expect(getCopyIcon().name).toBe('copy-outline'); |
|
||||
})); |
|
||||
|
|
||||
it('keeps the copy action accessible during confirmation', () => { |
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(getCopyButton().getAttribute('aria-label')).toBe( |
|
||||
'Copy to clipboard' |
|
||||
); |
|
||||
expect(getCopyButton().disabled).toBe(false); |
|
||||
expect(snackBar.open).toHaveBeenCalledTimes(1); |
|
||||
}); |
|
||||
|
|
||||
it('restores the copy affordance after two seconds', fakeAsync(() => { |
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
tick(1999); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(getCopyButton().title).toBe('Copied!'); |
|
||||
expect(getCopyIcon().name).toBe('checkmark-outline'); |
|
||||
|
|
||||
tick(1); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(getCopyButton().title).toBe('Copy to clipboard'); |
|
||||
expect(getCopyIcon().name).toBe('copy-outline'); |
|
||||
})); |
|
||||
|
|
||||
it('restarts the confirmation timer when copied again', fakeAsync(() => { |
|
||||
getCopyButton().click(); |
|
||||
tick(1999); |
|
||||
|
|
||||
getCopyButton().click(); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(clipboard.copy).toHaveBeenCalledTimes(2); |
|
||||
expect(snackBar.open).toHaveBeenCalledTimes(2); |
|
||||
|
|
||||
tick(1); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(getCopyButton().title).toBe('Copied!'); |
|
||||
expect(getCopyIcon().name).toBe('checkmark-outline'); |
|
||||
|
|
||||
tick(1999); |
|
||||
fixture.detectChanges(); |
|
||||
|
|
||||
expect(getCopyButton().title).toBe('Copy to clipboard'); |
|
||||
expect(getCopyIcon().name).toBe('copy-outline'); |
|
||||
})); |
|
||||
|
|
||||
it('cancels the pending confirmation timer when destroyed', fakeAsync(() => { |
|
||||
getCopyButton().click(); |
|
||||
|
|
||||
fixture.destroy(); |
|
||||
|
|
||||
expect(flush()).toBe(0); |
|
||||
})); |
|
||||
}); |
|
||||
Loading…
Reference in new issue