mirror of
https://github.com/bitwarden/browser
synced 2026-02-19 10:54:00 +00:00
Merge branch 'main' into PM-20040-all-tasks-complete-banner
This commit is contained in:
21
.github/workflows/test-browser-interactions.yml
vendored
21
.github/workflows/test-browser-interactions.yml
vendored
@@ -1,4 +1,5 @@
|
||||
name: Autofill BIT checks
|
||||
run-name: Autofill BIT checks on ${{ github.event.workflow_run.head_branch }} build
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -11,10 +12,23 @@ jobs:
|
||||
name: Check files
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
actions: read
|
||||
actions: write
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check for job requirements
|
||||
if: ${{ !(github.event.workflow_run.pull_requests && github.event.workflow_run.pull_requests.length > 0 && github.event.workflow_run.head_branch) }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh run cancel ${{ github.run_id }}
|
||||
gh run watch ${{ github.run_id }}
|
||||
|
||||
- name: Log in to Azure
|
||||
uses: bitwarden/gh-actions/azure-login@main
|
||||
with:
|
||||
@@ -42,11 +56,6 @@ jobs:
|
||||
repositories: browser-interactions-testing
|
||||
permission-actions: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
|
||||
@@ -1757,6 +1757,54 @@ describe("CollectAutofillContentService", () => {
|
||||
|
||||
expect(parsedText).toEqual("Hello! This is a test string.");
|
||||
});
|
||||
|
||||
it("preserves extended Latin letters like Š and ć", () => {
|
||||
const text = "Šifra ćevapčići korisnika";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("Šifra ćevapčići korisnika");
|
||||
});
|
||||
|
||||
it("removes zero-width and control characters", () => {
|
||||
const text = "Hello\u200B\u200C\u200D\u2060World\x00\x1F!";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("Hello World !");
|
||||
});
|
||||
|
||||
it("removes leading and trailing whitespace", () => {
|
||||
const text = " padded text with spaces ";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("padded text with spaces");
|
||||
});
|
||||
|
||||
it("replaces multiple whitespaces (tabs, newlines, spaces) with one space", () => {
|
||||
const text = "one\t\ntwo \n three\t\tfour";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("one two three four");
|
||||
});
|
||||
|
||||
it("preserves emoji and symbols", () => {
|
||||
const text = "Text with emoji 🐍🚀 and ©®✓ symbols";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("Text with emoji 🐍🚀 and ©®✓ symbols");
|
||||
});
|
||||
|
||||
it("handles RTL and LTR marks", () => {
|
||||
const text = "abc\u200F\u202Edеf";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("abc dеf");
|
||||
});
|
||||
|
||||
it("handles mathematical unicode letters", () => {
|
||||
const text = "Unicode math: 𝒜𝒷𝒸𝒹";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("Unicode math: 𝒜𝒷𝒸𝒹");
|
||||
});
|
||||
|
||||
it("removes only invisible non-printables, keeps Japanese", () => {
|
||||
const text = "これは\u200Bテストです";
|
||||
const result = collectAutofillContentService["trimAndRemoveNonPrintableText"](text);
|
||||
expect(result).toEqual("これは テストです");
|
||||
});
|
||||
});
|
||||
|
||||
describe("recursivelyGetTextFromPreviousSiblings", () => {
|
||||
|
||||
@@ -713,7 +713,7 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
|
||||
*/
|
||||
private trimAndRemoveNonPrintableText(textContent: string): string {
|
||||
return (textContent || "")
|
||||
.replace(/[^\x20-\x7E]+|\s+/g, " ") // Strip out non-primitive characters and replace multiple spaces with a single space
|
||||
.replace(/\p{C}+|\s+/gu, " ") // Strip out non-printable characters and replace multiple spaces with a single space
|
||||
.trim(); // Trim leading and trailing whitespace
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
[ngClass]="{ 'tw-hidden': passwordRevealed }"
|
||||
readonly
|
||||
bitInput
|
||||
#passwordInput
|
||||
type="password"
|
||||
[value]="cipher.login.password"
|
||||
aria-readonly="true"
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
import { CommonModule, DatePipe } from "@angular/common";
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
} from "@angular/core";
|
||||
import { Observable, switchMap } from "rxjs";
|
||||
|
||||
@@ -61,6 +63,8 @@ export class LoginCredentialsViewComponent implements OnChanges {
|
||||
@Input() activeUserId: UserId;
|
||||
@Input() hadPendingChangePasswordTask: boolean;
|
||||
@Output() handleChangePassword = new EventEmitter<void>();
|
||||
@ViewChild("passwordInput")
|
||||
private passwordInput!: ElementRef<HTMLInputElement>;
|
||||
|
||||
isPremium$: Observable<boolean> = this.accountService.activeAccount$.pipe(
|
||||
switchMap((account) =>
|
||||
@@ -92,6 +96,10 @@ export class LoginCredentialsViewComponent implements OnChanges {
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes["cipher"]) {
|
||||
if (this.passwordInput?.nativeElement) {
|
||||
// Reset password input type in case it's been toggled
|
||||
this.passwordInput.nativeElement.type = "password";
|
||||
}
|
||||
this.passwordRevealed = false;
|
||||
this.showPasswordCount = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user