mirror of
https://github.com/bitwarden/browser.git
synced 2025-03-28 16:16:50 +01:00
Feature/move to jest (#744)
* Switch to jest * Fix jslib-angular package name * Make angular test project * Split up tests by jslib project * Remove obsolete node test script * Use legacy deps with jest-preset-angular * Move web tests to common * Remove build from pipeline This was only being used because we were not using ts runners. We are now, so build is unnecessary
This commit is contained in:
parent
13ef7aea7d
commit
a4fba0e1c5
.eslintignore
.github/workflows
angular
common
jest.config.jstsconfig.jsontsconfig.spec.json
spec
importers
bitwardenJsonImporter.spec.tsbitwardenPasswordProtectedImporter.spec.tsdashlaneCsvImporter.spec.tsfirefoxCsvImporter.spec.tsfsecureFskImporter.spec.tskeepass2XmlImporter.spec.tskeeperJsonImporter.spec.tslastpassCsvImporter.spec.tsmykiCsvImporter.spec.tsnordpassCsvImporter.spec.tsonepassword1PifImporter.spec.tsonepassword1PuxImporter.spec.tsonepasswordMacCsvImporter.spec.tsonepasswordWinCsvImporter.spec.tssafariCsvImporter.spec.ts
testData
bitwardenJson
dashlaneCsv
credentials.csv.tsid.csv.tsmultiplePersonalInfo.csv.tspayments.csv.tspersonalInfo.csv.tssecurenotes.csv.ts
firefoxCsv
keeperJson
mykiCsv
UserAccount.csv.tsUserCreditCard.csv.tsUserIdCard.csv.tsUserIdentity.csv.tsUserNote.csv.tsUserTwofa.csv.ts
nordpassCsv
onePassword1Pux
APICredentials.tsBankAccount.tsCreditCard.tsDatabase.tsDriversLicense.tsEmailAccount.tsIdentityData.tsLoginData.tsMedicalRecord.tsMembership.tsOnepux_example.tsOutdoorLicense.tsPassport.tsPassword.tsRewardsProgram.tsSSN.tsSanitizedExport.tsSecureNote.tsServer.tsSoftwareLicense.tsWirelessRouter.ts
onePasswordCsv
creditCard.mac.csv.tscreditCard.windows.csv.tsidentity.mac.csv.tsidentity.windows.csv.tsmultipleItems.mac.csv.tsmultipleItems.windows.csv.ts
safariCsv
safeInCloud
misc
logInStrategies
apiLogIn.strategy.spec.tslogIn.strategy.spec.tspasswordLogIn.strategy.spec.tsssoLogIn.strategy.spec.ts
sequentialize.spec.tsthrottle.spec.tsutils.spec.tsservices
cipher.service.spec.tsconsoleLog.service.spec.tsexport.service.spec.tsimport.service.spec.tsstateMigration.service.ts
test.tsutils.tsweb/services
electron
jest.config.jsnode
@ -1,3 +1,4 @@
|
||||
**/dist
|
||||
**/jest.config.js
|
||||
|
||||
**/node_modules
|
||||
|
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -53,9 +53,6 @@ jobs:
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Run tests
|
||||
if: runner.os != 'Linux'
|
||||
run: npm run test
|
||||
@ -67,9 +64,6 @@ jobs:
|
||||
name: test-coverage
|
||||
path: coverage/
|
||||
|
||||
- name: Run Node tests
|
||||
run: npm run test:node
|
||||
|
||||
check-failures:
|
||||
name: Check for failures
|
||||
if: always()
|
||||
|
18
angular/jest.config.js
Normal file
18
angular/jest.config.js
Normal file
@ -0,0 +1,18 @@
|
||||
const { pathsToModuleNameMapper } = require("ts-jest/utils");
|
||||
|
||||
const { compilerOptions } = require("./tsconfig");
|
||||
|
||||
module.exports = {
|
||||
name: "angular",
|
||||
displayName: "angular tests",
|
||||
preset: "jest-preset-angular",
|
||||
roots: ["<rootDir>/spec/"],
|
||||
testMatch: ["**/+(*.)+(spec).+(ts)"],
|
||||
setupFilesAfterEnv: ["<rootDir>/spec/test.ts"],
|
||||
collectCoverage: true,
|
||||
coverageReporters: ["html", "lcov"],
|
||||
coverageDirectory: "coverage",
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
};
|
17
angular/package-lock.json
generated
17
angular/package-lock.json
generated
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@bitwarden/jslib-common",
|
||||
"name": "@bitwarden/jslib-angular",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@bitwarden/jslib-common",
|
||||
"name": "@bitwarden/jslib-angular",
|
||||
"version": "0.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
@ -31,6 +31,7 @@
|
||||
}
|
||||
},
|
||||
"../common": {
|
||||
"name": "@bitwarden/jslib-common",
|
||||
"version": "0.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
@ -39,7 +40,7 @@
|
||||
"big-integer": "1.6.48",
|
||||
"browser-hrtime": "^1.1.8",
|
||||
"lunr": "^2.3.9",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-forge": "^1.2.1",
|
||||
"papaparse": "^5.3.0",
|
||||
"rxjs": "^7.4.0",
|
||||
"tldjs": "^2.3.1",
|
||||
@ -47,8 +48,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lunr": "^2.3.3",
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node-forge": "^0.9.7",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/node-forge": "^1.0.1",
|
||||
"@types/papaparse": "^5.2.5",
|
||||
"@types/tldjs": "^2.3.0",
|
||||
"@types/zxcvbn": "^4.4.1",
|
||||
@ -472,15 +473,15 @@
|
||||
"@microsoft/signalr": "5.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "5.0.10",
|
||||
"@types/lunr": "^2.3.3",
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node-forge": "^0.9.7",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/node-forge": "^1.0.1",
|
||||
"@types/papaparse": "^5.2.5",
|
||||
"@types/tldjs": "^2.3.0",
|
||||
"@types/zxcvbn": "^4.4.1",
|
||||
"big-integer": "1.6.48",
|
||||
"browser-hrtime": "^1.1.8",
|
||||
"lunr": "^2.3.9",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-forge": "^1.2.1",
|
||||
"papaparse": "^5.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.4.0",
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@bitwarden/jslib-common",
|
||||
"name": "@bitwarden/jslib-angular",
|
||||
"version": "0.0.0",
|
||||
"description": "Common code used across Bitwarden JavaScript projects.",
|
||||
"keywords": [
|
||||
|
28
angular/spec/test.ts
Normal file
28
angular/spec/test.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { webcrypto } from "crypto";
|
||||
import "jest-preset-angular/setup-jest";
|
||||
|
||||
Object.defineProperty(window, "CSS", { value: null });
|
||||
Object.defineProperty(window, "getComputedStyle", {
|
||||
value: () => {
|
||||
return {
|
||||
display: "none",
|
||||
appearance: ["-webkit-appearance"],
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(document, "doctype", {
|
||||
value: "<!DOCTYPE html>",
|
||||
});
|
||||
Object.defineProperty(document.body.style, "transform", {
|
||||
value: () => {
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(window, "crypto", {
|
||||
value: webcrypto,
|
||||
});
|
@ -2,7 +2,8 @@
|
||||
"extends": "../shared/tsconfig",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"jslib-common/*": ["../common/src/*"]
|
||||
"jslib-common/*": ["../common/src/*"],
|
||||
"jslib-angular/*": ["./src/"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "spec"],
|
||||
|
3
angular/tsconfig.spec.json
Normal file
3
angular/tsconfig.spec.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "./tsconfig.json"
|
||||
}
|
19
common/jest.config.js
Normal file
19
common/jest.config.js
Normal file
@ -0,0 +1,19 @@
|
||||
const { pathsToModuleNameMapper } = require("ts-jest/utils");
|
||||
|
||||
const { compilerOptions } = require("./tsconfig");
|
||||
|
||||
module.exports = {
|
||||
name: "common",
|
||||
displayName: "common jslib tests",
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "jsdom",
|
||||
roots: ["<rootDir>/spec/"],
|
||||
testMatch: ["**/+(*.)+(spec).+(ts)"],
|
||||
setupFilesAfterEnv: ["<rootDir>/spec/test.ts"],
|
||||
collectCoverage: true,
|
||||
coverageReporters: ["html", "lcov"],
|
||||
coverageDirectory: "coverage",
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
};
|
@ -30,14 +30,12 @@ import { WirelessRouterData } from "./testData/onePassword1Pux/WirelessRouter";
|
||||
function validateCustomField(fields: FieldView[], fieldName: string, expectedValue: any) {
|
||||
expect(fields).toBeDefined();
|
||||
const customField = fields.find((f) => f.name === fieldName);
|
||||
expect(customField).withContext(`CustomField: ('${fieldName}') was not found`).toBeDefined();
|
||||
expect(customField).toBeDefined();
|
||||
|
||||
expect(customField.value)
|
||||
.withContext(`Customfield: ('${fieldName}'), should be equal to: '${expectedValue}'`)
|
||||
.toEqual(expectedValue);
|
||||
expect(customField.value).toEqual(expectedValue);
|
||||
}
|
||||
|
||||
describe("1Password 1Pux Importer", async () => {
|
||||
describe("1Password 1Pux Importer", () => {
|
||||
const OnePuxExampleFileJson = JSON.stringify(OnePuxExampleFile);
|
||||
const LoginDataJson = JSON.stringify(LoginData);
|
||||
const CreditCardDataJson = JSON.stringify(CreditCardData);
|
||||
@ -83,7 +81,7 @@ describe("1Password 1Pux Importer", async () => {
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.favorite).toBeTrue();
|
||||
expect(cipher.favorite).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle custom boolean fields", async () => {
|
@ -10,7 +10,7 @@ function expectIdentity(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
|
||||
expect(cipher.identity).toEqual(
|
||||
jasmine.objectContaining({
|
||||
expect.objectContaining({
|
||||
firstName: "first name",
|
||||
middleName: "mi",
|
||||
lastName: "last name",
|
||||
@ -28,7 +28,7 @@ function expectCreditCard(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
|
||||
expect(cipher.card).toEqual(
|
||||
jasmine.objectContaining({
|
||||
expect.objectContaining({
|
||||
number: "4111111111111111",
|
||||
code: "111",
|
||||
cardholderName: "test",
|
@ -12,7 +12,7 @@ function expectIdentity(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
|
||||
expect(cipher.identity).toEqual(
|
||||
jasmine.objectContaining({
|
||||
expect.objectContaining({
|
||||
firstName: "first name",
|
||||
middleName: "mi",
|
||||
lastName: "last name",
|
||||
@ -24,7 +24,7 @@ function expectIdentity(cipher: CipherView) {
|
||||
);
|
||||
|
||||
expect(cipher.fields).toEqual(
|
||||
jasmine.arrayContaining([
|
||||
expect.arrayContaining([
|
||||
Object.assign(new FieldView(), {
|
||||
type: FieldType.Text,
|
||||
name: "address",
|
||||
@ -38,7 +38,7 @@ function expectCreditCard(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
|
||||
expect(cipher.card).toEqual(
|
||||
jasmine.objectContaining({
|
||||
expect.objectContaining({
|
||||
number: "4111111111111111",
|
||||
code: "111",
|
||||
cardholderName: "test",
|
@ -57,25 +57,25 @@ describe("ConsoleLogService", () => {
|
||||
|
||||
it("writes debug/info messages to console.log", () => {
|
||||
logService.debug("this is a debug message");
|
||||
expect(caughtMessage).toEqual({
|
||||
log: jasmine.arrayWithExactContents(["this is a debug message"]),
|
||||
expect(caughtMessage).toMatchObject({
|
||||
log: { "0": "this is a debug message" },
|
||||
});
|
||||
|
||||
logService.info("this is an info message");
|
||||
expect(caughtMessage).toEqual({
|
||||
log: jasmine.arrayWithExactContents(["this is an info message"]),
|
||||
expect(caughtMessage).toMatchObject({
|
||||
log: { "0": "this is an info message" },
|
||||
});
|
||||
});
|
||||
it("writes warning messages to console.warn", () => {
|
||||
logService.warning("this is a warning message");
|
||||
expect(caughtMessage).toEqual({
|
||||
warn: jasmine.arrayWithExactContents(["this is a warning message"]),
|
||||
expect(caughtMessage).toMatchObject({
|
||||
warn: { 0: "this is a warning message" },
|
||||
});
|
||||
});
|
||||
it("writes error messages to console.error", () => {
|
||||
logService.error("this is an error message");
|
||||
expect(caughtMessage).toEqual({
|
||||
error: jasmine.arrayWithExactContents(["this is an error message"]),
|
||||
expect(caughtMessage).toMatchObject({
|
||||
error: { 0: "this is an error message" },
|
||||
});
|
||||
});
|
||||
|
||||
@ -87,9 +87,9 @@ describe("ConsoleLogService", () => {
|
||||
expect(duration[1]).toBeGreaterThan(0);
|
||||
expect(duration[1]).toBeLessThan(500 * 10e6);
|
||||
|
||||
expect(caughtMessage).toEqual(jasmine.arrayContaining([]));
|
||||
expect(caughtMessage).toEqual(expect.arrayContaining([]));
|
||||
expect(caughtMessage.log.length).toBe(1);
|
||||
expect(caughtMessage.log[0]).toEqual(jasmine.stringMatching(/^default: \d+\.?\d*ms$/));
|
||||
expect(caughtMessage.log[0]).toEqual(expect.stringMatching(/^default: \d+\.?\d*ms$/));
|
||||
});
|
||||
|
||||
it("filters time output", async () => {
|
@ -16,7 +16,7 @@ import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { LoginView } from "jslib-common/models/view/loginView";
|
||||
import { ExportService } from "jslib-common/services/export.service";
|
||||
|
||||
import { BuildTestObject, GetUniqueString } from "../../utils";
|
||||
import { BuildTestObject, GetUniqueString } from "../utils";
|
||||
|
||||
const UserCipherViews = [
|
||||
generateCipherView(false),
|
||||
@ -154,10 +154,10 @@ describe("ExportService", () => {
|
||||
mac = Substitute.for<EncString>();
|
||||
data = Substitute.for<EncString>();
|
||||
|
||||
mac.encryptedString = "mac";
|
||||
data.encryptedString = "encData";
|
||||
mac.encryptedString.returns("mac");
|
||||
data.encryptedString.returns("encData");
|
||||
|
||||
spyOn(Utils, "fromBufferToB64").and.returnValue(salt);
|
||||
jest.spyOn(Utils, "fromBufferToB64").mockReturnValue(salt);
|
||||
cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1));
|
||||
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
@ -184,13 +184,19 @@ describe("ExportService", () => {
|
||||
expect(exportObject.kdfType).toEqual(KdfType.PBKDF2_SHA256);
|
||||
});
|
||||
|
||||
it("has a mac property", () => {
|
||||
it("has a mac property", async () => {
|
||||
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(mac);
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
exportObject = JSON.parse(exportString);
|
||||
|
||||
expect(exportObject.encKeyValidation_DO_NOT_EDIT).toEqual(mac.encryptedString);
|
||||
});
|
||||
|
||||
it("has data property", () => {
|
||||
it("has data property", async () => {
|
||||
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(data);
|
||||
exportString = await exportService.getPasswordProtectedExport(password);
|
||||
exportObject = JSON.parse(exportString);
|
||||
|
||||
expect(exportObject.data).toEqual(data.encryptedString);
|
||||
});
|
||||
|
@ -65,7 +65,7 @@ describe("ImportService", () => {
|
||||
});
|
||||
|
||||
it("has the appropriate password", () => {
|
||||
expect(Object.entries(importer)).toEqual(jasmine.arrayContaining([["password", password]]));
|
||||
expect(Object.entries(importer)).toEqual(expect.arrayContaining([["password", password]]));
|
||||
});
|
||||
});
|
||||
});
|
5
common/spec/test.ts
Normal file
5
common/spec/test.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { webcrypto } from "crypto";
|
||||
|
||||
Object.defineProperty(window, "crypto", {
|
||||
value: webcrypto,
|
||||
});
|
@ -102,7 +102,7 @@ describe("WebCrypto Function Service", () => {
|
||||
32,
|
||||
"sha256"
|
||||
);
|
||||
await expectAsync(f).toBeRejectedWith(new Error("prk is too small."));
|
||||
await expect(f).rejects.toEqual(new Error("prk is too small."));
|
||||
});
|
||||
|
||||
it("should fail with outputByteSize is too large", async () => {
|
||||
@ -113,7 +113,7 @@ describe("WebCrypto Function Service", () => {
|
||||
8161,
|
||||
"sha256"
|
||||
);
|
||||
await expectAsync(f).toBeRejectedWith(new Error("outputByteSize is too large."));
|
||||
await expect(f).rejects.toEqual(new Error("outputByteSize is too large."));
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,10 @@
|
||||
{
|
||||
"extends": "../shared/tsconfig",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"jslib-common/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "spec"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
3
common/tsconfig.spec.json
Normal file
3
common/tsconfig.spec.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "./tsconfig.json"
|
||||
}
|
17
electron/jest.config.js
Normal file
17
electron/jest.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
const { pathsToModuleNameMapper } = require("ts-jest/utils");
|
||||
|
||||
const { compilerOptions } = require("./tsconfig");
|
||||
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "jsdom",
|
||||
roots: ["<rootDir>/spec/"],
|
||||
testMatch: ["**/+(*.)+(spec).+(ts)"],
|
||||
setupFilesAfterEnv: ["<rootDir>/spec/test.ts"],
|
||||
collectCoverage: true,
|
||||
coverageReporters: ["html", "lcov"],
|
||||
coverageDirectory: "coverage",
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
};
|
@ -4,6 +4,6 @@ describe("ElectronLogService", () => {
|
||||
it("sets dev based on electron method", () => {
|
||||
process.env.ELECTRON_IS_DEV = "1";
|
||||
const logService = new ElectronLogService();
|
||||
expect(logService).toEqual(jasmine.objectContaining({ isDev: true }) as any);
|
||||
expect(logService).toEqual(expect.objectContaining({ isDev: true }) as any);
|
||||
});
|
||||
});
|
0
electron/spec/test.ts
Normal file
0
electron/spec/test.ts
Normal file
@ -2,7 +2,8 @@
|
||||
"extends": "../shared/tsconfig",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"jslib-common/*": ["../common/src/*"]
|
||||
"jslib-common/*": ["../common/src/*"],
|
||||
"jslib-electron/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "spec"],
|
||||
|
3
electron/tsconfig.spec.json
Normal file
3
electron/tsconfig.spec.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "./tsconfig.json"
|
||||
}
|
18
jest.config.js
Normal file
18
jest.config.js
Normal file
@ -0,0 +1,18 @@
|
||||
const { pathsToModuleNameMapper } = require("ts-jest/utils");
|
||||
|
||||
const { compilerOptions } = require("./tsconfig");
|
||||
|
||||
module.exports = {
|
||||
collectCoverage: true,
|
||||
coverageReporters: ["html", "lcov"],
|
||||
coverageDirectory: "coverage",
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
projects: [
|
||||
"<rootDir>/angular/jest.config.js",
|
||||
"<rootDir>/common/jest.config.js",
|
||||
"<rootDir>/electron/jest.config.js",
|
||||
"<rootDir>/node/jest.config.js",
|
||||
],
|
||||
};
|
16
node/jest.config.js
Normal file
16
node/jest.config.js
Normal file
@ -0,0 +1,16 @@
|
||||
const { pathsToModuleNameMapper } = require("ts-jest/utils");
|
||||
|
||||
const { compilerOptions } = require("./tsconfig");
|
||||
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
roots: ["<rootDir>/spec/"],
|
||||
testMatch: ["**/+(*.)+(spec).+(ts)"],
|
||||
setupFilesAfterEnv: ["<rootDir>/spec/test.ts"],
|
||||
collectCoverage: true,
|
||||
coverageReporters: ["html", "lcov"],
|
||||
coverageDirectory: "coverage",
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user