mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
Apply Prettier (#581)
This commit is contained in:
@@ -1,73 +1,73 @@
|
||||
import { FirefoxCsvImporter as Importer } from 'jslib-common/importers/firefoxCsvImporter';
|
||||
import { FirefoxCsvImporter as Importer } from "jslib-common/importers/firefoxCsvImporter";
|
||||
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { LoginUriView } from 'jslib-common/models/view/loginUriView';
|
||||
import { LoginView } from 'jslib-common/models/view/loginView';
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { LoginUriView } from "jslib-common/models/view/loginUriView";
|
||||
import { LoginView } from "jslib-common/models/view/loginView";
|
||||
|
||||
import { data as firefoxAccountsData } from './testData/firefoxCsv/firefoxAccountsData.csv';
|
||||
import { data as simplePasswordData } from './testData/firefoxCsv/simplePasswordData.csv';
|
||||
import { data as firefoxAccountsData } from "./testData/firefoxCsv/firefoxAccountsData.csv";
|
||||
import { data as simplePasswordData } from "./testData/firefoxCsv/simplePasswordData.csv";
|
||||
|
||||
const CipherData = [
|
||||
{
|
||||
title: 'should parse password',
|
||||
csv: simplePasswordData,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: 'example.com',
|
||||
login: Object.assign(new LoginView(), {
|
||||
username: 'foo',
|
||||
password: 'bar',
|
||||
uris: [
|
||||
Object.assign(new LoginUriView(), {
|
||||
uri: 'https://example.com',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
notes: null,
|
||||
type: 1,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'should skip "chrome://FirefoxAccounts"',
|
||||
csv: firefoxAccountsData,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: 'example.com',
|
||||
login: Object.assign(new LoginView(), {
|
||||
username: 'foo',
|
||||
password: 'bar',
|
||||
uris: [
|
||||
Object.assign(new LoginUriView(), {
|
||||
uri: 'https://example.com',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
notes: null,
|
||||
type: 1,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "should parse password",
|
||||
csv: simplePasswordData,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: "example.com",
|
||||
login: Object.assign(new LoginView(), {
|
||||
username: "foo",
|
||||
password: "bar",
|
||||
uris: [
|
||||
Object.assign(new LoginUriView(), {
|
||||
uri: "https://example.com",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
notes: null,
|
||||
type: 1,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'should skip "chrome://FirefoxAccounts"',
|
||||
csv: firefoxAccountsData,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: "example.com",
|
||||
login: Object.assign(new LoginView(), {
|
||||
username: "foo",
|
||||
password: "bar",
|
||||
uris: [
|
||||
Object.assign(new LoginUriView(), {
|
||||
uri: "https://example.com",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
notes: null,
|
||||
type: 1,
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
describe('Firefox CSV Importer', () => {
|
||||
CipherData.forEach(data => {
|
||||
it(data.title, async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(data.csv);
|
||||
expect(result != null).toBe(true);
|
||||
expect(result.ciphers.length).toBeGreaterThan(0);
|
||||
describe("Firefox CSV Importer", () => {
|
||||
CipherData.forEach((data) => {
|
||||
it(data.title, async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(data.csv);
|
||||
expect(result != null).toBe(true);
|
||||
expect(result.ciphers.length).toBeGreaterThan(0);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
let property: keyof typeof data.expected;
|
||||
for (property in data.expected) {
|
||||
if (data.expected.hasOwnProperty(property)) {
|
||||
expect(cipher.hasOwnProperty(property)).toBe(true);
|
||||
expect(cipher[property]).toEqual(data.expected[property]);
|
||||
}
|
||||
}
|
||||
});
|
||||
const cipher = result.ciphers.shift();
|
||||
let property: keyof typeof data.expected;
|
||||
for (property in data.expected) {
|
||||
if (data.expected.hasOwnProperty(property)) {
|
||||
expect(cipher.hasOwnProperty(property)).toBe(true);
|
||||
expect(cipher[property]).toEqual(data.expected[property]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,80 +1,77 @@
|
||||
import { FSecureFskImporter as Importer } from 'jslib-common/importers/fsecureFskImporter';
|
||||
import { FSecureFskImporter as Importer } from "jslib-common/importers/fsecureFskImporter";
|
||||
|
||||
const TestDataWithStyleSetToWebsite: string =
|
||||
JSON.stringify({
|
||||
data: {
|
||||
'8d58b5cf252dd06fbd98f5289e918ab1': {
|
||||
color: '#00baff',
|
||||
reatedDate: 1609302913,
|
||||
creditCvv: '',
|
||||
creditExpiry: '',
|
||||
creditNumber: '',
|
||||
favorite: 0,
|
||||
modifiedDate: 1609302913,
|
||||
notes: 'note',
|
||||
password: 'word',
|
||||
passwordList: [],
|
||||
passwordModifiedDate: 1609302913,
|
||||
rev: 1,
|
||||
service: 'My first pass',
|
||||
style: 'website',
|
||||
type: 1,
|
||||
url: 'https://bitwarden.com',
|
||||
username: 'pass',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const TestDataWithStyleSetToGlobe: string =
|
||||
JSON.stringify({
|
||||
data: {
|
||||
'8d58b5cf252dd06fbd98f5289e918ab1': {
|
||||
color: '#00baff',
|
||||
reatedDate: 1609302913,
|
||||
creditCvv: '',
|
||||
creditExpiry: '',
|
||||
creditNumber: '',
|
||||
favorite: 0,
|
||||
modifiedDate: 1609302913,
|
||||
notes: 'note',
|
||||
password: 'word',
|
||||
passwordList: [],
|
||||
passwordModifiedDate: 1609302913,
|
||||
rev: 1,
|
||||
service: 'My first pass',
|
||||
style: 'globe',
|
||||
type: 1,
|
||||
url: 'https://bitwarden.com',
|
||||
username: 'pass',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
describe('FSecure FSK Importer', () => {
|
||||
it('should parse data with style set to website', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestDataWithStyleSetToWebsite);
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.login.username).toEqual('pass');
|
||||
expect(cipher.login.password).toEqual('word');
|
||||
expect(cipher.login.uris.length).toEqual(1);
|
||||
const uriView = cipher.login.uris.shift();
|
||||
expect(uriView.uri).toEqual('https://bitwarden.com');
|
||||
});
|
||||
|
||||
it('should parse data with style set to globe', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestDataWithStyleSetToGlobe);
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.login.username).toEqual('pass');
|
||||
expect(cipher.login.password).toEqual('word');
|
||||
expect(cipher.login.uris.length).toEqual(1);
|
||||
const uriView = cipher.login.uris.shift();
|
||||
expect(uriView.uri).toEqual('https://bitwarden.com');
|
||||
});
|
||||
const TestDataWithStyleSetToWebsite: string = JSON.stringify({
|
||||
data: {
|
||||
"8d58b5cf252dd06fbd98f5289e918ab1": {
|
||||
color: "#00baff",
|
||||
reatedDate: 1609302913,
|
||||
creditCvv: "",
|
||||
creditExpiry: "",
|
||||
creditNumber: "",
|
||||
favorite: 0,
|
||||
modifiedDate: 1609302913,
|
||||
notes: "note",
|
||||
password: "word",
|
||||
passwordList: [],
|
||||
passwordModifiedDate: 1609302913,
|
||||
rev: 1,
|
||||
service: "My first pass",
|
||||
style: "website",
|
||||
type: 1,
|
||||
url: "https://bitwarden.com",
|
||||
username: "pass",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const TestDataWithStyleSetToGlobe: string = JSON.stringify({
|
||||
data: {
|
||||
"8d58b5cf252dd06fbd98f5289e918ab1": {
|
||||
color: "#00baff",
|
||||
reatedDate: 1609302913,
|
||||
creditCvv: "",
|
||||
creditExpiry: "",
|
||||
creditNumber: "",
|
||||
favorite: 0,
|
||||
modifiedDate: 1609302913,
|
||||
notes: "note",
|
||||
password: "word",
|
||||
passwordList: [],
|
||||
passwordModifiedDate: 1609302913,
|
||||
rev: 1,
|
||||
service: "My first pass",
|
||||
style: "globe",
|
||||
type: 1,
|
||||
url: "https://bitwarden.com",
|
||||
username: "pass",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe("FSecure FSK Importer", () => {
|
||||
it("should parse data with style set to website", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestDataWithStyleSetToWebsite);
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.login.username).toEqual("pass");
|
||||
expect(cipher.login.password).toEqual("word");
|
||||
expect(cipher.login.uris.length).toEqual(1);
|
||||
const uriView = cipher.login.uris.shift();
|
||||
expect(uriView.uri).toEqual("https://bitwarden.com");
|
||||
});
|
||||
|
||||
it("should parse data with style set to globe", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestDataWithStyleSetToGlobe);
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.login.username).toEqual("pass");
|
||||
expect(cipher.login.password).toEqual("word");
|
||||
expect(cipher.login.uris.length).toEqual(1);
|
||||
const uriView = cipher.login.uris.shift();
|
||||
expect(uriView.uri).toEqual("https://bitwarden.com");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { KeePass2XmlImporter as Importer } from 'jslib-common/importers/keepass2XmlImporter';
|
||||
import { KeePass2XmlImporter as Importer } from "jslib-common/importers/keepass2XmlImporter";
|
||||
|
||||
const TestData: string = `<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<KeePassFile>
|
||||
@@ -180,10 +180,10 @@ line2</Value>
|
||||
</Root>
|
||||
</KeePassFile>`;
|
||||
|
||||
describe('KeePass2 Xml Importer', () => {
|
||||
it('should parse XML data', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
expect(result != null).toBe(true);
|
||||
});
|
||||
describe("KeePass2 Xml Importer", () => {
|
||||
it("should parse XML data", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
expect(result != null).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
import { LastPassCsvImporter as Importer } from 'jslib-common/importers/lastpassCsvImporter';
|
||||
import { LastPassCsvImporter as Importer } from "jslib-common/importers/lastpassCsvImporter";
|
||||
|
||||
import { ImportResult } from 'jslib-common/models/domain/importResult';
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { FieldView } from 'jslib-common/models/view/fieldView';
|
||||
import { ImportResult } from "jslib-common/models/domain/importResult";
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { FieldView } from "jslib-common/models/view/fieldView";
|
||||
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { FieldType } from 'jslib-common/enums/fieldType';
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
import { FieldType } from "jslib-common/enums/fieldType";
|
||||
|
||||
function baseExcept(result: ImportResult) {
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
}
|
||||
|
||||
function expectLogin(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Login);
|
||||
expect(cipher.type).toBe(CipherType.Login);
|
||||
|
||||
expect(cipher.name).toBe('example.com');
|
||||
expect(cipher.notes).toBe('super secure notes');
|
||||
expect(cipher.login.uri).toBe('http://example.com');
|
||||
expect(cipher.login.username).toBe('someUser');
|
||||
expect(cipher.login.password).toBe('myPassword');
|
||||
expect(cipher.login.totp).toBe('Y64VEVMBTSXCYIWRSHRNDZW62MPGVU2G');
|
||||
expect(cipher.name).toBe("example.com");
|
||||
expect(cipher.notes).toBe("super secure notes");
|
||||
expect(cipher.login.uri).toBe("http://example.com");
|
||||
expect(cipher.login.username).toBe("someUser");
|
||||
expect(cipher.login.password).toBe("myPassword");
|
||||
expect(cipher.login.totp).toBe("Y64VEVMBTSXCYIWRSHRNDZW62MPGVU2G");
|
||||
}
|
||||
|
||||
const CipherData = [
|
||||
{
|
||||
title: 'should parse expiration date',
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
{
|
||||
title: "should parse expiration date",
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
http://sn,,,"NoteType:Credit Card
|
||||
Name on Card:John Doe
|
||||
Type:
|
||||
@@ -37,32 +37,32 @@ Start Date:October,2017
|
||||
Expiration Date:June,2020
|
||||
Notes:some text
|
||||
",Credit-card,,0`,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: 'Credit-card',
|
||||
notes: 'some text\n',
|
||||
type: 3,
|
||||
card: {
|
||||
cardholderName: 'John Doe',
|
||||
number: '1234567812345678',
|
||||
code: '123',
|
||||
expYear: '2020',
|
||||
expMonth: '6',
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: 'Start Date',
|
||||
value: 'October,2017',
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
],
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: "Credit-card",
|
||||
notes: "some text\n",
|
||||
type: 3,
|
||||
card: {
|
||||
cardholderName: "John Doe",
|
||||
number: "1234567812345678",
|
||||
code: "123",
|
||||
expYear: "2020",
|
||||
expMonth: "6",
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: "Start Date",
|
||||
value: "October,2017",
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'should parse blank card note',
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "should parse blank card note",
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
http://sn,,,"NoteType:Credit Card
|
||||
Name on Card:
|
||||
Type:
|
||||
@@ -71,28 +71,28 @@ Security Code:
|
||||
Start Date:,
|
||||
Expiration Date:,
|
||||
Notes:",empty,,0`,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: 'empty',
|
||||
notes: null,
|
||||
type: 3,
|
||||
card: {
|
||||
expMonth: undefined,
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: 'Start Date',
|
||||
value: ',',
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
],
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: "empty",
|
||||
notes: null,
|
||||
type: 3,
|
||||
card: {
|
||||
expMonth: undefined,
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: "Start Date",
|
||||
value: ",",
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'should parse card expiration date w/ no exp year',
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "should parse card expiration date w/ no exp year",
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
http://sn,,,"NoteType:Credit Card
|
||||
Name on Card:John Doe
|
||||
Type:Visa
|
||||
@@ -101,36 +101,36 @@ Security Code:321
|
||||
Start Date:,
|
||||
Expiration Date:January,
|
||||
Notes:",noyear,,0`,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: 'noyear',
|
||||
notes: null,
|
||||
type: 3,
|
||||
card: {
|
||||
cardholderName: 'John Doe',
|
||||
number: '1234567887654321',
|
||||
code: '321',
|
||||
expMonth: '1',
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: 'Type',
|
||||
value: 'Visa',
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
Object.assign(new FieldView(), {
|
||||
name: 'Start Date',
|
||||
value: ',',
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
],
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: "noyear",
|
||||
notes: null,
|
||||
type: 3,
|
||||
card: {
|
||||
cardholderName: "John Doe",
|
||||
number: "1234567887654321",
|
||||
code: "321",
|
||||
expMonth: "1",
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: "Type",
|
||||
value: "Visa",
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'should parse card expiration date w/ no month',
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
Object.assign(new FieldView(), {
|
||||
name: "Start Date",
|
||||
value: ",",
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "should parse card expiration date w/ no month",
|
||||
csv: `url,username,password,extra,name,grouping,fav
|
||||
http://sn,,,"NoteType:Credit Card
|
||||
Name on Card:John Doe
|
||||
Type:Mastercard
|
||||
@@ -139,64 +139,64 @@ Security Code:987
|
||||
Start Date:,
|
||||
Expiration Date:,2020
|
||||
Notes:",nomonth,,0`,
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: 'nomonth',
|
||||
notes: null,
|
||||
type: 3,
|
||||
card: {
|
||||
cardholderName: 'John Doe',
|
||||
number: '8765432112345678',
|
||||
code: '987',
|
||||
expYear: '2020',
|
||||
expMonth: undefined,
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: 'Type',
|
||||
value: 'Mastercard',
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
Object.assign(new FieldView(), {
|
||||
name: 'Start Date',
|
||||
value: ',',
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
],
|
||||
expected: Object.assign(new CipherView(), {
|
||||
id: null,
|
||||
organizationId: null,
|
||||
folderId: null,
|
||||
name: "nomonth",
|
||||
notes: null,
|
||||
type: 3,
|
||||
card: {
|
||||
cardholderName: "John Doe",
|
||||
number: "8765432112345678",
|
||||
code: "987",
|
||||
expYear: "2020",
|
||||
expMonth: undefined,
|
||||
},
|
||||
fields: [
|
||||
Object.assign(new FieldView(), {
|
||||
name: "Type",
|
||||
value: "Mastercard",
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
},
|
||||
Object.assign(new FieldView(), {
|
||||
name: "Start Date",
|
||||
value: ",",
|
||||
type: FieldType.Text,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
describe('Lastpass CSV Importer', () => {
|
||||
CipherData.forEach(data => {
|
||||
it(data.title, async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(data.csv);
|
||||
expect(result != null).toBe(true);
|
||||
expect(result.ciphers.length).toBeGreaterThan(0);
|
||||
describe("Lastpass CSV Importer", () => {
|
||||
CipherData.forEach((data) => {
|
||||
it(data.title, async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(data.csv);
|
||||
expect(result != null).toBe(true);
|
||||
expect(result.ciphers.length).toBeGreaterThan(0);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
let property: keyof typeof data.expected;
|
||||
for (property in data.expected) {
|
||||
if (data.expected.hasOwnProperty(property)) {
|
||||
expect(cipher.hasOwnProperty(property)).toBe(true);
|
||||
expect(cipher[property]).toEqual(data.expected[property]);
|
||||
}
|
||||
}
|
||||
});
|
||||
const cipher = result.ciphers.shift();
|
||||
let property: keyof typeof data.expected;
|
||||
for (property in data.expected) {
|
||||
if (data.expected.hasOwnProperty(property)) {
|
||||
expect(cipher.hasOwnProperty(property)).toBe(true);
|
||||
expect(cipher[property]).toEqual(data.expected[property]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse login with totp', async () => {
|
||||
const input = `url,username,password,totp,extra,name,grouping,fav
|
||||
it("should parse login with totp", async () => {
|
||||
const input = `url,username,password,totp,extra,name,grouping,fav
|
||||
http://example.com,someUser,myPassword,Y64VEVMBTSXCYIWRSHRNDZW62MPGVU2G,super secure notes,example.com,,0`;
|
||||
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(input);
|
||||
baseExcept(result);
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(input);
|
||||
baseExcept(result);
|
||||
|
||||
const cipher = result.ciphers[0];
|
||||
expectLogin(cipher);
|
||||
});
|
||||
});
|
||||
const cipher = result.ciphers[0];
|
||||
expectLogin(cipher);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,181 +1,182 @@
|
||||
import { NordPassCsvImporter as Importer } from 'jslib-common/importers/nordpassCsvImporter';
|
||||
import { NordPassCsvImporter as Importer } from "jslib-common/importers/nordpassCsvImporter";
|
||||
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { SecureNoteType } from 'jslib-common/enums/secureNoteType';
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { IdentityView } from 'jslib-common/models/view/identityView';
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
import { SecureNoteType } from "jslib-common/enums/secureNoteType";
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { IdentityView } from "jslib-common/models/view/identityView";
|
||||
|
||||
import { data as creditCardData } from './testData/nordpassCsv/nordpass.card.csv';
|
||||
import { data as identityData } from './testData/nordpassCsv/nordpass.identity.csv';
|
||||
import { data as loginData } from './testData/nordpassCsv/nordpass.login.csv';
|
||||
import { data as secureNoteData } from './testData/nordpassCsv/nordpass.secureNote.csv';
|
||||
import { data as creditCardData } from "./testData/nordpassCsv/nordpass.card.csv";
|
||||
import { data as identityData } from "./testData/nordpassCsv/nordpass.identity.csv";
|
||||
import { data as loginData } from "./testData/nordpassCsv/nordpass.login.csv";
|
||||
import { data as secureNoteData } from "./testData/nordpassCsv/nordpass.secureNote.csv";
|
||||
|
||||
const namesTestData = [
|
||||
{
|
||||
title: 'Given #fullName should set firstName',
|
||||
fullName: 'MyFirstName',
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: 'MyFirstName',
|
||||
middleName: null,
|
||||
lastName: null,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'Given #fullName should set first- and lastName',
|
||||
fullName: 'MyFirstName MyLastName',
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: 'MyFirstName',
|
||||
middleName: null,
|
||||
lastName: 'MyLastName',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'Given #fullName should set first-, middle and lastName',
|
||||
fullName: 'MyFirstName MyMiddleName MyLastName',
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: 'MyFirstName',
|
||||
middleName: 'MyMiddleName',
|
||||
lastName: 'MyLastName',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'Given #fullName should set first-, middle and lastName with Jr',
|
||||
fullName: 'MyFirstName MyMiddleName MyLastName Jr',
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: 'MyFirstName',
|
||||
middleName: 'MyMiddleName',
|
||||
lastName: 'MyLastName Jr',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'Given #fullName should set first-, middle and lastName with Jr and III',
|
||||
fullName: 'MyFirstName MyMiddleName MyLastName Jr III',
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: 'MyFirstName',
|
||||
middleName: 'MyMiddleName',
|
||||
lastName: 'MyLastName Jr III',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "Given #fullName should set firstName",
|
||||
fullName: "MyFirstName",
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: "MyFirstName",
|
||||
middleName: null,
|
||||
lastName: null,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "Given #fullName should set first- and lastName",
|
||||
fullName: "MyFirstName MyLastName",
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: "MyFirstName",
|
||||
middleName: null,
|
||||
lastName: "MyLastName",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "Given #fullName should set first-, middle and lastName",
|
||||
fullName: "MyFirstName MyMiddleName MyLastName",
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: "MyFirstName",
|
||||
middleName: "MyMiddleName",
|
||||
lastName: "MyLastName",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "Given #fullName should set first-, middle and lastName with Jr",
|
||||
fullName: "MyFirstName MyMiddleName MyLastName Jr",
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: "MyFirstName",
|
||||
middleName: "MyMiddleName",
|
||||
lastName: "MyLastName Jr",
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: "Given #fullName should set first-, middle and lastName with Jr and III",
|
||||
fullName: "MyFirstName MyMiddleName MyLastName Jr III",
|
||||
expected: Object.assign(new IdentityView(), {
|
||||
firstName: "MyFirstName",
|
||||
middleName: "MyMiddleName",
|
||||
lastName: "MyLastName Jr III",
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
function expectLogin(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Login);
|
||||
expect(cipher.type).toBe(CipherType.Login);
|
||||
|
||||
expect(cipher.name).toBe('SomeVaultItemName');
|
||||
expect(cipher.notes).toBe('Some note for the VaultItem');
|
||||
expect(cipher.login.uri).toBe('https://example.com');
|
||||
expect(cipher.login.username).toBe('hello@bitwarden.com');
|
||||
expect(cipher.login.password).toBe('someStrongPassword');
|
||||
expect(cipher.name).toBe("SomeVaultItemName");
|
||||
expect(cipher.notes).toBe("Some note for the VaultItem");
|
||||
expect(cipher.login.uri).toBe("https://example.com");
|
||||
expect(cipher.login.username).toBe("hello@bitwarden.com");
|
||||
expect(cipher.login.password).toBe("someStrongPassword");
|
||||
}
|
||||
|
||||
function expectCreditCard(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
|
||||
expect(cipher.name).toBe('SomeVisa');
|
||||
expect(cipher.card.brand).toBe('Visa');
|
||||
expect(cipher.card.cardholderName).toBe('SomeHolder');
|
||||
expect(cipher.card.number).toBe('4024007103939509');
|
||||
expect(cipher.card.code).toBe('123');
|
||||
expect(cipher.card.expMonth).toBe('1');
|
||||
expect(cipher.card.expYear).toBe('22');
|
||||
expect(cipher.name).toBe("SomeVisa");
|
||||
expect(cipher.card.brand).toBe("Visa");
|
||||
expect(cipher.card.cardholderName).toBe("SomeHolder");
|
||||
expect(cipher.card.number).toBe("4024007103939509");
|
||||
expect(cipher.card.code).toBe("123");
|
||||
expect(cipher.card.expMonth).toBe("1");
|
||||
expect(cipher.card.expYear).toBe("22");
|
||||
}
|
||||
|
||||
function expectIdentity(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
|
||||
expect(cipher.name).toBe('SomeTitle');
|
||||
expect(cipher.identity.fullName).toBe('MyFirstName MyMiddleName MyLastName');
|
||||
expect(cipher.identity.firstName).toBe('MyFirstName');
|
||||
expect(cipher.identity.middleName).toBe('MyMiddleName');
|
||||
expect(cipher.identity.lastName).toBe('MyLastName');
|
||||
expect(cipher.identity.email).toBe('hello@bitwarden.com');
|
||||
expect(cipher.identity.phone).toBe('123456789');
|
||||
expect(cipher.name).toBe("SomeTitle");
|
||||
expect(cipher.identity.fullName).toBe("MyFirstName MyMiddleName MyLastName");
|
||||
expect(cipher.identity.firstName).toBe("MyFirstName");
|
||||
expect(cipher.identity.middleName).toBe("MyMiddleName");
|
||||
expect(cipher.identity.lastName).toBe("MyLastName");
|
||||
expect(cipher.identity.email).toBe("hello@bitwarden.com");
|
||||
expect(cipher.identity.phone).toBe("123456789");
|
||||
|
||||
expect(cipher.identity.address1).toBe('Test street 123');
|
||||
expect(cipher.identity.address2).toBe('additional addressinfo');
|
||||
expect(cipher.identity.postalCode).toBe('123456');
|
||||
expect(cipher.identity.city).toBe('Cologne');
|
||||
expect(cipher.identity.state).toBe('North-Rhine-Westphalia');
|
||||
expect(cipher.identity.country).toBe('GERMANY');
|
||||
expect(cipher.notes).toBe('SomeNoteToMyIdentity');
|
||||
expect(cipher.identity.address1).toBe("Test street 123");
|
||||
expect(cipher.identity.address2).toBe("additional addressinfo");
|
||||
expect(cipher.identity.postalCode).toBe("123456");
|
||||
expect(cipher.identity.city).toBe("Cologne");
|
||||
expect(cipher.identity.state).toBe("North-Rhine-Westphalia");
|
||||
expect(cipher.identity.country).toBe("GERMANY");
|
||||
expect(cipher.notes).toBe("SomeNoteToMyIdentity");
|
||||
}
|
||||
|
||||
function expectSecureNote(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.SecureNote);
|
||||
expect(cipher.type).toBe(CipherType.SecureNote);
|
||||
|
||||
expect(cipher.name).toBe('MySuperSecureNoteTitle');
|
||||
expect(cipher.secureNote.type).toBe(SecureNoteType.Generic);
|
||||
expect(cipher.notes).toBe('MySuperSecureNote');
|
||||
expect(cipher.name).toBe("MySuperSecureNoteTitle");
|
||||
expect(cipher.secureNote.type).toBe(SecureNoteType.Generic);
|
||||
expect(cipher.notes).toBe("MySuperSecureNote");
|
||||
}
|
||||
|
||||
describe('NordPass CSV Importer', () => {
|
||||
let importer: Importer;
|
||||
beforeEach(() => {
|
||||
importer = new Importer();
|
||||
describe("NordPass CSV Importer", () => {
|
||||
let importer: Importer;
|
||||
beforeEach(() => {
|
||||
importer = new Importer();
|
||||
});
|
||||
|
||||
it("should parse login records", async () => {
|
||||
const result = await importer.parse(loginData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectLogin(cipher);
|
||||
});
|
||||
|
||||
it("should parse credit card records", async () => {
|
||||
const result = await importer.parse(creditCardData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectCreditCard(cipher);
|
||||
});
|
||||
|
||||
it("should parse identity records", async () => {
|
||||
const result = await importer.parse(
|
||||
identityData.replace("#fullName", "MyFirstName MyMiddleName MyLastName")
|
||||
);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectIdentity(cipher);
|
||||
});
|
||||
|
||||
namesTestData.forEach((data) => {
|
||||
it(data.title.replace("#fullName", data.fullName), async () => {
|
||||
const result = await importer.parse(identityData.replace("#fullName", data.fullName));
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expect(cipher.identity.firstName).toBe(data.expected.firstName);
|
||||
expect(cipher.identity.middleName).toBe(data.expected.middleName);
|
||||
expect(cipher.identity.lastName).toBe(data.expected.lastName);
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse login records', async () => {
|
||||
const result = await importer.parse(loginData);
|
||||
it("should parse secureNote records", async () => {
|
||||
const result = await importer.parse(secureNoteData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectLogin(cipher);
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectSecureNote(cipher);
|
||||
});
|
||||
|
||||
it('should parse credit card records', async () => {
|
||||
const result = await importer.parse(creditCardData);
|
||||
it("should parse an item and create a folder", async () => {
|
||||
const result = await importer.parse(secureNoteData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectCreditCard(cipher);
|
||||
});
|
||||
|
||||
it('should parse identity records', async () => {
|
||||
const result = await importer.parse(identityData.replace('#fullName', 'MyFirstName MyMiddleName MyLastName'));
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectIdentity(cipher);
|
||||
});
|
||||
|
||||
namesTestData.forEach(data => {
|
||||
it(data.title.replace('#fullName', data.fullName), async () => {
|
||||
const result = await importer.parse(identityData.replace('#fullName', data.fullName));
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expect(cipher.identity.firstName).toBe(data.expected.firstName);
|
||||
expect(cipher.identity.middleName).toBe(data.expected.middleName);
|
||||
expect(cipher.identity.lastName).toBe(data.expected.lastName);
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse secureNote records', async () => {
|
||||
const result = await importer.parse(secureNoteData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectSecureNote(cipher);
|
||||
});
|
||||
|
||||
it('should parse an item and create a folder', async () => {
|
||||
const result = await importer.parse(secureNoteData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.folders.length).toBe(1);
|
||||
const folder = result.folders[0];
|
||||
expect(folder.name).toBe('notesFolder');
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.folders.length).toBe(1);
|
||||
const folder = result.folders[0];
|
||||
expect(folder.name).toBe("notesFolder");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,513 +1,514 @@
|
||||
import { FieldType } from 'jslib-common/enums/fieldType';
|
||||
import { OnePassword1PifImporter as Importer } from 'jslib-common/importers/onepasswordImporters/onepassword1PifImporter';
|
||||
import { FieldType } from "jslib-common/enums/fieldType";
|
||||
import { OnePassword1PifImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepassword1PifImporter";
|
||||
|
||||
const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
|
||||
JSON.stringify({
|
||||
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
updatedAt: 1486071244,
|
||||
securityLevel: 'SL5',
|
||||
contentsHash: 'aaaaaaaa',
|
||||
title: 'Imported Entry',
|
||||
location: 'https://www.google.com',
|
||||
secureContents: {
|
||||
fields: [
|
||||
{
|
||||
value: 'user@test.net',
|
||||
id: 'email-input',
|
||||
name: 'email',
|
||||
type: 'T',
|
||||
designation: 'username',
|
||||
},
|
||||
{
|
||||
value: 'myservicepassword',
|
||||
id: 'password-input',
|
||||
name: 'password',
|
||||
type: 'P',
|
||||
designation: 'password',
|
||||
},
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: 'concealed',
|
||||
n: 'AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC',
|
||||
v: 'console-password-123',
|
||||
t: 'console password',
|
||||
},
|
||||
],
|
||||
title: 'Admin Console',
|
||||
name: 'admin_console',
|
||||
},
|
||||
],
|
||||
passwordHistory: [
|
||||
{
|
||||
value: 'old-password',
|
||||
time: 1447791421,
|
||||
},
|
||||
],
|
||||
const TestData: string =
|
||||
"***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n" +
|
||||
JSON.stringify({
|
||||
uuid: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||
updatedAt: 1486071244,
|
||||
securityLevel: "SL5",
|
||||
contentsHash: "aaaaaaaa",
|
||||
title: "Imported Entry",
|
||||
location: "https://www.google.com",
|
||||
secureContents: {
|
||||
fields: [
|
||||
{
|
||||
value: "user@test.net",
|
||||
id: "email-input",
|
||||
name: "email",
|
||||
type: "T",
|
||||
designation: "username",
|
||||
},
|
||||
URLs: [
|
||||
{
|
||||
value: "myservicepassword",
|
||||
id: "password-input",
|
||||
name: "password",
|
||||
type: "P",
|
||||
designation: "password",
|
||||
},
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
label: 'website',
|
||||
url: 'https://www.google.com',
|
||||
k: "concealed",
|
||||
n: "AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC",
|
||||
v: "console-password-123",
|
||||
t: "console password",
|
||||
},
|
||||
],
|
||||
txTimestamp: 1508941334,
|
||||
createdAt: 1390426636,
|
||||
typeName: 'webforms.WebForm',
|
||||
});
|
||||
],
|
||||
title: "Admin Console",
|
||||
name: "admin_console",
|
||||
},
|
||||
],
|
||||
passwordHistory: [
|
||||
{
|
||||
value: "old-password",
|
||||
time: 1447791421,
|
||||
},
|
||||
],
|
||||
},
|
||||
URLs: [
|
||||
{
|
||||
label: "website",
|
||||
url: "https://www.google.com",
|
||||
},
|
||||
],
|
||||
txTimestamp: 1508941334,
|
||||
createdAt: 1390426636,
|
||||
typeName: "webforms.WebForm",
|
||||
});
|
||||
|
||||
const WindowsOpVaultTestData = JSON.stringify({
|
||||
category: '001',
|
||||
created: 1544823719,
|
||||
hmac: 'NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=',
|
||||
k: '**REMOVED LONG LINE FOR LINTER** -Kyle',
|
||||
tx: 1553395669,
|
||||
updated: 1553395669,
|
||||
uuid: '528AB076FB5F4FBF960884B8E01619AC',
|
||||
overview: {
|
||||
title: 'Google',
|
||||
URLs: [
|
||||
{
|
||||
u: 'google.com',
|
||||
},
|
||||
],
|
||||
url: 'google.com',
|
||||
ps: 26,
|
||||
ainfo: 'googluser',
|
||||
},
|
||||
details: {
|
||||
passwordHistory: [
|
||||
{
|
||||
value: 'oldpass1',
|
||||
time: 1553394449,
|
||||
},
|
||||
{
|
||||
value: 'oldpass2',
|
||||
time: 1553394457,
|
||||
},
|
||||
{
|
||||
value: 'oldpass3',
|
||||
time: 1553394458,
|
||||
},
|
||||
{
|
||||
value: 'oldpass4',
|
||||
time: 1553394459,
|
||||
},
|
||||
{
|
||||
value: 'oldpass5',
|
||||
time: 1553394460,
|
||||
},
|
||||
{
|
||||
value: 'oldpass6',
|
||||
time: 1553394461,
|
||||
},
|
||||
],
|
||||
category: "001",
|
||||
created: 1544823719,
|
||||
hmac: "NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=",
|
||||
k: "**REMOVED LONG LINE FOR LINTER** -Kyle",
|
||||
tx: 1553395669,
|
||||
updated: 1553395669,
|
||||
uuid: "528AB076FB5F4FBF960884B8E01619AC",
|
||||
overview: {
|
||||
title: "Google",
|
||||
URLs: [
|
||||
{
|
||||
u: "google.com",
|
||||
},
|
||||
],
|
||||
url: "google.com",
|
||||
ps: 26,
|
||||
ainfo: "googluser",
|
||||
},
|
||||
details: {
|
||||
passwordHistory: [
|
||||
{
|
||||
value: "oldpass1",
|
||||
time: 1553394449,
|
||||
},
|
||||
{
|
||||
value: "oldpass2",
|
||||
time: 1553394457,
|
||||
},
|
||||
{
|
||||
value: "oldpass3",
|
||||
time: 1553394458,
|
||||
},
|
||||
{
|
||||
value: "oldpass4",
|
||||
time: 1553394459,
|
||||
},
|
||||
{
|
||||
value: "oldpass5",
|
||||
time: 1553394460,
|
||||
},
|
||||
{
|
||||
value: "oldpass6",
|
||||
time: 1553394461,
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
type: "T",
|
||||
id: "username",
|
||||
name: "username",
|
||||
value: "googluser",
|
||||
designation: "username",
|
||||
},
|
||||
{
|
||||
type: "P",
|
||||
id: "password",
|
||||
name: "password",
|
||||
value: "12345678901",
|
||||
designation: "password",
|
||||
},
|
||||
],
|
||||
notesPlain: "This is a note\r\n\r\nline1\r\nline2",
|
||||
sections: [
|
||||
{
|
||||
title: "test",
|
||||
name: "1214FD88CD30405D9EED14BEB4D61B60",
|
||||
fields: [
|
||||
{
|
||||
type: 'T',
|
||||
id: 'username',
|
||||
name: 'username',
|
||||
value: 'googluser',
|
||||
designation: 'username',
|
||||
},
|
||||
{
|
||||
type: 'P',
|
||||
id: 'password',
|
||||
name: 'password',
|
||||
value: '12345678901',
|
||||
designation: 'password',
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "6CC3BD77482D4559A4B8BB2D360F821B",
|
||||
v: "fgfg",
|
||||
t: "fgggf",
|
||||
},
|
||||
{
|
||||
k: "concealed",
|
||||
n: "5CFE7BCAA1DF4578BBF7EB508959BFF3",
|
||||
v: "dfgdfgfdg",
|
||||
t: "pwfield",
|
||||
},
|
||||
],
|
||||
notesPlain: 'This is a note\r\n\r\nline1\r\nline2',
|
||||
sections: [
|
||||
{
|
||||
title: 'test',
|
||||
name: '1214FD88CD30405D9EED14BEB4D61B60',
|
||||
fields: [
|
||||
{
|
||||
k: 'string',
|
||||
n: '6CC3BD77482D4559A4B8BB2D360F821B',
|
||||
v: 'fgfg',
|
||||
t: 'fgggf',
|
||||
},
|
||||
{
|
||||
k: 'concealed',
|
||||
n: '5CFE7BCAA1DF4578BBF7EB508959BFF3',
|
||||
v: 'dfgdfgfdg',
|
||||
t: 'pwfield',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const IdentityTestData = JSON.stringify({
|
||||
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
updatedAt: 1553365894,
|
||||
securityLevel: 'SL5',
|
||||
contentsHash: 'eeeeeeee',
|
||||
title: 'Test Identity',
|
||||
secureContents: {
|
||||
lastname: 'Fritzenberger',
|
||||
zip: '223344',
|
||||
birthdate_dd: '11',
|
||||
homephone: '+49 333 222 111',
|
||||
company: 'Web Inc.',
|
||||
firstname: 'Frank',
|
||||
birthdate_mm: '3',
|
||||
country: 'de',
|
||||
sex: 'male',
|
||||
sections: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'firstname',
|
||||
v: 'Frank',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'first name',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'initial',
|
||||
v: 'MD',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'initial',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'lastname',
|
||||
v: 'Fritzenberger',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'last name',
|
||||
},
|
||||
{
|
||||
k: 'menu',
|
||||
v: 'male',
|
||||
n: 'sex',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'sex',
|
||||
},
|
||||
{
|
||||
k: 'date',
|
||||
v: 1552305660,
|
||||
n: 'birthdate',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'birth date',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'occupation',
|
||||
v: 'Engineer',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'occupation',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'company',
|
||||
v: 'Web Inc.',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'company',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'department',
|
||||
v: 'IT',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'department',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Words',
|
||||
},
|
||||
n: 'jobtitle',
|
||||
v: 'Developer',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'job title',
|
||||
},
|
||||
],
|
||||
title: 'Identification',
|
||||
name: 'name',
|
||||
uuid: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||
updatedAt: 1553365894,
|
||||
securityLevel: "SL5",
|
||||
contentsHash: "eeeeeeee",
|
||||
title: "Test Identity",
|
||||
secureContents: {
|
||||
lastname: "Fritzenberger",
|
||||
zip: "223344",
|
||||
birthdate_dd: "11",
|
||||
homephone: "+49 333 222 111",
|
||||
company: "Web Inc.",
|
||||
firstname: "Frank",
|
||||
birthdate_mm: "3",
|
||||
country: "de",
|
||||
sex: "male",
|
||||
sections: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: 'address',
|
||||
inputTraits: {
|
||||
autocapitalization: 'Sentences',
|
||||
},
|
||||
n: 'address',
|
||||
v: {
|
||||
street: 'Mainstreet 1',
|
||||
city: 'Berlin',
|
||||
country: 'de',
|
||||
zip: '223344',
|
||||
},
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'address',
|
||||
},
|
||||
{
|
||||
k: 'phone',
|
||||
v: '+49 001 222 333 44',
|
||||
n: 'defphone',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'default phone',
|
||||
},
|
||||
{
|
||||
k: 'phone',
|
||||
v: '+49 333 222 111',
|
||||
n: 'homephone',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'home',
|
||||
},
|
||||
{
|
||||
k: 'phone',
|
||||
n: 'cellphone',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'mobile',
|
||||
},
|
||||
{
|
||||
k: 'phone',
|
||||
n: 'busphone',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'business',
|
||||
},
|
||||
],
|
||||
title: 'Address',
|
||||
name: 'address',
|
||||
n: "firstname",
|
||||
v: "Frank",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: 'string',
|
||||
n: 'username',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'username',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'reminderq',
|
||||
t: 'reminder question',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'remindera',
|
||||
t: 'reminder answer',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
inputTraits: {
|
||||
keyboard: 'EmailAddress',
|
||||
},
|
||||
n: 'email',
|
||||
v: 'test@web.de',
|
||||
a: {
|
||||
guarded: 'yes',
|
||||
},
|
||||
t: 'email',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'website',
|
||||
inputTraits: {
|
||||
keyboard: 'URL',
|
||||
},
|
||||
t: 'website',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'icq',
|
||||
t: 'ICQ',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'skype',
|
||||
t: 'skype',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'aim',
|
||||
t: 'AOL/AIM',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'yahoo',
|
||||
t: 'Yahoo',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'msn',
|
||||
t: 'MSN',
|
||||
},
|
||||
{
|
||||
k: 'string',
|
||||
n: 'forumsig',
|
||||
t: 'forum signature',
|
||||
},
|
||||
],
|
||||
title: 'Internet Details',
|
||||
name: 'internet',
|
||||
t: "first name",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
{
|
||||
title: 'Related Items',
|
||||
name: 'linked items',
|
||||
n: "initial",
|
||||
v: "MD",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "initial",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
n: "lastname",
|
||||
v: "Fritzenberger",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "last name",
|
||||
},
|
||||
{
|
||||
k: "menu",
|
||||
v: "male",
|
||||
n: "sex",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "sex",
|
||||
},
|
||||
{
|
||||
k: "date",
|
||||
v: 1552305660,
|
||||
n: "birthdate",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "birth date",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
n: "occupation",
|
||||
v: "Engineer",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "occupation",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
n: "company",
|
||||
v: "Web Inc.",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "company",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
n: "department",
|
||||
v: "IT",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "department",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
autocapitalization: "Words",
|
||||
},
|
||||
n: "jobtitle",
|
||||
v: "Developer",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "job title",
|
||||
},
|
||||
],
|
||||
initial: 'MD',
|
||||
address1: 'Mainstreet 1',
|
||||
city: 'Berlin',
|
||||
jobtitle: 'Developer',
|
||||
occupation: 'Engineer',
|
||||
department: 'IT',
|
||||
email: 'test@web.de',
|
||||
birthdate_yy: '2019',
|
||||
homephone_local: '+49 333 222 111',
|
||||
defphone_local: '+49 001 222 333 44',
|
||||
defphone: '+49 001 222 333 44',
|
||||
},
|
||||
txTimestamp: 1553365894,
|
||||
createdAt: 1553364679,
|
||||
typeName: 'identities.Identity',
|
||||
title: "Identification",
|
||||
name: "name",
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: "address",
|
||||
inputTraits: {
|
||||
autocapitalization: "Sentences",
|
||||
},
|
||||
n: "address",
|
||||
v: {
|
||||
street: "Mainstreet 1",
|
||||
city: "Berlin",
|
||||
country: "de",
|
||||
zip: "223344",
|
||||
},
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "address",
|
||||
},
|
||||
{
|
||||
k: "phone",
|
||||
v: "+49 001 222 333 44",
|
||||
n: "defphone",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "default phone",
|
||||
},
|
||||
{
|
||||
k: "phone",
|
||||
v: "+49 333 222 111",
|
||||
n: "homephone",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "home",
|
||||
},
|
||||
{
|
||||
k: "phone",
|
||||
n: "cellphone",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "mobile",
|
||||
},
|
||||
{
|
||||
k: "phone",
|
||||
n: "busphone",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "business",
|
||||
},
|
||||
],
|
||||
title: "Address",
|
||||
name: "address",
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
k: "string",
|
||||
n: "username",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "username",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "reminderq",
|
||||
t: "reminder question",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "remindera",
|
||||
t: "reminder answer",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
inputTraits: {
|
||||
keyboard: "EmailAddress",
|
||||
},
|
||||
n: "email",
|
||||
v: "test@web.de",
|
||||
a: {
|
||||
guarded: "yes",
|
||||
},
|
||||
t: "email",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "website",
|
||||
inputTraits: {
|
||||
keyboard: "URL",
|
||||
},
|
||||
t: "website",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "icq",
|
||||
t: "ICQ",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "skype",
|
||||
t: "skype",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "aim",
|
||||
t: "AOL/AIM",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "yahoo",
|
||||
t: "Yahoo",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "msn",
|
||||
t: "MSN",
|
||||
},
|
||||
{
|
||||
k: "string",
|
||||
n: "forumsig",
|
||||
t: "forum signature",
|
||||
},
|
||||
],
|
||||
title: "Internet Details",
|
||||
name: "internet",
|
||||
},
|
||||
{
|
||||
title: "Related Items",
|
||||
name: "linked items",
|
||||
},
|
||||
],
|
||||
initial: "MD",
|
||||
address1: "Mainstreet 1",
|
||||
city: "Berlin",
|
||||
jobtitle: "Developer",
|
||||
occupation: "Engineer",
|
||||
department: "IT",
|
||||
email: "test@web.de",
|
||||
birthdate_yy: "2019",
|
||||
homephone_local: "+49 333 222 111",
|
||||
defphone_local: "+49 001 222 333 44",
|
||||
defphone: "+49 001 222 333 44",
|
||||
},
|
||||
txTimestamp: 1553365894,
|
||||
createdAt: 1553364679,
|
||||
typeName: "identities.Identity",
|
||||
});
|
||||
|
||||
describe('1Password 1Pif Importer', () => {
|
||||
it('should parse data', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
expect(result != null).toBe(true);
|
||||
describe("1Password 1Pif Importer", () => {
|
||||
it("should parse data", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.login.username).toEqual('user@test.net');
|
||||
expect(cipher.login.password).toEqual('myservicepassword');
|
||||
expect(cipher.login.uris.length).toEqual(1);
|
||||
const uriView = cipher.login.uris.shift();
|
||||
expect(uriView.uri).toEqual('https://www.google.com');
|
||||
});
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.login.username).toEqual("user@test.net");
|
||||
expect(cipher.login.password).toEqual("myservicepassword");
|
||||
expect(cipher.login.uris.length).toEqual(1);
|
||||
const uriView = cipher.login.uris.shift();
|
||||
expect(uriView.uri).toEqual("https://www.google.com");
|
||||
});
|
||||
|
||||
it('should create concealed field as "hidden" type', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
expect(result != null).toBe(true);
|
||||
it('should create concealed field as "hidden" type', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
expect(result != null).toBe(true);
|
||||
|
||||
const ciphers = result.ciphers;
|
||||
expect(ciphers.length).toEqual(1);
|
||||
const ciphers = result.ciphers;
|
||||
expect(ciphers.length).toEqual(1);
|
||||
|
||||
const cipher = ciphers.shift();
|
||||
const fields = cipher.fields;
|
||||
expect(fields.length).toEqual(1);
|
||||
const cipher = ciphers.shift();
|
||||
const fields = cipher.fields;
|
||||
expect(fields.length).toEqual(1);
|
||||
|
||||
const field = fields.shift();
|
||||
expect(field.name).toEqual('console password');
|
||||
expect(field.value).toEqual('console-password-123');
|
||||
expect(field.type).toEqual(FieldType.Hidden);
|
||||
});
|
||||
const field = fields.shift();
|
||||
expect(field.name).toEqual("console password");
|
||||
expect(field.value).toEqual("console-password-123");
|
||||
expect(field.type).toEqual(FieldType.Hidden);
|
||||
});
|
||||
|
||||
it('should create identity records', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(IdentityTestData);
|
||||
expect(result != null).toBe(true);
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.name).toEqual('Test Identity');
|
||||
it("should create identity records", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(IdentityTestData);
|
||||
expect(result != null).toBe(true);
|
||||
const cipher = result.ciphers.shift();
|
||||
expect(cipher.name).toEqual("Test Identity");
|
||||
|
||||
const identity = cipher.identity;
|
||||
expect(identity.firstName).toEqual('Frank');
|
||||
expect(identity.middleName).toEqual('MD');
|
||||
expect(identity.lastName).toEqual('Fritzenberger');
|
||||
expect(identity.company).toEqual('Web Inc.');
|
||||
expect(identity.address1).toEqual('Mainstreet 1');
|
||||
expect(identity.country).toEqual('DE');
|
||||
expect(identity.city).toEqual('Berlin');
|
||||
expect(identity.postalCode).toEqual('223344');
|
||||
expect(identity.phone).toEqual('+49 001 222 333 44');
|
||||
expect(identity.email).toEqual('test@web.de');
|
||||
const identity = cipher.identity;
|
||||
expect(identity.firstName).toEqual("Frank");
|
||||
expect(identity.middleName).toEqual("MD");
|
||||
expect(identity.lastName).toEqual("Fritzenberger");
|
||||
expect(identity.company).toEqual("Web Inc.");
|
||||
expect(identity.address1).toEqual("Mainstreet 1");
|
||||
expect(identity.country).toEqual("DE");
|
||||
expect(identity.city).toEqual("Berlin");
|
||||
expect(identity.postalCode).toEqual("223344");
|
||||
expect(identity.phone).toEqual("+49 001 222 333 44");
|
||||
expect(identity.email).toEqual("test@web.de");
|
||||
|
||||
// remaining fields as custom fields
|
||||
expect(cipher.fields.length).toEqual(6);
|
||||
});
|
||||
// remaining fields as custom fields
|
||||
expect(cipher.fields.length).toEqual(6);
|
||||
});
|
||||
|
||||
it('should create password history', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
const cipher = result.ciphers.shift();
|
||||
it("should create password history", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(TestData);
|
||||
const cipher = result.ciphers.shift();
|
||||
|
||||
expect(cipher.passwordHistory.length).toEqual(1);
|
||||
const ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual('old-password');
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual('2015-11-17T20:17:01.000Z');
|
||||
});
|
||||
expect(cipher.passwordHistory.length).toEqual(1);
|
||||
const ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual("old-password");
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual("2015-11-17T20:17:01.000Z");
|
||||
});
|
||||
|
||||
it('should create password history from windows opvault 1pif format', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(WindowsOpVaultTestData);
|
||||
const cipher = result.ciphers.shift();
|
||||
it("should create password history from windows opvault 1pif format", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(WindowsOpVaultTestData);
|
||||
const cipher = result.ciphers.shift();
|
||||
|
||||
expect(cipher.passwordHistory.length).toEqual(5);
|
||||
let ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual('oldpass6');
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:41.000Z');
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual('oldpass5');
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:40.000Z');
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual('oldpass4');
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:39.000Z');
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual('oldpass3');
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:38.000Z');
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual('oldpass2');
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:37.000Z');
|
||||
});
|
||||
expect(cipher.passwordHistory.length).toEqual(5);
|
||||
let ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual("oldpass6");
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:41.000Z");
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual("oldpass5");
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:40.000Z");
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual("oldpass4");
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:39.000Z");
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual("oldpass3");
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:38.000Z");
|
||||
ph = cipher.passwordHistory.shift();
|
||||
expect(ph.password).toEqual("oldpass2");
|
||||
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:37.000Z");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,71 +1,75 @@
|
||||
import { OnePasswordMacCsvImporter as Importer } from 'jslib-common/importers/onepasswordImporters/onepasswordMacCsvImporter';
|
||||
import { OnePasswordMacCsvImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepasswordMacCsvImporter";
|
||||
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
|
||||
import { data as creditCardData } from './testData/onePasswordCsv/creditCard.mac.csv';
|
||||
import { data as identityData } from './testData/onePasswordCsv/identity.mac.csv';
|
||||
import { data as multiTypeData } from './testData/onePasswordCsv/multipleItems.mac.csv';
|
||||
import { data as creditCardData } from "./testData/onePasswordCsv/creditCard.mac.csv";
|
||||
import { data as identityData } from "./testData/onePasswordCsv/identity.mac.csv";
|
||||
import { data as multiTypeData } from "./testData/onePasswordCsv/multipleItems.mac.csv";
|
||||
|
||||
function expectIdentity(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
|
||||
expect(cipher.identity).toEqual(jasmine.objectContaining({
|
||||
firstName: 'first name',
|
||||
middleName: 'mi',
|
||||
lastName: 'last name',
|
||||
username: 'userNam3',
|
||||
company: 'bitwarden',
|
||||
phone: '8005555555',
|
||||
email: 'email@bitwarden.com',
|
||||
}));
|
||||
expect(cipher.identity).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstName: "first name",
|
||||
middleName: "mi",
|
||||
lastName: "last name",
|
||||
username: "userNam3",
|
||||
company: "bitwarden",
|
||||
phone: "8005555555",
|
||||
email: "email@bitwarden.com",
|
||||
})
|
||||
);
|
||||
|
||||
expect(cipher.notes).toContain('address\ncity state zip\nUnited States');
|
||||
expect(cipher.notes).toContain("address\ncity state zip\nUnited States");
|
||||
}
|
||||
|
||||
function expectCreditCard(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
|
||||
expect(cipher.card).toEqual(jasmine.objectContaining({
|
||||
number: '4111111111111111',
|
||||
code: '111',
|
||||
cardholderName: 'test',
|
||||
expMonth: '1',
|
||||
expYear: '2030',
|
||||
}));
|
||||
expect(cipher.card).toEqual(
|
||||
jasmine.objectContaining({
|
||||
number: "4111111111111111",
|
||||
code: "111",
|
||||
cardholderName: "test",
|
||||
expMonth: "1",
|
||||
expYear: "2030",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
describe('1Password mac CSV Importer', () => {
|
||||
it('should parse identity records', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(identityData);
|
||||
describe("1Password mac CSV Importer", () => {
|
||||
it("should parse identity records", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(identityData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectIdentity(cipher);
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectIdentity(cipher);
|
||||
});
|
||||
|
||||
it('should parse credit card records', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(creditCardData);
|
||||
it("should parse credit card records", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(creditCardData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectCreditCard(cipher);
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectCreditCard(cipher);
|
||||
});
|
||||
|
||||
it('should parse csv\'s with multiple record type', async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(multiTypeData);
|
||||
it("should parse csv's with multiple record type", async () => {
|
||||
const importer = new Importer();
|
||||
const result = await importer.parse(multiTypeData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(4);
|
||||
expectIdentity(result.ciphers[1]);
|
||||
expectCreditCard(result.ciphers[2]);
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(4);
|
||||
expectIdentity(result.ciphers[1]);
|
||||
expectCreditCard(result.ciphers[2]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,82 +1,88 @@
|
||||
import { OnePasswordWinCsvImporter as Importer } from 'jslib-common/importers/onepasswordImporters/onepasswordWinCsvImporter';
|
||||
import { OnePasswordWinCsvImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepasswordWinCsvImporter";
|
||||
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { FieldType } from 'jslib-common/enums/fieldType';
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { FieldView } from 'jslib-common/models/view/fieldView';
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
import { FieldType } from "jslib-common/enums/fieldType";
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { FieldView } from "jslib-common/models/view/fieldView";
|
||||
|
||||
import { data as creditCardData } from './testData/onePasswordCsv/creditCard.windows.csv';
|
||||
import { data as identityData } from './testData/onePasswordCsv/identity.windows.csv';
|
||||
import { data as multiTypeData } from './testData/onePasswordCsv/multipleItems.windows.csv';
|
||||
import { data as creditCardData } from "./testData/onePasswordCsv/creditCard.windows.csv";
|
||||
import { data as identityData } from "./testData/onePasswordCsv/identity.windows.csv";
|
||||
import { data as multiTypeData } from "./testData/onePasswordCsv/multipleItems.windows.csv";
|
||||
|
||||
function expectIdentity(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
expect(cipher.type).toBe(CipherType.Identity);
|
||||
|
||||
expect(cipher.identity).toEqual(jasmine.objectContaining({
|
||||
firstName: 'first name',
|
||||
middleName: 'mi',
|
||||
lastName: 'last name',
|
||||
username: 'userNam3',
|
||||
company: 'bitwarden',
|
||||
phone: '8005555555',
|
||||
email: 'email@bitwarden.com',
|
||||
}));
|
||||
expect(cipher.identity).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstName: "first name",
|
||||
middleName: "mi",
|
||||
lastName: "last name",
|
||||
username: "userNam3",
|
||||
company: "bitwarden",
|
||||
phone: "8005555555",
|
||||
email: "email@bitwarden.com",
|
||||
})
|
||||
);
|
||||
|
||||
expect(cipher.fields).toEqual(jasmine.arrayContaining([
|
||||
Object.assign(new FieldView(), {
|
||||
type: FieldType.Text,
|
||||
name: 'address',
|
||||
value: 'address city state zip us',
|
||||
}),
|
||||
]));
|
||||
expect(cipher.fields).toEqual(
|
||||
jasmine.arrayContaining([
|
||||
Object.assign(new FieldView(), {
|
||||
type: FieldType.Text,
|
||||
name: "address",
|
||||
value: "address city state zip us",
|
||||
}),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function expectCreditCard(cipher: CipherView) {
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
expect(cipher.type).toBe(CipherType.Card);
|
||||
|
||||
expect(cipher.card).toEqual(jasmine.objectContaining({
|
||||
number: '4111111111111111',
|
||||
code: '111',
|
||||
cardholderName: 'test',
|
||||
expMonth: '1',
|
||||
expYear: '1970',
|
||||
}));
|
||||
expect(cipher.card).toEqual(
|
||||
jasmine.objectContaining({
|
||||
number: "4111111111111111",
|
||||
code: "111",
|
||||
cardholderName: "test",
|
||||
expMonth: "1",
|
||||
expYear: "1970",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
describe('1Password windows CSV Importer', () => {
|
||||
let importer: Importer;
|
||||
beforeEach(() => {
|
||||
importer = new Importer();
|
||||
});
|
||||
describe("1Password windows CSV Importer", () => {
|
||||
let importer: Importer;
|
||||
beforeEach(() => {
|
||||
importer = new Importer();
|
||||
});
|
||||
|
||||
it('should parse identity records', async () => {
|
||||
const result = await importer.parse(identityData);
|
||||
it("should parse identity records", async () => {
|
||||
const result = await importer.parse(identityData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectIdentity(cipher);
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectIdentity(cipher);
|
||||
});
|
||||
|
||||
it('should parse credit card records', async () => {
|
||||
const result = await importer.parse(creditCardData);
|
||||
it("should parse credit card records", async () => {
|
||||
const result = await importer.parse(creditCardData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectCreditCard(cipher);
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(1);
|
||||
const cipher = result.ciphers[0];
|
||||
expectCreditCard(cipher);
|
||||
});
|
||||
|
||||
it('should parse csv\'s with multiple record types', async () => {
|
||||
const result = await importer.parse(multiTypeData);
|
||||
it("should parse csv's with multiple record types", async () => {
|
||||
const result = await importer.parse(multiTypeData);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(4);
|
||||
expect(result).not.toBeNull();
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.ciphers.length).toBe(4);
|
||||
|
||||
expectIdentity(result.ciphers[1]);
|
||||
expectCreditCard(result.ciphers[2]);
|
||||
});
|
||||
expectIdentity(result.ciphers[1]);
|
||||
expectCreditCard(result.ciphers[2]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export const data = `name,url,username,password,note,cardholdername,cardnumber,cvc,expirydate,zipcode,folder,full_name,phone_number,email,address1,address2,city,country,state
|
||||
notesFolder,,,,,,,,,,,,,,,,,,
|
||||
MySuperSecureNoteTitle,,,,MySuperSecureNote,,,,,,notesFolder,,,,,,,,`;
|
||||
MySuperSecureNoteTitle,,,,MySuperSecureNote,,,,,,notesFolder,,,,,,,,`;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export const data = `"UUID","TITLE","SCOPE","AUTOSUBMIT","1: CARDHOLDER NAME","2: NUMBER","3: VERIFICATION NUMBER","4: EXPIRY DATE","SECTION 2: SECTION_PZET7LEKRQXZUINIEGH5ABA2UY","SECTION_PZET7LEKRQXZUINIEGH5ABA2UY 1: LABEL"
|
||||
"sd26pt226etnsijbl3kqzi5bmm","test card","Default","Default","test","4111111111111111","111","1/3/1970 12:23 AM","section","field (phone)"`;
|
||||
export const data = `"UUID","TITLE","SCOPE","AUTOSUBMIT","1: CARDHOLDER NAME","2: NUMBER","3: VERIFICATION NUMBER","4: EXPIRY DATE","SECTION 2: SECTION_PZET7LEKRQXZUINIEGH5ABA2UY","SECTION_PZET7LEKRQXZUINIEGH5ABA2UY 1: LABEL"
|
||||
"sd26pt226etnsijbl3kqzi5bmm","test card","Default","Default","test","4111111111111111","111","1/3/1970 12:23 AM","section","field (phone)"`;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export const data = `"UUID","TITLE","SCOPE","AUTOSUBMIT","TAGS","NOTES","SECTION 1: NAME","NAME 1: FIRST NAME","NAME 2: INITIAL","NAME 3: LAST NAME","NAME 4: BIRTH DATE","NAME 5: OCCUPATION","NAME 6: COMPANY","NAME 7: DEPARTMENT","NAME 8: JOB TITLE","SECTION 2: ADDRESS","ADDRESS 1: ADDRESS","ADDRESS 2: DEFAULT PHONE","SECTION 3: INTERNET","INTERNET 1: USERNAME","INTERNET 2: EMAIL","SECTION 4: MFJQKMWEOYDZDFH4YMR7WLJKIY","MFJQKMWEOYDZDFH4YMR7WLJKIY 1: SECTION FIELD","MFJQKMWEOYDZDFH4YMR7WLJKIY 2: SECTION FIELD"
|
||||
"6v56y5z4tejwg37jsettta7d7m","Identity Item","Default","Default","Starter Kit","It’s you! 🖐 Select Edit to fill in more details, like your address and contact information.","Identification","first name","mi","last name","12/2/2020 4:01 AM","occupation","bitwarden","department","job title","Address","address city state zip us","8005555555","Internet Details","userNam3","email@bitwarden.com","💡 Did you know?","1Password can fill names and addresses into webpages:","https://support.1password.com/credit-card-address-filling/"`;
|
||||
export const data = `"UUID","TITLE","SCOPE","AUTOSUBMIT","TAGS","NOTES","SECTION 1: NAME","NAME 1: FIRST NAME","NAME 2: INITIAL","NAME 3: LAST NAME","NAME 4: BIRTH DATE","NAME 5: OCCUPATION","NAME 6: COMPANY","NAME 7: DEPARTMENT","NAME 8: JOB TITLE","SECTION 2: ADDRESS","ADDRESS 1: ADDRESS","ADDRESS 2: DEFAULT PHONE","SECTION 3: INTERNET","INTERNET 1: USERNAME","INTERNET 2: EMAIL","SECTION 4: MFJQKMWEOYDZDFH4YMR7WLJKIY","MFJQKMWEOYDZDFH4YMR7WLJKIY 1: SECTION FIELD","MFJQKMWEOYDZDFH4YMR7WLJKIY 2: SECTION FIELD"
|
||||
"6v56y5z4tejwg37jsettta7d7m","Identity Item","Default","Default","Starter Kit","It’s you! 🖐 Select Edit to fill in more details, like your address and contact information.","Identification","first name","mi","last name","12/2/2020 4:01 AM","occupation","bitwarden","department","job title","Address","address city state zip us","8005555555","Internet Details","userNam3","email@bitwarden.com","💡 Did you know?","1Password can fill names and addresses into webpages:","https://support.1password.com/credit-card-address-filling/"`;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const data = `"UUID","TITLE","USERNAME","PASSWORD","URL","URLS","EMAIL","MASTER-PASSWORD","ACCOUNT-KEY","SCOPE","AUTOSUBMIT","TAGS","NOTES","SECTION 1: WXHDKEQREE3TH6QRFCPFPSD3AE","WXHDKEQREE3TH6QRFCPFPSD3AE 1: SECRET KEY","SECTION 1: NAME","NAME 1: FIRST NAME","NAME 2: INITIAL","NAME 3: LAST NAME","NAME 4: BIRTH DATE","NAME 5: OCCUPATION","NAME 6: COMPANY","NAME 7: DEPARTMENT","NAME 8: JOB TITLE","SECTION 2: ADDRESS","ADDRESS 1: ADDRESS","ADDRESS 2: DEFAULT PHONE","SECTION 3: INTERNET","INTERNET 1: USERNAME","INTERNET 2: EMAIL","SECTION 4: MFJQKMWEOYDZDFH4YMR7WLJKIY","MFJQKMWEOYDZDFH4YMR7WLJKIY 1: SECTION FIELD","MFJQKMWEOYDZDFH4YMR7WLJKIY 2: SECTION FIELD","1: CARDHOLDER NAME","2: NUMBER","3: VERIFICATION NUMBER","4: EXPIRY DATE","SECTION 2: SECTION_PZET7LEKRQXZUINIEGH5ABA2UY","SECTION_PZET7LEKRQXZUINIEGH5ABA2UY 1: LABEL","SECTION 1: 4PQVXPR4BMOPGC3DBMTP5U4OFY","4PQVXPR4BMOPGC3DBMTP5U4OFY 1: SECTION FIELD","4PQVXPR4BMOPGC3DBMTP5U4OFY 2: SECTION FIELD","SECTION 2: M2NTUZZBFOFTPAYXVXE6EMZ5JU","M2NTUZZBFOFTPAYXVXE6EMZ5JU 1: SECTION FIELD","M2NTUZZBFOFTPAYXVXE6EMZ5JU 2: SECTION FIELD","SECTION 3: WC3KPAWH6ZAEQB2ARJB6WYZ3DQ","WC3KPAWH6ZAEQB2ARJB6WYZ3DQ 1: SECTION FIELD","WC3KPAWH6ZAEQB2ARJB6WYZ3DQ 2: SECTION FIELD","WC3KPAWH6ZAEQB2ARJB6WYZ3DQ 3: SECTION FIELD","SECTION 4: TOHUYJEJEMGMI6GEQAZ2LJODFE","TOHUYJEJEMGMI6GEQAZ2LJODFE 1: SECTION FIELD","TOHUYJEJEMGMI6GEQAZ2LJODFE 2: SECTION FIELD","SECTION 5: O26UWJJTXRAANG3ONYYOUUJHDM","O26UWJJTXRAANG3ONYYOUUJHDM 1: SECTION FIELD","O26UWJJTXRAANG3ONYYOUUJHDM 2: WATCH VIDEOS","O26UWJJTXRAANG3ONYYOUUJHDM 3: GET SUPPORT","O26UWJJTXRAANG3ONYYOUUJHDM 4: READ THE BLOG","O26UWJJTXRAANG3ONYYOUUJHDM 5: CONTACT US"
|
||||
"xjq32axcswefpcxu2mtxxqnufa","1Password Account","email@bitwarden.com","the account's password","https://my.1password.com","https://my.1password.com","email@bitwarden.com","the account's password","A3-76TR2N-NJG3TZ-9NXFX-WT8GF-6YQC9-R2659","Default","Default","Starter Kit","You can use this login to sign in to your account on 1password.com.","🔑 Secret Key","the account's secret key","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"6v56y5z4tejwg37jsettta7d7m","Identity Item","","","","","","","","Default","Default","Starter Kit","It’s you! 🖐 Select Edit to fill in more details, like your address and contact information.","","","Identification","first name","mi","last name","12/2/2020 4:01 AM","occupation","bitwarden","department","job title","Address","address city state zip us","8005555555","Internet Details","userNam3","email@bitwarden.com","💡 Did you know?","1Password can fill names and addresses into webpages:","https://support.1password.com/credit-card-address-filling/","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"sd26pt226etnsijbl3kqzi5bmm","test card","","","","","","","","Default","Default","","","","","","","","","","","","","","","","","","","","","","","test","4111111111111111","111","1/3/1970 12:23 AM","section","field (phone)","","","","","","","","","","","","","","","","","","",""
|
||||
"oml2sgit3yk7737kxdis65o4xq","🎉 Welcome to 1Password!","","","","","","","","Default","Default","Starter Kit","Follow these steps to get started.","","","","","","","","","","","","","","","","","","","","","","","","","","","1️⃣ Get the apps","https://1password.com/downloads","Install 1Password everywhere you need your passwords.","2️⃣ Get 1Password in your browser","https://1password.com/downloads/#browsers","Install 1Password in your browser to save and fill passwords.","3️⃣ Save your first password","1. Sign in to your favorite website.","2. 1Password will ask to save your username and password.","3. Click Save Login.","4️⃣ Fill passwords and more","https://support.1password.com/explore/extension/","Save and fill passwords, credit cards, and addresses.","📚 Learn 1Password","Check out our videos and articles:","https://youtube.com/1PasswordVideos","https://support.1password.com/","https://blog.1password.com/","https://support.1password.com/contact-us/"`;
|
||||
export const data = `"UUID","TITLE","USERNAME","PASSWORD","URL","URLS","EMAIL","MASTER-PASSWORD","ACCOUNT-KEY","SCOPE","AUTOSUBMIT","TAGS","NOTES","SECTION 1: WXHDKEQREE3TH6QRFCPFPSD3AE","WXHDKEQREE3TH6QRFCPFPSD3AE 1: SECRET KEY","SECTION 1: NAME","NAME 1: FIRST NAME","NAME 2: INITIAL","NAME 3: LAST NAME","NAME 4: BIRTH DATE","NAME 5: OCCUPATION","NAME 6: COMPANY","NAME 7: DEPARTMENT","NAME 8: JOB TITLE","SECTION 2: ADDRESS","ADDRESS 1: ADDRESS","ADDRESS 2: DEFAULT PHONE","SECTION 3: INTERNET","INTERNET 1: USERNAME","INTERNET 2: EMAIL","SECTION 4: MFJQKMWEOYDZDFH4YMR7WLJKIY","MFJQKMWEOYDZDFH4YMR7WLJKIY 1: SECTION FIELD","MFJQKMWEOYDZDFH4YMR7WLJKIY 2: SECTION FIELD","1: CARDHOLDER NAME","2: NUMBER","3: VERIFICATION NUMBER","4: EXPIRY DATE","SECTION 2: SECTION_PZET7LEKRQXZUINIEGH5ABA2UY","SECTION_PZET7LEKRQXZUINIEGH5ABA2UY 1: LABEL","SECTION 1: 4PQVXPR4BMOPGC3DBMTP5U4OFY","4PQVXPR4BMOPGC3DBMTP5U4OFY 1: SECTION FIELD","4PQVXPR4BMOPGC3DBMTP5U4OFY 2: SECTION FIELD","SECTION 2: M2NTUZZBFOFTPAYXVXE6EMZ5JU","M2NTUZZBFOFTPAYXVXE6EMZ5JU 1: SECTION FIELD","M2NTUZZBFOFTPAYXVXE6EMZ5JU 2: SECTION FIELD","SECTION 3: WC3KPAWH6ZAEQB2ARJB6WYZ3DQ","WC3KPAWH6ZAEQB2ARJB6WYZ3DQ 1: SECTION FIELD","WC3KPAWH6ZAEQB2ARJB6WYZ3DQ 2: SECTION FIELD","WC3KPAWH6ZAEQB2ARJB6WYZ3DQ 3: SECTION FIELD","SECTION 4: TOHUYJEJEMGMI6GEQAZ2LJODFE","TOHUYJEJEMGMI6GEQAZ2LJODFE 1: SECTION FIELD","TOHUYJEJEMGMI6GEQAZ2LJODFE 2: SECTION FIELD","SECTION 5: O26UWJJTXRAANG3ONYYOUUJHDM","O26UWJJTXRAANG3ONYYOUUJHDM 1: SECTION FIELD","O26UWJJTXRAANG3ONYYOUUJHDM 2: WATCH VIDEOS","O26UWJJTXRAANG3ONYYOUUJHDM 3: GET SUPPORT","O26UWJJTXRAANG3ONYYOUUJHDM 4: READ THE BLOG","O26UWJJTXRAANG3ONYYOUUJHDM 5: CONTACT US"
|
||||
"xjq32axcswefpcxu2mtxxqnufa","1Password Account","email@bitwarden.com","the account's password","https://my.1password.com","https://my.1password.com","email@bitwarden.com","the account's password","A3-76TR2N-NJG3TZ-9NXFX-WT8GF-6YQC9-R2659","Default","Default","Starter Kit","You can use this login to sign in to your account on 1password.com.","🔑 Secret Key","the account's secret key","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"6v56y5z4tejwg37jsettta7d7m","Identity Item","","","","","","","","Default","Default","Starter Kit","It’s you! 🖐 Select Edit to fill in more details, like your address and contact information.","","","Identification","first name","mi","last name","12/2/2020 4:01 AM","occupation","bitwarden","department","job title","Address","address city state zip us","8005555555","Internet Details","userNam3","email@bitwarden.com","💡 Did you know?","1Password can fill names and addresses into webpages:","https://support.1password.com/credit-card-address-filling/","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"sd26pt226etnsijbl3kqzi5bmm","test card","","","","","","","","Default","Default","","","","","","","","","","","","","","","","","","","","","","","test","4111111111111111","111","1/3/1970 12:23 AM","section","field (phone)","","","","","","","","","","","","","","","","","","",""
|
||||
"oml2sgit3yk7737kxdis65o4xq","🎉 Welcome to 1Password!","","","","","","","","Default","Default","Starter Kit","Follow these steps to get started.","","","","","","","","","","","","","","","","","","","","","","","","","","","1️⃣ Get the apps","https://1password.com/downloads","Install 1Password everywhere you need your passwords.","2️⃣ Get 1Password in your browser","https://1password.com/downloads/#browsers","Install 1Password in your browser to save and fill passwords.","3️⃣ Save your first password","1. Sign in to your favorite website.","2. 1Password will ask to save your username and password.","3. Click Save Login.","4️⃣ Fill passwords and more","https://support.1password.com/explore/extension/","Save and fill passwords, credit cards, and addresses.","📚 Learn 1Password","Check out our videos and articles:","https://youtube.com/1PasswordVideos","https://support.1password.com/","https://blog.1password.com/","https://support.1password.com/contact-us/"`;
|
||||
|
||||
@@ -59,4 +59,4 @@ export const data = `
|
||||
<label_id>3</label_id>
|
||||
</card>
|
||||
</database>
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -1,141 +1,127 @@
|
||||
import { sequentialize } from 'jslib-common/misc/sequentialize';
|
||||
import { sequentialize } from "jslib-common/misc/sequentialize";
|
||||
|
||||
describe('sequentialize decorator', () => {
|
||||
it('should call the function once', async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
describe("sequentialize decorator", () => {
|
||||
it("should call the function once", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(1);
|
||||
});
|
||||
expect(foo.calls).toBe(1);
|
||||
});
|
||||
|
||||
it('should call the function once for each instance of the object', async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
promises.push(foo2.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
it("should call the function once for each instance of the object", async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
promises.push(foo2.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(1);
|
||||
expect(foo2.calls).toBe(1);
|
||||
});
|
||||
expect(foo.calls).toBe(1);
|
||||
expect(foo2.calls).toBe(1);
|
||||
});
|
||||
|
||||
it('should call the function once with key function', async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
it("should call the function once with key function", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(1);
|
||||
});
|
||||
expect(foo.calls).toBe(1);
|
||||
});
|
||||
|
||||
it('should call the function again when already resolved', async () => {
|
||||
const foo = new Foo();
|
||||
await foo.bar(1);
|
||||
expect(foo.calls).toBe(1);
|
||||
await foo.bar(1);
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
it("should call the function again when already resolved", async () => {
|
||||
const foo = new Foo();
|
||||
await foo.bar(1);
|
||||
expect(foo.calls).toBe(1);
|
||||
await foo.bar(1);
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
|
||||
it('should call the function again when already resolved with a key function', async () => {
|
||||
const foo = new Foo();
|
||||
await foo.baz(1);
|
||||
expect(foo.calls).toBe(1);
|
||||
await foo.baz(1);
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
it("should call the function again when already resolved with a key function", async () => {
|
||||
const foo = new Foo();
|
||||
await foo.baz(1);
|
||||
expect(foo.calls).toBe(1);
|
||||
await foo.baz(1);
|
||||
expect(foo.calls).toBe(2);
|
||||
});
|
||||
|
||||
it('should call the function for each argument', async () => {
|
||||
const foo = new Foo();
|
||||
await Promise.all([
|
||||
foo.bar(1),
|
||||
foo.bar(1),
|
||||
foo.bar(2),
|
||||
foo.bar(2),
|
||||
foo.bar(3),
|
||||
foo.bar(3),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
});
|
||||
it("should call the function for each argument", async () => {
|
||||
const foo = new Foo();
|
||||
await Promise.all([foo.bar(1), foo.bar(1), foo.bar(2), foo.bar(2), foo.bar(3), foo.bar(3)]);
|
||||
expect(foo.calls).toBe(3);
|
||||
});
|
||||
|
||||
it('should call the function for each argument with key function', async () => {
|
||||
const foo = new Foo();
|
||||
await Promise.all([
|
||||
foo.baz(1),
|
||||
foo.baz(1),
|
||||
foo.baz(2),
|
||||
foo.baz(2),
|
||||
foo.baz(3),
|
||||
foo.baz(3),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
});
|
||||
it("should call the function for each argument with key function", async () => {
|
||||
const foo = new Foo();
|
||||
await Promise.all([foo.baz(1), foo.baz(1), foo.baz(2), foo.baz(2), foo.baz(3), foo.baz(3)]);
|
||||
expect(foo.calls).toBe(3);
|
||||
});
|
||||
|
||||
it('should return correct result for each call', async () => {
|
||||
const foo = new Foo();
|
||||
const allRes: number[] = [];
|
||||
it("should return correct result for each call", async () => {
|
||||
const foo = new Foo();
|
||||
const allRes: number[] = [];
|
||||
|
||||
await Promise.all([
|
||||
foo.bar(1).then(res => allRes.push(res)),
|
||||
foo.bar(1).then(res => allRes.push(res)),
|
||||
foo.bar(2).then(res => allRes.push(res)),
|
||||
foo.bar(2).then(res => allRes.push(res)),
|
||||
foo.bar(3).then(res => allRes.push(res)),
|
||||
foo.bar(3).then(res => allRes.push(res)),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
expect(allRes.length).toBe(6);
|
||||
allRes.sort();
|
||||
expect(allRes).toEqual([2, 2, 4, 4, 6, 6]);
|
||||
});
|
||||
await Promise.all([
|
||||
foo.bar(1).then((res) => allRes.push(res)),
|
||||
foo.bar(1).then((res) => allRes.push(res)),
|
||||
foo.bar(2).then((res) => allRes.push(res)),
|
||||
foo.bar(2).then((res) => allRes.push(res)),
|
||||
foo.bar(3).then((res) => allRes.push(res)),
|
||||
foo.bar(3).then((res) => allRes.push(res)),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
expect(allRes.length).toBe(6);
|
||||
allRes.sort();
|
||||
expect(allRes).toEqual([2, 2, 4, 4, 6, 6]);
|
||||
});
|
||||
|
||||
it('should return correct result for each call with key function', async () => {
|
||||
const foo = new Foo();
|
||||
const allRes: number[] = [];
|
||||
it("should return correct result for each call with key function", async () => {
|
||||
const foo = new Foo();
|
||||
const allRes: number[] = [];
|
||||
|
||||
await Promise.all([
|
||||
foo.baz(1).then(res => allRes.push(res)),
|
||||
foo.baz(1).then(res => allRes.push(res)),
|
||||
foo.baz(2).then(res => allRes.push(res)),
|
||||
foo.baz(2).then(res => allRes.push(res)),
|
||||
foo.baz(3).then(res => allRes.push(res)),
|
||||
foo.baz(3).then(res => allRes.push(res)),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
expect(allRes.length).toBe(6);
|
||||
allRes.sort();
|
||||
expect(allRes).toEqual([3, 3, 6, 6, 9, 9]);
|
||||
});
|
||||
await Promise.all([
|
||||
foo.baz(1).then((res) => allRes.push(res)),
|
||||
foo.baz(1).then((res) => allRes.push(res)),
|
||||
foo.baz(2).then((res) => allRes.push(res)),
|
||||
foo.baz(2).then((res) => allRes.push(res)),
|
||||
foo.baz(3).then((res) => allRes.push(res)),
|
||||
foo.baz(3).then((res) => allRes.push(res)),
|
||||
]);
|
||||
expect(foo.calls).toBe(3);
|
||||
expect(allRes.length).toBe(6);
|
||||
allRes.sort();
|
||||
expect(allRes).toEqual([3, 3, 6, 6, 9, 9]);
|
||||
});
|
||||
});
|
||||
|
||||
class Foo {
|
||||
calls = 0;
|
||||
calls = 0;
|
||||
|
||||
@sequentialize(args => 'bar' + args[0])
|
||||
bar(a: number): Promise<number> {
|
||||
this.calls++;
|
||||
return new Promise(res => {
|
||||
setTimeout(() => {
|
||||
res(a * 2);
|
||||
}, Math.random() * 100);
|
||||
});
|
||||
}
|
||||
@sequentialize((args) => "bar" + args[0])
|
||||
bar(a: number): Promise<number> {
|
||||
this.calls++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res(a * 2);
|
||||
}, Math.random() * 100);
|
||||
});
|
||||
}
|
||||
|
||||
@sequentialize(args => 'baz' + args[0])
|
||||
baz(a: number): Promise<number> {
|
||||
this.calls++;
|
||||
return new Promise(res => {
|
||||
setTimeout(() => {
|
||||
res(a * 3);
|
||||
}, Math.random() * 100);
|
||||
});
|
||||
}
|
||||
@sequentialize((args) => "baz" + args[0])
|
||||
baz(a: number): Promise<number> {
|
||||
this.calls++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res(a * 3);
|
||||
}, Math.random() * 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,110 +1,110 @@
|
||||
import { sequentialize } from 'jslib-common/misc/sequentialize';
|
||||
import { throttle } from 'jslib-common/misc/throttle';
|
||||
import { sequentialize } from "jslib-common/misc/sequentialize";
|
||||
import { throttle } from "jslib-common/misc/throttle";
|
||||
|
||||
describe('throttle decorator', () => {
|
||||
it('should call the function once at a time', async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
describe("throttle decorator", () => {
|
||||
it("should call the function once at a time", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(10);
|
||||
});
|
||||
expect(foo.calls).toBe(10);
|
||||
});
|
||||
|
||||
it('should call the function once at a time for each object', async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
promises.push(foo2.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
it("should call the function once at a time for each object", async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.bar(1));
|
||||
promises.push(foo2.bar(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(10);
|
||||
expect(foo2.calls).toBe(10);
|
||||
});
|
||||
expect(foo.calls).toBe(10);
|
||||
expect(foo2.calls).toBe(10);
|
||||
});
|
||||
|
||||
it('should call the function limit at a time', async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
it("should call the function limit at a time", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(10);
|
||||
});
|
||||
expect(foo.calls).toBe(10);
|
||||
});
|
||||
|
||||
it('should call the function limit at a time for each object', async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
promises.push(foo2.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
it("should call the function limit at a time for each object", async () => {
|
||||
const foo = new Foo();
|
||||
const foo2 = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.baz(1));
|
||||
promises.push(foo2.baz(1));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(10);
|
||||
expect(foo2.calls).toBe(10);
|
||||
});
|
||||
expect(foo.calls).toBe(10);
|
||||
expect(foo2.calls).toBe(10);
|
||||
});
|
||||
|
||||
it('should work together with sequentialize', async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.qux(Math.floor(i / 2) * 2));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
it("should work together with sequentialize", async () => {
|
||||
const foo = new Foo();
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(foo.qux(Math.floor(i / 2) * 2));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(foo.calls).toBe(5);
|
||||
});
|
||||
expect(foo.calls).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
class Foo {
|
||||
calls = 0;
|
||||
inflight = 0;
|
||||
calls = 0;
|
||||
inflight = 0;
|
||||
|
||||
@throttle(1, () => 'bar')
|
||||
bar(a: number) {
|
||||
this.calls++;
|
||||
this.inflight++;
|
||||
return new Promise(res => {
|
||||
setTimeout(() => {
|
||||
expect(this.inflight).toBe(1);
|
||||
this.inflight--;
|
||||
res(a * 2);
|
||||
}, Math.random() * 10);
|
||||
});
|
||||
}
|
||||
@throttle(1, () => "bar")
|
||||
bar(a: number) {
|
||||
this.calls++;
|
||||
this.inflight++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
expect(this.inflight).toBe(1);
|
||||
this.inflight--;
|
||||
res(a * 2);
|
||||
}, Math.random() * 10);
|
||||
});
|
||||
}
|
||||
|
||||
@throttle(5, () => 'baz')
|
||||
baz(a: number) {
|
||||
this.calls++;
|
||||
this.inflight++;
|
||||
return new Promise(res => {
|
||||
setTimeout(() => {
|
||||
expect(this.inflight).toBeLessThanOrEqual(5);
|
||||
this.inflight--;
|
||||
res(a * 3);
|
||||
}, Math.random() * 10);
|
||||
});
|
||||
}
|
||||
@throttle(5, () => "baz")
|
||||
baz(a: number) {
|
||||
this.calls++;
|
||||
this.inflight++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
expect(this.inflight).toBeLessThanOrEqual(5);
|
||||
this.inflight--;
|
||||
res(a * 3);
|
||||
}, Math.random() * 10);
|
||||
});
|
||||
}
|
||||
|
||||
@sequentialize(args => 'qux' + args[0])
|
||||
@throttle(1, () => 'qux')
|
||||
qux(a: number) {
|
||||
this.calls++;
|
||||
this.inflight++;
|
||||
return new Promise(res => {
|
||||
setTimeout(() => {
|
||||
expect(this.inflight).toBe(1);
|
||||
this.inflight--;
|
||||
res(a * 3);
|
||||
}, Math.random() * 10);
|
||||
});
|
||||
}
|
||||
@sequentialize((args) => "qux" + args[0])
|
||||
@throttle(1, () => "qux")
|
||||
qux(a: number) {
|
||||
this.calls++;
|
||||
this.inflight++;
|
||||
return new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
expect(this.inflight).toBe(1);
|
||||
this.inflight--;
|
||||
res(a * 3);
|
||||
}, Math.random() * 10);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +1,73 @@
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
|
||||
describe('Utils Service', () => {
|
||||
describe('getDomain', () => {
|
||||
it('should fail for invalid urls', () => {
|
||||
expect(Utils.getDomain(null)).toBeNull();
|
||||
expect(Utils.getDomain(undefined)).toBeNull();
|
||||
expect(Utils.getDomain(' ')).toBeNull();
|
||||
expect(Utils.getDomain('https://bit!:"_&ward.com')).toBeNull();
|
||||
expect(Utils.getDomain('bitwarden')).toBeNull();
|
||||
});
|
||||
|
||||
it('should fail for data urls', () => {
|
||||
expect(Utils.getDomain('data:image/jpeg;base64,AAA')).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle urls without protocol', () => {
|
||||
expect(Utils.getDomain('bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getDomain('wrong://bitwarden.com')).toBe('bitwarden.com');
|
||||
});
|
||||
|
||||
it('should handle valid urls', () => {
|
||||
expect(Utils.getDomain('https://bitwarden')).toBe('bitwarden');
|
||||
expect(Utils.getDomain('https://bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getDomain('http://bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getDomain('http://vault.bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getDomain('https://user:password@bitwarden.com:8080/password/sites?and&query#hash'))
|
||||
.toBe('bitwarden.com');
|
||||
expect(Utils.getDomain('https://bitwarden.unknown')).toBe('bitwarden.unknown');
|
||||
});
|
||||
|
||||
it('should support localhost and IP', () => {
|
||||
expect(Utils.getDomain('https://localhost')).toBe('localhost');
|
||||
expect(Utils.getDomain('https://192.168.1.1')).toBe('192.168.1.1');
|
||||
});
|
||||
|
||||
it('should reject invalid hostnames', () => {
|
||||
expect(Utils.getDomain('https://mywebsite.com$.mywebsite.com')).toBeNull();
|
||||
expect(Utils.getDomain('https://mywebsite.com!.mywebsite.com')).toBeNull();
|
||||
});
|
||||
describe("Utils Service", () => {
|
||||
describe("getDomain", () => {
|
||||
it("should fail for invalid urls", () => {
|
||||
expect(Utils.getDomain(null)).toBeNull();
|
||||
expect(Utils.getDomain(undefined)).toBeNull();
|
||||
expect(Utils.getDomain(" ")).toBeNull();
|
||||
expect(Utils.getDomain('https://bit!:"_&ward.com')).toBeNull();
|
||||
expect(Utils.getDomain("bitwarden")).toBeNull();
|
||||
});
|
||||
|
||||
describe('getHostname', () => {
|
||||
it('should fail for invalid urls', () => {
|
||||
expect(Utils.getHostname(null)).toBeNull();
|
||||
expect(Utils.getHostname(undefined)).toBeNull();
|
||||
expect(Utils.getHostname(' ')).toBeNull();
|
||||
expect(Utils.getHostname('https://bit!:"_&ward.com')).toBeNull();
|
||||
expect(Utils.getHostname('bitwarden')).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle valid urls', () => {
|
||||
expect(Utils.getHostname('bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getHostname('https://bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getHostname('http://bitwarden.com')).toBe('bitwarden.com');
|
||||
expect(Utils.getHostname('http://vault.bitwarden.com')).toBe('vault.bitwarden.com');
|
||||
});
|
||||
|
||||
it('should support localhost and IP', () => {
|
||||
expect(Utils.getHostname('https://localhost')).toBe('localhost');
|
||||
expect(Utils.getHostname('https://192.168.1.1')).toBe('192.168.1.1');
|
||||
});
|
||||
it("should fail for data urls", () => {
|
||||
expect(Utils.getDomain("data:image/jpeg;base64,AAA")).toBeNull();
|
||||
});
|
||||
|
||||
describe('newGuid', () => {
|
||||
it('should create a valid guid', () => {
|
||||
const validGuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
expect(Utils.newGuid()).toMatch(validGuid);
|
||||
});
|
||||
it("should handle urls without protocol", () => {
|
||||
expect(Utils.getDomain("bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(Utils.getDomain("wrong://bitwarden.com")).toBe("bitwarden.com");
|
||||
});
|
||||
|
||||
it("should handle valid urls", () => {
|
||||
expect(Utils.getDomain("https://bitwarden")).toBe("bitwarden");
|
||||
expect(Utils.getDomain("https://bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(Utils.getDomain("http://bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(Utils.getDomain("http://vault.bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(
|
||||
Utils.getDomain("https://user:password@bitwarden.com:8080/password/sites?and&query#hash")
|
||||
).toBe("bitwarden.com");
|
||||
expect(Utils.getDomain("https://bitwarden.unknown")).toBe("bitwarden.unknown");
|
||||
});
|
||||
|
||||
it("should support localhost and IP", () => {
|
||||
expect(Utils.getDomain("https://localhost")).toBe("localhost");
|
||||
expect(Utils.getDomain("https://192.168.1.1")).toBe("192.168.1.1");
|
||||
});
|
||||
|
||||
it("should reject invalid hostnames", () => {
|
||||
expect(Utils.getDomain("https://mywebsite.com$.mywebsite.com")).toBeNull();
|
||||
expect(Utils.getDomain("https://mywebsite.com!.mywebsite.com")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getHostname", () => {
|
||||
it("should fail for invalid urls", () => {
|
||||
expect(Utils.getHostname(null)).toBeNull();
|
||||
expect(Utils.getHostname(undefined)).toBeNull();
|
||||
expect(Utils.getHostname(" ")).toBeNull();
|
||||
expect(Utils.getHostname('https://bit!:"_&ward.com')).toBeNull();
|
||||
expect(Utils.getHostname("bitwarden")).toBeNull();
|
||||
});
|
||||
|
||||
it("should handle valid urls", () => {
|
||||
expect(Utils.getHostname("bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(Utils.getHostname("https://bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(Utils.getHostname("http://bitwarden.com")).toBe("bitwarden.com");
|
||||
expect(Utils.getHostname("http://vault.bitwarden.com")).toBe("vault.bitwarden.com");
|
||||
});
|
||||
|
||||
it("should support localhost and IP", () => {
|
||||
expect(Utils.getHostname("https://localhost")).toBe("localhost");
|
||||
expect(Utils.getHostname("https://192.168.1.1")).toBe("192.168.1.1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("newGuid", () => {
|
||||
it("should create a valid guid", () => {
|
||||
const validGuid =
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
expect(Utils.newGuid()).toMatch(validGuid);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,61 +1,71 @@
|
||||
import { Arg, Substitute, SubstituteOf } from '@fluffy-spoon/substitute';
|
||||
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { FileUploadService } from 'jslib-common/abstractions/fileUpload.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { SearchService } from 'jslib-common/abstractions/search.service';
|
||||
import { SettingsService } from 'jslib-common/abstractions/settings.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { FileUploadService } from "jslib-common/abstractions/fileUpload.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { SearchService } from "jslib-common/abstractions/search.service";
|
||||
import { SettingsService } from "jslib-common/abstractions/settings.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
import { Cipher } from 'jslib-common/models/domain/cipher';
|
||||
import { EncArrayBuffer } from 'jslib-common/models/domain/encArrayBuffer';
|
||||
import { EncString } from 'jslib-common/models/domain/encString';
|
||||
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
import { Cipher } from "jslib-common/models/domain/cipher";
|
||||
import { EncArrayBuffer } from "jslib-common/models/domain/encArrayBuffer";
|
||||
import { EncString } from "jslib-common/models/domain/encString";
|
||||
import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey";
|
||||
|
||||
import { CipherService } from 'jslib-common/services/cipher.service';
|
||||
import { CipherService } from "jslib-common/services/cipher.service";
|
||||
|
||||
const ENCRYPTED_TEXT = 'This data has been encrypted';
|
||||
const ENCRYPTED_TEXT = "This data has been encrypted";
|
||||
const ENCRYPTED_BYTES = new EncArrayBuffer(Utils.fromUtf8ToArray(ENCRYPTED_TEXT).buffer);
|
||||
|
||||
describe('Cipher Service', () => {
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
let stateService: SubstituteOf<StateService>;
|
||||
let settingsService: SubstituteOf<SettingsService>;
|
||||
let apiService: SubstituteOf<ApiService>;
|
||||
let fileUploadService: SubstituteOf<FileUploadService>;
|
||||
let i18nService: SubstituteOf<I18nService>;
|
||||
let searchService: SubstituteOf<SearchService>;
|
||||
let logService: SubstituteOf<LogService>;
|
||||
describe("Cipher Service", () => {
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
let stateService: SubstituteOf<StateService>;
|
||||
let settingsService: SubstituteOf<SettingsService>;
|
||||
let apiService: SubstituteOf<ApiService>;
|
||||
let fileUploadService: SubstituteOf<FileUploadService>;
|
||||
let i18nService: SubstituteOf<I18nService>;
|
||||
let searchService: SubstituteOf<SearchService>;
|
||||
let logService: SubstituteOf<LogService>;
|
||||
|
||||
let cipherService: CipherService;
|
||||
let cipherService: CipherService;
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoService = Substitute.for<CryptoService>();
|
||||
stateService = Substitute.for<StateService>();
|
||||
settingsService = Substitute.for<SettingsService>();
|
||||
apiService = Substitute.for<ApiService>();
|
||||
fileUploadService = Substitute.for<FileUploadService>();
|
||||
i18nService = Substitute.for<I18nService>();
|
||||
searchService = Substitute.for<SearchService>();
|
||||
logService = Substitute.for<LogService>();
|
||||
beforeEach(() => {
|
||||
cryptoService = Substitute.for<CryptoService>();
|
||||
stateService = Substitute.for<StateService>();
|
||||
settingsService = Substitute.for<SettingsService>();
|
||||
apiService = Substitute.for<ApiService>();
|
||||
fileUploadService = Substitute.for<FileUploadService>();
|
||||
i18nService = Substitute.for<I18nService>();
|
||||
searchService = Substitute.for<SearchService>();
|
||||
logService = Substitute.for<LogService>();
|
||||
|
||||
cryptoService.encryptToBytes(Arg.any(), Arg.any()).resolves(ENCRYPTED_BYTES);
|
||||
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(new EncString(ENCRYPTED_TEXT));
|
||||
cryptoService.encryptToBytes(Arg.any(), Arg.any()).resolves(ENCRYPTED_BYTES);
|
||||
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(new EncString(ENCRYPTED_TEXT));
|
||||
|
||||
cipherService = new CipherService(cryptoService, settingsService, apiService, fileUploadService,
|
||||
i18nService, () => searchService, logService, stateService);
|
||||
});
|
||||
cipherService = new CipherService(
|
||||
cryptoService,
|
||||
settingsService,
|
||||
apiService,
|
||||
fileUploadService,
|
||||
i18nService,
|
||||
() => searchService,
|
||||
logService,
|
||||
stateService
|
||||
);
|
||||
});
|
||||
|
||||
it('attachments upload encrypted file contents', async () => {
|
||||
const fileName = 'filename';
|
||||
const fileData = new Uint8Array(10).buffer;
|
||||
cryptoService.getOrgKey(Arg.any()).resolves(new SymmetricCryptoKey(new Uint8Array(32).buffer));
|
||||
it("attachments upload encrypted file contents", async () => {
|
||||
const fileName = "filename";
|
||||
const fileData = new Uint8Array(10).buffer;
|
||||
cryptoService.getOrgKey(Arg.any()).resolves(new SymmetricCryptoKey(new Uint8Array(32).buffer));
|
||||
|
||||
await cipherService.saveAttachmentRawWithServer(new Cipher(), fileName, fileData);
|
||||
await cipherService.saveAttachmentRawWithServer(new Cipher(), fileName, fileData);
|
||||
|
||||
fileUploadService.received(1).uploadCipherAttachment(Arg.any(), Arg.any(), new EncString(ENCRYPTED_TEXT), ENCRYPTED_BYTES);
|
||||
});
|
||||
fileUploadService
|
||||
.received(1)
|
||||
.uploadCipherAttachment(Arg.any(), Arg.any(), new EncString(ENCRYPTED_TEXT), ENCRYPTED_BYTES);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ConsoleLogService } from 'jslib-common/services/consoleLog.service';
|
||||
import { ConsoleLogService } from "jslib-common/services/consoleLog.service";
|
||||
|
||||
const originalConsole = console;
|
||||
let caughtMessage: any;
|
||||
@@ -6,90 +6,97 @@ let caughtMessage: any;
|
||||
declare var console: any;
|
||||
|
||||
export function interceptConsole(interceptions: any): object {
|
||||
console = {
|
||||
// tslint:disable-next-line
|
||||
log: function () {
|
||||
interceptions.log = arguments;
|
||||
},
|
||||
// tslint:disable-next-line
|
||||
warn: function () {
|
||||
interceptions.warn = arguments;
|
||||
},
|
||||
// tslint:disable-next-line
|
||||
error: function () {
|
||||
interceptions.error = arguments;
|
||||
},
|
||||
};
|
||||
return interceptions;
|
||||
console = {
|
||||
// tslint:disable-next-line
|
||||
log: function () {
|
||||
interceptions.log = arguments;
|
||||
},
|
||||
// tslint:disable-next-line
|
||||
warn: function () {
|
||||
interceptions.warn = arguments;
|
||||
},
|
||||
// tslint:disable-next-line
|
||||
error: function () {
|
||||
interceptions.error = arguments;
|
||||
},
|
||||
};
|
||||
return interceptions;
|
||||
}
|
||||
|
||||
export function restoreConsole() {
|
||||
console = originalConsole;
|
||||
console = originalConsole;
|
||||
}
|
||||
|
||||
describe('ConsoleLogService', () => {
|
||||
let logService: ConsoleLogService;
|
||||
beforeEach(() => {
|
||||
caughtMessage = {};
|
||||
interceptConsole(caughtMessage);
|
||||
logService = new ConsoleLogService(true);
|
||||
describe("ConsoleLogService", () => {
|
||||
let logService: ConsoleLogService;
|
||||
beforeEach(() => {
|
||||
caughtMessage = {};
|
||||
interceptConsole(caughtMessage);
|
||||
logService = new ConsoleLogService(true);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
it("filters messages below the set threshold", () => {
|
||||
logService = new ConsoleLogService(true, (level) => true);
|
||||
logService.debug("debug");
|
||||
logService.info("info");
|
||||
logService.warning("warning");
|
||||
logService.error("error");
|
||||
|
||||
expect(caughtMessage).toEqual({});
|
||||
});
|
||||
it("only writes debug messages in dev mode", () => {
|
||||
logService = new ConsoleLogService(false);
|
||||
|
||||
logService.debug("debug message");
|
||||
expect(caughtMessage.log).toBeUndefined();
|
||||
});
|
||||
|
||||
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"]),
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
restoreConsole();
|
||||
logService.info("this is an info message");
|
||||
expect(caughtMessage).toEqual({
|
||||
log: jasmine.arrayWithExactContents(["this is an info message"]),
|
||||
});
|
||||
|
||||
it('filters messages below the set threshold', () => {
|
||||
logService = new ConsoleLogService(true, level => true);
|
||||
logService.debug('debug');
|
||||
logService.info('info');
|
||||
logService.warning('warning');
|
||||
logService.error('error');
|
||||
|
||||
expect(caughtMessage).toEqual({});
|
||||
});
|
||||
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"]),
|
||||
});
|
||||
it('only writes debug messages in dev mode', () => {
|
||||
logService = new ConsoleLogService(false);
|
||||
|
||||
logService.debug('debug message');
|
||||
expect(caughtMessage.log).toBeUndefined();
|
||||
});
|
||||
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"]),
|
||||
});
|
||||
});
|
||||
|
||||
it("times with output to info", async () => {
|
||||
logService.time();
|
||||
await new Promise((r) => setTimeout(r, 250));
|
||||
const duration = logService.timeEnd();
|
||||
expect(duration[0]).toBe(0);
|
||||
expect(duration[1]).toBeGreaterThan(0);
|
||||
expect(duration[1]).toBeLessThan(500 * 10e6);
|
||||
|
||||
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).toEqual(jasmine.arrayContaining([]));
|
||||
expect(caughtMessage.log.length).toBe(1);
|
||||
expect(caughtMessage.log[0]).toEqual(jasmine.stringMatching(/^default: \d+\.?\d*ms$/));
|
||||
});
|
||||
|
||||
logService.info('this is an info message');
|
||||
expect(caughtMessage).toEqual({ log: jasmine.arrayWithExactContents(['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']) });
|
||||
});
|
||||
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']) });
|
||||
});
|
||||
it("filters time output", async () => {
|
||||
logService = new ConsoleLogService(true, (level) => true);
|
||||
logService.time();
|
||||
logService.timeEnd();
|
||||
|
||||
it('times with output to info', async () => {
|
||||
logService.time();
|
||||
await new Promise(r => setTimeout(r, 250));
|
||||
const duration = logService.timeEnd();
|
||||
expect(duration[0]).toBe(0);
|
||||
expect(duration[1]).toBeGreaterThan(0);
|
||||
expect(duration[1]).toBeLessThan(500 * 10e6);
|
||||
|
||||
expect(caughtMessage).toEqual(jasmine.arrayContaining([]));
|
||||
expect(caughtMessage.log.length).toBe(1);
|
||||
expect(caughtMessage.log[0]).toEqual(jasmine.stringMatching(/^default: \d+\.?\d*ms$/));
|
||||
});
|
||||
|
||||
it('filters time output', async () => {
|
||||
logService = new ConsoleLogService(true, level => true);
|
||||
logService.time();
|
||||
logService.timeEnd();
|
||||
|
||||
expect(caughtMessage).toEqual({});
|
||||
});
|
||||
expect(caughtMessage).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,123 +1,135 @@
|
||||
import { Substitute, SubstituteOf } from '@fluffy-spoon/substitute';
|
||||
import { Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { FolderService } from 'jslib-common/abstractions/folder.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CipherService } from "jslib-common/abstractions/cipher.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { FolderService } from "jslib-common/abstractions/folder.service";
|
||||
|
||||
import { ExportService } from 'jslib-common/services/export.service';
|
||||
import { ExportService } from "jslib-common/services/export.service";
|
||||
|
||||
import { Cipher } from 'jslib-common/models/domain/cipher';
|
||||
import { EncString } from 'jslib-common/models/domain/encString';
|
||||
import { Login } from 'jslib-common/models/domain/login';
|
||||
import { CipherWithIds as CipherExport } from 'jslib-common/models/export/cipherWithIds';
|
||||
import { Cipher } from "jslib-common/models/domain/cipher";
|
||||
import { EncString } from "jslib-common/models/domain/encString";
|
||||
import { Login } from "jslib-common/models/domain/login";
|
||||
import { CipherWithIds as CipherExport } from "jslib-common/models/export/cipherWithIds";
|
||||
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { LoginView } from 'jslib-common/models/view/loginView';
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
import { CipherView } from "jslib-common/models/view/cipherView";
|
||||
import { LoginView } from "jslib-common/models/view/loginView";
|
||||
|
||||
import { BuildTestObject, GetUniqueString } from '../../utils';
|
||||
import { BuildTestObject, GetUniqueString } from "../../utils";
|
||||
|
||||
const UserCipherViews = [
|
||||
generateCipherView(false),
|
||||
generateCipherView(false),
|
||||
generateCipherView(true),
|
||||
generateCipherView(false),
|
||||
generateCipherView(false),
|
||||
generateCipherView(true),
|
||||
];
|
||||
|
||||
const UserCipherDomains = [
|
||||
generateCipherDomain(false),
|
||||
generateCipherDomain(false),
|
||||
generateCipherDomain(true),
|
||||
generateCipherDomain(false),
|
||||
generateCipherDomain(false),
|
||||
generateCipherDomain(true),
|
||||
];
|
||||
|
||||
function generateCipherView(deleted: boolean) {
|
||||
return BuildTestObject({
|
||||
id: GetUniqueString('id'),
|
||||
notes: GetUniqueString('notes'),
|
||||
type: CipherType.Login,
|
||||
login: BuildTestObject<LoginView>({
|
||||
username: GetUniqueString('username'),
|
||||
password: GetUniqueString('password'),
|
||||
}, LoginView),
|
||||
collectionIds: null,
|
||||
deletedDate: deleted ? new Date() : null,
|
||||
}, CipherView);
|
||||
return BuildTestObject(
|
||||
{
|
||||
id: GetUniqueString("id"),
|
||||
notes: GetUniqueString("notes"),
|
||||
type: CipherType.Login,
|
||||
login: BuildTestObject<LoginView>(
|
||||
{
|
||||
username: GetUniqueString("username"),
|
||||
password: GetUniqueString("password"),
|
||||
},
|
||||
LoginView
|
||||
),
|
||||
collectionIds: null,
|
||||
deletedDate: deleted ? new Date() : null,
|
||||
},
|
||||
CipherView
|
||||
);
|
||||
}
|
||||
|
||||
function generateCipherDomain(deleted: boolean) {
|
||||
return BuildTestObject({
|
||||
id: GetUniqueString('id'),
|
||||
notes: new EncString(GetUniqueString('notes')),
|
||||
type: CipherType.Login,
|
||||
login: BuildTestObject<Login>({
|
||||
username: new EncString(GetUniqueString('username')),
|
||||
password: new EncString(GetUniqueString('password')),
|
||||
}, Login),
|
||||
collectionIds: null,
|
||||
deletedDate: deleted ? new Date() : null,
|
||||
}, Cipher);
|
||||
return BuildTestObject(
|
||||
{
|
||||
id: GetUniqueString("id"),
|
||||
notes: new EncString(GetUniqueString("notes")),
|
||||
type: CipherType.Login,
|
||||
login: BuildTestObject<Login>(
|
||||
{
|
||||
username: new EncString(GetUniqueString("username")),
|
||||
password: new EncString(GetUniqueString("password")),
|
||||
},
|
||||
Login
|
||||
),
|
||||
collectionIds: null,
|
||||
deletedDate: deleted ? new Date() : null,
|
||||
},
|
||||
Cipher
|
||||
);
|
||||
}
|
||||
|
||||
function expectEqualCiphers(ciphers: CipherView[] | Cipher[], jsonResult: string) {
|
||||
const actual = JSON.stringify(JSON.parse(jsonResult).items);
|
||||
const items: CipherExport[] = [];
|
||||
ciphers.forEach((c: CipherView | Cipher) => {
|
||||
const item = new CipherExport();
|
||||
item.build(c);
|
||||
items.push(item);
|
||||
});
|
||||
const actual = JSON.stringify(JSON.parse(jsonResult).items);
|
||||
const items: CipherExport[] = [];
|
||||
ciphers.forEach((c: CipherView | Cipher) => {
|
||||
const item = new CipherExport();
|
||||
item.build(c);
|
||||
items.push(item);
|
||||
});
|
||||
|
||||
expect(actual).toEqual(JSON.stringify(items));
|
||||
expect(actual).toEqual(JSON.stringify(items));
|
||||
}
|
||||
|
||||
describe('ExportService', () => {
|
||||
let exportService: ExportService;
|
||||
let apiService: SubstituteOf<ApiService>;
|
||||
let cipherService: SubstituteOf<CipherService>;
|
||||
let folderService: SubstituteOf<FolderService>;
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
describe("ExportService", () => {
|
||||
let exportService: ExportService;
|
||||
let apiService: SubstituteOf<ApiService>;
|
||||
let cipherService: SubstituteOf<CipherService>;
|
||||
let folderService: SubstituteOf<FolderService>;
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
|
||||
beforeEach(() => {
|
||||
apiService = Substitute.for<ApiService>();
|
||||
cipherService = Substitute.for<CipherService>();
|
||||
folderService = Substitute.for<FolderService>();
|
||||
cryptoService = Substitute.for<CryptoService>();
|
||||
beforeEach(() => {
|
||||
apiService = Substitute.for<ApiService>();
|
||||
cipherService = Substitute.for<CipherService>();
|
||||
folderService = Substitute.for<FolderService>();
|
||||
cryptoService = Substitute.for<CryptoService>();
|
||||
|
||||
folderService.getAllDecrypted().resolves([]);
|
||||
folderService.getAll().resolves([]);
|
||||
folderService.getAllDecrypted().resolves([]);
|
||||
folderService.getAll().resolves([]);
|
||||
|
||||
exportService = new ExportService(folderService, cipherService, apiService, cryptoService);
|
||||
});
|
||||
exportService = new ExportService(folderService, cipherService, apiService, cryptoService);
|
||||
});
|
||||
|
||||
it('exports unecrypted user ciphers', async () => {
|
||||
cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1));
|
||||
it("exports unecrypted user ciphers", async () => {
|
||||
cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1));
|
||||
|
||||
const actual = await exportService.getExport('json');
|
||||
const actual = await exportService.getExport("json");
|
||||
|
||||
expectEqualCiphers(UserCipherViews.slice(0, 1), actual);
|
||||
});
|
||||
expectEqualCiphers(UserCipherViews.slice(0, 1), actual);
|
||||
});
|
||||
|
||||
it('exports encrypted json user ciphers', async () => {
|
||||
cipherService.getAll().resolves(UserCipherDomains.slice(0, 1));
|
||||
it("exports encrypted json user ciphers", async () => {
|
||||
cipherService.getAll().resolves(UserCipherDomains.slice(0, 1));
|
||||
|
||||
const actual = await exportService.getExport('encrypted_json');
|
||||
const actual = await exportService.getExport("encrypted_json");
|
||||
|
||||
expectEqualCiphers(UserCipherDomains.slice(0, 1), actual);
|
||||
});
|
||||
expectEqualCiphers(UserCipherDomains.slice(0, 1), actual);
|
||||
});
|
||||
|
||||
it('does not unecrypted export trashed user items', async () => {
|
||||
cipherService.getAllDecrypted().resolves(UserCipherViews);
|
||||
it("does not unecrypted export trashed user items", async () => {
|
||||
cipherService.getAllDecrypted().resolves(UserCipherViews);
|
||||
|
||||
const actual = await exportService.getExport('json');
|
||||
const actual = await exportService.getExport("json");
|
||||
|
||||
expectEqualCiphers(UserCipherViews.slice(0, 2), actual);
|
||||
});
|
||||
expectEqualCiphers(UserCipherViews.slice(0, 2), actual);
|
||||
});
|
||||
|
||||
it('does not encrypted export trashed user items', async () => {
|
||||
cipherService.getAll().resolves(UserCipherDomains);
|
||||
it("does not encrypted export trashed user items", async () => {
|
||||
cipherService.getAll().resolves(UserCipherDomains);
|
||||
|
||||
const actual = await exportService.getExport('encrypted_json');
|
||||
const actual = await exportService.getExport("encrypted_json");
|
||||
|
||||
expectEqualCiphers(UserCipherDomains.slice(0, 2), actual);
|
||||
});
|
||||
expectEqualCiphers(UserCipherDomains.slice(0, 2), actual);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user