mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 22:33:35 +00:00
[PM-26653] - fix uri match strategy logic (#17142)
* fix uri match strategy logic * fix variable name * update logic and specs * add test case
This commit is contained in:
@@ -181,10 +181,21 @@ describe("ItemMoreOptionsComponent", () => {
|
|||||||
expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled();
|
expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not show the exact match dialog when the default match strategy is Exact and autofill confirmation is not to be shown", async () => {
|
||||||
|
// autofill confirmation dialog is not shown when either the feature flag is disabled or search text is not present
|
||||||
|
uriMatchStrategy$.next(UriMatchStrategy.Exact);
|
||||||
|
autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com/path" });
|
||||||
|
await component.doAutofill();
|
||||||
|
|
||||||
|
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
describe("autofill confirmation dialog", () => {
|
describe("autofill confirmation dialog", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
// autofill confirmation dialog is shown when feature flag is enabled and search text is present
|
||||||
featureFlag$.next(true);
|
featureFlag$.next(true);
|
||||||
hasSearchText$.next(true);
|
hasSearchText$.next(true);
|
||||||
|
uriMatchStrategy$.next(UriMatchStrategy.Domain);
|
||||||
passwordRepromptService.passwordRepromptCheck.mockResolvedValue(true);
|
passwordRepromptService.passwordRepromptCheck.mockResolvedValue(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -243,47 +254,122 @@ describe("ItemMoreOptionsComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("URI match strategy handling", () => {
|
describe("URI match strategy handling", () => {
|
||||||
it("shows the exact match dialog when the uri match strategy is Exact", async () => {
|
describe("when the default URI match strategy is Exact", () => {
|
||||||
uriMatchStrategy$.next(UriMatchStrategy.Exact);
|
beforeEach(() => {
|
||||||
autofillSvc.currentAutofillTab$.next({ url: "https://no-match.example.com" });
|
uriMatchStrategy$.next(UriMatchStrategy.Exact);
|
||||||
|
});
|
||||||
|
|
||||||
await component.doAutofill();
|
it("shows the exact match dialog and not the password dialog", async () => {
|
||||||
|
autofillSvc.currentAutofillTab$.next({ url: "https://no-match.example.com" });
|
||||||
|
|
||||||
expect(dialogService.openSimpleDialog).toHaveBeenCalledTimes(1);
|
await component.doAutofill();
|
||||||
expect(dialogService.openSimpleDialog).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
expect(dialogService.openSimpleDialog).toHaveBeenCalledTimes(1);
|
||||||
title: expect.objectContaining({ key: "cannotAutofill" }),
|
expect(dialogService.openSimpleDialog).toHaveBeenCalledWith(
|
||||||
content: expect.objectContaining({ key: "cannotAutofillExactMatch" }),
|
expect.objectContaining({
|
||||||
type: "info",
|
title: expect.objectContaining({ key: "cannotAutofill" }),
|
||||||
}),
|
content: expect.objectContaining({ key: "cannotAutofillExactMatch" }),
|
||||||
);
|
type: "info",
|
||||||
expect(autofillSvc.doAutofill).not.toHaveBeenCalled();
|
}),
|
||||||
expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled();
|
);
|
||||||
|
expect(autofillSvc.doAutofill).not.toHaveBeenCalled();
|
||||||
|
expect(passwordRepromptService.passwordRepromptCheck).not.toHaveBeenCalled();
|
||||||
|
expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows the exact match dialog and not the password reprompt dialog when the uri match strategy is Exact and the item has master password reprompt enabled", async () => {
|
describe("when the default URI match strategy is not Exact", () => {
|
||||||
uriMatchStrategy$.next(UriMatchStrategy.Exact);
|
beforeEach(() => {
|
||||||
|
mockConfirmDialogResult(AutofillConfirmationDialogResult.Canceled);
|
||||||
|
uriMatchStrategy$.next(UriMatchStrategy.Domain);
|
||||||
|
});
|
||||||
|
it("does not show the exact match dialog", async () => {
|
||||||
|
cipherService.getFullCipherView.mockImplementation(async (c) => ({
|
||||||
|
...baseCipher,
|
||||||
|
...c,
|
||||||
|
login: {
|
||||||
|
...baseCipher.login,
|
||||||
|
uris: [
|
||||||
|
{ uri: "https://one.example.com", match: UriMatchStrategy.Exact },
|
||||||
|
{ uri: "https://page.example.com", match: UriMatchStrategy.Domain },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" });
|
||||||
|
|
||||||
|
await component.doAutofill();
|
||||||
|
|
||||||
|
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the exact match dialog when the cipher has a single uri with a match strategy of Exact", async () => {
|
||||||
|
cipherService.getFullCipherView.mockImplementation(async (c) => ({
|
||||||
|
...baseCipher,
|
||||||
|
...c,
|
||||||
|
login: {
|
||||||
|
...baseCipher.login,
|
||||||
|
uris: [{ uri: "https://one.example.com", match: UriMatchStrategy.Exact }],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
autofillSvc.currentAutofillTab$.next({ url: "https://no-match.example.com" });
|
||||||
|
|
||||||
|
await component.doAutofill();
|
||||||
|
|
||||||
|
expect(dialogService.openSimpleDialog).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
title: expect.objectContaining({ key: "cannotAutofill" }),
|
||||||
|
content: expect.objectContaining({ key: "cannotAutofillExactMatch" }),
|
||||||
|
type: "info",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(autofillSvc.doAutofill).not.toHaveBeenCalled();
|
||||||
|
expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not show the exact match dialog when the cipher has no uris", async () => {
|
||||||
|
mockConfirmDialogResult(AutofillConfirmationDialogResult.Canceled);
|
||||||
|
cipherService.getFullCipherView.mockImplementation(async (c) => ({
|
||||||
|
...baseCipher,
|
||||||
|
...c,
|
||||||
|
login: {
|
||||||
|
...baseCipher.login,
|
||||||
|
uris: [],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
autofillSvc.currentAutofillTab$.next({ url: "https://no-match.example.com" });
|
autofillSvc.currentAutofillTab$.next({ url: "https://no-match.example.com" });
|
||||||
|
|
||||||
await component.doAutofill();
|
await component.doAutofill();
|
||||||
|
|
||||||
expect(dialogService.openSimpleDialog).toHaveBeenCalledTimes(1);
|
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||||
expect(dialogService.openSimpleDialog).toHaveBeenCalledWith(
|
});
|
||||||
expect.objectContaining({
|
|
||||||
title: expect.objectContaining({ key: "cannotAutofill" }),
|
it("does not show the exact match dialog when the cipher has a uri with a match strategy of Exact and a uri with a match strategy of Domain", async () => {
|
||||||
content: expect.objectContaining({ key: "cannotAutofillExactMatch" }),
|
mockConfirmDialogResult(AutofillConfirmationDialogResult.Canceled);
|
||||||
type: "info",
|
cipherService.getFullCipherView.mockImplementation(async (c) => ({
|
||||||
}),
|
...baseCipher,
|
||||||
);
|
...c,
|
||||||
expect(autofillSvc.doAutofill).not.toHaveBeenCalled();
|
login: {
|
||||||
expect(passwordRepromptService.passwordRepromptCheck).not.toHaveBeenCalled();
|
...baseCipher.login,
|
||||||
expect(autofillSvc.doAutofillAndSave).not.toHaveBeenCalled();
|
uris: [
|
||||||
|
{ uri: "https://one.example.com", match: UriMatchStrategy.Exact },
|
||||||
|
{ uri: "https://page.example.com", match: UriMatchStrategy.Domain },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
autofillSvc.currentAutofillTab$.next({ url: "https://page.example.com" });
|
||||||
|
|
||||||
|
await component.doAutofill();
|
||||||
|
|
||||||
|
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("hides the 'Fill and Save' button when showAutofillConfirmation$ is true", async () => {
|
it("hides the 'Fill and Save' button when showAutofillConfirmation$ is true", async () => {
|
||||||
// Enable both feature flag and search text → makes showAutofillConfirmation$ true
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
|
|||||||
@@ -202,8 +202,17 @@ export class ItemMoreOptionsComponent {
|
|||||||
async doAutofill() {
|
async doAutofill() {
|
||||||
const cipher = await this.cipherService.getFullCipherView(this.cipher);
|
const cipher = await this.cipherService.getFullCipherView(this.cipher);
|
||||||
|
|
||||||
|
const uris = cipher.login?.uris ?? [];
|
||||||
|
const cipherHasAllExactMatchLoginUris =
|
||||||
|
uris.length > 0 && uris.every((u) => u.uri && u.match === UriMatchStrategy.Exact);
|
||||||
|
|
||||||
|
const showAutofillConfirmation = await firstValueFrom(this.showAutofillConfirmation$);
|
||||||
const uriMatchStrategy = await firstValueFrom(this.uriMatchStrategy$);
|
const uriMatchStrategy = await firstValueFrom(this.uriMatchStrategy$);
|
||||||
if (uriMatchStrategy === UriMatchStrategy.Exact) {
|
|
||||||
|
if (
|
||||||
|
showAutofillConfirmation &&
|
||||||
|
(cipherHasAllExactMatchLoginUris || uriMatchStrategy === UriMatchStrategy.Exact)
|
||||||
|
) {
|
||||||
await this.dialogService.openSimpleDialog({
|
await this.dialogService.openSimpleDialog({
|
||||||
title: { key: "cannotAutofill" },
|
title: { key: "cannotAutofill" },
|
||||||
content: { key: "cannotAutofillExactMatch" },
|
content: { key: "cannotAutofillExactMatch" },
|
||||||
@@ -218,8 +227,6 @@ export class ItemMoreOptionsComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const showAutofillConfirmation = await firstValueFrom(this.showAutofillConfirmation$);
|
|
||||||
|
|
||||||
if (!showAutofillConfirmation) {
|
if (!showAutofillConfirmation) {
|
||||||
await this.vaultPopupAutofillService.doAutofill(cipher, true, true);
|
await this.vaultPopupAutofillService.doAutofill(cipher, true, true);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user