solid-logic 1.3.17-2bf19bb6 → 1.3.17-64c8b7a5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/authn/SolidAuthnLogic.js +1 -1
- package/lib/authn/SolidAuthnLogic.js.map +1 -1
- package/lib/discovery/discoveryLogic.d.ts +31 -7
- package/lib/discovery/discoveryLogic.d.ts.map +1 -1
- package/lib/discovery/discoveryLogic.js +380 -81
- package/lib/discovery/discoveryLogic.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +17 -4
- package/lib/index.js.map +1 -1
- package/lib/typeIndex/typeIndexLogic.js.map +1 -1
- package/lib/util/UtilityLogic.js +1 -1
- package/lib/util/UtilityLogic.js.map +1 -1
- package/package.json +3 -1
- package/src/authn/SolidAuthnLogic.ts +5 -5
- package/src/discovery/discoveryLogic.ts +227 -48
- package/src/index.ts +16 -3
- package/src/typeIndex/typeIndexLogic.ts +1 -1
- package/src/util/UtilityLogic.ts +1 -1
- package/test/discoveryLogic.test.ts +712 -0
- package/test/typeIndexLogic.test.ts +5 -4
|
@@ -0,0 +1,712 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*
|
|
4
|
+
*/
|
|
5
|
+
import fetchMock from 'jest-fetch-mock'
|
|
6
|
+
import { Fetcher, Store, sym, UpdateManager } from 'rdflib'
|
|
7
|
+
import * as $rdf from 'rdflib'
|
|
8
|
+
import {
|
|
9
|
+
followOrCreateLink, getAppInstances, getScopedAppInstances, loadCommunityTypeIndexes, loadOrCreateIfNotExists,
|
|
10
|
+
loadPreferences, loadProfile, loadTypeIndexesFor, registerInstanceInTypeIndex, uniqueNodes
|
|
11
|
+
} from '../src/discovery/discoveryLogic'
|
|
12
|
+
import solidNamespace from 'solid-namespace'
|
|
13
|
+
|
|
14
|
+
/* Discovery Logic tests */
|
|
15
|
+
|
|
16
|
+
const ns = solidNamespace($rdf)
|
|
17
|
+
|
|
18
|
+
const prefixes = Object.keys(ns).map(prefix => `@prefix ${prefix}: ${ns[prefix]('')}.\n`).join('') // In turtle
|
|
19
|
+
|
|
20
|
+
const Alice = sym('https://alice.example.com/profile/card.ttl#me')
|
|
21
|
+
const AliceProfileFile = Alice.doc()
|
|
22
|
+
const AlicePreferencesFile = sym('https://alice.example.com/settings/prefs.ttl')
|
|
23
|
+
const AlicePublicTypeIndex = sym('https://alice.example.com/profle/public-type-index.ttl')
|
|
24
|
+
const AlicePrivateTypeIndex = sym('https://alice.example.com/settings/private-type-index.ttl')
|
|
25
|
+
const AlicePhotoFolder = sym(Alice.dir().uri + "Photos/")
|
|
26
|
+
|
|
27
|
+
// the Club is a community which Alice is involved and so she gets to
|
|
28
|
+
// interact with things in its type indexes.
|
|
29
|
+
|
|
30
|
+
const Club = sym('https://club.example.com/profile/card.ttl#it')
|
|
31
|
+
const ClubProfileFile = Club.doc()
|
|
32
|
+
const ClubPreferencesFile = sym('https://club.example.com/settings/prefs.ttl')
|
|
33
|
+
const ClubPublicTypeIndex = sym('https://club.example.com/profle/public-type-index.ttl')
|
|
34
|
+
const ClubPrivateTypeIndex = sym('https://club.example.com/settings/private-type-index.ttl')
|
|
35
|
+
|
|
36
|
+
const Bob = sym('https://bob.example.com/profile/card.ttl#me')
|
|
37
|
+
|
|
38
|
+
window.$SolidTestEnvironment = { username: Alice.uri }
|
|
39
|
+
|
|
40
|
+
const user = Alice
|
|
41
|
+
const profile = user.doc()
|
|
42
|
+
|
|
43
|
+
// const klass = sym('http://www.w3.org/2006/vcard/ns#AddressBook')
|
|
44
|
+
const klass = ns.wf('Tracker')
|
|
45
|
+
const Tracker = ns.wf('Tracker')
|
|
46
|
+
const Image = ns.schema('Image')
|
|
47
|
+
|
|
48
|
+
//////////////////////////////////////////////////////////// User Alice
|
|
49
|
+
const AliceProfile = `
|
|
50
|
+
<#me> a vcard:Individual;
|
|
51
|
+
space:preferencesFile ${AlicePreferencesFile};
|
|
52
|
+
solid:publicTypeIndex ${AlicePublicTypeIndex};
|
|
53
|
+
vcard:fn "Alice" .
|
|
54
|
+
`
|
|
55
|
+
const AlicePreferences = `
|
|
56
|
+
${Alice} solid:privateTypeIndex ${AlicePrivateTypeIndex};
|
|
57
|
+
solid:community ${Club} .
|
|
58
|
+
`
|
|
59
|
+
const AlicePublicTypes = `
|
|
60
|
+
|
|
61
|
+
:chat1 solid:forClass meeting:LongChat; solid:instance <../publicStuff/myChat.ttl#this> .
|
|
62
|
+
|
|
63
|
+
:todo solid:forClass wf:Tracker; solid:instance <../publicStuff/actionItems.ttl#this>.
|
|
64
|
+
|
|
65
|
+
:issues solid:forClass wf:Tracker; solid:instance <../project4/issues.ttl#this>.
|
|
66
|
+
|
|
67
|
+
:photos solid:forClass schema:Image; solid:instanceContainer ${AlicePhotoFolder} .
|
|
68
|
+
# :bookmarks
|
|
69
|
+
# a solid:TypeRegistration;
|
|
70
|
+
# solid:forClass bookm:Bookmark;
|
|
71
|
+
# solid:instance </public/poddit.ttl>.
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const AlicePrivateTypes = `
|
|
75
|
+
:id1592319218311 solid:forClass wf:Tracker; solid:instance <../privateStuff/ToDo.ttl#this>.
|
|
76
|
+
|
|
77
|
+
:id1592319391415 solid:forClass wf:Tracker; solid:instance <../privateStuff/Goals.ttl#this>.
|
|
78
|
+
|
|
79
|
+
:id1595595377864 solid:forClass wf:Tracker; solid:instance <../privateStuff/workingOn.ttl#this>.
|
|
80
|
+
|
|
81
|
+
:id1596123375929 solid:forClass meeting:Meeting; solid:instance <../project4/meeting1.ttl#this>.
|
|
82
|
+
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
const AlicePhotos = `
|
|
86
|
+
<>
|
|
87
|
+
a ldp:BasicContainer, ldp:Container;
|
|
88
|
+
dct:modified "2021-04-26T05:34:16Z"^^xsd:dateTime;
|
|
89
|
+
ldp:contains
|
|
90
|
+
<photo1.png>, <photo2.png>, <photo3.png> ;
|
|
91
|
+
stat:mtime 1619415256.541;
|
|
92
|
+
stat:size 4096 .
|
|
93
|
+
`
|
|
94
|
+
|
|
95
|
+
//////////////////////////////////////////////////////////// User Bob
|
|
96
|
+
const BobProfile = `
|
|
97
|
+
<#me> a vcard:Individual;
|
|
98
|
+
|
|
99
|
+
vcard:fn "Bob" .
|
|
100
|
+
`
|
|
101
|
+
|
|
102
|
+
//////////////////////////////////////////////////////////// User Club
|
|
103
|
+
const ClubProfile = `
|
|
104
|
+
|
|
105
|
+
<#it> a vcard:Organization;
|
|
106
|
+
space:preferencesFile ${ClubPreferencesFile};
|
|
107
|
+
solid:publicTypeIndex ${ClubPublicTypeIndex};
|
|
108
|
+
vcard:fn "Card Club" .
|
|
109
|
+
`
|
|
110
|
+
const ClubPreferences = `
|
|
111
|
+
${Club} solid:privateTypeIndex ${ClubPrivateTypeIndex} .
|
|
112
|
+
`
|
|
113
|
+
const ClubPublicTypes = `
|
|
114
|
+
|
|
115
|
+
:chat1 solid:forClass meeting:LongChat; solid:instance <../publicStuff/ourChat.ttl#this> .
|
|
116
|
+
|
|
117
|
+
:todo solid:forClass wf:Tracker; solid:instance <../publicStuff/actionItems.ttl#this>.
|
|
118
|
+
|
|
119
|
+
:issues solid:forClass wf:Tracker; solid:instance <../project4/clubIssues.ttl#this>.
|
|
120
|
+
|
|
121
|
+
# :bookmarks
|
|
122
|
+
# a solid:TypeRegistration;
|
|
123
|
+
# solid:forClass bookm:Bookmark;
|
|
124
|
+
# solid:instance </public/poddit.ttl>.
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
const ClubPrivateTypes = `
|
|
128
|
+
:id1592319218311 solid:forClass wf:Tracker; solid:instance <../privateStuff/ToDo.ttl#this>.
|
|
129
|
+
|
|
130
|
+
:id1592319391415 solid:forClass wf:Tracker; solid:instance <../privateStuff/Goals.ttl#this>.
|
|
131
|
+
|
|
132
|
+
:id1595595377864 solid:forClass wf:Tracker; solid:instance <../privateStuff/tasks.ttl#this>.
|
|
133
|
+
|
|
134
|
+
:id1596123375929 solid:forClass meeting:Meeting; solid:instance <../project4/clubMeeting.ttl#this>.
|
|
135
|
+
|
|
136
|
+
`;
|
|
137
|
+
|
|
138
|
+
////////////////////////////////////////////////////////////////////////////
|
|
139
|
+
|
|
140
|
+
const web = {}
|
|
141
|
+
web[profile.uri] = AliceProfile
|
|
142
|
+
web[AlicePreferencesFile.uri] = AlicePreferences
|
|
143
|
+
web[AlicePrivateTypeIndex.uri] = AlicePrivateTypes
|
|
144
|
+
web[AlicePublicTypeIndex.uri] = AlicePublicTypes
|
|
145
|
+
web[AlicePhotoFolder.uri] = AlicePhotos
|
|
146
|
+
web[Bob.doc().uri] = BobProfile
|
|
147
|
+
|
|
148
|
+
web[Club.doc().uri] = ClubProfile
|
|
149
|
+
web[ClubPreferencesFile.uri] = ClubPreferences
|
|
150
|
+
web[ClubPrivateTypeIndex.uri] = ClubPrivateTypes
|
|
151
|
+
web[ClubPublicTypeIndex.uri] = ClubPublicTypes
|
|
152
|
+
|
|
153
|
+
let requests = []
|
|
154
|
+
let statustoBeReturned = 200
|
|
155
|
+
|
|
156
|
+
describe("Discovery Logic", () => {
|
|
157
|
+
let store;
|
|
158
|
+
let options;
|
|
159
|
+
beforeEach(() => {
|
|
160
|
+
fetchMock.resetMocks();
|
|
161
|
+
requests = []
|
|
162
|
+
statustoBeReturned = 200
|
|
163
|
+
const init = {headers: { "Content-Type": "text/turtle" }} // Fetch options tend to be called this
|
|
164
|
+
|
|
165
|
+
fetchMock.mockIf(/^https?.*$/, async req => {
|
|
166
|
+
|
|
167
|
+
if (req.method !== 'GET') {
|
|
168
|
+
requests.push(req)
|
|
169
|
+
if (req.method === 'PUT') {
|
|
170
|
+
const contents = await req.text()
|
|
171
|
+
web[req.url] = contents // Update our dummy web
|
|
172
|
+
console.log(`Tetst: Updated ${req.url} on PUT to <<<${web[req.url]}>>>`)
|
|
173
|
+
}
|
|
174
|
+
return { status: statustoBeReturned }
|
|
175
|
+
}
|
|
176
|
+
const contents = web[req.url]
|
|
177
|
+
if (contents !== undefined) { //
|
|
178
|
+
return {
|
|
179
|
+
body: prefixes + contents, // Add namespaces to anything
|
|
180
|
+
status: 200,
|
|
181
|
+
headers: {
|
|
182
|
+
"Content-Type": "text/turtle",
|
|
183
|
+
"WAC-Allow": 'user="write", public="read"',
|
|
184
|
+
"Accept-Patch": "application/sparql-update"
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
} // if contents
|
|
188
|
+
return {
|
|
189
|
+
status: 404,
|
|
190
|
+
body: 'Not Found'
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
options = { fetch: fetch };
|
|
196
|
+
store = new Store()
|
|
197
|
+
store.fetcher = new Fetcher (store, options);
|
|
198
|
+
store.updater = new UpdateManager(store);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe('uniqueNodes', () => {
|
|
202
|
+
it('exists', () => {
|
|
203
|
+
expect(uniqueNodes).toBeInstanceOf(Function)
|
|
204
|
+
})
|
|
205
|
+
it('removed duplicates', async () => {
|
|
206
|
+
const input = [ sym('https://a.com/'), sym('https://b.com/'),sym('https://a.com/'), sym('https://a.com/'), sym('https://c.com/'), ]
|
|
207
|
+
const expected = [ sym('https://a.com/'), sym('https://b.com/'), sym('https://c.com/'), ]
|
|
208
|
+
const result = uniqueNodes(input)
|
|
209
|
+
expect(result).toEqual(expected)
|
|
210
|
+
|
|
211
|
+
})
|
|
212
|
+
it('handles an empty array', async () => {
|
|
213
|
+
const result = await uniqueNodes([])
|
|
214
|
+
expect(result).toEqual([])
|
|
215
|
+
})
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
describe('loadOrCreateIfNotExists', () => {
|
|
219
|
+
it('exists', () => {
|
|
220
|
+
expect(loadOrCreateIfNotExists).toBeInstanceOf(Function)
|
|
221
|
+
})
|
|
222
|
+
it('does nothing if existing file', async () => {
|
|
223
|
+
const result = await loadOrCreateIfNotExists(store, Alice.doc())
|
|
224
|
+
expect(requests).toEqual([])
|
|
225
|
+
|
|
226
|
+
})
|
|
227
|
+
it('creates empty file if did not exist', async () => {
|
|
228
|
+
const newFile = sym(Bob.doc().uri + '/refhoijhoegg/')
|
|
229
|
+
const result = await loadOrCreateIfNotExists(store, newFile)
|
|
230
|
+
expect(requests[0].method).toEqual('PUT')
|
|
231
|
+
expect(requests[0].url).toEqual(newFile.uri)
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
describe('followOrCreateLink', () => {
|
|
236
|
+
it('exists', () => {
|
|
237
|
+
expect(followOrCreateLink).toBeInstanceOf(Function)
|
|
238
|
+
})
|
|
239
|
+
it('follows existing link', async () => {
|
|
240
|
+
const suggestion = 'https://alice.example.com/settings/prefsSuggestion.ttl'
|
|
241
|
+
const result = await followOrCreateLink(store, Alice, ns.space('preferencesFile'), sym(suggestion), Alice.doc())
|
|
242
|
+
expect(result).toEqual(AlicePreferencesFile)
|
|
243
|
+
|
|
244
|
+
})
|
|
245
|
+
it('creates empty file if did not exist and new link', async () => {
|
|
246
|
+
const suggestion = 'https://bob.example.com/settings/prefsSuggestion.ttl'
|
|
247
|
+
const result = await followOrCreateLink(store, Bob, ns.space('preferencesFile'), sym(suggestion), Bob.doc())
|
|
248
|
+
expect(result).toEqual(sym(suggestion))
|
|
249
|
+
expect(requests[0].method).toEqual('PATCH') // or patch first?
|
|
250
|
+
expect(requests[0].url).toEqual(Bob.doc().uri)
|
|
251
|
+
expect(requests[1].method).toEqual('PUT') // or patch first?
|
|
252
|
+
expect(requests[1].url).toEqual(suggestion)
|
|
253
|
+
expect(store.holds(Bob, ns.space('preferencesFile'), sym(suggestion), Bob.doc())).toEqual(true)
|
|
254
|
+
})
|
|
255
|
+
//
|
|
256
|
+
it('returns null if it cannot create the new file', async () => {
|
|
257
|
+
const suggestion = 'https://bob.example.com/settings/prefsSuggestion.ttl'
|
|
258
|
+
statustoBeReturned = 403 // Unauthorized
|
|
259
|
+
const result = await followOrCreateLink(store, Bob, ns.space('preferencesFile'), sym(suggestion), Bob.doc())
|
|
260
|
+
expect(result).toEqual(null)
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
describe('loadProfile', () => {
|
|
266
|
+
it('exists', () => {
|
|
267
|
+
expect(loadProfile).toBeInstanceOf(Function)
|
|
268
|
+
})
|
|
269
|
+
it('loads data', async () => {
|
|
270
|
+
const result = await loadProfile(store, user)
|
|
271
|
+
expect(result).toBeInstanceOf(Object)
|
|
272
|
+
expect(result.uri).toEqual(AliceProfileFile.uri)
|
|
273
|
+
expect(store.holds(user, ns.rdf('type'), ns.vcard('Individual'), profile)).toEqual(true)
|
|
274
|
+
expect(store.holds(user, ns.space('preferencesFile'), AlicePreferencesFile, profile)).toEqual(true)
|
|
275
|
+
expect(store.statementsMatching(null, null, null, profile).length).toEqual(4)
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
describe('loadPreferences', () => {
|
|
280
|
+
it('exists', () => {
|
|
281
|
+
expect(loadPreferences).toBeInstanceOf(Function)
|
|
282
|
+
})
|
|
283
|
+
it('loads data', async () => {
|
|
284
|
+
const result = await loadPreferences(store, Alice)
|
|
285
|
+
expect(result).toBeInstanceOf(Object)
|
|
286
|
+
expect(result.uri).toEqual(AlicePreferencesFile.uri)
|
|
287
|
+
expect(store.holds(user, ns.rdf('type'), ns.vcard('Individual'), profile)).toEqual(true)
|
|
288
|
+
expect(store.statementsMatching(null, null, null, profile).length).toEqual(4)
|
|
289
|
+
|
|
290
|
+
expect(store.statementsMatching(null, null, null, AlicePreferencesFile).length).toEqual(2)
|
|
291
|
+
expect(store.holds(user, ns.solid('privateTypeIndex'), AlicePrivateTypeIndex, AlicePreferencesFile)).toEqual(true)
|
|
292
|
+
})
|
|
293
|
+
it('creates new file', async () => {
|
|
294
|
+
const result = await loadPreferences(store, Bob)
|
|
295
|
+
|
|
296
|
+
const patchRequest = requests[0]
|
|
297
|
+
expect(patchRequest.method).toEqual('PATCH')
|
|
298
|
+
expect(patchRequest.url).toEqual(Bob.doc().uri)
|
|
299
|
+
const text = await patchRequest.text()
|
|
300
|
+
expect(text).toContain('INSERT DATA { <https://bob.example.com/profile/card.ttl#me> <http://www.w3.org/ns/pim/space#preferencesFile> <https://bob.example.com/Settings/Preferences.ttl> .')
|
|
301
|
+
|
|
302
|
+
const putRequest = requests[1]
|
|
303
|
+
expect(putRequest.method).toEqual('PUT')
|
|
304
|
+
expect(putRequest.url).toEqual('https://bob.example.com/Settings/Preferences.ttl')
|
|
305
|
+
expect(web[putRequest.url]).toEqual('')
|
|
306
|
+
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
const AliceScopes = [ {
|
|
312
|
+
"agent": {
|
|
313
|
+
"classOrder": 5,
|
|
314
|
+
"termType": "NamedNode",
|
|
315
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
316
|
+
},
|
|
317
|
+
"index": {
|
|
318
|
+
"classOrder": 5,
|
|
319
|
+
"termType": "NamedNode",
|
|
320
|
+
"value": "https://alice.example.com/profle/public-type-index.ttl",
|
|
321
|
+
},
|
|
322
|
+
"label": "public",
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"agent": {
|
|
326
|
+
"classOrder": 5,
|
|
327
|
+
"termType": "NamedNode",
|
|
328
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
329
|
+
},
|
|
330
|
+
"index": {
|
|
331
|
+
"classOrder": 5,
|
|
332
|
+
"termType": "NamedNode",
|
|
333
|
+
"value": "https://alice.example.com/settings/private-type-index.ttl",
|
|
334
|
+
},
|
|
335
|
+
"label": "private",
|
|
336
|
+
}
|
|
337
|
+
];
|
|
338
|
+
|
|
339
|
+
describe('loadTypeIndexesFor', () => {
|
|
340
|
+
it('exists', () => {
|
|
341
|
+
expect(loadTypeIndexesFor).toBeInstanceOf(Function)
|
|
342
|
+
})
|
|
343
|
+
it('loads data', async () => {
|
|
344
|
+
const result = await loadTypeIndexesFor(store, user)
|
|
345
|
+
expect(result).toEqual(AliceScopes)
|
|
346
|
+
expect(store.statementsMatching(null, null, null, AlicePrivateTypeIndex).length).toEqual(8)
|
|
347
|
+
expect(store.statementsMatching(null, null, null, AlicePublicTypeIndex).length).toEqual(8)
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
const ClubScopes =
|
|
352
|
+
[
|
|
353
|
+
{
|
|
354
|
+
"agent": {
|
|
355
|
+
"classOrder": 5,
|
|
356
|
+
"termType": "NamedNode",
|
|
357
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
358
|
+
},
|
|
359
|
+
"index": {
|
|
360
|
+
"classOrder": 5,
|
|
361
|
+
"termType": "NamedNode",
|
|
362
|
+
"value": "https://club.example.com/profle/public-type-index.ttl",
|
|
363
|
+
},
|
|
364
|
+
"label": "public",
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"agent": {
|
|
368
|
+
"classOrder": 5,
|
|
369
|
+
"termType": "NamedNode",
|
|
370
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
371
|
+
},
|
|
372
|
+
"index": {
|
|
373
|
+
"classOrder": 5,
|
|
374
|
+
"termType": "NamedNode",
|
|
375
|
+
"value": "https://club.example.com/settings/private-type-index.ttl",
|
|
376
|
+
},
|
|
377
|
+
"label": "private",
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
describe('loadCommunityTypeIndexes', () => {
|
|
381
|
+
it('exists', () => {
|
|
382
|
+
expect(loadCommunityTypeIndexes).toBeInstanceOf(Function)
|
|
383
|
+
})
|
|
384
|
+
it('loads data', async () => {
|
|
385
|
+
const result = await loadCommunityTypeIndexes(store, user)
|
|
386
|
+
expect(result).toEqual(ClubScopes)
|
|
387
|
+
})
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
const AliceAndClubScopes =
|
|
391
|
+
[
|
|
392
|
+
{
|
|
393
|
+
"instance": {
|
|
394
|
+
"classOrder": 5,
|
|
395
|
+
"termType": "NamedNode",
|
|
396
|
+
"value": "https://alice.example.com/publicStuff/actionItems.ttl#this",
|
|
397
|
+
},
|
|
398
|
+
"scope": {
|
|
399
|
+
"agent": {
|
|
400
|
+
"classOrder": 5,
|
|
401
|
+
"termType": "NamedNode",
|
|
402
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
403
|
+
},
|
|
404
|
+
"index": {
|
|
405
|
+
"classOrder": 5,
|
|
406
|
+
"termType": "NamedNode",
|
|
407
|
+
"value": "https://alice.example.com/profle/public-type-index.ttl",
|
|
408
|
+
},
|
|
409
|
+
"label": "public",
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"instance": {
|
|
414
|
+
"classOrder": 5,
|
|
415
|
+
"termType": "NamedNode",
|
|
416
|
+
"value": "https://alice.example.com/project4/issues.ttl#this",
|
|
417
|
+
},
|
|
418
|
+
"scope": {
|
|
419
|
+
"agent": {
|
|
420
|
+
"classOrder": 5,
|
|
421
|
+
"termType": "NamedNode",
|
|
422
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
423
|
+
},
|
|
424
|
+
"index": {
|
|
425
|
+
"classOrder": 5,
|
|
426
|
+
"termType": "NamedNode",
|
|
427
|
+
"value": "https://alice.example.com/profle/public-type-index.ttl",
|
|
428
|
+
},
|
|
429
|
+
"label": "public",
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"instance": {
|
|
434
|
+
"classOrder": 5,
|
|
435
|
+
"termType": "NamedNode",
|
|
436
|
+
"value": "https://alice.example.com/privateStuff/ToDo.ttl#this",
|
|
437
|
+
},
|
|
438
|
+
"scope": {
|
|
439
|
+
"agent": {
|
|
440
|
+
"classOrder": 5,
|
|
441
|
+
"termType": "NamedNode",
|
|
442
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
443
|
+
},
|
|
444
|
+
"index": {
|
|
445
|
+
"classOrder": 5,
|
|
446
|
+
"termType": "NamedNode",
|
|
447
|
+
"value": "https://alice.example.com/settings/private-type-index.ttl",
|
|
448
|
+
},
|
|
449
|
+
"label": "private",
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"instance": {
|
|
454
|
+
"classOrder": 5,
|
|
455
|
+
"termType": "NamedNode",
|
|
456
|
+
"value": "https://alice.example.com/privateStuff/Goals.ttl#this",
|
|
457
|
+
},
|
|
458
|
+
"scope": {
|
|
459
|
+
"agent": {
|
|
460
|
+
"classOrder": 5,
|
|
461
|
+
"termType": "NamedNode",
|
|
462
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
463
|
+
},
|
|
464
|
+
"index": {
|
|
465
|
+
"classOrder": 5,
|
|
466
|
+
"termType": "NamedNode",
|
|
467
|
+
"value": "https://alice.example.com/settings/private-type-index.ttl",
|
|
468
|
+
},
|
|
469
|
+
"label": "private",
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"instance": {
|
|
474
|
+
"classOrder": 5,
|
|
475
|
+
"termType": "NamedNode",
|
|
476
|
+
"value": "https://alice.example.com/privateStuff/workingOn.ttl#this",
|
|
477
|
+
},
|
|
478
|
+
"scope": {
|
|
479
|
+
"agent": {
|
|
480
|
+
"classOrder": 5,
|
|
481
|
+
"termType": "NamedNode",
|
|
482
|
+
"value": "https://alice.example.com/profile/card.ttl#me",
|
|
483
|
+
},
|
|
484
|
+
"index": {
|
|
485
|
+
"classOrder": 5,
|
|
486
|
+
"termType": "NamedNode",
|
|
487
|
+
"value": "https://alice.example.com/settings/private-type-index.ttl",
|
|
488
|
+
},
|
|
489
|
+
"label": "private",
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"instance": {
|
|
494
|
+
"classOrder": 5,
|
|
495
|
+
"termType": "NamedNode",
|
|
496
|
+
"value": "https://club.example.com/publicStuff/actionItems.ttl#this",
|
|
497
|
+
},
|
|
498
|
+
"scope": {
|
|
499
|
+
"agent": {
|
|
500
|
+
"classOrder": 5,
|
|
501
|
+
"termType": "NamedNode",
|
|
502
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
503
|
+
},
|
|
504
|
+
"index": {
|
|
505
|
+
"classOrder": 5,
|
|
506
|
+
"termType": "NamedNode",
|
|
507
|
+
"value": "https://club.example.com/profle/public-type-index.ttl",
|
|
508
|
+
},
|
|
509
|
+
"label": "public",
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"instance": {
|
|
514
|
+
"classOrder": 5,
|
|
515
|
+
"termType": "NamedNode",
|
|
516
|
+
"value": "https://club.example.com/project4/clubIssues.ttl#this",
|
|
517
|
+
},
|
|
518
|
+
"scope": {
|
|
519
|
+
"agent": {
|
|
520
|
+
"classOrder": 5,
|
|
521
|
+
"termType": "NamedNode",
|
|
522
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
523
|
+
},
|
|
524
|
+
"index": {
|
|
525
|
+
"classOrder": 5,
|
|
526
|
+
"termType": "NamedNode",
|
|
527
|
+
"value": "https://club.example.com/profle/public-type-index.ttl",
|
|
528
|
+
},
|
|
529
|
+
"label": "public",
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"instance": {
|
|
534
|
+
"classOrder": 5,
|
|
535
|
+
"termType": "NamedNode",
|
|
536
|
+
"value": "https://club.example.com/privateStuff/ToDo.ttl#this",
|
|
537
|
+
},
|
|
538
|
+
"scope": {
|
|
539
|
+
"agent": {
|
|
540
|
+
"classOrder": 5,
|
|
541
|
+
"termType": "NamedNode",
|
|
542
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
543
|
+
},
|
|
544
|
+
"index": {
|
|
545
|
+
"classOrder": 5,
|
|
546
|
+
"termType": "NamedNode",
|
|
547
|
+
"value": "https://club.example.com/settings/private-type-index.ttl",
|
|
548
|
+
},
|
|
549
|
+
"label": "private",
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
"instance": {
|
|
554
|
+
"classOrder": 5,
|
|
555
|
+
"termType": "NamedNode",
|
|
556
|
+
"value": "https://club.example.com/privateStuff/Goals.ttl#this",
|
|
557
|
+
},
|
|
558
|
+
"scope": {
|
|
559
|
+
"agent": {
|
|
560
|
+
"classOrder": 5,
|
|
561
|
+
"termType": "NamedNode",
|
|
562
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
563
|
+
},
|
|
564
|
+
"index": {
|
|
565
|
+
"classOrder": 5,
|
|
566
|
+
"termType": "NamedNode",
|
|
567
|
+
"value": "https://club.example.com/settings/private-type-index.ttl",
|
|
568
|
+
},
|
|
569
|
+
"label": "private",
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
"instance": {
|
|
574
|
+
"classOrder": 5,
|
|
575
|
+
"termType": "NamedNode",
|
|
576
|
+
"value": "https://club.example.com/privateStuff/tasks.ttl#this",
|
|
577
|
+
},
|
|
578
|
+
"scope": {
|
|
579
|
+
"agent": {
|
|
580
|
+
"classOrder": 5,
|
|
581
|
+
"termType": "NamedNode",
|
|
582
|
+
"value": "https://club.example.com/profile/card.ttl#it",
|
|
583
|
+
},
|
|
584
|
+
"index": {
|
|
585
|
+
"classOrder": 5,
|
|
586
|
+
"termType": "NamedNode",
|
|
587
|
+
"value": "https://club.example.com/settings/private-type-index.ttl",
|
|
588
|
+
},
|
|
589
|
+
"label": "private",
|
|
590
|
+
},
|
|
591
|
+
},
|
|
592
|
+
]
|
|
593
|
+
|
|
594
|
+
describe('getScopedAppInstances', () => {
|
|
595
|
+
it('exists', () => {
|
|
596
|
+
expect(getScopedAppInstances).toBeInstanceOf(Function)
|
|
597
|
+
})
|
|
598
|
+
it('pulls in users scopes and also community ones', async () => {
|
|
599
|
+
const result = await getScopedAppInstances(store, Tracker, user)
|
|
600
|
+
expect(result).toEqual(AliceAndClubScopes)
|
|
601
|
+
})
|
|
602
|
+
it('creates new typeIndeex files where they dont exist', async () => {
|
|
603
|
+
const result = await getScopedAppInstances(store, Tracker, Bob)
|
|
604
|
+
|
|
605
|
+
expect(requests[0].method).toEqual('PATCH') // Add link to preferrencesFile
|
|
606
|
+
expect(requests[0].url).toEqual('https://bob.example.com/profile/card.ttl')
|
|
607
|
+
|
|
608
|
+
expect(requests[1].method).toEqual('PUT') // Link to pub typ ind
|
|
609
|
+
expect(requests[1].url).toEqual('https://bob.example.com/profile/publicTypeIndex.ttl')
|
|
610
|
+
|
|
611
|
+
expect(requests[2].method).toEqual('PATCH') // Add link to preferrencesFile
|
|
612
|
+
expect(requests[2].url).toEqual('https://bob.example.com/profile/card.ttl')
|
|
613
|
+
|
|
614
|
+
expect(requests[3].method).toEqual('PATCH')
|
|
615
|
+
expect(requests[3].url).toEqual('https://bob.example.com/Settings/Preferences.ttl')
|
|
616
|
+
|
|
617
|
+
expect(requests[4].method).toEqual('PUT')
|
|
618
|
+
expect(requests[4].url).toEqual('https://bob.example.com/Settings/privateTypeIndex.ttl')
|
|
619
|
+
|
|
620
|
+
expect(requests.length).toEqual(5)
|
|
621
|
+
|
|
622
|
+
})
|
|
623
|
+
})
|
|
624
|
+
|
|
625
|
+
const TRACKERS =
|
|
626
|
+
[
|
|
627
|
+
{
|
|
628
|
+
"classOrder": 5,
|
|
629
|
+
"termType": "NamedNode",
|
|
630
|
+
"value": "https://alice.example.com/publicStuff/actionItems.ttl#this",
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
"classOrder": 5,
|
|
634
|
+
"termType": "NamedNode",
|
|
635
|
+
"value": "https://alice.example.com/project4/issues.ttl#this",
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
"classOrder": 5,
|
|
639
|
+
"termType": "NamedNode",
|
|
640
|
+
"value": "https://alice.example.com/privateStuff/ToDo.ttl#this",
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
"classOrder": 5,
|
|
644
|
+
"termType": "NamedNode",
|
|
645
|
+
"value": "https://alice.example.com/privateStuff/Goals.ttl#this",
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
"classOrder": 5,
|
|
649
|
+
"termType": "NamedNode",
|
|
650
|
+
"value": "https://alice.example.com/privateStuff/workingOn.ttl#this",
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
"classOrder": 5,
|
|
654
|
+
"termType": "NamedNode",
|
|
655
|
+
"value": "https://club.example.com/publicStuff/actionItems.ttl#this",
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
"classOrder": 5,
|
|
659
|
+
"termType": "NamedNode",
|
|
660
|
+
"value": "https://club.example.com/project4/clubIssues.ttl#this",
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
"classOrder": 5,
|
|
664
|
+
"termType": "NamedNode",
|
|
665
|
+
"value": "https://club.example.com/privateStuff/ToDo.ttl#this",
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
"classOrder": 5,
|
|
669
|
+
"termType": "NamedNode",
|
|
670
|
+
"value": "https://club.example.com/privateStuff/Goals.ttl#this",
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
"classOrder": 5,
|
|
674
|
+
"termType": "NamedNode",
|
|
675
|
+
"value": "https://club.example.com/privateStuff/tasks.ttl#this",
|
|
676
|
+
},
|
|
677
|
+
]
|
|
678
|
+
|
|
679
|
+
describe('getAppInstances', () => {
|
|
680
|
+
it('exists', () => {
|
|
681
|
+
expect(getAppInstances).toBeInstanceOf(Function)
|
|
682
|
+
})
|
|
683
|
+
it('finds trackers', async () => {
|
|
684
|
+
const result = await getAppInstances(store, Tracker)
|
|
685
|
+
expect(result).toEqual(TRACKERS)
|
|
686
|
+
expect(result).toEqual(uniqueNodes(result)) // shoud have no dups
|
|
687
|
+
})
|
|
688
|
+
it('finds images in containers', async () => {
|
|
689
|
+
const result = await getAppInstances(store, Image)
|
|
690
|
+
expect(result.length).toEqual(3)
|
|
691
|
+
expect(result).toEqual(uniqueNodes(result)) // shoud have no dups
|
|
692
|
+
expect(result.map(x => x.uri).join()).toEqual("https://alice.example.com/profile/Photos/photo1.png,https://alice.example.com/profile/Photos/photo2.png,https://alice.example.com/profile/Photos/photo3.png")
|
|
693
|
+
})
|
|
694
|
+
})
|
|
695
|
+
|
|
696
|
+
describe('registerInstanceInTypeIndex', () => {
|
|
697
|
+
it('exists', () => {
|
|
698
|
+
expect(registerInstanceInTypeIndex).toBeInstanceOf(Function)
|
|
699
|
+
})
|
|
700
|
+
it('adds a registration', async () => {
|
|
701
|
+
const instance = sym(Alice.doc().uri + 'trackers/myToDo.ttl#this')
|
|
702
|
+
const index = AlicePublicTypeIndex
|
|
703
|
+
const result = await registerInstanceInTypeIndex(store, instance, index, klass)
|
|
704
|
+
expect(result.doc()).toEqual(index)
|
|
705
|
+
expect(store.any(result, ns.solid('forClass'), null, index)).toEqual(klass)
|
|
706
|
+
expect(store.any(result, ns.solid('instance'), null, index)).toEqual(instance)
|
|
707
|
+
expect(store.holds(result, ns.rdf('type'), ns.solid('TypeRegistration'), index)).toEqual(true)
|
|
708
|
+
expect(requests[0].url).toEqual(index.uri)
|
|
709
|
+
})
|
|
710
|
+
})
|
|
711
|
+
|
|
712
|
+
})
|