mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-14 10:26:19 +01:00
[PM-14183] Show success toast on copy history value (#11911)
* Remove unnecessary copy icon * Fix styling of copy success toast - Use CopyClick directive instead of manually copying and showing the toast - Adjust tests --------- Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
parent
e8dac0cc12
commit
b23d62a280
@ -15,10 +15,10 @@
|
|||||||
bitIconButton="bwi-clone"
|
bitIconButton="bwi-clone"
|
||||||
[appA11yTitle]="'copyPassword' | i18n"
|
[appA11yTitle]="'copyPassword' | i18n"
|
||||||
appStopClick
|
appStopClick
|
||||||
(click)="copy(h.password)"
|
[appCopyClick]="h.password"
|
||||||
>
|
[valueLabel]="'password' | i18n"
|
||||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
showToast
|
||||||
</button>
|
></button>
|
||||||
</bit-item-action>
|
</bit-item-action>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</bit-item>
|
</bit-item>
|
||||||
|
@ -3,14 +3,13 @@ import { By } from "@angular/platform-browser";
|
|||||||
import { BehaviorSubject } from "rxjs";
|
import { BehaviorSubject } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { ColorPasswordModule, ItemModule, ToastService } from "@bitwarden/components";
|
import { ColorPasswordModule, ItemModule } from "@bitwarden/components";
|
||||||
import { ColorPasswordComponent } from "@bitwarden/components/src/color-password/color-password.component";
|
import { ColorPasswordComponent } from "@bitwarden/components/src/color-password/color-password.component";
|
||||||
|
|
||||||
import { PasswordHistoryViewComponent } from "./password-history-view.component";
|
import { PasswordHistoryViewComponent } from "./password-history-view.component";
|
||||||
@ -25,8 +24,6 @@ describe("PasswordHistoryViewComponent", () => {
|
|||||||
organizationId: "222-444-555",
|
organizationId: "222-444-555",
|
||||||
} as CipherView;
|
} as CipherView;
|
||||||
|
|
||||||
const copyToClipboard = jest.fn();
|
|
||||||
const showToast = jest.fn();
|
|
||||||
const activeAccount$ = new BehaviorSubject<{ id: string }>({ id: "666-444-444" });
|
const activeAccount$ = new BehaviorSubject<{ id: string }>({ id: "666-444-444" });
|
||||||
const mockCipherService = {
|
const mockCipherService = {
|
||||||
get: jest.fn().mockResolvedValue({ decrypt: jest.fn().mockResolvedValue(mockCipher) }),
|
get: jest.fn().mockResolvedValue({ decrypt: jest.fn().mockResolvedValue(mockCipher) }),
|
||||||
@ -36,17 +33,13 @@ describe("PasswordHistoryViewComponent", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockCipherService.get.mockClear();
|
mockCipherService.get.mockClear();
|
||||||
mockCipherService.getKeyForCipherKeyDecryption.mockClear();
|
mockCipherService.getKeyForCipherKeyDecryption.mockClear();
|
||||||
copyToClipboard.mockClear();
|
|
||||||
showToast.mockClear();
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ItemModule, ColorPasswordModule, JslibModule],
|
imports: [ItemModule, ColorPasswordModule, JslibModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: WINDOW, useValue: window },
|
|
||||||
{ provide: CipherService, useValue: mockCipherService },
|
{ provide: CipherService, useValue: mockCipherService },
|
||||||
{ provide: PlatformUtilsService, useValue: { copyToClipboard } },
|
{ provide: PlatformUtilsService },
|
||||||
{ provide: AccountService, useValue: { activeAccount$ } },
|
{ provide: AccountService, useValue: { activeAccount$ } },
|
||||||
{ provide: ToastService, useValue: { showToast } },
|
|
||||||
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
@ -80,18 +73,5 @@ describe("PasswordHistoryViewComponent", () => {
|
|||||||
"bad-password-2",
|
"bad-password-2",
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("copies a password", () => {
|
|
||||||
const copyButton = fixture.debugElement.query(By.css("button"));
|
|
||||||
|
|
||||||
copyButton.nativeElement.click();
|
|
||||||
|
|
||||||
expect(copyToClipboard).toHaveBeenCalledWith("bad-password-1", { window: window });
|
|
||||||
expect(showToast).toHaveBeenCalledWith({
|
|
||||||
message: "passwordCopied",
|
|
||||||
title: "",
|
|
||||||
variant: "info",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,21 +1,14 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { OnInit, Inject, Component, Input } from "@angular/core";
|
import { OnInit, Component, Input } from "@angular/core";
|
||||||
import { firstValueFrom, map } from "rxjs";
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
||||||
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { PasswordHistoryView } from "@bitwarden/common/vault/models/view/password-history.view";
|
import { PasswordHistoryView } from "@bitwarden/common/vault/models/view/password-history.view";
|
||||||
import {
|
import { ItemModule, ColorPasswordModule, IconButtonModule } from "@bitwarden/components";
|
||||||
ToastService,
|
|
||||||
ItemModule,
|
|
||||||
ColorPasswordModule,
|
|
||||||
IconButtonModule,
|
|
||||||
} from "@bitwarden/components";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "vault-password-history-view",
|
selector: "vault-password-history-view",
|
||||||
@ -33,29 +26,15 @@ export class PasswordHistoryViewComponent implements OnInit {
|
|||||||
history: PasswordHistoryView[] = [];
|
history: PasswordHistoryView[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(WINDOW) private win: Window,
|
|
||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected accountService: AccountService,
|
protected accountService: AccountService,
|
||||||
protected toastService: ToastService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
await this.init();
|
await this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copies a password to the clipboard. */
|
|
||||||
copy(password: string) {
|
|
||||||
const copyOptions = this.win != null ? { window: this.win } : undefined;
|
|
||||||
this.platformUtilsService.copyToClipboard(password, copyOptions);
|
|
||||||
this.toastService.showToast({
|
|
||||||
variant: "info",
|
|
||||||
title: "",
|
|
||||||
message: this.i18nService.t("passwordCopied"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve the password history for the given cipher */
|
/** Retrieve the password history for the given cipher */
|
||||||
protected async init() {
|
protected async init() {
|
||||||
const cipher = await this.cipherService.get(this.cipherId);
|
const cipher = await this.cipherService.get(this.cipherId);
|
||||||
|
Loading…
Reference in New Issue
Block a user