diff --git a/test/identities/browser.spec.js b/test/identities/browser.spec.js
new file mode 100644
index 0000000..f347894
--- /dev/null
+++ b/test/identities/browser.spec.js
@@ -0,0 +1,28 @@
+// import path from 'path'
+// import isNode from 'is-node'
+
+// // This file will be picked up by webpack into the
+// // tests bundle and the code here gets run when imported
+// // into the browser tests index through browser/run.js
+// if (!isNode) {
+// const existingKey = (await import('./fixtures/keys/existing.json')).default
+// const testKey1 = (await import('./fixtures/keys/QmPhnEjVkYE1Ym7F5MkRUfkD6NtuSptE7ugu1Ggr149W2X.json')).default
+// const testKey2 = (await import('./fixtures/keys/0260baeaffa1de1e4135e5b395e0380563a622b9599d1b8e012a0f7603f516bdaa.json')).default
+
+// // If in browser, put the fixture keys in local storage
+// // so that Keystore can find them
+// const levelup = (await import('levelup')).default
+// const level = (await import('level-js')).default
+// const storagePath = path.resolve('./test/fixtures/savedKeys')
+// const signingStore = levelup(level(storagePath))
+
+// const copyFixtures = []
+// copyFixtures.push(signingStore)
+
+// /* global localStorage */
+// copyFixtures.push(localStorage.setItem('existing.json', JSON.stringify(existingKey)))
+// copyFixtures.push(signingStore.put('QmPhnEjVkYE1Ym7F5MkRUfkD6NtuSptE7ugu1Ggr149W2X', JSON.stringify(testKey1)))
+// copyFixtures.push(signingStore.put('0260baeaffa1de1e4135e5b395e0380563a622b9599d1b8e012a0f7603f516bdaa', JSON.stringify(testKey2)))
+
+// Promise.all(copyFixtures)
+// }
diff --git a/test/identities/browser/index.html b/test/identities/browser/index.html
new file mode 100644
index 0000000..bf1c0e0
--- /dev/null
+++ b/test/identities/browser/index.html
@@ -0,0 +1,21 @@
+
+
+
+ Mocha Tests
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/identities/did-identity-provider.spec.js b/test/identities/did-identity-provider.spec.js
new file mode 100644
index 0000000..a8f1859
--- /dev/null
+++ b/test/identities/did-identity-provider.spec.js
@@ -0,0 +1,138 @@
+import assert from 'assert'
+import path from 'path'
+import rmrf from 'rimraf'
+import { KeyStore, IdentityProvider } from '../../src/index.js'
+import { Identity } from '../../src/identities/index.js'
+import { Ed25519Provider } from 'key-did-provider-ed25519'
+import KeyDidResolver from 'key-did-resolver'
+import DIDIdentityProvider from '../../src/identities/providers/did.js'
+const keypath = path.resolve('./test/identies/fixtures/keys')
+let keystore
+
+const seed = new Uint8Array([157, 94, 116, 198, 19, 248, 93, 239, 173, 82, 245, 222, 199, 7, 183, 177, 123, 238, 83, 240, 143, 188, 87, 191, 33, 95, 58, 136, 46, 218, 219, 245])
+const didStr = 'did:key:z6MkpnTJwrrVuphNh1uKb5DB7eRxvqniVaSDUHU6jtGVmn3r'
+
+const type = DIDIdentityProvider.type
+describe('DID Identity Provider', function () {
+ before(async () => {
+ DIDIdentityProvider.setDIDResolver(KeyDidResolver.getResolver())
+ IdentityProvider.addIdentityProvider(DIDIdentityProvider)
+ keystore = new KeyStore(keypath)
+ await keystore.open()
+ })
+
+ after(async () => {
+ await keystore.close()
+ })
+
+ describe('create an DID identity', () => {
+ let identity
+
+ before(async () => {
+ const didProvider = new Ed25519Provider(seed)
+ identity = await IdentityProvider.createIdentity({ type, keystore, didProvider })
+ })
+
+ it('has the correct id', async () => {
+ assert.strictEqual(identity.id, didStr)
+ })
+
+ it('created a key for id in keystore', async () => {
+ const key = await keystore.getKey(didStr)
+ assert.notStrictEqual(key, undefined)
+ })
+
+ it('has the correct public key', async () => {
+ const signingKey = await keystore.getKey(didStr)
+ assert.notStrictEqual(signingKey, undefined)
+ assert.strictEqual(identity.publicKey, keystore.getPublic(signingKey))
+ })
+
+ it('has a signature for the id', async () => {
+ const signingKey = await keystore.getKey(didStr)
+ const idSignature = await keystore.sign(signingKey, didStr)
+ const verifies = await KeyStore.verify(idSignature, identity.publicKey, didStr)
+ assert.strictEqual(verifies, true)
+ assert.strictEqual(identity.signatures.id, idSignature)
+ })
+
+ it('has a signature for the publicKey', async () => {
+ const signingKey = await keystore.getKey(didStr)
+ const idSignature = await keystore.sign(signingKey, didStr)
+ assert.notStrictEqual(idSignature, undefined)
+ })
+ })
+
+ describe('verify identity', () => {
+ let identity
+
+ before(async () => {
+ const didProvider = new Ed25519Provider(seed)
+ identity = await IdentityProvider.createIdentity({ type, keystore, didProvider })
+ })
+
+ it('DID identity verifies', async () => {
+ const verified = await IdentityProvider.verifyIdentity(identity)
+ assert.strictEqual(verified, true)
+ })
+
+ it('DID identity with incorrect id does not verify', async () => {
+ const identity2 = new Identity('NotAnId', identity.publicKey, identity.signatures.id, identity.signatures.publicKey, identity.type, identity.provider)
+ const verified = await IdentityProvider.verifyIdentity(identity2)
+ assert.strictEqual(verified, false)
+ })
+ })
+
+ describe('sign data with an identity', () => {
+ let identity
+ const data = 'hello friend'
+
+ before(async () => {
+ const didProvider = new Ed25519Provider(seed)
+ identity = await IdentityProvider.createIdentity({ type, keystore, didProvider })
+ })
+
+ it('sign data', async () => {
+ const signingKey = await keystore.getKey(identity.id)
+ const expectedSignature = await keystore.sign(signingKey, data)
+ const signature = await identity.provider.sign(identity, data, keystore)
+ assert.strictEqual(signature, expectedSignature)
+ })
+
+ it('throws an error if private key is not found from keystore', async () => {
+ // Remove the key from the keystore (we're using a mock storage in these tests)
+ const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type, identity.provider)
+ let signature
+ let err
+ try {
+ signature = await identity.provider.sign(modifiedIdentity, data, keystore)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(signature, undefined)
+ assert.strictEqual(err, 'Error: Private signing key not found from KeyStore')
+ })
+
+ describe('verify data signed by an identity', () => {
+ const data = 'hello friend'
+ let identity
+ let signature
+
+ before(async () => {
+ const didProvider = new Ed25519Provider(seed)
+ identity = await IdentityProvider.createIdentity({ type, keystore, didProvider })
+ signature = await identity.provider.sign(identity, data, keystore)
+ })
+
+ it('verifies that the signature is valid', async () => {
+ const verified = await identity.provider.verify(signature, identity.publicKey, data)
+ assert.strictEqual(verified, true)
+ })
+
+ it('doesn\'t verify invalid signature', async () => {
+ const verified = await identity.provider.verify('invalid', identity.publicKey, data)
+ assert.strictEqual(verified, false)
+ })
+ })
+ })
+})
diff --git a/test/identities/ethereum-identity-provider.spec.js b/test/identities/ethereum-identity-provider.spec.js
new file mode 100644
index 0000000..1223642
--- /dev/null
+++ b/test/identities/ethereum-identity-provider.spec.js
@@ -0,0 +1,133 @@
+import assert from 'assert'
+import path from 'path'
+import rmrf from 'rimraf'
+import { KeyStore, IdentityProvider } from '../../src/index.js'
+import { Identity } from '../../src/identities/index.js'
+import EthIdentityProvider from '../../src/identities/providers/ethereum.js'
+
+const keypath = path.resolve('./test/identities/fixtures/keys')
+let keystore
+
+const type = EthIdentityProvider.type
+describe('Ethereum Identity Provider', function () {
+ before(async () => {
+ IdentityProvider.addIdentityProvider(EthIdentityProvider)
+ keystore = new KeyStore(keypath)
+ await keystore.open()
+ })
+
+ after(async () => {
+ await keystore.close()
+ })
+
+ describe('create an ethereum identity', () => {
+ let identity
+ let wallet
+
+ before(async () => {
+ const ethIdentityProvider = new EthIdentityProvider()
+ wallet = await ethIdentityProvider._createWallet()
+ identity = await IdentityProvider.createIdentity({ type, keystore, wallet })
+ })
+
+ it('has the correct id', async () => {
+ assert.strictEqual(identity.id, wallet.address)
+ })
+
+ it('created a key for id in keystore', async () => {
+ const key = await keystore.getKey(wallet.address)
+ assert.notStrictEqual(key, undefined)
+ })
+
+ it('has the correct public key', async () => {
+ const signingKey = await keystore.getKey(wallet.address)
+ assert.notStrictEqual(signingKey, undefined)
+ assert.strictEqual(identity.publicKey, keystore.getPublic(signingKey))
+ })
+
+ it('has a signature for the id', async () => {
+ const signingKey = await keystore.getKey(wallet.address)
+ const idSignature = await keystore.sign(signingKey, wallet.address)
+ const verifies = await KeyStore.verify(idSignature, Buffer.from(signingKey.public.marshal()).toString('hex'), wallet.address)
+ assert.strictEqual(verifies, true)
+ assert.strictEqual(identity.signatures.id, idSignature)
+ })
+
+ it('has a signature for the publicKey', async () => {
+ const signingKey = await keystore.getKey(wallet.address)
+ const idSignature = await keystore.sign(signingKey, wallet.address)
+ const publicKeyAndIdSignature = await wallet.signMessage(identity.publicKey + idSignature)
+ assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature)
+ })
+ })
+
+ describe('verify identity', () => {
+ let identity
+
+ before(async () => {
+ identity = await IdentityProvider.createIdentity({ keystore, type })
+ })
+
+ it('ethereum identity verifies', async () => {
+ const verified = await IdentityProvider.verifyIdentity(identity)
+ assert.strictEqual(verified, true)
+ })
+
+ it('ethereum identity with incorrect id does not verify', async () => {
+ const identity2 = new Identity('NotAnId', identity.publicKey, identity.signatures.id, identity.signatures.publicKey, identity.type, identity.provider)
+ const verified = await IdentityProvider.verifyIdentity(identity2)
+ assert.strictEqual(verified, false)
+ })
+ })
+
+ describe('sign data with an identity', () => {
+ let identity
+ const data = 'hello friend'
+
+ before(async () => {
+ identity = await IdentityProvider.createIdentity({ keystore, type })
+ })
+
+ it('sign data', async () => {
+ const signingKey = await keystore.getKey(identity.id)
+ const expectedSignature = await keystore.sign(signingKey, data)
+ const signature = await identity.provider.sign(identity, data, keystore)
+ assert.strictEqual(signature, expectedSignature)
+ })
+
+ it('throws an error if private key is not found from keystore', async () => {
+ // Remove the key from the keystore (we're using a mock storage in these tests)
+ const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type, identity.provider)
+ let signature
+ let err
+ try {
+ signature = await identity.provider.sign(modifiedIdentity, data, keystore)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(signature, undefined)
+ assert.strictEqual(err, 'Error: Private signing key not found from KeyStore')
+ })
+
+ describe('verify data signed by an identity', () => {
+ const data = 'hello friend'
+ let identity
+ let signature
+
+ before(async () => {
+ identity = await IdentityProvider.createIdentity({ type, keystore })
+ signature = await identity.provider.sign(identity, data, keystore)
+ })
+
+ it('verifies that the signature is valid', async () => {
+ const verified = await identity.provider.verify(signature, identity.publicKey, data)
+ assert.strictEqual(verified, true)
+ })
+
+ it('doesn\'t verify invalid signature', async () => {
+ const verified = await identity.provider.verify('invalid', identity.publicKey, data)
+ assert.strictEqual(verified, false)
+ })
+ })
+ })
+})
diff --git a/test/identities/identity-provider.spec.js b/test/identities/identity-provider.spec.js
new file mode 100644
index 0000000..f22f45c
--- /dev/null
+++ b/test/identities/identity-provider.spec.js
@@ -0,0 +1,311 @@
+import assert from 'assert'
+import path from 'path'
+import rmrf from 'rimraf'
+import { KeyStore, IdentityProvider } from '../../src/index.js'
+import { Identity } from '../../src/identities/index.js'
+import fs from 'fs-extra'
+const fixturesPath = path.resolve('./test/identities/fixtures/keys')
+const savedKeysPath = path.resolve('./test/identities/fixtures/savedKeys')
+const signingKeysPath = path.resolve('./test/identities/signingKeys')
+const identityKeysPath = path.resolve('./test/identities/identityKeys')
+const type = 'orbitdb'
+
+describe('Identity Provider', function () {
+ before(async () => {
+ rmrf.sync(signingKeysPath)
+ rmrf.sync(identityKeysPath)
+ })
+
+ after(async () => {
+ rmrf.sync(signingKeysPath)
+ rmrf.sync(identityKeysPath)
+ })
+
+ describe('Creating IdentityProvider', () => {
+ const id = 'A'
+ let identity
+
+ it('identityKeysPath only - has the correct id', async () => {
+ identity = await IdentityProvider.createIdentity({ id, identityKeysPath })
+ const key = await identity.provider.keystore.getKey(id)
+ const externalId = Buffer.from(key.public.marshal()).toString('hex')
+ assert.strictEqual(identity.id, externalId)
+ })
+
+ it('identityKeysPath and signingKeysPath - has a different id', async () => {
+ identity = await IdentityProvider.createIdentity({ id, identityKeysPath, signingKeysPath })
+ const key = await identity.provider.keystore.getKey(id)
+ const externalId = Buffer.from(key.public.marshal()).toString('hex')
+ assert.notStrictEqual(identity.id, externalId)
+ })
+
+ afterEach(async () => {
+ await identity.provider.keystore.close()
+ await identity.provider.signingKeyStore.close()
+ })
+ })
+
+ describe('Passing in custom keystore', async () => {
+ const id = 'B'; let identity; let keystore; let signingKeyStore
+
+ before(async () => {
+ keystore = new KeyStore(identityKeysPath)
+ await keystore.open()
+ signingKeyStore = new KeyStore(signingKeysPath)
+ await signingKeyStore.open()
+ })
+
+ it('has the correct id', async () => {
+ identity = await IdentityProvider.createIdentity({ id, keystore })
+ keystore = identity.provider._keystore
+ const key = await keystore.getKey(id)
+ const externalId = Buffer.from(key.public.marshal()).toString('hex')
+ assert.strictEqual(identity.id, externalId)
+ })
+
+
+ it('created a key for id in identity-keystore', async () => {
+ const key = await keystore.getKey(id)
+ assert.notStrictEqual(key, undefined)
+ })
+
+ it('has the correct public key', async () => {
+ const key = await keystore.getKey(id)
+ const externalId = Buffer.from(key.public.marshal()).toString('hex')
+ const signingKey = await keystore.getKey(externalId)
+ assert.notStrictEqual(signingKey, undefined)
+ assert.strictEqual(identity.publicKey, keystore.getPublic(signingKey))
+ })
+
+ it('has a signature for the id', async () => {
+ const key = await keystore.getKey(id)
+ const externalId = Buffer.from(key.public.marshal()).toString('hex')
+ const signingKey = await keystore.getKey(externalId)
+ const idSignature = await keystore.sign(signingKey, externalId)
+ const publicKey = Buffer.from(signingKey.public.marshal()).toString('hex')
+ const verifies = await KeyStore.verify(idSignature, publicKey, externalId)
+ assert.strictEqual(verifies, true)
+ assert.strictEqual(identity.signatures.id, idSignature)
+ })
+
+ it('has a signature for the publicKey', async () => {
+ const key = await keystore.getKey(id)
+ const externalId = Buffer.from(key.public.marshal()).toString('hex')
+ const signingKey = await keystore.getKey(externalId)
+ const idSignature = await keystore.sign(signingKey, externalId)
+ const externalKey = await keystore.getKey(id)
+ const publicKeyAndIdSignature = await keystore.sign(externalKey, identity.publicKey + idSignature)
+ assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature)
+ })
+
+ after(async () => {
+ await keystore.close()
+ await signingKeyStore.close()
+ })
+ })
+
+ describe('create an identity with saved keys', () => {
+ let keystore, signingKeyStore
+
+ let savedKeysKeyStore, identity
+ const id = 'QmPhnEjVkYE1Ym7F5MkRUfkD6NtuSptE7ugu1Ggr149W2X'
+
+ const expectedPublicKey = '040d78ff62afb656ac62db1aae3b1536a614991e28bb4d721498898b7d4194339640cd18c37b259e2c77738de0d6f9a5d52e0b936611de6b6ba78891a8b2a38317'
+ const expectedIdSignature = '30450221009de7b91952d73f577e85962aa6301350865212e3956862f80f4ebb626ffc126b022027d57415fb145b7e06cf06320fbfa63ea98a958b065726fe86eaab809a6bf607'
+ const expectedPkIdSignature = '304402202806e7c2406ca1f35961d38adc3997c179e142d54e1ca838ace373fae27124fd02200d6ca3aea6e1341bf5e4e0b84b559bbeefecfade34115de266a69d04d924905e'
+
+ before(async () => {
+ keystore = new KeyStore(identityKeysPath)
+ await keystore.open()
+ signingKeyStore = new KeyStore(signingKeysPath)
+ await signingKeyStore.open()
+
+ await fs.copy(fixturesPath, savedKeysPath)
+ savedKeysKeyStore = new KeyStore(savedKeysPath)
+ await savedKeysKeyStore.open()
+ identity = await IdentityProvider.createIdentity({ id, keystore: savedKeysKeyStore })
+ })
+
+ after(async () => {
+ rmrf.sync(savedKeysPath)
+ })
+
+ it('has the correct id', async () => {
+ const key = await savedKeysKeyStore.getKey(id)
+ assert.strictEqual(identity.id, Buffer.from(key.public.marshal()).toString('hex'))
+ })
+
+ it('has the correct public key', async () => {
+ assert.strictEqual(identity.publicKey, expectedPublicKey)
+ })
+
+ it('has the correct identity type', async () => {
+ assert.strictEqual(identity.type, type)
+ })
+
+ it('has the correct idSignature', async () => {
+ assert.strictEqual(identity.signatures.id, expectedIdSignature)
+ })
+
+ it('has a pubKeyIdSignature for the publicKey', async () => {
+ assert.strictEqual(identity.signatures.publicKey, expectedPkIdSignature)
+ })
+
+ it('has the correct signatures', async () => {
+ const internalSigningKey = await savedKeysKeyStore.getKey(identity.id)
+ const externalSigningKey = await savedKeysKeyStore.getKey(id)
+ const idSignature = await savedKeysKeyStore.sign(internalSigningKey, identity.id)
+ const pubKeyIdSignature = await savedKeysKeyStore.sign(externalSigningKey, identity.publicKey + idSignature)
+ const expectedSignature = { id: idSignature, publicKey: pubKeyIdSignature }
+ assert.deepStrictEqual(identity.signatures, expectedSignature)
+ })
+
+ after(async () => {
+ await keystore.close()
+ await signingKeyStore.close()
+ })
+ })
+
+ describe('verify identity\'s signature', () => {
+ const id = 'QmFoo'
+ let identity, keystore, signingKeyStore
+
+ before(async () => {
+ keystore = new KeyStore(identityKeysPath)
+ await keystore.open()
+ signingKeyStore = new KeyStore(signingKeysPath)
+ await signingKeyStore.open()
+ })
+
+ it('identity pkSignature verifies', async () => {
+ identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore })
+ const verified = await KeyStore.verify(identity.signatures.id, identity.publicKey, identity.id)
+ assert.strictEqual(verified, true)
+ })
+
+ it('identity signature verifies', async () => {
+ identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore })
+ const verified = await KeyStore.verify(identity.signatures.publicKey, identity.id, identity.publicKey + identity.signatures.id)
+ assert.strictEqual(verified, true)
+ })
+
+ it('false signature doesn\'t verify', async () => {
+ class IP {
+ async getId () { return 'pubKey' }
+
+ async signIdentity (data) { return `false signature '${data}'` }
+
+ static async verifyIdentity (data) { return false }
+
+ static get type () { return 'fake' }
+ }
+
+ IdentityProvider.addIdentityProvider(IP)
+ identity = await IdentityProvider.createIdentity({ type: IP.type, keystore, signingKeyStore })
+ const verified = await IdentityProvider.verifyIdentity(identity)
+ assert.strictEqual(verified, false)
+ })
+
+ after(async () => {
+ await keystore.close()
+ await signingKeyStore.close()
+ })
+ })
+
+ describe('verify identity', () => {
+ const id = 'QmFoo'
+ let identity, keystore, signingKeyStore
+
+ before(async () => {
+ keystore = new KeyStore(identityKeysPath)
+ await keystore.open()
+ signingKeyStore = new KeyStore(signingKeysPath)
+ await signingKeyStore.open()
+ })
+
+ it('identity verifies', async () => {
+ identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore })
+ const verified = await identity.provider.verifyIdentity(identity)
+ assert.strictEqual(verified, true)
+ })
+
+ after(async () => {
+ await keystore.close()
+ await signingKeyStore.close()
+ })
+ })
+
+ describe('sign data with an identity', () => {
+ const id = '0x01234567890abcdefghijklmnopqrstuvwxyz'
+ const data = 'hello friend'
+ let identity, keystore, signingKeyStore
+
+ before(async () => {
+ keystore = new KeyStore(identityKeysPath)
+ await keystore.open()
+ signingKeyStore = new KeyStore(signingKeysPath)
+ await signingKeyStore.open()
+ identity = await IdentityProvider.createIdentity({ id, keystore, signingKeyStore })
+ })
+
+ it('sign data', async () => {
+ const signingKey = await keystore.getKey(identity.id)
+ const expectedSignature = await keystore.sign(signingKey, data)
+ const signature = await identity.provider.sign(identity, data, keystore)
+ assert.strictEqual(signature, expectedSignature)
+ })
+
+ it('throws an error if private key is not found from keystore', async () => {
+ // Remove the key from the keystore (we're using a mock storage in these tests)
+ const modifiedIdentity = new Identity('this id does not exist', identity.publicKey, '', identity.signatures, identity.type, identity.provider)
+ let signature
+ let err
+ try {
+ signature = await identity.provider.sign(modifiedIdentity, data, keystore)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(signature, undefined)
+ assert.strictEqual(err, 'Error: Private signing key not found from KeyStore')
+ })
+
+ after(async () => {
+ await keystore.close()
+ await signingKeyStore.close()
+ })
+ })
+
+ describe('verify data signed by an identity', () => {
+ const id = '03602a3da3eb35f1148e8028f141ec415ef7f6d4103443edbfec2a0711d716f53f'
+ const data = 'hello friend'
+ let identity, keystore, signingKeyStore
+ let signature
+
+ before(async () => {
+ keystore = new KeyStore(identityKeysPath)
+ await keystore.open()
+ signingKeyStore = new KeyStore(signingKeysPath)
+ await signingKeyStore.open()
+ })
+
+ beforeEach(async () => {
+ identity = await IdentityProvider.createIdentity({ id, type, keystore, signingKeyStore })
+ signature = await identity.provider.sign(identity, data, keystore)
+ })
+
+ it('verifies that the signature is valid', async () => {
+ const verified = await identity.provider.verify(signature, identity.publicKey, data)
+ assert.strictEqual(verified, true)
+ })
+
+ it('doesn\'t verify invalid signature', async () => {
+ const verified = await identity.provider.verify('invalid', identity.publicKey, data)
+ assert.strictEqual(verified, false)
+ })
+
+ after(async () => {
+ await keystore.close()
+ await signingKeyStore.close()
+ })
+ })
+})
diff --git a/test/identities/identity.spec.js b/test/identities/identity.spec.js
new file mode 100644
index 0000000..0d03e16
--- /dev/null
+++ b/test/identities/identity.spec.js
@@ -0,0 +1,109 @@
+import assert from 'assert'
+import { Identity } from '../../src/identities/index.js'
+
+describe('Identity', function () {
+ const id = '0x01234567890abcdefghijklmnopqrstuvwxyz'
+ const publicKey = ''
+ const idSignature = 'signature for '
+ const publicKeyAndIdSignature = 'signature for '
+ const type = 'orbitdb'
+ const provider = 'IdentityProviderInstance'
+
+ let identity
+
+ before(async () => {
+ identity = new Identity(id, publicKey, idSignature, publicKeyAndIdSignature, type, provider)
+ })
+
+ it('has the correct id', async () => {
+ assert.strictEqual(identity.id, id)
+ })
+
+ it('has the correct publicKey', async () => {
+ assert.strictEqual(identity.publicKey, publicKey)
+ })
+
+ it('has the correct idSignature', async () => {
+ assert.strictEqual(identity.signatures.id, idSignature)
+ })
+
+ it('has the correct publicKeyAndIdSignature', async () => {
+ assert.strictEqual(identity.signatures.publicKey, publicKeyAndIdSignature)
+ })
+
+ it('has the correct provider', async () => {
+ assert.deepStrictEqual(identity.provider, provider)
+ })
+
+ it('converts identity to a JSON object', async () => {
+ const expected = {
+ id,
+ publicKey,
+ signatures: { id: idSignature, publicKey: publicKeyAndIdSignature },
+ type
+ }
+ assert.deepStrictEqual(identity.toJSON(), expected)
+ })
+
+ describe('Constructor inputs', () => {
+ it('throws and error if id was not given in constructor', async () => {
+ let err
+ try {
+ identity = new Identity()
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(err, 'Error: Identity id is required')
+ })
+
+ it('throws and error if publicKey was not given in constructor', async () => {
+ let err
+ try {
+ identity = new Identity('abc')
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(err, 'Error: Invalid public key')
+ })
+
+ it('throws and error if identity signature was not given in constructor', async () => {
+ let err
+ try {
+ identity = new Identity('abc', publicKey)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(err, 'Error: Signature of the id (idSignature) is required')
+ })
+
+ it('throws and error if identity signature was not given in constructor', async () => {
+ let err
+ try {
+ identity = new Identity('abc', publicKey, idSignature)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(err, 'Error: Signature of (publicKey + idSignature) is required')
+ })
+
+ it('throws and error if identity provider was not given in constructor', async () => {
+ let err
+ try {
+ identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, type)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(err, 'Error: Identity provider is required')
+ })
+
+ it('throws and error if identity type was not given in constructor', async () => {
+ let err
+ try {
+ identity = new Identity('abc', publicKey, idSignature, publicKeyAndIdSignature, null, provider)
+ } catch (e) {
+ err = e.toString()
+ }
+ assert.strictEqual(err, 'Error: Identity type is required')
+ })
+ })
+})