blockstack
Version:
The Blockstack Javascript library for identity and authentication.
336 lines (286 loc) • 14.9 kB
JavaScript
import blueTest from 'blue-tape'
import test from 'tape'
import fs from 'fs'
import FetchMock from 'fetch-mock'
import {
validateProofs, containsValidProofStatement, containsValidAddressProofStatement, profileServices
} from '../../../lib'
import { sampleProfiles, sampleProofs, sampleVerifications, sampleAddressBasedVerifications } from './sampleData'
function mockRequests() {
const naval = sampleVerifications.naval
const larry = sampleVerifications.larry
const addressBasedLarry = sampleAddressBasedVerifications.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) {
mockRequests()
blueTest('Profiles', (t) => {
return validateProofs(profile, 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 3 claimed accounts")
FetchMock.restore()
})
})
}
export function runProofStatementUnitTests() {
test('getProofStatement', (t) => {
t.plan(7)
const larry = sampleVerifications.larry
const naval = sampleVerifications.naval
const ken = sampleAddressBasedVerifications.ken
t.equal(profileServices.facebook.getProofStatement(larry.facebook.body),
'Verifying that "larry.id" is my Blockstack 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 Blockstack 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 Blockstack 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 Blockstack ID is secured with the address 1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5',
'Should extract address-based proof statement from Hacker News profile')
t.equal(profileServices.linkedIn.getProofStatement(ken.linkedIn.body),
'Verifying my Blockstack ID is secured with the address 1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5',
'Should extract address-based proof statement from Hacker News profile')
t.equal(profileServices.linkedIn.getProofStatement(ken.linkedInBroken.body),
'',
'Should not crash on broken LinkedIn proof link')
})
}
export function runOwnerAddressBasedProofsUnitTests() {
test('containsValidAddressProofStatement', (t) => {
t.plan(12)
const larry = sampleAddressBasedVerifications.larry
const ken = sampleAddressBasedVerifications.ken
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(ken.linkedIn.body)
t.equals(containsValidAddressProofStatement(facebookProofStatement, '1EyuZ8qxdhHjcnTChwQLyQaN3cmdK55DkH', true),
true, "Facebook post meta tags should contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(facebookProofStatement, 'differentBitcoinAddress', true),
false, "Facebook post meta tags should not contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(twitterProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', true),
true, "Twitter status meta tags should contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(twitterProofStatement, 'differentBitcoinAddress', true),
false, "Twitter status meta tags should not contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(githubProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', true),
true, "Github gist body should contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(githubProofStatement, 'differentBitcoinAddress', true),
false, "Github gist body should not contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(instagramProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', true),
true, "Instagram body should contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(instagramProofStatement, 'differentBitcoinAddress', true),
false, "Instagram body should not contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(hackerNewsProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', true),
true, "Hacker News body should contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(hackerNewsProofStatement, 'differentBitcoinAddress', true),
false, "Hacker News body should not contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(linkedInProofStatement, '1AtFqXxcckuoEN4iMNNe7n83c5nugxpzb5', true),
true, "LinkedIn body should contain valid bitcoin address proof statement")
t.equals(containsValidAddressProofStatement(linkedInProofStatement, 'differentBitcoinAddress', true),
false, "LinkedIn body should not contain valid bitcoin address proof statement")
})
}
export function runInBodyIdentityVerificationTests() {
test('getProofIdentity', (t) => {
t.plan(2)
const ken = sampleAddressBasedVerifications.ken
t.equal(profileServices.instagram.getProofIdentity(ken.instagram.body),
'blckstcktest',
'Should extract social proof identity from Instagram proof page body')
t.equal(profileServices.linkedIn.getProofIdentity(ken.linkedIn.body),
'blck-stck',
'Should extract social proof identity from LinkedIn proof page body')
})
}
export function runProofUtilsUnitTests() {
test('containsValidProofStatement', (t) => {
t.plan(8)
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")
t.throws(() => {
containsValidProofStatement(larry.facebook.body, 'larry')
}, /Error/, "Using non-fully qualified blockstack name should throw exception")
})
}
export function runProofServicesUnitTests() {
test('normalize Facebook URLs', (t) => {
t.plan(6)
t.equal(profileServices.facebook.normalizeFacebookUrl(
{
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.normalizeFacebookUrl(
{
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.normalizeFacebookUrl(
{
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.normalizeFacebookUrl(
{
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.normalizeFacebookUrl(
{
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.normalizeFacebookUrl(
{
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.normalizeInstagramUrl(
{
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.normalizeInstagramUrl(
{
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.normalizeInstagramUrl(
{
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.normalizeInstagramUrl(
{
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(10)
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.throws(() => {
// const notLarry = Object.assign({},
// sampleProofs.larry[0], {
// proof_url: 'https://www.facebook.com/not.larry/posts/10100341028448093'
// })
// profileServices.facebook.getProofUrl(notLarry)
// }, /Error/, 'Not having claimed account identifier in Facebook proof URL should throw exception')
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)
}