mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-24 12:06:15 +01:00
[ADR-0006][AC-319] Migrate all tests to use jest mock instead of substitute (#6520)
Standardize on using jest mock instead of having two mocking frameworks which can be confusing.
This commit is contained in:
parent
5cacd79d8c
commit
ffb67be0a2
@ -104,10 +104,7 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"no-restricted-imports": [
|
"no-restricted-imports": ["error", { "patterns": ["src/**/*"] }]
|
||||||
"error",
|
|
||||||
{ "patterns": ["src/**/*"], "paths": ["@fluffy-spoon/substitute"] }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
|
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
|
|
||||||
|
|
||||||
import BrowserLocalStorageService from "./browser-local-storage.service";
|
import BrowserLocalStorageService from "./browser-local-storage.service";
|
||||||
import BrowserMemoryStorageService from "./browser-memory-storage.service";
|
import BrowserMemoryStorageService from "./browser-memory-storage.service";
|
||||||
@ -12,8 +11,8 @@ import { KeyGenerationService } from "./key-generation.service";
|
|||||||
import { LocalBackedSessionStorageService } from "./local-backed-session-storage.service";
|
import { LocalBackedSessionStorageService } from "./local-backed-session-storage.service";
|
||||||
|
|
||||||
describe("Browser Session Storage Service", () => {
|
describe("Browser Session Storage Service", () => {
|
||||||
let encryptService: SubstituteOf<EncryptServiceImplementation>;
|
let encryptService: MockProxy<EncryptService>;
|
||||||
let keyGenerationService: SubstituteOf<KeyGenerationService>;
|
let keyGenerationService: MockProxy<KeyGenerationService>;
|
||||||
|
|
||||||
let cache: Map<string, any>;
|
let cache: Map<string, any>;
|
||||||
const testObj = { a: 1, b: 2 };
|
const testObj = { a: 1, b: 2 };
|
||||||
@ -28,8 +27,8 @@ describe("Browser Session Storage Service", () => {
|
|||||||
let sut: LocalBackedSessionStorageService;
|
let sut: LocalBackedSessionStorageService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
encryptService = Substitute.for();
|
encryptService = mock<EncryptService>();
|
||||||
keyGenerationService = Substitute.for();
|
keyGenerationService = mock<KeyGenerationService>();
|
||||||
|
|
||||||
sut = new LocalBackedSessionStorageService(encryptService, keyGenerationService);
|
sut = new LocalBackedSessionStorageService(encryptService, keyGenerationService);
|
||||||
|
|
||||||
@ -138,6 +137,8 @@ describe("Browser Session Storage Service", () => {
|
|||||||
jest.spyOn(sessionStorage, "get").mockResolvedValue(null);
|
jest.spyOn(sessionStorage, "get").mockResolvedValue(null);
|
||||||
jest.spyOn(localStorage, "save").mockResolvedValue();
|
jest.spyOn(localStorage, "save").mockResolvedValue();
|
||||||
jest.spyOn(sessionStorage, "save").mockResolvedValue();
|
jest.spyOn(sessionStorage, "save").mockResolvedValue();
|
||||||
|
|
||||||
|
encryptService.encrypt.mockResolvedValue(mockEnc("{}"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove key from cache if value is null", async () => {
|
it("should remove key from cache if value is null", async () => {
|
||||||
@ -205,7 +206,7 @@ describe("Browser Session Storage Service", () => {
|
|||||||
describe("new key creation", () => {
|
describe("new key creation", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(sessionStorage, "get").mockResolvedValue(null);
|
jest.spyOn(sessionStorage, "get").mockResolvedValue(null);
|
||||||
keyGenerationService.makeEphemeralKey().resolves(key);
|
keyGenerationService.makeEphemeralKey.mockResolvedValue(key);
|
||||||
jest.spyOn(sut, "setSessionEncKey").mockResolvedValue();
|
jest.spyOn(sut, "setSessionEncKey").mockResolvedValue();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -213,7 +214,7 @@ describe("Browser Session Storage Service", () => {
|
|||||||
const result = await sut.getSessionEncKey();
|
const result = await sut.getSessionEncKey();
|
||||||
|
|
||||||
expect(result).toStrictEqual(key);
|
expect(result).toStrictEqual(key);
|
||||||
keyGenerationService.received(1).makeEphemeralKey();
|
expect(keyGenerationService.makeEphemeralKey).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should store a symmetric crypto key if it makes one", async () => {
|
it("should store a symmetric crypto key if it makes one", async () => {
|
||||||
@ -244,19 +245,23 @@ describe("Browser Session Storage Service", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should decrypt returned sessions", async () => {
|
it("should decrypt returned sessions", async () => {
|
||||||
encryptService.decryptToUtf8(encSession, key).resolves(decryptedSession);
|
encryptService.decryptToUtf8
|
||||||
|
.calledWith(expect.anything(), key)
|
||||||
|
.mockResolvedValue(decryptedSession);
|
||||||
await sut.getLocalSession(key);
|
await sut.getLocalSession(key);
|
||||||
encryptService.received(1).decryptToUtf8(encSession, key);
|
expect(encryptService.decryptToUtf8).toHaveBeenNthCalledWith(1, encSession, key);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should parse session", async () => {
|
it("should parse session", async () => {
|
||||||
encryptService.decryptToUtf8(encSession, key).resolves(decryptedSession);
|
encryptService.decryptToUtf8
|
||||||
|
.calledWith(expect.anything(), key)
|
||||||
|
.mockResolvedValue(decryptedSession);
|
||||||
const result = await sut.getLocalSession(key);
|
const result = await sut.getLocalSession(key);
|
||||||
expect(result).toEqual(session);
|
expect(result).toEqual(session);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove state if decryption fails", async () => {
|
it("should remove state if decryption fails", async () => {
|
||||||
encryptService.decryptToUtf8(Arg.any(), Arg.any()).resolves(null);
|
encryptService.decryptToUtf8.mockResolvedValue(null);
|
||||||
const setSessionEncKeySpy = jest.spyOn(sut, "setSessionEncKey").mockResolvedValue();
|
const setSessionEncKeySpy = jest.spyOn(sut, "setSessionEncKey").mockResolvedValue();
|
||||||
const removeLocalSessionSpy = jest.spyOn(localStorage, "remove").mockResolvedValue();
|
const removeLocalSessionSpy = jest.spyOn(localStorage, "remove").mockResolvedValue();
|
||||||
|
|
||||||
@ -274,15 +279,15 @@ describe("Browser Session Storage Service", () => {
|
|||||||
const testJSON = JSON.stringify(testSession);
|
const testJSON = JSON.stringify(testSession);
|
||||||
|
|
||||||
it("should encrypt a stringified session", async () => {
|
it("should encrypt a stringified session", async () => {
|
||||||
encryptService.encrypt(Arg.any(), Arg.any()).mimicks(mockEnc);
|
encryptService.encrypt.mockImplementation(mockEnc);
|
||||||
jest.spyOn(localStorage, "save").mockResolvedValue();
|
jest.spyOn(localStorage, "save").mockResolvedValue();
|
||||||
await sut.setLocalSession(testSession, key);
|
await sut.setLocalSession(testSession, key);
|
||||||
|
|
||||||
encryptService.received(1).encrypt(testJSON, key);
|
expect(encryptService.encrypt).toHaveBeenNthCalledWith(1, testJSON, key);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove local session if null", async () => {
|
it("should remove local session if null", async () => {
|
||||||
encryptService.encrypt(Arg.any(), Arg.any()).resolves(null);
|
encryptService.encrypt.mockResolvedValue(null);
|
||||||
const spy = jest.spyOn(localStorage, "remove").mockResolvedValue();
|
const spy = jest.spyOn(localStorage, "remove").mockResolvedValue();
|
||||||
await sut.setLocalSession(null, key);
|
await sut.setLocalSession(null, key);
|
||||||
|
|
||||||
@ -290,7 +295,7 @@ describe("Browser Session Storage Service", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should save encrypted string", async () => {
|
it("should save encrypted string", async () => {
|
||||||
encryptService.encrypt(Arg.any(), Arg.any()).mimicks(mockEnc);
|
encryptService.encrypt.mockImplementation(mockEnc);
|
||||||
const spy = jest.spyOn(localStorage, "save").mockResolvedValue();
|
const spy = jest.spyOn(localStorage, "save").mockResolvedValue();
|
||||||
await sut.setLocalSession(testSession, key);
|
await sut.setLocalSession(testSession, key);
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
// eslint-disable-next-line no-restricted-imports
|
|
||||||
import { Substitute } from "@fluffy-spoon/substitute";
|
|
||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
@ -28,15 +26,15 @@ describe("GeneratorComponent", () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: PasswordGenerationServiceAbstraction,
|
provide: PasswordGenerationServiceAbstraction,
|
||||||
useClass: Substitute.for<PasswordGenerationServiceAbstraction>(),
|
useValue: mock<PasswordGenerationServiceAbstraction>(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: UsernameGenerationServiceAbstraction,
|
provide: UsernameGenerationServiceAbstraction,
|
||||||
useClass: Substitute.for<UsernameGenerationServiceAbstraction>(),
|
useValue: mock<UsernameGenerationServiceAbstraction>(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: StateService,
|
provide: StateService,
|
||||||
useClass: Substitute.for<StateService>(),
|
useValue: mock<StateService>(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: PlatformUtilsService,
|
provide: PlatformUtilsService,
|
||||||
@ -44,15 +42,15 @@ describe("GeneratorComponent", () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: I18nService,
|
provide: I18nService,
|
||||||
useClass: Substitute.for<I18nService>(),
|
useValue: mock<I18nService>(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: ActivatedRoute,
|
provide: ActivatedRoute,
|
||||||
useClass: Substitute.for<ActivatedRoute>(),
|
useValue: mock<ActivatedRoute>(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: LogService,
|
provide: LogService,
|
||||||
useClass: Substitute.for<LogService>(),
|
useValue: mock<LogService>(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA],
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
"@bitwarden/web-vault/*",
|
"@bitwarden/web-vault/*",
|
||||||
"src/**/*",
|
"src/**/*",
|
||||||
"bitwarden_license"
|
"bitwarden_license"
|
||||||
],
|
]
|
||||||
"paths": ["@fluffy-spoon/substitute"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
|
|
||||||
@ -22,11 +21,11 @@ export function BuildTestObject<T, K extends keyof T = keyof T>(
|
|||||||
return Object.assign(constructor === null ? {} : new constructor(), def) as T;
|
return Object.assign(constructor === null ? {} : new constructor(), def) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockEnc(s: string): EncString {
|
export function mockEnc(s: string): MockProxy<EncString> {
|
||||||
const mock = Substitute.for<EncString>();
|
const mocked = mock<EncString>();
|
||||||
mock.decrypt(Arg.any(), Arg.any()).resolves(s);
|
mocked.decrypt.mockResolvedValue(s);
|
||||||
|
|
||||||
return mock;
|
return mocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeStaticByteArray(length: number, start = 0) {
|
export function makeStaticByteArray(length: number, start = 0) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
|
||||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
|
||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
|
import { makeStaticByteArray } from "../../../../spec";
|
||||||
import { EncryptionType } from "../../../enums";
|
import { EncryptionType } from "../../../enums";
|
||||||
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
|
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
|
||||||
import {
|
import {
|
||||||
@ -64,11 +63,16 @@ describe("EncString", () => {
|
|||||||
describe("decrypt", () => {
|
describe("decrypt", () => {
|
||||||
const encString = new EncString(EncryptionType.Rsa2048_OaepSha256_B64, "data");
|
const encString = new EncString(EncryptionType.Rsa2048_OaepSha256_B64, "data");
|
||||||
|
|
||||||
const cryptoService = Substitute.for<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
cryptoService.getOrgKey(null).resolves(null);
|
cryptoService.hasUserKey.mockResolvedValue(true);
|
||||||
|
cryptoService.getUserKeyWithLegacySupport.mockResolvedValue(
|
||||||
|
new SymmetricCryptoKey(makeStaticByteArray(32)) as UserKey
|
||||||
|
);
|
||||||
|
|
||||||
const encryptService = Substitute.for<EncryptService>();
|
const encryptService = mock<EncryptService>();
|
||||||
encryptService.decryptToUtf8(encString, Arg.any()).resolves("decrypted");
|
encryptService.decryptToUtf8
|
||||||
|
.calledWith(encString, expect.anything())
|
||||||
|
.mockResolvedValue("decrypted");
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
(window as any).bitwardenContainerService = new ContainerService(
|
(window as any).bitwardenContainerService = new ContainerService(
|
||||||
@ -85,7 +89,7 @@ describe("EncString", () => {
|
|||||||
|
|
||||||
it("result should be cached", async () => {
|
it("result should be cached", async () => {
|
||||||
const decrypted = await encString.decrypt(null);
|
const decrypted = await encString.decrypt(null);
|
||||||
encryptService.received(1).decryptToUtf8(Arg.any(), Arg.any());
|
expect(encryptService.decryptToUtf8).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect(decrypted).toBe("decrypted");
|
expect(decrypted).toBe("decrypted");
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock } from "jest-mock-extended";
|
||||||
import { Substitute } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
import { Utils } from "../../platform/misc/utils";
|
import { Utils } from "../../platform/misc/utils";
|
||||||
import { PlatformUtilsService } from "../abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "../abstractions/platform-utils.service";
|
||||||
@ -582,8 +581,8 @@ function testRsaGenerateKeyPair(length: 1024 | 2048 | 4096) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getWebCryptoFunctionService() {
|
function getWebCryptoFunctionService() {
|
||||||
const platformUtilsMock = Substitute.for<PlatformUtilsService>();
|
const platformUtilsMock = mock<PlatformUtilsService>();
|
||||||
platformUtilsMock.isEdge().mimicks(() => navigator.userAgent.indexOf(" Edg/") !== -1);
|
platformUtilsMock.isEdge.mockImplementation(() => navigator.userAgent.indexOf(" Edg/") !== -1);
|
||||||
|
|
||||||
return new WebCryptoFunctionService(window);
|
return new WebCryptoFunctionService(window);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
|
||||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { OrganizationService } from "../admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "../admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
@ -22,19 +21,19 @@ import { StateService } from "../platform/services/state.service";
|
|||||||
describe("PolicyService", () => {
|
describe("PolicyService", () => {
|
||||||
let policyService: PolicyService;
|
let policyService: PolicyService;
|
||||||
|
|
||||||
let cryptoService: SubstituteOf<CryptoService>;
|
let cryptoService: MockProxy<CryptoService>;
|
||||||
let stateService: SubstituteOf<StateService>;
|
let stateService: MockProxy<StateService>;
|
||||||
let organizationService: SubstituteOf<OrganizationService>;
|
let organizationService: MockProxy<OrganizationService>;
|
||||||
let encryptService: SubstituteOf<EncryptService>;
|
let encryptService: MockProxy<EncryptService>;
|
||||||
let activeAccount: BehaviorSubject<string>;
|
let activeAccount: BehaviorSubject<string>;
|
||||||
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stateService = Substitute.for();
|
stateService = mock<StateService>();
|
||||||
organizationService = Substitute.for();
|
organizationService = mock<OrganizationService>();
|
||||||
organizationService
|
organizationService.getAll
|
||||||
.getAll("user")
|
.calledWith("user")
|
||||||
.resolves([
|
.mockResolvedValue([
|
||||||
new Organization(
|
new Organization(
|
||||||
organizationData(
|
organizationData(
|
||||||
"test-organization",
|
"test-organization",
|
||||||
@ -45,24 +44,24 @@ describe("PolicyService", () => {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
organizationService.getAll(undefined).resolves([]);
|
organizationService.getAll.calledWith(undefined).mockResolvedValue([]);
|
||||||
organizationService.getAll(null).resolves([]);
|
organizationService.getAll.calledWith(null).mockResolvedValue([]);
|
||||||
activeAccount = new BehaviorSubject("123");
|
activeAccount = new BehaviorSubject("123");
|
||||||
activeAccountUnlocked = new BehaviorSubject(true);
|
activeAccountUnlocked = new BehaviorSubject(true);
|
||||||
stateService.getDecryptedPolicies({ userId: "user" }).resolves(null);
|
stateService.getDecryptedPolicies.calledWith({ userId: "user" }).mockResolvedValue(null);
|
||||||
stateService.getEncryptedPolicies({ userId: "user" }).resolves({
|
stateService.getEncryptedPolicies.calledWith({ userId: "user" }).mockResolvedValue({
|
||||||
"1": policyData("1", "test-organization", PolicyType.MaximumVaultTimeout, true, {
|
"1": policyData("1", "test-organization", PolicyType.MaximumVaultTimeout, true, {
|
||||||
minutes: 14,
|
minutes: 14,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
stateService.getEncryptedPolicies().resolves({
|
stateService.getEncryptedPolicies.mockResolvedValue({
|
||||||
"1": policyData("1", "test-organization", PolicyType.MaximumVaultTimeout, true, {
|
"1": policyData("1", "test-organization", PolicyType.MaximumVaultTimeout, true, {
|
||||||
minutes: 14,
|
minutes: 14,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
stateService.activeAccount$.returns(activeAccount);
|
stateService.activeAccount$ = activeAccount;
|
||||||
stateService.activeAccountUnlocked$.returns(activeAccountUnlocked);
|
stateService.activeAccountUnlocked$ = activeAccountUnlocked;
|
||||||
stateService.getUserId().resolves("user");
|
stateService.getUserId.mockResolvedValue("user");
|
||||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||||
|
|
||||||
policyService = new PolicyService(stateService, organizationService);
|
policyService = new PolicyService(stateService, organizationService);
|
||||||
@ -120,7 +119,7 @@ describe("PolicyService", () => {
|
|||||||
it("null userId", async () => {
|
it("null userId", async () => {
|
||||||
await policyService.clear();
|
await policyService.clear();
|
||||||
|
|
||||||
stateService.received(1).setEncryptedPolicies(Arg.any(), Arg.any());
|
expect(stateService.setEncryptedPolicies).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(policyService.policies$)).length).toBe(0);
|
expect((await firstValueFrom(policyService.policies$)).length).toBe(0);
|
||||||
});
|
});
|
||||||
@ -128,7 +127,7 @@ describe("PolicyService", () => {
|
|||||||
it("matching userId", async () => {
|
it("matching userId", async () => {
|
||||||
await policyService.clear("user");
|
await policyService.clear("user");
|
||||||
|
|
||||||
stateService.received(1).setEncryptedPolicies(Arg.any(), Arg.any());
|
expect(stateService.setEncryptedPolicies).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(policyService.policies$)).length).toBe(0);
|
expect((await firstValueFrom(policyService.policies$)).length).toBe(0);
|
||||||
});
|
});
|
||||||
@ -136,7 +135,7 @@ describe("PolicyService", () => {
|
|||||||
it("mismatching userId", async () => {
|
it("mismatching userId", async () => {
|
||||||
await policyService.clear("12");
|
await policyService.clear("12");
|
||||||
|
|
||||||
stateService.received(1).setEncryptedPolicies(Arg.any(), Arg.any());
|
expect(stateService.setEncryptedPolicies).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(policyService.policies$)).length).toBe(1);
|
expect((await firstValueFrom(policyService.policies$)).length).toBe(1);
|
||||||
});
|
});
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
|
||||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { CryptoService } from "../platform/abstractions/crypto.service";
|
import { CryptoService } from "../platform/abstractions/crypto.service";
|
||||||
import { EncryptService } from "../platform/abstractions/encrypt.service";
|
import { EncryptService } from "../platform/abstractions/encrypt.service";
|
||||||
|
import { StateService } from "../platform/abstractions/state.service";
|
||||||
import { ContainerService } from "../platform/services/container.service";
|
import { ContainerService } from "../platform/services/container.service";
|
||||||
import { StateService } from "../platform/services/state.service";
|
|
||||||
|
|
||||||
import { SettingsService } from "./settings.service";
|
import { SettingsService } from "./settings.service";
|
||||||
|
|
||||||
describe("SettingsService", () => {
|
describe("SettingsService", () => {
|
||||||
let settingsService: SettingsService;
|
let settingsService: SettingsService;
|
||||||
|
|
||||||
let cryptoService: SubstituteOf<CryptoService>;
|
let cryptoService: MockProxy<CryptoService>;
|
||||||
let encryptService: SubstituteOf<EncryptService>;
|
let encryptService: MockProxy<EncryptService>;
|
||||||
let stateService: SubstituteOf<StateService>;
|
let stateService: MockProxy<StateService>;
|
||||||
let activeAccount: BehaviorSubject<string>;
|
let activeAccount: BehaviorSubject<string>;
|
||||||
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
||||||
|
|
||||||
@ -25,15 +24,15 @@ describe("SettingsService", () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cryptoService = Substitute.for();
|
cryptoService = mock<CryptoService>();
|
||||||
encryptService = Substitute.for();
|
encryptService = mock<EncryptService>();
|
||||||
stateService = Substitute.for();
|
stateService = mock<StateService>();
|
||||||
activeAccount = new BehaviorSubject("123");
|
activeAccount = new BehaviorSubject("123");
|
||||||
activeAccountUnlocked = new BehaviorSubject(true);
|
activeAccountUnlocked = new BehaviorSubject(true);
|
||||||
|
|
||||||
stateService.getSettings().resolves({ equivalentDomains: mockEquivalentDomains });
|
stateService.getSettings.mockResolvedValue({ equivalentDomains: mockEquivalentDomains });
|
||||||
stateService.activeAccount$.returns(activeAccount);
|
stateService.activeAccount$ = activeAccount;
|
||||||
stateService.activeAccountUnlocked$.returns(activeAccountUnlocked);
|
stateService.activeAccountUnlocked$ = activeAccountUnlocked;
|
||||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||||
|
|
||||||
settingsService = new SettingsService(stateService);
|
settingsService = new SettingsService(stateService);
|
||||||
@ -66,7 +65,7 @@ describe("SettingsService", () => {
|
|||||||
it("setEquivalentDomains", async () => {
|
it("setEquivalentDomains", async () => {
|
||||||
await settingsService.setEquivalentDomains([["test2"], ["domains2"]]);
|
await settingsService.setEquivalentDomains([["test2"], ["domains2"]]);
|
||||||
|
|
||||||
stateService.received(1).setSettings(Arg.any());
|
expect(stateService.setSettings).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(settingsService.settings$)).equivalentDomains).toEqual([
|
expect((await firstValueFrom(settingsService.settings$)).equivalentDomains).toEqual([
|
||||||
["test2"],
|
["test2"],
|
||||||
@ -77,7 +76,7 @@ describe("SettingsService", () => {
|
|||||||
it("clear", async () => {
|
it("clear", async () => {
|
||||||
await settingsService.clear();
|
await settingsService.clear();
|
||||||
|
|
||||||
stateService.received(1).setSettings(Arg.any(), Arg.any());
|
expect(stateService.setSettings).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect(await firstValueFrom(settingsService.settings$)).toEqual({});
|
expect(await firstValueFrom(settingsService.settings$)).toEqual({});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock } from "jest-mock-extended";
|
||||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
import { mockEnc } from "../../../../../spec";
|
import { mockEnc } from "../../../../../spec";
|
||||||
import { SendType } from "../../enums/send-type";
|
import { SendType } from "../../enums/send-type";
|
||||||
@ -61,8 +60,8 @@ describe("SendAccess", () => {
|
|||||||
sendAccess.type = SendType.Text;
|
sendAccess.type = SendType.Text;
|
||||||
sendAccess.name = mockEnc("name");
|
sendAccess.name = mockEnc("name");
|
||||||
|
|
||||||
const text = Substitute.for<SendText>();
|
const text = mock<SendText>();
|
||||||
text.decrypt(Arg.any()).resolves({} as any);
|
text.decrypt.mockResolvedValue({} as any);
|
||||||
sendAccess.text = text;
|
sendAccess.text = text;
|
||||||
|
|
||||||
sendAccess.expirationDate = new Date("2022-01-31T12:00:00.000Z");
|
sendAccess.expirationDate = new Date("2022-01-31T12:00:00.000Z");
|
||||||
@ -70,7 +69,7 @@ describe("SendAccess", () => {
|
|||||||
|
|
||||||
const view = await sendAccess.decrypt(null);
|
const view = await sendAccess.decrypt(null);
|
||||||
|
|
||||||
text.received(1).decrypt(Arg.any());
|
expect(text.decrypt).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
expect(view).toEqual({
|
expect(view).toEqual({
|
||||||
id: "id",
|
id: "id",
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock } from "jest-mock-extended";
|
||||||
import { Substitute, Arg, SubstituteOf } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
import { makeStaticByteArray, mockEnc } from "../../../../../spec";
|
import { makeStaticByteArray, mockEnc } from "../../../../../spec";
|
||||||
import { CryptoService } from "../../../../platform/abstractions/crypto.service";
|
import { CryptoService } from "../../../../platform/abstractions/crypto.service";
|
||||||
import { EncryptService } from "../../../../platform/abstractions/encrypt.service";
|
import { EncryptService } from "../../../../platform/abstractions/encrypt.service";
|
||||||
import { EncString } from "../../../../platform/models/domain/enc-string";
|
|
||||||
import { ContainerService } from "../../../../platform/services/container.service";
|
import { ContainerService } from "../../../../platform/services/container.service";
|
||||||
import { SendType } from "../../enums/send-type";
|
import { SendType } from "../../enums/send-type";
|
||||||
import { SendData } from "../data/send.data";
|
import { SendData } from "../data/send.data";
|
||||||
@ -89,8 +87,8 @@ describe("Send", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Decrypt", async () => {
|
it("Decrypt", async () => {
|
||||||
const text = Substitute.for<SendText>();
|
const text = mock<SendText>();
|
||||||
text.decrypt(Arg.any()).resolves("textView" as any);
|
text.decrypt.mockResolvedValue("textView" as any);
|
||||||
|
|
||||||
const send = new Send();
|
const send = new Send();
|
||||||
send.id = "id";
|
send.id = "id";
|
||||||
@ -108,18 +106,20 @@ describe("Send", () => {
|
|||||||
send.disabled = false;
|
send.disabled = false;
|
||||||
send.hideEmail = true;
|
send.hideEmail = true;
|
||||||
|
|
||||||
const cryptoService = Substitute.for<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
cryptoService.decryptToBytes(send.key, null).resolves(makeStaticByteArray(32));
|
cryptoService.decryptToBytes
|
||||||
cryptoService.makeSendKey(Arg.any()).resolves("cryptoKey" as any);
|
.calledWith(send.key, null)
|
||||||
|
.mockResolvedValue(makeStaticByteArray(32));
|
||||||
|
cryptoService.makeSendKey.mockResolvedValue("cryptoKey" as any);
|
||||||
|
|
||||||
const encryptService = Substitute.for<EncryptService>();
|
const encryptService = mock<EncryptService>();
|
||||||
|
|
||||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||||
|
|
||||||
const view = await send.decrypt();
|
const view = await send.decrypt();
|
||||||
|
|
||||||
text.received(1).decrypt("cryptoKey" as any);
|
expect(text.decrypt).toHaveBeenNthCalledWith(1, "cryptoKey");
|
||||||
(send.name as SubstituteOf<EncString>).received(1).decrypt(null, "cryptoKey" as any);
|
expect(send.name.decrypt).toHaveBeenNthCalledWith(1, null, "cryptoKey");
|
||||||
|
|
||||||
expect(view).toMatchObject({
|
expect(view).toMatchObject({
|
||||||
id: "id",
|
id: "id",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock } from "jest-mock-extended";
|
||||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
|
||||||
import { Jsonify } from "type-fest";
|
import { Jsonify } from "type-fest";
|
||||||
|
|
||||||
import { makeStaticByteArray, mockEnc, mockFromJson } from "../../../../spec/utils";
|
import { makeStaticByteArray, mockEnc, mockFromJson } from "../../../../spec/utils";
|
||||||
@ -219,15 +218,15 @@ describe("Cipher DTO", () => {
|
|||||||
loginView.username = "username";
|
loginView.username = "username";
|
||||||
loginView.password = "password";
|
loginView.password = "password";
|
||||||
|
|
||||||
const login = Substitute.for<Login>();
|
const login = mock<Login>();
|
||||||
login.decrypt(Arg.any(), Arg.any()).resolves(loginView);
|
login.decrypt.mockResolvedValue(loginView);
|
||||||
cipher.login = login;
|
cipher.login = login;
|
||||||
|
|
||||||
const cryptoService = Substitute.for<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
const encryptService = Substitute.for<EncryptService>();
|
const encryptService = mock<EncryptService>();
|
||||||
const cipherService = Substitute.for<CipherService>();
|
const cipherService = mock<CipherService>();
|
||||||
|
|
||||||
encryptService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(64));
|
encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(64));
|
||||||
|
|
||||||
(window as any).bitwardenContainerService = new ContainerService(
|
(window as any).bitwardenContainerService = new ContainerService(
|
||||||
cryptoService,
|
cryptoService,
|
||||||
@ -343,11 +342,11 @@ describe("Cipher DTO", () => {
|
|||||||
cipher.secureNote.type = SecureNoteType.Generic;
|
cipher.secureNote.type = SecureNoteType.Generic;
|
||||||
cipher.key = mockEnc("EncKey");
|
cipher.key = mockEnc("EncKey");
|
||||||
|
|
||||||
const cryptoService = Substitute.for<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
const encryptService = Substitute.for<EncryptService>();
|
const encryptService = mock<EncryptService>();
|
||||||
const cipherService = Substitute.for<CipherService>();
|
const cipherService = mock<CipherService>();
|
||||||
|
|
||||||
encryptService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(64));
|
encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(64));
|
||||||
|
|
||||||
(window as any).bitwardenContainerService = new ContainerService(
|
(window as any).bitwardenContainerService = new ContainerService(
|
||||||
cryptoService,
|
cryptoService,
|
||||||
@ -477,15 +476,15 @@ describe("Cipher DTO", () => {
|
|||||||
cardView.cardholderName = "cardholderName";
|
cardView.cardholderName = "cardholderName";
|
||||||
cardView.number = "4111111111111111";
|
cardView.number = "4111111111111111";
|
||||||
|
|
||||||
const card = Substitute.for<Card>();
|
const card = mock<Card>();
|
||||||
card.decrypt(Arg.any(), Arg.any()).resolves(cardView);
|
card.decrypt.mockResolvedValue(cardView);
|
||||||
cipher.card = card;
|
cipher.card = card;
|
||||||
|
|
||||||
const cryptoService = Substitute.for<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
const encryptService = Substitute.for<EncryptService>();
|
const encryptService = mock<EncryptService>();
|
||||||
const cipherService = Substitute.for<CipherService>();
|
const cipherService = mock<CipherService>();
|
||||||
|
|
||||||
encryptService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(64));
|
encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(64));
|
||||||
|
|
||||||
(window as any).bitwardenContainerService = new ContainerService(
|
(window as any).bitwardenContainerService = new ContainerService(
|
||||||
cryptoService,
|
cryptoService,
|
||||||
@ -639,15 +638,15 @@ describe("Cipher DTO", () => {
|
|||||||
identityView.firstName = "firstName";
|
identityView.firstName = "firstName";
|
||||||
identityView.lastName = "lastName";
|
identityView.lastName = "lastName";
|
||||||
|
|
||||||
const identity = Substitute.for<Identity>();
|
const identity = mock<Identity>();
|
||||||
identity.decrypt(Arg.any(), Arg.any()).resolves(identityView);
|
identity.decrypt.mockResolvedValue(identityView);
|
||||||
cipher.identity = identity;
|
cipher.identity = identity;
|
||||||
|
|
||||||
const cryptoService = Substitute.for<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
const encryptService = Substitute.for<EncryptService>();
|
const encryptService = mock<EncryptService>();
|
||||||
const cipherService = Substitute.for<CipherService>();
|
const cipherService = mock<CipherService>();
|
||||||
|
|
||||||
encryptService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(64));
|
encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(64));
|
||||||
|
|
||||||
(window as any).bitwardenContainerService = new ContainerService(
|
(window as any).bitwardenContainerService = new ContainerService(
|
||||||
cryptoService,
|
cryptoService,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock } from "jest-mock-extended";
|
||||||
import { Substitute, Arg } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
import { mockEnc, mockFromJson } from "../../../../spec";
|
import { mockEnc, mockFromJson } from "../../../../spec";
|
||||||
import { UriMatchType } from "../../../enums";
|
import { UriMatchType } from "../../../enums";
|
||||||
@ -51,10 +50,10 @@ describe("Login DTO", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Decrypts correctly", async () => {
|
it("Decrypts correctly", async () => {
|
||||||
const loginUri = Substitute.for<LoginUri>();
|
const loginUri = mock<LoginUri>();
|
||||||
const loginUriView = new LoginUriView();
|
const loginUriView = new LoginUriView();
|
||||||
loginUriView.uri = "decrypted uri";
|
loginUriView.uri = "decrypted uri";
|
||||||
loginUri.decrypt(Arg.any()).resolves(loginUriView);
|
loginUri.decrypt.mockResolvedValue(loginUriView);
|
||||||
|
|
||||||
const login = new Login();
|
const login = new Login();
|
||||||
login.uris = [loginUri];
|
login.uris = [loginUri];
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
|
||||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { makeStaticByteArray } from "../../../../spec";
|
||||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||||
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
|
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
|
||||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||||
|
import { StateService } from "../../../platform/abstractions/state.service";
|
||||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||||
|
import { SymmetricCryptoKey, UserKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||||
import { ContainerService } from "../../../platform/services/container.service";
|
import { ContainerService } from "../../../platform/services/container.service";
|
||||||
import { StateService } from "../../../platform/services/state.service";
|
|
||||||
import { CipherService } from "../../abstractions/cipher.service";
|
import { CipherService } from "../../abstractions/cipher.service";
|
||||||
import { FolderData } from "../../models/data/folder.data";
|
import { FolderData } from "../../models/data/folder.data";
|
||||||
import { FolderView } from "../../models/view/folder.view";
|
import { FolderView } from "../../models/view/folder.view";
|
||||||
@ -16,28 +17,36 @@ import { FolderService } from "../../services/folder/folder.service";
|
|||||||
describe("Folder Service", () => {
|
describe("Folder Service", () => {
|
||||||
let folderService: FolderService;
|
let folderService: FolderService;
|
||||||
|
|
||||||
let cryptoService: SubstituteOf<CryptoService>;
|
let cryptoService: MockProxy<CryptoService>;
|
||||||
let encryptService: SubstituteOf<EncryptService>;
|
let encryptService: MockProxy<EncryptService>;
|
||||||
let i18nService: SubstituteOf<I18nService>;
|
let i18nService: MockProxy<I18nService>;
|
||||||
let cipherService: SubstituteOf<CipherService>;
|
let cipherService: MockProxy<CipherService>;
|
||||||
let stateService: SubstituteOf<StateService>;
|
let stateService: MockProxy<StateService>;
|
||||||
let activeAccount: BehaviorSubject<string>;
|
let activeAccount: BehaviorSubject<string>;
|
||||||
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cryptoService = Substitute.for();
|
cryptoService = mock<CryptoService>();
|
||||||
encryptService = Substitute.for();
|
encryptService = mock<EncryptService>();
|
||||||
i18nService = Substitute.for();
|
i18nService = mock<I18nService>();
|
||||||
cipherService = Substitute.for();
|
cipherService = mock<CipherService>();
|
||||||
stateService = Substitute.for();
|
stateService = mock<StateService>();
|
||||||
activeAccount = new BehaviorSubject("123");
|
activeAccount = new BehaviorSubject("123");
|
||||||
activeAccountUnlocked = new BehaviorSubject(true);
|
activeAccountUnlocked = new BehaviorSubject(true);
|
||||||
|
|
||||||
stateService.getEncryptedFolders().resolves({
|
i18nService.collator = new Intl.Collator("en");
|
||||||
|
stateService.getEncryptedFolders.mockResolvedValue({
|
||||||
"1": folderData("1", "test"),
|
"1": folderData("1", "test"),
|
||||||
});
|
});
|
||||||
stateService.activeAccount$.returns(activeAccount);
|
stateService.activeAccount$ = activeAccount;
|
||||||
stateService.activeAccountUnlocked$.returns(activeAccountUnlocked);
|
stateService.activeAccountUnlocked$ = activeAccountUnlocked;
|
||||||
|
|
||||||
|
cryptoService.hasUserKey.mockResolvedValue(true);
|
||||||
|
cryptoService.getUserKeyWithLegacySupport.mockResolvedValue(
|
||||||
|
new SymmetricCryptoKey(makeStaticByteArray(32)) as UserKey
|
||||||
|
);
|
||||||
|
encryptService.decryptToUtf8.mockResolvedValue("DEC");
|
||||||
|
|
||||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||||
|
|
||||||
folderService = new FolderService(cryptoService, i18nService, cipherService, stateService);
|
folderService = new FolderService(cryptoService, i18nService, cipherService, stateService);
|
||||||
@ -48,8 +57,8 @@ describe("Folder Service", () => {
|
|||||||
model.id = "2";
|
model.id = "2";
|
||||||
model.name = "Test Folder";
|
model.name = "Test Folder";
|
||||||
|
|
||||||
cryptoService.encrypt(Arg.any()).resolves(new EncString("ENC"));
|
cryptoService.encrypt.mockResolvedValue(new EncString("ENC"));
|
||||||
cryptoService.decryptToUtf8(Arg.any()).resolves("DEC");
|
cryptoService.decryptToUtf8.mockResolvedValue("DEC");
|
||||||
|
|
||||||
const result = await folderService.encrypt(model);
|
const result = await folderService.encrypt(model);
|
||||||
|
|
||||||
@ -69,9 +78,9 @@ describe("Folder Service", () => {
|
|||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
id: "1",
|
id: "1",
|
||||||
name: {
|
name: {
|
||||||
decryptedValue: [],
|
|
||||||
encryptedString: "test",
|
encryptedString: "test",
|
||||||
encryptionType: 0,
|
encryptionType: 0,
|
||||||
|
decryptedValue: "DEC",
|
||||||
},
|
},
|
||||||
revisionDate: null,
|
revisionDate: null,
|
||||||
});
|
});
|
||||||
@ -91,27 +100,27 @@ describe("Folder Service", () => {
|
|||||||
{
|
{
|
||||||
id: "1",
|
id: "1",
|
||||||
name: {
|
name: {
|
||||||
decryptedValue: [],
|
|
||||||
encryptedString: "test",
|
encryptedString: "test",
|
||||||
encryptionType: 0,
|
encryptionType: 0,
|
||||||
|
decryptedValue: "DEC",
|
||||||
},
|
},
|
||||||
revisionDate: null,
|
revisionDate: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: "2",
|
||||||
name: {
|
name: {
|
||||||
decryptedValue: [],
|
|
||||||
encryptedString: "test 2",
|
encryptedString: "test 2",
|
||||||
encryptionType: 0,
|
encryptionType: 0,
|
||||||
|
decryptedValue: "DEC",
|
||||||
},
|
},
|
||||||
revisionDate: null,
|
revisionDate: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(await firstValueFrom(folderService.folderViews$)).toEqual([
|
expect(await firstValueFrom(folderService.folderViews$)).toEqual([
|
||||||
{ id: "1", name: [], revisionDate: null },
|
{ id: "1", name: "DEC", revisionDate: null },
|
||||||
{ id: "2", name: [], revisionDate: null },
|
{ id: "2", name: "DEC", revisionDate: null },
|
||||||
{ id: null, name: [], revisionDate: null },
|
{ id: null, name: undefined, revisionDate: null },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -122,7 +131,7 @@ describe("Folder Service", () => {
|
|||||||
{
|
{
|
||||||
id: "2",
|
id: "2",
|
||||||
name: {
|
name: {
|
||||||
decryptedValue: [],
|
decryptedValue: "DEC",
|
||||||
encryptedString: "test 2",
|
encryptedString: "test 2",
|
||||||
encryptionType: 0,
|
encryptionType: 0,
|
||||||
},
|
},
|
||||||
@ -131,8 +140,8 @@ describe("Folder Service", () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(await firstValueFrom(folderService.folderViews$)).toEqual([
|
expect(await firstValueFrom(folderService.folderViews$)).toEqual([
|
||||||
{ id: "2", name: [], revisionDate: null },
|
{ id: "2", name: "DEC", revisionDate: null },
|
||||||
{ id: null, name: [], revisionDate: null },
|
{ id: null, name: undefined, revisionDate: null },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -142,7 +151,7 @@ describe("Folder Service", () => {
|
|||||||
expect((await firstValueFrom(folderService.folders$)).length).toBe(0);
|
expect((await firstValueFrom(folderService.folders$)).length).toBe(0);
|
||||||
|
|
||||||
expect(await firstValueFrom(folderService.folderViews$)).toEqual([
|
expect(await firstValueFrom(folderService.folderViews$)).toEqual([
|
||||||
{ id: null, name: [], revisionDate: null },
|
{ id: null, name: undefined, revisionDate: null },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -166,17 +175,17 @@ describe("Folder Service", () => {
|
|||||||
it("null userId", async () => {
|
it("null userId", async () => {
|
||||||
await folderService.clear();
|
await folderService.clear();
|
||||||
|
|
||||||
stateService.received(1).setEncryptedFolders(Arg.any(), Arg.any());
|
expect(stateService.setEncryptedFolders).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(folderService.folders$)).length).toBe(0);
|
expect((await firstValueFrom(folderService.folders$)).length).toBe(0);
|
||||||
expect((await firstValueFrom(folderService.folderViews$)).length).toBe(0);
|
expect((await firstValueFrom(folderService.folderViews$)).length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("matching userId", async () => {
|
it("matching userId", async () => {
|
||||||
stateService.getUserId().resolves("1");
|
stateService.getUserId.mockResolvedValue("1");
|
||||||
await folderService.clear("1");
|
await folderService.clear("1");
|
||||||
|
|
||||||
stateService.received(1).setEncryptedFolders(Arg.any(), Arg.any());
|
expect(stateService.setEncryptedFolders).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(folderService.folders$)).length).toBe(0);
|
expect((await firstValueFrom(folderService.folders$)).length).toBe(0);
|
||||||
expect((await firstValueFrom(folderService.folderViews$)).length).toBe(0);
|
expect((await firstValueFrom(folderService.folderViews$)).length).toBe(0);
|
||||||
@ -185,7 +194,7 @@ describe("Folder Service", () => {
|
|||||||
it("missmatching userId", async () => {
|
it("missmatching userId", async () => {
|
||||||
await folderService.clear("12");
|
await folderService.clear("12");
|
||||||
|
|
||||||
stateService.received(1).setEncryptedFolders(Arg.any(), Arg.any());
|
expect(stateService.setEncryptedFolders).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect((await firstValueFrom(folderService.folders$)).length).toBe(1);
|
expect((await firstValueFrom(folderService.folders$)).length).toBe(1);
|
||||||
expect((await firstValueFrom(folderService.folderViews$)).length).toBe(2);
|
expect((await firstValueFrom(folderService.folderViews$)).length).toBe(2);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||||
@ -142,25 +141,26 @@ function expectEqualFolders(folders: Folder[], jsonResult: string) {
|
|||||||
|
|
||||||
describe("VaultExportService", () => {
|
describe("VaultExportService", () => {
|
||||||
let exportService: VaultExportService;
|
let exportService: VaultExportService;
|
||||||
let apiService: SubstituteOf<ApiService>;
|
let apiService: MockProxy<ApiService>;
|
||||||
let cryptoFunctionService: SubstituteOf<CryptoFunctionService>;
|
let cryptoFunctionService: MockProxy<CryptoFunctionService>;
|
||||||
let cipherService: SubstituteOf<CipherService>;
|
let cipherService: MockProxy<CipherService>;
|
||||||
let folderService: SubstituteOf<FolderService>;
|
let folderService: MockProxy<FolderService>;
|
||||||
let cryptoService: SubstituteOf<CryptoService>;
|
let cryptoService: MockProxy<CryptoService>;
|
||||||
let stateService: SubstituteOf<StateService>;
|
let stateService: MockProxy<StateService>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
apiService = Substitute.for<ApiService>();
|
apiService = mock<ApiService>();
|
||||||
cryptoFunctionService = Substitute.for<CryptoFunctionService>();
|
cryptoFunctionService = mock<CryptoFunctionService>();
|
||||||
cipherService = Substitute.for<CipherService>();
|
cipherService = mock<CipherService>();
|
||||||
folderService = Substitute.for<FolderService>();
|
folderService = mock<FolderService>();
|
||||||
cryptoService = Substitute.for<CryptoService>();
|
cryptoService = mock<CryptoService>();
|
||||||
stateService = Substitute.for<StateService>();
|
stateService = mock<StateService>();
|
||||||
|
|
||||||
folderService.getAllDecryptedFromState().resolves(UserFolderViews);
|
folderService.getAllDecryptedFromState.mockResolvedValue(UserFolderViews);
|
||||||
folderService.getAllFromState().resolves(UserFolders);
|
folderService.getAllFromState.mockResolvedValue(UserFolders);
|
||||||
stateService.getKdfType().resolves(KdfType.PBKDF2_SHA256);
|
stateService.getKdfType.mockResolvedValue(KdfType.PBKDF2_SHA256);
|
||||||
stateService.getKdfConfig().resolves(new KdfConfig(DEFAULT_PBKDF2_ITERATIONS));
|
stateService.getKdfConfig.mockResolvedValue(new KdfConfig(DEFAULT_PBKDF2_ITERATIONS));
|
||||||
|
cryptoService.encrypt.mockResolvedValue(new EncString("encrypted"));
|
||||||
|
|
||||||
exportService = new VaultExportService(
|
exportService = new VaultExportService(
|
||||||
folderService,
|
folderService,
|
||||||
@ -173,7 +173,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("exports unencrypted user ciphers", async () => {
|
it("exports unencrypted user ciphers", async () => {
|
||||||
cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1));
|
cipherService.getAllDecrypted.mockResolvedValue(UserCipherViews.slice(0, 1));
|
||||||
|
|
||||||
const actual = await exportService.getExport("json");
|
const actual = await exportService.getExport("json");
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("exports encrypted json user ciphers", async () => {
|
it("exports encrypted json user ciphers", async () => {
|
||||||
cipherService.getAll().resolves(UserCipherDomains.slice(0, 1));
|
cipherService.getAll.mockResolvedValue(UserCipherDomains.slice(0, 1));
|
||||||
|
|
||||||
const actual = await exportService.getExport("encrypted_json");
|
const actual = await exportService.getExport("encrypted_json");
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not unencrypted export trashed user items", async () => {
|
it("does not unencrypted export trashed user items", async () => {
|
||||||
cipherService.getAllDecrypted().resolves(UserCipherViews);
|
cipherService.getAllDecrypted.mockResolvedValue(UserCipherViews);
|
||||||
|
|
||||||
const actual = await exportService.getExport("json");
|
const actual = await exportService.getExport("json");
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not encrypted export trashed user items", async () => {
|
it("does not encrypted export trashed user items", async () => {
|
||||||
cipherService.getAll().resolves(UserCipherDomains);
|
cipherService.getAll.mockResolvedValue(UserCipherDomains);
|
||||||
|
|
||||||
const actual = await exportService.getExport("encrypted_json");
|
const actual = await exportService.getExport("encrypted_json");
|
||||||
|
|
||||||
@ -207,21 +207,21 @@ describe("VaultExportService", () => {
|
|||||||
describe("password protected export", () => {
|
describe("password protected export", () => {
|
||||||
let exportString: string;
|
let exportString: string;
|
||||||
let exportObject: any;
|
let exportObject: any;
|
||||||
let mac: SubstituteOf<EncString>;
|
let mac: MockProxy<EncString>;
|
||||||
let data: SubstituteOf<EncString>;
|
let data: MockProxy<EncString>;
|
||||||
const password = "password";
|
const password = "password";
|
||||||
const salt = "salt";
|
const salt = "salt";
|
||||||
|
|
||||||
describe("export json object", () => {
|
describe("export json object", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mac = Substitute.for<EncString>();
|
mac = mock<EncString>();
|
||||||
data = Substitute.for<EncString>();
|
data = mock<EncString>();
|
||||||
|
|
||||||
mac.encryptedString.returns("mac" as EncryptedString);
|
mac.encryptedString = "mac" as EncryptedString;
|
||||||
data.encryptedString.returns("encData" as EncryptedString);
|
data.encryptedString = "encData" as EncryptedString;
|
||||||
|
|
||||||
jest.spyOn(Utils, "fromBufferToB64").mockReturnValue(salt);
|
jest.spyOn(Utils, "fromBufferToB64").mockReturnValue(salt);
|
||||||
cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1));
|
cipherService.getAllDecrypted.mockResolvedValue(UserCipherViews.slice(0, 1));
|
||||||
|
|
||||||
exportString = await exportService.getPasswordProtectedExport(password);
|
exportString = await exportService.getPasswordProtectedExport(password);
|
||||||
exportObject = JSON.parse(exportString);
|
exportObject = JSON.parse(exportString);
|
||||||
@ -248,7 +248,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has a mac property", async () => {
|
it("has a mac property", async () => {
|
||||||
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(mac);
|
cryptoService.encrypt.mockResolvedValue(mac);
|
||||||
exportString = await exportService.getPasswordProtectedExport(password);
|
exportString = await exportService.getPasswordProtectedExport(password);
|
||||||
exportObject = JSON.parse(exportString);
|
exportObject = JSON.parse(exportString);
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has data property", async () => {
|
it("has data property", async () => {
|
||||||
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(data);
|
cryptoService.encrypt.mockResolvedValue(data);
|
||||||
exportString = await exportService.getPasswordProtectedExport(password);
|
exportString = await exportService.getPasswordProtectedExport(password);
|
||||||
exportObject = JSON.parse(exportString);
|
exportObject = JSON.parse(exportString);
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("exported unencrypted object contains folders", async () => {
|
it("exported unencrypted object contains folders", async () => {
|
||||||
cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1));
|
cipherService.getAllDecrypted.mockResolvedValue(UserCipherViews.slice(0, 1));
|
||||||
await folderService.getAllDecryptedFromState();
|
await folderService.getAllDecryptedFromState();
|
||||||
const actual = await exportService.getExport("json");
|
const actual = await exportService.getExport("json");
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ describe("VaultExportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("exported encrypted json contains folders", async () => {
|
it("exported encrypted json contains folders", async () => {
|
||||||
cipherService.getAll().resolves(UserCipherDomains.slice(0, 1));
|
cipherService.getAll.mockResolvedValue(UserCipherDomains.slice(0, 1));
|
||||||
await folderService.getAllFromState();
|
await folderService.getAllFromState();
|
||||||
const actual = await exportService.getExport("encrypted_json");
|
const actual = await exportService.getExport("encrypted_json");
|
||||||
|
|
||||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -79,7 +79,6 @@
|
|||||||
"@compodoc/compodoc": "1.1.21",
|
"@compodoc/compodoc": "1.1.21",
|
||||||
"@electron/notarize": "1.2.4",
|
"@electron/notarize": "1.2.4",
|
||||||
"@electron/rebuild": "3.2.13",
|
"@electron/rebuild": "3.2.13",
|
||||||
"@fluffy-spoon/substitute": "1.208.0",
|
|
||||||
"@ngtools/webpack": "15.2.9",
|
"@ngtools/webpack": "15.2.9",
|
||||||
"@storybook/addon-a11y": "7.3.0",
|
"@storybook/addon-a11y": "7.3.0",
|
||||||
"@storybook/addon-actions": "7.3.0",
|
"@storybook/addon-actions": "7.3.0",
|
||||||
@ -6011,19 +6010,6 @@
|
|||||||
"integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==",
|
"integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@fluffy-spoon/substitute": {
|
|
||||||
"version": "1.208.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz",
|
|
||||||
"integrity": "sha512-BU5vKRoK4OYlKzDtyg4HbtWnUNLOvV0ntqEZIphz+mq2G0HlVFywwJ7M+FbIcnJVDbUReS01FyL5x8R01r7zBg==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/substitute-js#section-contribute"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@foliojs-fork/fontkit": {
|
"node_modules/@foliojs-fork/fontkit": {
|
||||||
"version": "1.9.1",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.1.tgz",
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
"@compodoc/compodoc": "1.1.21",
|
"@compodoc/compodoc": "1.1.21",
|
||||||
"@electron/notarize": "1.2.4",
|
"@electron/notarize": "1.2.4",
|
||||||
"@electron/rebuild": "3.2.13",
|
"@electron/rebuild": "3.2.13",
|
||||||
"@fluffy-spoon/substitute": "1.208.0",
|
|
||||||
"@ngtools/webpack": "15.2.9",
|
"@ngtools/webpack": "15.2.9",
|
||||||
"@storybook/addon-a11y": "7.3.0",
|
"@storybook/addon-a11y": "7.3.0",
|
||||||
"@storybook/addon-actions": "7.3.0",
|
"@storybook/addon-actions": "7.3.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user