@ssb-graphql/whakapapa
Version:
GraphQL types and resolvers for the ssb-whakapapa plugin
295 lines (258 loc) • 7.9 kB
JavaScript
const test = require('tape')
const { promisify: p } = require('util')
const TestBot = require('../test-bot')
const CHILD = 'link/profile-profile/child'
const PARTNER = 'link/profile-profile/partner'
const compare = (a, b) => {
return (a.parent + a.child).localeCompare(b.parent + b.child)
}
test('loadFamilyOfPerson', async t => {
const { ssb, apollo } = await TestBot({ loadContext: true })
const { groupId } = await p(ssb.tribes.create)({})
const content = (opts = {}) => ({
...opts,
authors: { add: [ssb.id] },
recps: [groupId]
})
// A has partners:
// - X their ex!
// - B their current partner
// A has children:
// - ax
// - ab
// B has another child:
// - bc (with parent C)
// X has another child:
// - xy (with parent Y - relationshipType: null)
//
// Like so:
//
// Y X A---B C
// \ / \ / | \ /
// xy ax ab bc
// TODO - also queue up partners as other people to explore
const [A, B, C, X, Y, ax, ab, bc, xy] = await Promise.all(
new Array(9).fill(0)
.map(() => p(ssb.profile.person.group.create)(content()))
)
const details = { recps: [groupId] }
await p(ssb.whakapapa.link.create)({ type: PARTNER, parent: B, child: A }, details)
// TODO add relationshipType to partners then enable this
// await p(ssb.whakapapa.link.create)({ type: PARTNER, parent: A, child: B, relationshipType: 'divorced' })
const childLinks = await Promise.all([
{ parent: A, child: ax }, // 0
{ parent: A, child: ax }, // 1 deliberate duplicate
{ parent: A, child: ab }, // 2
{ parent: B, child: ab }, // 3
{ parent: B, child: bc }, // 4
{ parent: C, child: bc }, // 5
{ parent: X, child: xy }, // 6
{ parent: X, child: ax }, // 7
{ parent: Y, child: xy } // 8
].map(link =>
p(ssb.whakapapa.link.create)({ type: CHILD, ...link }, details)
))
// console.timeEnd('setup relationships')
const linkAax = childLinks[0]
const linkXax = childLinks[7]
const QUERY = `query ($profileId: String!, $extended: Boolean) {
loadFamilyOfPerson(id: $profileId, extended: $extended) {
childLinks {
parent
child
relationshipType
}
partnerLinks {
parent
child
relationshipType
}
}
}`
let result
// shallow
result = await apollo.query({
query: QUERY,
variables: {
profileId: A
// extended: false
}
}).catch(err => { throw err })
let actual = result.data.loadFamilyOfPerson
let expected = {
childLinks: [
{ parent: A, child: ax, relationshipType: null },
{ parent: A, child: ab, relationshipType: null }
],
partnerLinks: [
{ parent: B, child: A, relationshipType: 'partners' }
]
}
t.deepEqual(actual, expected, 'simple family')
// if A-ax + X-ax are birth relationships, we infer another (ex) partner
await p(ssb.whakapapa.link.update)(linkAax, { relationshipType: 'birth' })
await p(ssb.whakapapa.link.update)(linkXax, { relationshipType: 'birth' })
result = await apollo.query({
query: QUERY,
variables: {
profileId: A
// extended: false
}
}).catch(err => { throw err })
actual = result.data.loadFamilyOfPerson
expected = {
childLinks: [
{ parent: A, child: ax, relationshipType: 'birth' },
{ parent: A, child: ab, relationshipType: null },
{ parent: X, child: ax, relationshipType: 'birth' }
],
partnerLinks: [
{ parent: B, child: A, relationshipType: 'partners' },
inferredPartnerLink(A, X)
]
}
t.deepEqual(
actual.childLinks.sort(compare),
expected.childLinks.sort(compare),
'an ex-partner you had a child with'
)
t.deepEqual(
actual.partnerLinks.sort(compare),
expected.partnerLinks.sort(compare),
'an ex-partner you had a child with'
)
ssb.close()
t.end()
})
test('loadFamilyOfPerson (extended: true)', async t => {
const { ssb, apollo } = await TestBot({ loadContext: true })
const { groupId } = await p(ssb.tribes.create)({})
const content = (opts = {}) => ({
...opts,
authors: { add: [ssb.id] },
recps: [groupId]
})
// A has partners:
// - X their ex!
// - B their current partner
// A has children:
// - ax
// - ab
// B has another child:
// - bc (with parent C)
// X has another child:
// - xy (with parent Y)
//
// Like so:
//
// Y X A---B C
// \ / \ / | \ /
// xy ax ab bc
// ssb.post(m => ssb.get({ id: m.key, private: true }, (err, val) => console.log(val.content)))
const [A, B, C, X, Y, ax, ab, bc, xy] = await Promise.all(
new Array(9).fill(0)
.map(() => p(ssb.profile.person.group.create)(content()))
)
const details = { recps: [groupId] }
await p(ssb.whakapapa.link.create)({ type: PARTNER, parent: A, child: B }, details)
// TODO add relationshipType to partners then enable this
// await p(ssb.whakapapa.link.create)({ type: PARTNER, parent: A, child: B, relationshipType: 'divorced' })
details.relationshipType = 'birth'
await Promise.all([
{ parent: A, child: ax }, // 0
{ parent: A, child: ax }, // 1 deliberate duplicate
{ parent: A, child: ab }, // 2
{ parent: B, child: ab }, // 3
{ parent: B, child: bc }, // 4
{ parent: C, child: bc }, // 5
{ parent: X, child: xy }, // 6
{ parent: X, child: ax } // 7
// { parent: Y, child: xy } // 8
].map(link =>
p(ssb.whakapapa.link.create)({ type: CHILD, ...link }, details)
))
// NOTE one link of relationshipType: null
await p(ssb.whakapapa.link.create)({ type: CHILD, parent: Y, child: xy }, { recps: [groupId] }) // 8
const QUERY = `query ($profileId: String!, $extended: Boolean) {
loadFamilyOfPerson(id: $profileId, extended: $extended) {
childLinks {
parent
child
relationshipType
}
partnerLinks {
parent
child
relationshipType
}
}
}`
// extended
const result = await apollo.query({
query: QUERY,
variables: {
profileId: A,
extended: true
}
}).catch(err => { throw err })
t.deepEqual(
result.data.loadFamilyOfPerson.childLinks.sort(compare),
[
{ parent: A, child: ax, relationshipType: 'birth' }, // 0
{ parent: A, child: ab, relationshipType: 'birth' }, // 1
{ parent: X, child: ax, relationshipType: 'birth' }, // 7
{ parent: B, child: ab, relationshipType: 'birth' }, // 3
{ parent: B, child: bc, relationshipType: 'birth' }, // 4
{ parent: C, child: bc, relationshipType: 'birth' }, // 5
{ parent: X, child: xy, relationshipType: 'birth' }, // 6
{ parent: Y, child: xy, relationshipType: null } // 8
].sort(compare),
'childLinks ok'
)
t.deepEqual(
result.data.loadFamilyOfPerson.partnerLinks.sort(compare),
[
{ parent: A, child: B, relationshipType: 'partners' },
inferredPartnerLink(A, X),
inferredPartnerLink(B, C)
// inferredPartnerLink(X, Y) // Y-xy = not birth relationship
].sort(compare),
'partnerLinks ok'
)
/* A function that's useful for debugging
function prettyPrint (label, links) {
const map = {
[A]: 'A',
[B]: 'B',
[C]: 'C',
[X]: 'X',
[Y]: 'Y',
[ab]: 'ab',
[ax]: 'ax',
[bc]: 'bc',
[xy]: 'xy'
}
const decode = (link) => ({
...link,
parent: map[link.parent],
child: map[link.child]
})
console.log(
label,
JSON.stringify(
links.sort(compare).map(decode),
null,
2
)
)
}
*/
ssb.close()
t.end()
})
function inferredPartnerLink (a, b) {
const [parent, child] = [a, b].sort()
return { parent, child, relationshipType: 'inferred' }
// this is how the fns builds the inferred links,
// so we emulate this here for predictable tests
}