mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Use notification v0.2 features in discovery
This commit is contained in:
parent
23db528472
commit
10980e90a3
@ -9,7 +9,6 @@
|
|||||||
"comment": "Handles the storage description triples used for discovery of a WebHookSubscription2021 endpoint.",
|
"comment": "Handles the storage description triples used for discovery of a WebHookSubscription2021 endpoint.",
|
||||||
"@type": "WebHookDescriber",
|
"@type": "WebHookDescriber",
|
||||||
"route": { "@id": "urn:solid-server:default:WebHookRoute" },
|
"route": { "@id": "urn:solid-server:default:WebHookRoute" },
|
||||||
"relative": "#webhookNotification",
|
|
||||||
"webIdRoute": { "@id": "urn:solid-server:default:WebHookWebIdRoute" }
|
"webIdRoute": { "@id": "urn:solid-server:default:WebHookWebIdRoute" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"comment": "Handles the storage description triples used for discovery of a WebSocketSubscription2021 endpoint.",
|
"comment": "Handles the storage description triples used for discovery of a WebSocketSubscription2021 endpoint.",
|
||||||
"@type": "NotificationDescriber",
|
"@type": "NotificationDescriber",
|
||||||
"route": { "@id": "urn:solid-server:default:WebSocket2021Route" },
|
"route": { "@id": "urn:solid-server:default:WebSocket2021Route" },
|
||||||
"relative": "#websocketNotification",
|
|
||||||
"type": "http://www.w3.org/ns/solid/notifications#WebSocketSubscription2021"
|
"type": "http://www.w3.org/ns/solid/notifications#WebSocketSubscription2021"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2,52 +2,48 @@ import type { NamedNode, Quad } from '@rdfjs/types';
|
|||||||
import { DataFactory } from 'n3';
|
import { DataFactory } from 'n3';
|
||||||
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier';
|
||||||
import type { InteractionRoute } from '../../identity/interaction/routing/InteractionRoute';
|
import type { InteractionRoute } from '../../identity/interaction/routing/InteractionRoute';
|
||||||
import { NOTIFY, RDF } from '../../util/Vocabularies';
|
import { NOTIFY } from '../../util/Vocabularies';
|
||||||
import { StorageDescriber } from '../description/StorageDescriber';
|
import { StorageDescriber } from '../description/StorageDescriber';
|
||||||
const { namedNode, quad } = DataFactory;
|
const { namedNode, quad } = DataFactory;
|
||||||
|
|
||||||
export const DEFAULT_NOTIFICATION_FEATURES = [
|
export const DEFAULT_NOTIFICATION_FEATURES = [
|
||||||
NOTIFY.accept,
|
NOTIFY.accept,
|
||||||
NOTIFY.expiration,
|
NOTIFY.endAt,
|
||||||
NOTIFY.rate,
|
NOTIFY.rate,
|
||||||
|
NOTIFY.startAt,
|
||||||
NOTIFY.state,
|
NOTIFY.state,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outputs quads describing how to access a specific Notification Subscription type and its features,
|
* Outputs quads describing a Notification Subscription Service,
|
||||||
* as described in https://solidproject.org/TR/notifications-protocol#discovery.
|
* as described in https://solidproject.org/TR/2022/notifications-protocol-20221231#discovery and
|
||||||
|
* https://solidproject.org/TR/2022/notifications-protocol-20221231#description-resource-data-model.
|
||||||
*/
|
*/
|
||||||
export class NotificationDescriber extends StorageDescriber {
|
export class NotificationDescriber extends StorageDescriber {
|
||||||
private readonly path: NamedNode;
|
private readonly path: NamedNode;
|
||||||
private readonly relative: string;
|
|
||||||
private readonly type: NamedNode;
|
private readonly type: NamedNode;
|
||||||
private readonly features: NamedNode[];
|
private readonly features: NamedNode[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param route - The route describing where the subscription target is.
|
* @param route - The route describing where the subscription target is.
|
||||||
* @param relative - Will be appended to the input path to generate a named node corresponding to the description.
|
|
||||||
* E.g., "#websocketNotification".
|
|
||||||
* @param type - The rdf:type of the subscription type.
|
* @param type - The rdf:type of the subscription type.
|
||||||
* @param features - Which features are enabled for this subscription type. Defaults to accept/expiration/rate/state.
|
* @param features - Which features are enabled for this subscription type. Defaults to accept/expiration/rate/state.
|
||||||
*/
|
*/
|
||||||
public constructor(route: InteractionRoute, relative: string, type: string,
|
public constructor(route: InteractionRoute, type: string,
|
||||||
features: string[] = DEFAULT_NOTIFICATION_FEATURES) {
|
features: string[] = DEFAULT_NOTIFICATION_FEATURES) {
|
||||||
super();
|
super();
|
||||||
this.path = namedNode(route.getPath());
|
this.path = namedNode(route.getPath());
|
||||||
this.relative = relative;
|
|
||||||
this.type = namedNode(type);
|
this.type = namedNode(type);
|
||||||
this.features = features.map(namedNode);
|
this.features = features.map(namedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async handle(input: ResourceIdentifier): Promise<Quad[]> {
|
public async handle(input: ResourceIdentifier): Promise<Quad[]> {
|
||||||
const subject = namedNode(input.path);
|
const subject = namedNode(input.path);
|
||||||
const subscription = namedNode(`${input.path}${this.relative}`);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
quad(subject, NOTIFY.terms.notificationChannel, subscription),
|
quad(subject, NOTIFY.terms.subscription, this.path),
|
||||||
quad(subscription, RDF.terms.type, this.type),
|
quad(this.path, NOTIFY.terms.channelType, this.type),
|
||||||
quad(subscription, NOTIFY.terms.subscription, this.path),
|
...this.features.map((feature): Quad => quad(this.path, NOTIFY.terms.feature, feature)),
|
||||||
...this.features.map((feature): Quad => quad(subscription, NOTIFY.terms.feature, feature)),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,18 @@ import { DataFactory } from 'n3';
|
|||||||
import type { Quad } from 'rdf-js';
|
import type { Quad } from 'rdf-js';
|
||||||
import type { ResourceIdentifier } from '../../../http/representation/ResourceIdentifier';
|
import type { ResourceIdentifier } from '../../../http/representation/ResourceIdentifier';
|
||||||
import type { InteractionRoute } from '../../../identity/interaction/routing/InteractionRoute';
|
import type { InteractionRoute } from '../../../identity/interaction/routing/InteractionRoute';
|
||||||
import { NOTIFY, RDF } from '../../../util/Vocabularies';
|
import { NOTIFY } from '../../../util/Vocabularies';
|
||||||
import { DEFAULT_NOTIFICATION_FEATURES, NotificationDescriber } from '../NotificationDescriber';
|
import { DEFAULT_NOTIFICATION_FEATURES, NotificationDescriber } from '../NotificationDescriber';
|
||||||
const { namedNode, quad } = DataFactory;
|
const { namedNode, quad } = DataFactory;
|
||||||
|
|
||||||
export interface WebHookStorageDescriberArgs {
|
export interface WebHookStorageDescriberArgs {
|
||||||
route: InteractionRoute;
|
route: InteractionRoute;
|
||||||
relative: string;
|
|
||||||
webIdRoute: InteractionRoute;
|
webIdRoute: InteractionRoute;
|
||||||
features?: string[];
|
features?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the necessary triples for describing a WebHookSubcription2021 notification channel.
|
* Handles the necessary triples for describing a WebHookSubscription2021 subscription service.
|
||||||
*
|
*
|
||||||
* Extends {@link NotificationDescriber} by adding the necessary `notify:webid` and `notify:webhookAuth` triples.
|
* Extends {@link NotificationDescriber} by adding the necessary `notify:webid` and `notify:webhookAuth` triples.
|
||||||
*/
|
*/
|
||||||
@ -25,7 +24,7 @@ export class WebHookDescriber extends NotificationDescriber {
|
|||||||
public constructor(args: WebHookStorageDescriberArgs) {
|
public constructor(args: WebHookStorageDescriberArgs) {
|
||||||
const features = args.features ?? [ ...DEFAULT_NOTIFICATION_FEATURES ];
|
const features = args.features ?? [ ...DEFAULT_NOTIFICATION_FEATURES ];
|
||||||
features.push(NOTIFY.webhookAuth);
|
features.push(NOTIFY.webhookAuth);
|
||||||
super(args.route, args.relative, NOTIFY.WebHookSubscription2021, features);
|
super(args.route, NOTIFY.WebHookSubscription2021, features);
|
||||||
|
|
||||||
this.webId = namedNode(args.webIdRoute.getPath());
|
this.webId = namedNode(args.webIdRoute.getPath());
|
||||||
}
|
}
|
||||||
@ -34,7 +33,7 @@ export class WebHookDescriber extends NotificationDescriber {
|
|||||||
const quads = await super.handle(input);
|
const quads = await super.handle(input);
|
||||||
|
|
||||||
// Find the notification channel subject
|
// Find the notification channel subject
|
||||||
const typeQuad = quads.find((entry): boolean => entry.predicate.equals(RDF.terms.type) &&
|
const typeQuad = quads.find((entry): boolean => entry.predicate.equals(NOTIFY.terms.channelType) &&
|
||||||
entry.object.equals(NOTIFY.terms.WebHookSubscription2021));
|
entry.object.equals(NOTIFY.terms.WebHookSubscription2021));
|
||||||
quads.push(quad(typeQuad!.subject, NOTIFY.terms.webid, this.webId));
|
quads.push(quad(typeQuad!.subject, NOTIFY.terms.webid, this.webId));
|
||||||
|
|
||||||
|
@ -193,10 +193,11 @@ export const MA = createVocabulary('http://www.w3.org/ns/ma-ont#',
|
|||||||
|
|
||||||
export const NOTIFY = createVocabulary('http://www.w3.org/ns/solid/notifications#',
|
export const NOTIFY = createVocabulary('http://www.w3.org/ns/solid/notifications#',
|
||||||
'accept',
|
'accept',
|
||||||
'expiration',
|
'channelType',
|
||||||
|
'endAt',
|
||||||
'feature',
|
'feature',
|
||||||
'notificationChannel',
|
|
||||||
'rate',
|
'rate',
|
||||||
|
'startAt',
|
||||||
'state',
|
'state',
|
||||||
'subscription',
|
'subscription',
|
||||||
'webhookAuth',
|
'webhookAuth',
|
||||||
|
@ -1,21 +1,58 @@
|
|||||||
{
|
{
|
||||||
"@context": {
|
"@context": {
|
||||||
|
"@version": 1.1,
|
||||||
|
"@protected": true,
|
||||||
"id": "@id",
|
"id": "@id",
|
||||||
"type": "@type",
|
"type": "@type",
|
||||||
"notify": "http://www.w3.org/ns/solid/notifications#",
|
"notify": "http://www.w3.org/ns/solid/notifications#",
|
||||||
"WebSocketSubscription2021": "notify:WebSocketSubscription2021",
|
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
||||||
"features": {
|
|
||||||
"@id": "notify:features",
|
"accept": "notify:accept",
|
||||||
"@type": "@id"
|
|
||||||
},
|
"channel": {
|
||||||
"notificationChannel": {
|
"@id": "notify:channel",
|
||||||
"@id": "notify:notificationChannel",
|
"@type": "@id" },
|
||||||
"@type": "@id"
|
|
||||||
},
|
"channelType": {
|
||||||
|
"@id": "notify:channelType",
|
||||||
|
"@type": "@vocab" },
|
||||||
|
|
||||||
|
"endAt": {
|
||||||
|
"@id": "notify:endAt",
|
||||||
|
"@type": "xsd:dateTime" },
|
||||||
|
|
||||||
|
"feature": {
|
||||||
|
"@id": "notify:feature",
|
||||||
|
"@type": "@vocab" },
|
||||||
|
|
||||||
|
"rate": {
|
||||||
|
"@id": "notify:rate",
|
||||||
|
"@type": "xsd:duration" },
|
||||||
|
|
||||||
|
"receiveFrom": {
|
||||||
|
"@id": "notify:receiveFrom",
|
||||||
|
"@type": "@id" },
|
||||||
|
|
||||||
|
"sender": {
|
||||||
|
"@id": "notify:sender",
|
||||||
|
"@type": "@id" },
|
||||||
|
|
||||||
|
"sendTo": {
|
||||||
|
"@id": "notify:sendTo",
|
||||||
|
"@type": "@id" },
|
||||||
|
|
||||||
"state": "notify:state",
|
"state": "notify:state",
|
||||||
|
|
||||||
|
"startAt": {
|
||||||
|
"@id": "notify:startAt",
|
||||||
|
"@type": "xsd:dateTime" },
|
||||||
|
|
||||||
"subscription": {
|
"subscription": {
|
||||||
"@id": "notify:subscription",
|
"@id": "notify:subscription",
|
||||||
"@type": "@id"
|
"@type": "@id" },
|
||||||
}
|
|
||||||
|
"topic": {
|
||||||
|
"@id": "notify:topic",
|
||||||
|
"@type": "@id" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import type { App } from '../../src/init/App';
|
|||||||
import { matchesAuthorizationScheme } from '../../src/util/HeaderUtil';
|
import { matchesAuthorizationScheme } from '../../src/util/HeaderUtil';
|
||||||
import { joinUrl, trimTrailingSlashes } from '../../src/util/PathUtil';
|
import { joinUrl, trimTrailingSlashes } from '../../src/util/PathUtil';
|
||||||
import { readJsonStream } from '../../src/util/StreamUtil';
|
import { readJsonStream } from '../../src/util/StreamUtil';
|
||||||
import { NOTIFY, RDF } from '../../src/util/Vocabularies';
|
import { NOTIFY } from '../../src/util/Vocabularies';
|
||||||
import { expectNotification, subscribe } from '../util/NotificationUtil';
|
import { expectNotification, subscribe } from '../util/NotificationUtil';
|
||||||
import { getPort } from '../util/Util';
|
import { getPort } from '../util/Util';
|
||||||
import {
|
import {
|
||||||
@ -95,17 +95,15 @@ describe.each(stores)('A server supporting WebHookSubscription2021 using %s', (n
|
|||||||
const quads = new Store(new Parser().parse(await response.text()));
|
const quads = new Store(new Parser().parse(await response.text()));
|
||||||
|
|
||||||
// Find the notification channel for websockets
|
// Find the notification channel for websockets
|
||||||
const channels = quads.getObjects(storageDescriptionUrl, NOTIFY.terms.notificationChannel, null);
|
const subscriptions = quads.getObjects(storageDescriptionUrl, NOTIFY.terms.subscription, null);
|
||||||
const webHookChannels = channels.filter((channel): boolean => quads.has(
|
const webhookSubscriptions = subscriptions.filter((channel): boolean => quads.has(
|
||||||
quad(channel as NamedNode, RDF.terms.type, namedNode(`${NOTIFY.namespace}WebHookSubscription2021`)),
|
quad(channel as NamedNode, NOTIFY.terms.channelType, namedNode(`${NOTIFY.namespace}WebHookSubscription2021`)),
|
||||||
));
|
));
|
||||||
expect(webHookChannels).toHaveLength(1);
|
expect(webhookSubscriptions).toHaveLength(1);
|
||||||
const subscriptionUrls = quads.getObjects(webHookChannels[0], NOTIFY.terms.subscription, null);
|
subscriptionUrl = webhookSubscriptions[0].value;
|
||||||
expect(subscriptionUrls).toHaveLength(1);
|
|
||||||
subscriptionUrl = subscriptionUrls[0].value;
|
|
||||||
|
|
||||||
// It should also link to the server WebID
|
// It should also link to the server WebID
|
||||||
const webIds = quads.getObjects(webHookChannels[0], NOTIFY.terms.webid, null);
|
const webIds = quads.getObjects(webhookSubscriptions[0], NOTIFY.terms.webid, null);
|
||||||
expect(webIds).toHaveLength(1);
|
expect(webIds).toHaveLength(1);
|
||||||
serverWebId = webIds[0].value;
|
serverWebId = webIds[0].value;
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,7 @@ import { BasicRepresentation } from '../../src/http/representation/BasicRepresen
|
|||||||
import type { App } from '../../src/init/App';
|
import type { App } from '../../src/init/App';
|
||||||
import type { ResourceStore } from '../../src/storage/ResourceStore';
|
import type { ResourceStore } from '../../src/storage/ResourceStore';
|
||||||
import { joinUrl } from '../../src/util/PathUtil';
|
import { joinUrl } from '../../src/util/PathUtil';
|
||||||
import { NOTIFY, RDF } from '../../src/util/Vocabularies';
|
import { NOTIFY } from '../../src/util/Vocabularies';
|
||||||
import { expectNotification, subscribe } from '../util/NotificationUtil';
|
import { expectNotification, subscribe } from '../util/NotificationUtil';
|
||||||
import { getPort } from '../util/Util';
|
import { getPort } from '../util/Util';
|
||||||
import {
|
import {
|
||||||
@ -86,14 +86,12 @@ describe.each(stores)('A server supporting WebSocketSubscription2021 using %s',
|
|||||||
const quads = new Store(new Parser().parse(await response.text()));
|
const quads = new Store(new Parser().parse(await response.text()));
|
||||||
|
|
||||||
// Find the notification channel for websockets
|
// Find the notification channel for websockets
|
||||||
const channels = quads.getObjects(storageDescriptionUrl, NOTIFY.terms.notificationChannel, null);
|
const subscriptions = quads.getObjects(storageDescriptionUrl, NOTIFY.terms.subscription, null);
|
||||||
const websocketChannels = channels.filter((channel): boolean => quads.has(
|
const websocketSubscriptions = subscriptions.filter((channel): boolean => quads.has(
|
||||||
quad(channel as NamedNode, RDF.terms.type, namedNode(`${NOTIFY.namespace}WebSocketSubscription2021`)),
|
quad(channel as NamedNode, NOTIFY.terms.channelType, namedNode(`${NOTIFY.namespace}WebSocketSubscription2021`)),
|
||||||
));
|
));
|
||||||
expect(websocketChannels).toHaveLength(1);
|
expect(websocketSubscriptions).toHaveLength(1);
|
||||||
const subscriptionUrls = quads.getObjects(websocketChannels[0], NOTIFY.terms.subscription, null);
|
subscriptionUrl = websocketSubscriptions[0].value;
|
||||||
expect(subscriptionUrls).toHaveLength(1);
|
|
||||||
subscriptionUrl = subscriptionUrls[0].value;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports subscribing.', async(): Promise<void> => {
|
it('supports subscribing.', async(): Promise<void> => {
|
||||||
|
@ -5,29 +5,28 @@ import {
|
|||||||
AbsolutePathInteractionRoute,
|
AbsolutePathInteractionRoute,
|
||||||
} from '../../../../src/identity/interaction/routing/AbsolutePathInteractionRoute';
|
} from '../../../../src/identity/interaction/routing/AbsolutePathInteractionRoute';
|
||||||
import { NotificationDescriber } from '../../../../src/server/notifications/NotificationDescriber';
|
import { NotificationDescriber } from '../../../../src/server/notifications/NotificationDescriber';
|
||||||
import { NOTIFY, RDF } from '../../../../src/util/Vocabularies';
|
import { NOTIFY } from '../../../../src/util/Vocabularies';
|
||||||
const { namedNode, quad } = DataFactory;
|
const { namedNode, quad } = DataFactory;
|
||||||
|
|
||||||
describe('A NotificationDescriber', (): void => {
|
describe('A NotificationDescriber', (): void => {
|
||||||
const identifier: ResourceIdentifier = { path: 'http://example.com/foo' };
|
const identifier: ResourceIdentifier = { path: 'http://example.com/foo' };
|
||||||
const route = new AbsolutePathInteractionRoute('http://example.com/.notifications/websockets/');
|
const route = new AbsolutePathInteractionRoute('http://example.com/.notifications/websockets/');
|
||||||
const relative = '#websocketNotification';
|
|
||||||
const type = 'http://www.w3.org/ns/solid/notifications#WebSocketSubscription2021';
|
const type = 'http://www.w3.org/ns/solid/notifications#WebSocketSubscription2021';
|
||||||
let describer: NotificationDescriber;
|
let describer: NotificationDescriber;
|
||||||
|
|
||||||
beforeEach(async(): Promise<void> => {
|
beforeEach(async(): Promise<void> => {
|
||||||
describer = new NotificationDescriber(route, relative, type);
|
describer = new NotificationDescriber(route, type);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('outputs the expected quads.', async(): Promise<void> => {
|
it('outputs the expected quads.', async(): Promise<void> => {
|
||||||
const subscription = namedNode('http://example.com/foo#websocketNotification');
|
const subscription = namedNode('http://example.com/.notifications/websockets/');
|
||||||
const quads = await describer.handle(identifier);
|
const quads = await describer.handle(identifier);
|
||||||
expect(quads).toBeRdfIsomorphic([
|
expect(quads).toBeRdfIsomorphic([
|
||||||
quad(namedNode(identifier.path), NOTIFY.terms.notificationChannel, subscription),
|
quad(namedNode(identifier.path), NOTIFY.terms.subscription, subscription),
|
||||||
quad(subscription, RDF.terms.type, namedNode(type)),
|
quad(subscription, NOTIFY.terms.channelType, namedNode(type)),
|
||||||
quad(subscription, NOTIFY.terms.subscription, namedNode('http://example.com/.notifications/websockets/')),
|
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.accept),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.accept),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.expiration),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.endAt),
|
||||||
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.startAt),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.rate),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.rate),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.state),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.state),
|
||||||
]);
|
]);
|
||||||
|
@ -5,30 +5,29 @@ import {
|
|||||||
AbsolutePathInteractionRoute,
|
AbsolutePathInteractionRoute,
|
||||||
} from '../../../../../src/identity/interaction/routing/AbsolutePathInteractionRoute';
|
} from '../../../../../src/identity/interaction/routing/AbsolutePathInteractionRoute';
|
||||||
import { WebHookDescriber } from '../../../../../src/server/notifications/WebHookSubscription2021/WebHookDescriber';
|
import { WebHookDescriber } from '../../../../../src/server/notifications/WebHookSubscription2021/WebHookDescriber';
|
||||||
import { NOTIFY, RDF } from '../../../../../src/util/Vocabularies';
|
import { NOTIFY } from '../../../../../src/util/Vocabularies';
|
||||||
const { namedNode, quad } = DataFactory;
|
const { namedNode, quad } = DataFactory;
|
||||||
|
|
||||||
describe('A WebHookDescriber', (): void => {
|
describe('A WebHookDescriber', (): void => {
|
||||||
const identifier: ResourceIdentifier = { path: 'http://example.com/foo' };
|
const identifier: ResourceIdentifier = { path: 'http://example.com/foo' };
|
||||||
const route = new AbsolutePathInteractionRoute('http://example.com/.notifications/webhooks/');
|
const route = new AbsolutePathInteractionRoute('http://example.com/.notifications/webhooks/');
|
||||||
const webIdRoute = new AbsolutePathInteractionRoute('http://example.com/.notifications/webhooks/webId');
|
const webIdRoute = new AbsolutePathInteractionRoute('http://example.com/.notifications/webhooks/webId');
|
||||||
const relative = '#webhookNotification';
|
|
||||||
const type = 'http://www.w3.org/ns/solid/notifications#WebHookSubscription2021';
|
const type = 'http://www.w3.org/ns/solid/notifications#WebHookSubscription2021';
|
||||||
let describer: WebHookDescriber;
|
let describer: WebHookDescriber;
|
||||||
|
|
||||||
beforeEach(async(): Promise<void> => {
|
beforeEach(async(): Promise<void> => {
|
||||||
describer = new WebHookDescriber({ route, webIdRoute, relative });
|
describer = new WebHookDescriber({ route, webIdRoute });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('outputs the expected quads.', async(): Promise<void> => {
|
it('outputs the expected quads.', async(): Promise<void> => {
|
||||||
const subscription = namedNode('http://example.com/foo#webhookNotification');
|
const subscription = namedNode('http://example.com/.notifications/webhooks/');
|
||||||
const quads = await describer.handle(identifier);
|
const quads = await describer.handle(identifier);
|
||||||
expect(quads).toBeRdfIsomorphic([
|
expect(quads).toBeRdfIsomorphic([
|
||||||
quad(namedNode(identifier.path), NOTIFY.terms.notificationChannel, subscription),
|
quad(namedNode(identifier.path), NOTIFY.terms.subscription, subscription),
|
||||||
quad(subscription, RDF.terms.type, namedNode(type)),
|
quad(subscription, NOTIFY.terms.channelType, namedNode(type)),
|
||||||
quad(subscription, NOTIFY.terms.subscription, namedNode('http://example.com/.notifications/webhooks/')),
|
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.accept),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.accept),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.expiration),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.endAt),
|
||||||
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.startAt),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.rate),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.rate),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.state),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.state),
|
||||||
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.webhookAuth),
|
quad(subscription, NOTIFY.terms.feature, NOTIFY.terms.webhookAuth),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user