mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 15:53:27 +00:00
[PM-22179] Redirect user to /setup-extension (#15375)
* add end user feature flag * add initial setup extension component and route * redirect users from registration completion to the setup extension page * add `hideIcon` to anon layout for web - matches implementation on the browser. * integrate with anon layout for extension wrapper * add initial loading state * conditionally redirect the user upon initialization * redirect the user to the vault if the extension is installed * add initial copy for setup-extension page * add confirmation dialog for skipping the extension installation * add success state for setup extension page * only show loggedin toast when end user activation is not enabled. * add image alt * lower threshold for polling extension * close the dialog when linking to the vault * update party colors * use the platform specific registration service to to only forward the web registrations to `/setup-extension` * call `super` rather than `/vault` directly, it could change in the future
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { Router, RouterModule } from "@angular/router";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { DeviceType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
import { WebBrowserInteractionService } from "../../services/web-browser-interaction.service";
|
||||
|
||||
import { SetupExtensionComponent } from "./setup-extension.component";
|
||||
|
||||
describe("SetupExtensionComponent", () => {
|
||||
let fixture: ComponentFixture<SetupExtensionComponent>;
|
||||
let component: SetupExtensionComponent;
|
||||
|
||||
const getFeatureFlag = jest.fn().mockResolvedValue(false);
|
||||
const navigate = jest.fn().mockResolvedValue(true);
|
||||
const openExtension = jest.fn().mockResolvedValue(true);
|
||||
const extensionInstalled$ = new BehaviorSubject<boolean | null>(null);
|
||||
|
||||
beforeEach(async () => {
|
||||
navigate.mockClear();
|
||||
openExtension.mockClear();
|
||||
getFeatureFlag.mockClear().mockResolvedValue(true);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [SetupExtensionComponent, RouterModule.forRoot([])],
|
||||
providers: [
|
||||
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
||||
{ provide: ConfigService, useValue: { getFeatureFlag } },
|
||||
{ provide: WebBrowserInteractionService, useValue: { extensionInstalled$, openExtension } },
|
||||
{ provide: PlatformUtilsService, useValue: { getDevice: () => DeviceType.UnknownBrowser } },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(SetupExtensionComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
const router = TestBed.inject(Router);
|
||||
router.navigate = navigate;
|
||||
});
|
||||
|
||||
it("initially shows the loading spinner", () => {
|
||||
const spinner = fixture.debugElement.query(By.css("i"));
|
||||
|
||||
expect(spinner.nativeElement.title).toBe("loading");
|
||||
});
|
||||
|
||||
it("sets webStoreUrl", () => {
|
||||
expect(component["webStoreUrl"]).toBe("https://bitwarden.com/download/#downloads-web-browser");
|
||||
});
|
||||
|
||||
describe("initialization", () => {
|
||||
it("redirects to the vault if the feature flag is disabled", async () => {
|
||||
Utils.isMobileBrowser = false;
|
||||
getFeatureFlag.mockResolvedValue(false);
|
||||
navigate.mockClear();
|
||||
|
||||
await component.ngOnInit();
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith(["/vault"]);
|
||||
});
|
||||
|
||||
it("redirects to the vault if the user is on a mobile browser", async () => {
|
||||
Utils.isMobileBrowser = true;
|
||||
getFeatureFlag.mockResolvedValue(true);
|
||||
navigate.mockClear();
|
||||
|
||||
await component.ngOnInit();
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith(["/vault"]);
|
||||
});
|
||||
|
||||
it("does not redirect the user", async () => {
|
||||
Utils.isMobileBrowser = false;
|
||||
getFeatureFlag.mockResolvedValue(true);
|
||||
navigate.mockClear();
|
||||
|
||||
await component.ngOnInit();
|
||||
|
||||
expect(getFeatureFlag).toHaveBeenCalledWith(FeatureFlag.PM19315EndUserActivationMvp);
|
||||
expect(navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("extensionInstalled$", () => {
|
||||
it("redirects the user to the vault when the first emitted value is true", () => {
|
||||
extensionInstalled$.next(true);
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith(["/vault"]);
|
||||
});
|
||||
|
||||
describe("success state", () => {
|
||||
beforeEach(() => {
|
||||
// avoid initial redirect
|
||||
extensionInstalled$.next(false);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
extensionInstalled$.next(true);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("shows link to the vault", () => {
|
||||
const successLink = fixture.debugElement.query(By.css("a"));
|
||||
|
||||
expect(successLink.nativeElement.href).toContain("/vault");
|
||||
});
|
||||
|
||||
it("shows open extension button", () => {
|
||||
const openExtensionButton = fixture.debugElement.query(By.css("button"));
|
||||
|
||||
openExtensionButton.triggerEventHandler("click");
|
||||
|
||||
expect(openExtension).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user