mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-25 12:15:18 +01:00
[PM-10424][PM-10425] Extension Refresh - Copy success toast (#10353)
* add option to pass toast variant into copy-click directive * refactor copy toast to use success variant * add tests for copy-click directive * swap `success` to be the default toast variant
This commit is contained in:
parent
0738495dee
commit
ffc9022f54
90
libs/angular/src/directives/copy-click.directive.spec.ts
Normal file
90
libs/angular/src/directives/copy-click.directive.spec.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { Component, ElementRef, ViewChild } from "@angular/core";
|
||||||
|
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||||
|
|
||||||
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
import { ToastService } from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { CopyClickDirective } from "./copy-click.directive";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<button appCopyClick="no toast shown" #noToast></button>
|
||||||
|
<button appCopyClick="info toast shown" showToast="info" #infoToast></button>
|
||||||
|
<button appCopyClick="success toast shown" showToast #successToast></button>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
class TestCopyClickComponent {
|
||||||
|
@ViewChild("noToast") noToastButton: ElementRef<HTMLButtonElement>;
|
||||||
|
@ViewChild("infoToast") infoToastButton: ElementRef<HTMLButtonElement>;
|
||||||
|
@ViewChild("successToast") successToastButton: ElementRef<HTMLButtonElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("CopyClickDirective", () => {
|
||||||
|
let fixture: ComponentFixture<TestCopyClickComponent>;
|
||||||
|
const copyToClipboard = jest.fn();
|
||||||
|
const showToast = jest.fn();
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
copyToClipboard.mockClear();
|
||||||
|
showToast.mockClear();
|
||||||
|
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [CopyClickDirective, TestCopyClickComponent],
|
||||||
|
providers: [
|
||||||
|
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
||||||
|
{ provide: PlatformUtilsService, useValue: { copyToClipboard } },
|
||||||
|
{ provide: ToastService, useValue: { showToast } },
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TestCopyClickComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("copies the the value for all variants of toasts ", () => {
|
||||||
|
const noToastButton = fixture.componentInstance.noToastButton.nativeElement;
|
||||||
|
|
||||||
|
noToastButton.click();
|
||||||
|
expect(copyToClipboard).toHaveBeenCalledWith("no toast shown");
|
||||||
|
|
||||||
|
const infoToastButton = fixture.componentInstance.infoToastButton.nativeElement;
|
||||||
|
|
||||||
|
infoToastButton.click();
|
||||||
|
expect(copyToClipboard).toHaveBeenCalledWith("info toast shown");
|
||||||
|
|
||||||
|
const successToastButton = fixture.componentInstance.successToastButton.nativeElement;
|
||||||
|
|
||||||
|
successToastButton.click();
|
||||||
|
expect(copyToClipboard).toHaveBeenCalledWith("success toast shown");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not show a toast when showToast is not present", () => {
|
||||||
|
const noToastButton = fixture.componentInstance.noToastButton.nativeElement;
|
||||||
|
|
||||||
|
noToastButton.click();
|
||||||
|
expect(showToast).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows a success toast when showToast is present", () => {
|
||||||
|
const successToastButton = fixture.componentInstance.successToastButton.nativeElement;
|
||||||
|
|
||||||
|
successToastButton.click();
|
||||||
|
expect(showToast).toHaveBeenCalledWith({
|
||||||
|
message: "copySuccessful",
|
||||||
|
title: null,
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the toast variant when set with showToast", () => {
|
||||||
|
const infoToastButton = fixture.componentInstance.infoToastButton.nativeElement;
|
||||||
|
|
||||||
|
infoToastButton.click();
|
||||||
|
expect(showToast).toHaveBeenCalledWith({
|
||||||
|
message: "copySuccessful",
|
||||||
|
title: null,
|
||||||
|
variant: "info",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,14 +1,17 @@
|
|||||||
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
|
||||||
import { Directive, HostListener, Input } from "@angular/core";
|
import { Directive, HostListener, Input } from "@angular/core";
|
||||||
|
|
||||||
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 { ToastService } from "@bitwarden/components";
|
import { ToastService } from "@bitwarden/components";
|
||||||
|
import { ToastVariant } from "@bitwarden/components/src/toast/toast.component";
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: "[appCopyClick]",
|
selector: "[appCopyClick]",
|
||||||
})
|
})
|
||||||
export class CopyClickDirective {
|
export class CopyClickDirective {
|
||||||
|
private _showToast = false;
|
||||||
|
private toastVariant: ToastVariant = "success";
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
@ -16,14 +19,36 @@ export class CopyClickDirective {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Input("appCopyClick") valueToCopy = "";
|
@Input("appCopyClick") valueToCopy = "";
|
||||||
@Input({ transform: coerceBooleanProperty }) showToast?: boolean;
|
|
||||||
|
/**
|
||||||
|
* When set without a value, a success toast will be shown when the value is copied
|
||||||
|
* @example
|
||||||
|
* ```html
|
||||||
|
* <app-component [appCopyClick]="value to copy" showToast/></app-component>
|
||||||
|
* ```
|
||||||
|
* When set with a value, a toast with the specified variant will be shown when the value is copied
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```html
|
||||||
|
* <app-component [appCopyClick]="value to copy" showToast="info"/></app-component>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@Input() set showToast(value: ToastVariant | "") {
|
||||||
|
// When the `showToast` is set without a value, an empty string will be passed
|
||||||
|
if (value === "") {
|
||||||
|
this._showToast = true;
|
||||||
|
} else {
|
||||||
|
this._showToast = true;
|
||||||
|
this.toastVariant = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@HostListener("click") onClick() {
|
@HostListener("click") onClick() {
|
||||||
this.platformUtilsService.copyToClipboard(this.valueToCopy);
|
this.platformUtilsService.copyToClipboard(this.valueToCopy);
|
||||||
|
|
||||||
if (this.showToast) {
|
if (this._showToast) {
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
variant: "info",
|
variant: this.toastVariant,
|
||||||
title: null,
|
title: null,
|
||||||
message: this.i18nService.t("copySuccessful"),
|
message: this.i18nService.t("copySuccessful"),
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user