UNPKG

aladinnetwork-blockstack

Version:

The Aladin Javascript library for authentication, identity, and storage.

407 lines (356 loc) 18.2 kB
import test from 'tape-promise/tape' import FetchMock from 'fetch-mock' import { validateProofs, containsValidProofStatement, containsValidAddressProofStatement } from '../../../src' import { profileServices } from '../../../src/profiles/services' import { sampleProfiles, sampleProofs, sampleVerifications, sampleAddressBasedVerifications } from './sampleData' function mockRequests() { const naval = sampleVerifications.naval const larry = sampleVerifications.larry FetchMock.get(naval.facebook.url, naval.facebook.body) FetchMock.get(`${naval.github.url}/raw`, naval.github.body) FetchMock.get(naval.twitter.url, naval.twitter.body) FetchMock.get(larry.facebook.url, larry.facebook.body) } function testProofs(profile, username, totalProofs) { test(`Profiles ${username}`, (t) => { // FetchMock.get('https://www.facebook.com/larry.salibra/posts/10100341028448093', 'hi') mockRequests() return validateProofs(profile, undefined, username).then((proofs) => { t.ok(proofs, 'Proofs must have been created') t.equal(proofs instanceof Array, true, 'Proofs should be an Array') t.equal(proofs.length, totalProofs, `Should have a proof for each of the ${totalProofs} claimed accounts`) t.equal(proofs.filter(x => x.valid).length, totalProofs, 'Should all be valid claims') FetchMock.restore() }) }) } function brokenProofs() { const naval = sampleVerifications.naval // adding a 'b' to the url, so they don't overlap with other mocked fetches. const navalAccounts = [{ '@type': 'Account', service: 'facebook', identifier: 'navalr', proofType: 'http', proofUrl: 'https://facebook.com/navalr/posts/10152190734077261b' }, { '@type': 'Account', service: 'twitter', identifier: 'naval', proofType: 'http', proofUrl: 'https://twitter.com/naval/status/486609266212499456b' }, { '@type': 'Account', service: 'github', identifier: 'navalr', proofType: 'http', proofUrl: 'https://gist.github.com/navalr/f31a74054f859ec0ac6ab' }] test('brokenProofs', (t) => { FetchMock.get(`${naval.facebook.url}b`, naval.facebook.body) FetchMock.get(`${naval.github.url}b/raw`, naval.github.body) FetchMock.get(`${naval.twitter.url}b`, { body: '', status: 400 }) t.plan(2) validateProofs({ account: navalAccounts }, undefined, 'naval.id') .then((proofs) => { t.equal(proofs.length, 3) t.equal(proofs.filter(x => x.valid).length, 2) FetchMock.restore() }) }) } export function runProofStatementUnitTests() { test('getProofStatement', (t) => { t.plan(6) const larry = sampleVerifications.larry const naval = sampleVerifications.naval const ken = sampleAddressBasedVerifications.ken const oscar = sampleAddressBasedVerifications.oscar t.equal(profileServices.facebook.getProofStatement(larry.facebook.body), 'Verifying that "larry.id" is my Aladin ID.', 'Should extract proof statement from Facebook page meta tags') t.equal(profileServices.twitter.getProofStatement(naval.twitter.body), 'Verifying myself: My Bitcoin username is +naval. https://t.co/DdpZv8tMAH #bitcoin', 'Should extract proof statement from Twitter page meta tags') t.equal(profileServices.twitter.getProofStatement(ken.twitter.body), 'Verifying my Aladin ID is secured with the address 1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', 'Should extract address-based proof statement from Twitter page meta tags') t.equal(profileServices.instagram.getProofStatement(ken.instagram.body), 'Verifying my Aladin ID is secured with the address 1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', 'Should extract address-based proof statement from Instagram meta tags') t.equal(profileServices.hackerNews.getProofStatement(ken.hackerNews.body), 'Verifying my Aladin ID is secured with the address 1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', 'Should extract address-based proof statement from Hacker News profile') t.equal(profileServices.linkedIn.getProofStatement(oscar.linkedIn.body), 'Oscar Lafarga on LinkedIn: "Verifying my Aladin ID is secured with the address 1JbfoCkyyg2yn98jZ9A2HzGPzhHoc34WB7 https://lnkd.in/gM-KvXa"', 'Should extract address-based proof statement from LinkedIn meta tags') }) } export function runOwnerAddressBasedProofsUnitTests() { test('containsValidAddressProofStatement', (t) => { t.plan(12) const larry = sampleAddressBasedVerifications.larry const ken = sampleAddressBasedVerifications.ken const oscar = sampleAddressBasedVerifications.oscar const facebookProofStatement = profileServices.facebook.getProofStatement(larry.facebook.body) const twitterProofStatement = profileServices.twitter.getProofStatement(ken.twitter.body) const githubProofStatement = profileServices.github.getProofStatement(ken.github.body) const instagramProofStatement = profileServices.instagram.getProofStatement(ken.instagram.body) const hackerNewsProofStatement = profileServices.hackerNews .getProofStatement(ken.hackerNews.body) const linkedInProofStatement = profileServices.linkedIn.getProofStatement(oscar.linkedIn.body) t.equals(containsValidAddressProofStatement(facebookProofStatement, '1EyuZ8qxdhHjcnTChwQLyQaN3cmdK55DkH'), true, 'Facebook post meta tags should contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(facebookProofStatement, 'differentBitcoinAddress'), false, 'Facebook post meta tags should not contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(twitterProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5'), true, 'Twitter status meta tags should contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(twitterProofStatement, 'differentBitcoinAddress'), false, 'Twitter status meta tags should not contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(githubProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5'), true, 'Github gist body should contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(githubProofStatement, 'differentBitcoinAddress'), false, 'Github gist body should not contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(instagramProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5'), true, 'Instagram body should contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(instagramProofStatement, 'differentBitcoinAddress'), false, 'Instagram body should not contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(hackerNewsProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5'), true, 'Hacker News body should contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(hackerNewsProofStatement, 'differentBitcoinAddress'), false, 'Hacker News body should not contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(linkedInProofStatement, '1JbfoCkyyg2yn98jZ9A2HzGPzhHoc34WB7'), true, 'LinkedIn body should contain valid bitcoin address proof statement') t.equals(containsValidAddressProofStatement(linkedInProofStatement, 'differentBitcoinAddress'), false, 'LinkedIn body should not contain valid bitcoin address proof statement') }) } export function runInBodyIdentityVerificationTests() { test('getProofIdentity', (t) => { t.plan(3) const ken = sampleAddressBasedVerifications.ken const oscar = sampleAddressBasedVerifications.oscar t.equal(profileServices.instagram.getProofIdentity(ken.instagram.body), 'blckstcktest', 'Should extract social proof identity from Instagram proof page body') t.equal(profileServices.instagram.getProofIdentity(ken.instagramRegression.body), 'blckstcktest', 'Should extract social proof identity from Instagram proof page body') t.equal(profileServices.linkedIn.getProofIdentity(oscar.linkedIn.body), 'oscarlafarga', 'Should extract social proof identity from LinkedIn proof page body') }) } export function runProofUtilsUnitTests() { test('containsValidProofStatement', (t) => { t.plan(9) const naval = sampleVerifications.naval t.equal(containsValidProofStatement(naval.facebook.body, 'naval.id'), true, 'Facebook post body should contain valid proof statement for naval.id') t.equal(containsValidProofStatement(naval.github.body, 'naval.id'), true, 'Github gist post body should contain valid proof statement for naval.id') t.equal(containsValidProofStatement(naval.twitter.body, 'naval.id'), true, 'Twitter post body should contain valid proof statement for naval.id') const larry = sampleVerifications.larry t.equal(containsValidProofStatement(naval.facebook.body, 'larry.id'), false, 'Github gist post body should not contain valid proof statement for larry.id') t.equal(containsValidProofStatement(naval.github.body, 'larry.id'), false, 'Github gist post body should not contain valid proof statement for larry.id') t.equal(containsValidProofStatement(naval.twitter.body, 'larry.id'), false, 'Github gist post body should not contain valid proof statement for larry.id') t.equal(containsValidProofStatement(larry.facebook.body, 'larry.id'), true, 'Facebook post body should contain valid proof statement for larry.id') const subdomainId = 'subdomainiac.id.aladin' t.equal(containsValidProofStatement( `verifying that ${subdomainId} is my aladin id`, subdomainId ), true, 'Subdomain IDs work as proofs') t.throws(() => { containsValidProofStatement(larry.facebook.body, 'larry') }, /Error/, 'Using non-fully qualified aladin name should throw exception') }) } export function runProofServicesUnitTests() { test('normalize Facebook URLs', (t) => { t.plan(6) t.equal(profileServices.facebook.normalizeUrl( { service: 'facebook', proof_url: 'https://www.facebook.com/navalr/posts/10152190734077261', identifier: 'navalr' } ), 'https://www.facebook.com/navalr/posts/10152190734077261', 'Facebook URL should be normalized') t.equal(profileServices.facebook.normalizeUrl( { service: 'facebook', proof_url: 'https://facebook.com/navalr/posts/10152190734077261', identifier: 'navalr' } ), 'https://www.facebook.com/navalr/posts/10152190734077261', 'Facebook URL should be normalized') t.equal(profileServices.facebook.normalizeUrl( { service: 'facebook', proof_url: 'https://www.facebook.com/larrysalibra/posts/10100341028448093', identifier: 'larrysalibra' } ), 'https://www.facebook.com/larrysalibra/posts/10100341028448093', 'Facebook URL should be normalized') t.notEqual(profileServices.facebook.normalizeUrl( { service: 'facebook', proof_url: 'https://www.facebook.com/larry.salibra/posts/10100341028448093', identifier: 'larry.salibra' } ), 'https://www.facebook.com/larrysalibra/posts/10100341028448093', 'Facebook URL should be normalized') t.notEqual(profileServices.facebook.normalizeUrl( { service: 'facebook', proof_url: 'https://facebook.com/larry.salibra/posts/10100341028448093', identifier: 'larry.salibra' } ), 'https://www.facebook.com/larrysalibra/posts/10100341028448093', 'Facebook URL should be normalized') t.equal(profileServices.facebook.normalizeUrl( { service: 'facebook', proof_url: 'https://facebook.com/larrysalibra/posts/10100341028448093', identifier: 'larrysalibra' } ), 'https://www.facebook.com/larrysalibra/posts/10100341028448093', 'Facebook URL should be normalized') }) test('normalize Instagarm URLs', (t) => { t.plan(4) t.equal(profileServices.instagram.normalizeUrl( { service: 'instagram', proof_url: 'https://www.instagram.com/p/BZ7KMM0A-Qc/', identifier: 'blckstcktest' } ), 'https://www.instagram.com/p/BZ7KMM0A-Qc/', 'Instagram URL should be normalized') t.equal(profileServices.instagram.normalizeUrl( { service: 'instagram', proof_url: 'https://instagram.com/p/BZ7KMM0A-Qc/', identifier: 'blckstcktest' } ), 'https://www.instagram.com/p/BZ7KMM0A-Qc/', 'Instagram URL should be normalized') t.equal(profileServices.instagram.normalizeUrl( { service: 'instagram', proof_url: 'http://www.instagram.com/p/BZ7KMM0A-Qc/', identifier: 'blckstcktest' } ), 'https://www.instagram.com/p/BZ7KMM0A-Qc/', 'Instagram URL should be normalized') t.equal(profileServices.instagram.normalizeUrl( { service: 'instagram', proof_url: 'http://instagram.com/p/BZ7KMM0A-Qc/', identifier: 'blckstcktest' } ), 'https://www.instagram.com/p/BZ7KMM0A-Qc/', 'Instagram URL should be normalized') }) test('get proof url', (t) => { t.plan(11) t.equal(profileServices.facebook.getProofUrl(sampleProofs.naval[1]), 'https://www.facebook.com/navalr/posts/10152190734077261', 'Facebook proof URL should match reference') t.equal(profileServices.github.getProofUrl(sampleProofs.naval[2]), 'https://gist.github.com/navalr/f31a74054f859ec0ac6a/raw', 'Github proof URL should match reference') t.equal(profileServices.twitter.getProofUrl(sampleProofs.naval[0]), 'https://twitter.com/naval/status/486609266212499456', 'Twitter proof URL should match reference') t.equal(profileServices.facebook.getProofUrl(sampleProofs.larry[0]), 'https://www.facebook.com/larry.salibra/posts/10100341028448093', 'Facebook proof URL should match reference') t.equal(profileServices.instagram.getProofUrl(sampleProofs.ken[0]), 'https://www.instagram.com/p/BYj6UDwgaX7/', 'Instagram proof URL should match reference') t.equal(profileServices.hackerNews.getProofUrl(sampleProofs.ken[1]), 'https://news.ycombinator.com/user?id=yukanl', 'Hacker News proof URL should match reference') t.equal(profileServices.linkedIn.getProofUrl(sampleProofs.ken[2]), 'https://www.linkedin.com/feed/update/urn:li:activity:6311587377647222784/', 'LinkedIn proof URL should match reference') t.equal(profileServices.hackerNews.getProofUrl(sampleProofs.bruno[0]), 'https://news.ycombinator.com/user?id=BrunoBernardino', 'Hacker News proof URL should match reference') t.throws(() => { const notNavalTwitter = Object.assign({}, sampleProofs.naval[0], { proof_url: 'https://twitter.com/not_naval/status/486609266212499456' }) profileServices.twitter.getProofUrl(notNavalTwitter) }, /Error/, 'Not having claimed account identifier in Twitter proof URL should throw exception') t.throws(() => { const notNavalGithub = Object.assign({}, sampleProofs.naval[2], { proof_url: 'https://gist.github.com/not_naval/f31a74054f859ec0ac6a' }) profileServices.github.getProofUrl(notNavalGithub) }, /Error/, 'Not having claimed account identifier in Github proof URL should throw exception') t.throws(() => { const notKenHackerNews = Object.assign({}, sampleProofs.ken[0], { proof_url: 'https://news.ycombinator.com/user?id=notken' }) profileServices.github.getProofUrl(notKenHackerNews) }, /Error/, 'Not having claimed account identifier in Hacker News proof URL should throw exception') }) } export function runProofsUnitTests() { // Proof utils runProofUtilsUnitTests() // Proof statements runProofStatementUnitTests() // Proof address based runOwnerAddressBasedProofsUnitTests() // Proof identity extract from response body runInBodyIdentityVerificationTests() // Proof services runProofServicesUnitTests() // Proof HTML // testProofs(sampleProfiles.naval, 'naval.id', 3) testProofs(sampleProfiles.larry, 'larry.id', 1) // Broken proofs brokenProofs() }