diff --git a/libs/vault/src/cipher-view/card-details/card-details-view.component.ts b/libs/vault/src/cipher-view/card-details/card-details-view.component.ts index c571321f714..b9bb0a767c6 100644 --- a/libs/vault/src/cipher-view/card-details/card-details-view.component.ts +++ b/libs/vault/src/cipher-view/card-details/card-details-view.component.ts @@ -4,7 +4,6 @@ import { CommonModule } from "@angular/common"; import { Component, Input, OnChanges, SimpleChanges } from "@angular/core"; import { JslibModule } from "@bitwarden/angular/jslib.module"; -import { CreditCardNumberPipe } from "@bitwarden/angular/pipes/credit-card-number.pipe"; import { EventCollectionService, EventType } from "@bitwarden/common/dirt/event-logs"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; @@ -15,6 +14,7 @@ import { IconButtonModule, } from "@bitwarden/components"; +import { CreditCardNumberPipe } from "../../pipes/credit-card-number.pipe"; import { ReadOnlyCipherCardComponent } from "../read-only-cipher-card/read-only-cipher-card.component"; // FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush diff --git a/libs/vault/src/index.ts b/libs/vault/src/index.ts index cf4d6687064..5d7bc189ce6 100644 --- a/libs/vault/src/index.ts +++ b/libs/vault/src/index.ts @@ -13,6 +13,7 @@ export { OrgIconDirective } from "./components/org-icon.directive"; export { CanDeleteCipherDirective } from "./components/can-delete-cipher.directive"; export { DarkImageSourceDirective } from "./components/dark-image-source.directive"; export { GetOrgNameFromIdPipe } from "./pipes/get-organization-name.pipe"; +export { CreditCardNumberPipe } from "./pipes/credit-card-number.pipe"; export * from "./cipher-view"; export * from "./cipher-form"; diff --git a/libs/vault/src/pipes/credit-card-number.pipe.spec.ts b/libs/vault/src/pipes/credit-card-number.pipe.spec.ts new file mode 100644 index 00000000000..72e7ad2dfdd --- /dev/null +++ b/libs/vault/src/pipes/credit-card-number.pipe.spec.ts @@ -0,0 +1,49 @@ +import { CreditCardNumberPipe } from "./credit-card-number.pipe"; + +describe("CreditCardNumberPipe", () => { + let pipe: CreditCardNumberPipe; + + beforeEach(() => { + pipe = new CreditCardNumberPipe(); + }); + + it("formats a 16-digit card as 4-4-4-4", () => { + expect(pipe.transform("4111111111111111", "Visa")).toBe("4111 1111 1111 1111"); + }); + + it("formats a 15-digit Amex as 4-6-5", () => { + expect(pipe.transform("378282246310005", "Amex")).toBe("3782 822463 10005"); + }); + + it("formats a 14-digit Diners Club as 4-6-4", () => { + expect(pipe.transform("36259600000004", "Diners Club")).toBe("3625 960000 0004"); + }); + + it("formats a 19-digit UnionPay as 6-13", () => { + expect(pipe.transform("6200000000000000003", "UnionPay")).toBe("620000 0000000000003"); + }); + + it("falls back to Other format for unknown brands", () => { + expect(pipe.transform("4111111111111111", "UnknownBrand")).toBe("4111 1111 1111 1111"); + }); + + it("strips non-numeric characters before formatting", () => { + expect(pipe.transform("4111-1111-1111-1111", "Visa")).toBe("4111 1111 1111 1111"); + }); + + it("strips spaces before formatting", () => { + expect(pipe.transform("4111 1111 1111 1111", "Visa")).toBe("4111 1111 1111 1111"); + }); + + it("strips mixed non-numeric characters", () => { + expect(pipe.transform("4111.1111/1111#1111", "Visa")).toBe("4111 1111 1111 1111"); + }); + + it("appends remaining digits when number exceeds expected length", () => { + expect(pipe.transform("41111111111111115555", "Visa")).toBe("4111 1111 1111 1111 5555"); + }); + + it("handles a card number that is only non-numeric characters", () => { + expect(pipe.transform("----", "Visa")).toBe(" "); + }); +}); diff --git a/libs/angular/src/pipes/credit-card-number.pipe.ts b/libs/vault/src/pipes/credit-card-number.pipe.ts similarity index 96% rename from libs/angular/src/pipes/credit-card-number.pipe.ts rename to libs/vault/src/pipes/credit-card-number.pipe.ts index aeb43ef4389..7bd134522dd 100644 --- a/libs/angular/src/pipes/credit-card-number.pipe.ts +++ b/libs/vault/src/pipes/credit-card-number.pipe.ts @@ -33,6 +33,8 @@ const numberFormats: Record = { }) export class CreditCardNumberPipe implements PipeTransform { transform(creditCardNumber: string, brand: string): string { + creditCardNumber = creditCardNumber.replace(/\D/g, ""); + let rules = numberFormats[brand]; if (rules == null) {