@ssb-graphql/whakapapa
Version:
GraphQL types and resolvers for the ssb-whakapapa plugin
440 lines (374 loc) • 11.8 kB
JavaScript
const tape = require('tape')
const { isMsgId } = require('ssb-ref')
const { promisify: p } = require('util')
const { createWhakapapaTree } = require('ahau-fixtures')
const TestBot = require('./test-bot')
const { SaveWhakapapa, GetWhakapapa, SaveLink } = require('./lib/helpers')
tape('whakapapaView (saveWhakapapaView + whakakapaView)', async (t) => {
t.plan(11)
const { ssb, apollo } = await TestBot({ loadContext: true })
const { groupId } = await p(ssb.tribes.create)({})
const save = SaveWhakapapa(apollo, t)
const get = GetWhakapapa(apollo, t)
const createProfile = () => p(ssb.profile.person.group.create)({ authors: { add: [ssb.id] }, recps: [groupId] })
const TEST_PROFILE_ID = await createProfile()
const TEST_PROFILE_ID_2 = await createProfile()
const TEST_PROFILE_ID_3 = await createProfile()
const TEST_PROFILE_ID_4 = await createProfile()
const TEST_PROFILE_ID_5 = await createProfile()
await p(ssb.whakapapa.link.create)({ type: 'link/profile-profile/partner', parent: TEST_PROFILE_ID_3, child: TEST_PROFILE_ID_4 }, { recps: [ssb.id] })
await p(ssb.whakapapa.link.create)({ type: 'link/profile-profile/partner', parent: TEST_PROFILE_ID_3, child: TEST_PROFILE_ID_5 }, { recps: [ssb.id] })
// SAVE NEW WHAKAPAPA
const whakapapaId = await save({
name: 'Smith Family',
description: 'The whakapapa tree of the Smith Family',
focus: TEST_PROFILE_ID,
importantRelationships: { profileId: TEST_PROFILE_ID_3, important: [TEST_PROFILE_ID_4, TEST_PROFILE_ID_5] },
mode: 'ancestors',
permission: 'view',
recps: [ssb.id],
recordCount: 1,
authors: {
add: [ssb.id]
}
})
t.true(isMsgId(whakapapaId), 'saveWhakapapaView returns messageId')
// GET WHAKAPAPA BY ID
const whakapapa = await get(whakapapaId)
t.true(whakapapa.name === 'Smith Family', 'returns correct name')
t.true(whakapapa.focus === TEST_PROFILE_ID, 'returns correct focus')
t.true(whakapapa.permission === 'view', 'returns correct permission')
t.deepEqual(
whakapapa.importantRelationships,
[{
profileId: TEST_PROFILE_ID_3,
primary: { profileId: TEST_PROFILE_ID_4, relationshipType: 'partner' },
other: [{ profileId: TEST_PROFILE_ID_5, relationshipType: 'partner' }]
}],
'returns correct important relationships'
)
// UPDATE WHAKAPAPA
await save({
id: whakapapaId, // pass the ID to allow for update instead of create
focus: TEST_PROFILE_ID_2, // update the focus
permission: 'edit' // update permission to edt
// NOTE: this is an update so it doesnt need recps
}).catch(t.error)
// GET THE UPDATED WHAKAPAPA
const updatedWhakapapa = await get(whakapapaId)
t.true(updatedWhakapapa.focus === TEST_PROFILE_ID_2, 'returns updated focus')
t.true(updatedWhakapapa.permission === 'edit', 'returns updated permission')
ssb.close()
})
tape('whakapapaView.importantRelationships (saveWhakapapaView, whakapapaView)', async t => {
// ///
// This tests the behaviour of important relationships when links are tombstoned and the important relationship has no rules
// ///
t.plan(13)
const { ssb, apollo } = await TestBot({ loadContext: true })
const { groupId } = await p(ssb.tribes.create)({})
const saveWhakapapa = SaveWhakapapa(apollo, t)
const get = GetWhakapapa(apollo, t)
const saveLink = SaveLink(apollo, t)
// const getProfile = GetProfile(apollo, t)
const createProfile = () => p(ssb.profile.person.group.create)({ authors: { add: [ssb.id] }, recps: [groupId] })
const deleteProfile = (id) => p(ssb.profile.person.group.tombstone)(id, { date: new Date().toISOString().slice(0, 10) })
const createLink = (parent, child, relationshipType) => saveLink({
type: 'link/profile-profile/child',
parent,
child,
relationshipType,
recps: [ssb.id]
})
/*
Recreating this tree:
(grandad)
| \
(dad) (grandchild)
|
(grandchild)
*/
const grandad = await createProfile()
const dad = await createProfile()
const grandchild = await createProfile()
await createLink(grandad, dad, 'birth')
const linkId = await createLink(dad, grandchild, 'birth')
await createLink(grandad, grandchild, 'whangai') // this is the important relationship
const whakapapaId = await saveWhakapapa({
name: 'Smith Family',
description: 'The whakapapa tree of the Smith Family',
focus: grandad,
importantRelationships: { profileId: grandchild, important: [grandad, dad] },
mode: 'ancestors',
permission: 'edit',
recps: [ssb.id],
recordCount: 1,
authors: {
add: [ssb.id]
}
})
let whakapapa = await get(whakapapaId)
t.deepEqual(
whakapapa.importantRelationships,
[
{
profileId: grandchild,
primary: {
profileId: grandad,
relationshipType: 'whangai'
},
other: [
{
profileId: dad,
relationshipType: 'birth'
}
]
}
],
'returns correct important relationships'
)
// remove the link between dad and grandchild
await saveLink({
linkId,
tombstone: {
date: new Date().toISOString().slice(0, 10),
reason: 'user deleted link'
}
})
// the whakapapa important relationships must be updated to handle the removal
await saveWhakapapa({
id: whakapapaId,
importantRelationships: { profileId: grandchild, important: [grandad] }
})
whakapapa = await get(whakapapaId)
t.deepEqual(
whakapapa.importantRelationships,
[
{
profileId: grandchild,
primary: {
profileId: grandad,
relationshipType: 'whangai'
},
other: []
}
],
'returns correct important relationships after update'
)
// lets see what happens to important relationships when a profile is tombstoned
await deleteProfile(grandchild)
// wipe important relationship?
await saveWhakapapa({
id: whakapapaId,
importantRelationships: { profileId: grandchild, important: [] }
})
whakapapa = await get(whakapapaId)
t.deepEqual(
whakapapa.importantRelationships,
[],
'returns correct important relationships after person is removed'
)
ssb.close()
t.end()
})
tape('whakapapaView.importantRelationships (update)', async t => {
// ///
// This tests the behaviour of important relationships when are removed then readded
// ///
t.plan(14)
const { ssb, apollo } = await TestBot({ loadContext: true })
const { groupId } = await p(ssb.tribes.create)({})
const saveWhakapapa = SaveWhakapapa(apollo, t)
const get = GetWhakapapa(apollo, t)
const saveLink = SaveLink(apollo, t)
// const getProfile = GetProfile(apollo, t)
const createProfile = () => p(ssb.profile.person.group.create)({ authors: { add: [ssb.id] }, recps: [groupId] })
const createLink = (parent, child, relationshipType) => saveLink({
type: 'link/profile-profile/child',
parent,
child,
relationshipType,
recps: [ssb.id]
})
/*
Recreating this tree:
(grandad)
| \
(dad) (grandchild)
|
(grandchild)
*/
const grandad = await createProfile()
const dad = await createProfile()
const grandchild = await createProfile()
await createLink(grandad, dad, 'birth')
const linkId = await createLink(dad, grandchild, 'birth')
await createLink(grandad, grandchild, 'whangai') // this is the important relationship
const whakapapaId = await saveWhakapapa({
name: 'Smith Family',
description: 'The whakapapa tree of the Smith Family',
focus: grandad,
importantRelationships: { profileId: grandchild, important: [grandad, dad] },
mode: 'ancestors',
permission: 'view',
recps: [ssb.id],
recordCount: 1,
authors: {
add: [ssb.id]
}
})
let whakapapa = await get(whakapapaId)
t.deepEqual(
whakapapa.importantRelationships,
[
{
profileId: grandchild,
primary: {
profileId: grandad,
relationshipType: 'whangai'
},
other: [
{
profileId: dad,
relationshipType: 'birth'
}
]
}
],
'returns correct important relationships'
)
// remove the link between dad and grandchild
await saveLink({
linkId,
tombstone: {
date: new Date().toISOString().slice(0, 10),
reason: 'user deleted link'
}
})
// the whakapapa important relationships must be updated to handle the removal
await saveWhakapapa({
id: whakapapaId,
importantRelationships: { profileId: grandchild, important: [grandad] }
})
whakapapa = await get(whakapapaId)
t.deepEqual(
whakapapa.importantRelationships,
[
{
profileId: grandchild,
primary: {
profileId: grandad,
relationshipType: 'whangai'
},
other: []
}
],
'returns correct important relationships after update'
)
// what happens when the important relationship is readded
await createLink(dad, grandchild, 'birth')
await saveWhakapapa({
id: whakapapaId,
importantRelationships: { profileId: grandchild, important: [dad, grandad] }
})
whakapapa = await get(whakapapaId)
t.deepEqual(
whakapapa.importantRelationships,
[
{
profileId: grandchild,
primary: {
profileId: dad,
relationshipType: 'birth'
},
other: [
{
profileId: grandad,
relationshipType: 'whangai'
}
]
}
],
'returns correct important relationships after its readded back in'
)
ssb.close()
t.end()
})
tape('whakapapaView { links }', async (t) => {
const { ssb, apollo } = await TestBot({ loadContext: true })
const { groupId } = await p(ssb.tribes.create)({})
const recps = [groupId]
// random whakapapa
await createWhakapapaTree(ssb, groupId, 10)
const createProfile = (name) => ssb.profile.person.group.create({
preferredName: name,
authors: { add: [ssb.id] },
recps
})
const [mum, dad, baby] = await Promise.all(['mum', 'dad', 'baby'].map(createProfile))
await ssb.whakapapa.partner.create({ parent: dad, child: mum }, { recps })
await ssb.whakapapa.child.create({ parent: dad, child: baby }, { relationshipType: 'adopted', recps })
await ssb.whakapapa.child.create({ parent: mum, child: baby }, { relationshipType: 'birth', recps })
const viewId = await ssb.whakapapa.view.create({
name: 'lil fam',
focus: mum,
permission: 'view',
authors: { add: [ssb.id] },
recps: [groupId]
})
const res = await apollo.query({
query: `query($viewId: String!) {
whakapapaView(id: $viewId) {
focus
permission
links {
childLinks {
parent
child
relationshipType
}
partnerLinks {
parent
child
relationshipType
}
}
}
}`,
variables: { viewId }
})
const { focus, links } = res.data.whakapapaView
t.equal(focus, mum, 'correct focus')
t.deepEqual(
links.childLinks.sort(linkComparator),
[
{
parent: dad,
child: baby,
relationshipType: 'adopted'
},
{
parent: mum,
child: baby,
relationshipType: 'birth'
}
].sort(linkComparator),
'partnerLinks'
)
t.deepEqual(
links.partnerLinks,
[{
parent: dad,
child: mum,
relationshipType: null
}],
'partnerLinks'
)
ssb.close()
t.end()
})
function linkComparator (a, b) {
const A = (a.parent + a.child)
const B = (b.parent + b.child)
return A < B ? -1 : 1
}