UNPKG

@inrupt/solid-client

Version:

Make your web apps work with Solid Pods.

1,427 lines (1,307 loc) • 54.7 kB
// Copyright Inrupt Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the // Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // import { describe, it, expect } from "@jest/globals"; import type { NamedNode } from "@rdfjs/types"; import { DataFactory } from "n3"; import { createThing, getThing, getThingAll, setThing } from "../thing/thing"; import type { Matcher } from "./matcher"; import { addAgent, addNoneOfMatcherUrl, addAnyOfMatcherUrl, addAllOfMatcherUrl, createMatcher, getAgentAll, getNoneOfMatcherUrlAll, getAnyOfMatcherUrlAll, getAllOfMatcherUrlAll, removeNoneOfMatcherUrl, removeAnyOfMatcherUrl, removeAllOfMatcherUrl, getMatcher, hasAuthenticated, hasPublic, removeAgent, setAgent, setAuthenticated, setNoneOfMatcherUrl, setAnyOfMatcherUrl, setPublic, setAllOfMatcherUrl, getMatcherAll, setMatcher, hasCreator, setCreator, matcherAsMarkdown, removeMatcher, getClientAll, addClient, removeClient, hasAnyClient, setAnyClient, removePublic, removeAuthenticated, removeCreator, removeAnyClient, getResourceMatcher, getResourceMatcherAll, removeResourceMatcher, setResourceMatcher, createResourceMatcherFor, setClient, } from "./matcher"; import type { Policy } from "./policy"; import { createSolidDataset } from "../resource/solidDataset"; import { setUrl } from "../thing/set"; import type { Thing, ThingPersisted, Url } from "../interfaces"; import { acp, rdf } from "../constants"; import { getIri, getIriAll, getSourceUrl, mockSolidDatasetFrom, } from "../index"; import { addMockAcrTo, mockAcrFor } from "./mock"; import { internal_getAcr } from "./control.internal"; import { addStringNoLocale, addUrl } from "../thing/add"; import { getStringNoLocaleAll, getUrl, getUrlAll } from "../thing/get"; import { internal_isValidUrl } from "../datatypes"; // Vocabulary terms const ACP_ANY = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#anyOf"); const ACP_ALL = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#allOf"); const ACP_NONE = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#noneOf"); const RDF_TYPE = DataFactory.namedNode( "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", ); const ACP_MATCHER = DataFactory.namedNode( "http://www.w3.org/ns/solid/acp#Matcher", ); const ACP_AGENT = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#agent"); const ACP_CLIENT = DataFactory.namedNode( "http://www.w3.org/ns/solid/acp#client", ); const ACP_PUBLIC = DataFactory.namedNode( "http://www.w3.org/ns/solid/acp#PublicAgent", ); const ACP_AUTHENTICATED = DataFactory.namedNode( "http://www.w3.org/ns/solid/acp#AuthenticatedAgent", ); const ACP_CREATOR = DataFactory.namedNode( "http://www.w3.org/ns/solid/acp#CreatorAgent", ); const SOLID_PUBLIC_CLIENT = DataFactory.namedNode( "http://www.w3.org/ns/solid/terms#PublicOidcClient", ); // Test data const MOCKED_POLICY_IRI = DataFactory.namedNode( "https://some.pod/policy-resource#policy", ); const MOCKED_MATCHER_IRI = DataFactory.namedNode( "https://some.pod/matcher-resource#a-matcher", ); const OTHER_MOCKED_MATCHER_IRI = DataFactory.namedNode( "https://some.pod/matcher-resource#another-matcher", ); const ALLOF_MATCHER_IRI = DataFactory.namedNode( "https://some.pod/matcher-resource#allOf-matcher", ); const ANYOF_MATCHER_IRI = DataFactory.namedNode( "https://some.pod/matcher-resource#anyOf-matcher", ); const NONEOF_MATCHER_IRI = DataFactory.namedNode( "https://some.pod/matcher-resource#noneOf-matcher", ); const MOCK_WEBID_ME = DataFactory.namedNode("https://my.pod/profile#me"); const MOCK_WEBID_YOU = DataFactory.namedNode("https://your.pod/profile#you"); const MOCK_CLIENT_IDENTIFIER_1 = DataFactory.namedNode( "https://my.app/registration#it", ); const MOCK_CLIENT_IDENTIFIER_2 = DataFactory.namedNode( "https://your.app/registration#it", ); const MOCK_CLIENT_ID_3 = "test_string_client_id"; const MOCK_CLIENT_ID_4 = "other_string_client_id"; const addAllObjects = ( thing: ThingPersisted, predicate: NamedNode, objects: (Url | string)[], ): ThingPersisted => { return objects.reduce((thingAcc, object) => { return internal_isValidUrl(object) ? addUrl(thingAcc, predicate, object) : addStringNoLocale(thingAcc, predicate, object.toString()); }, thing); }; const addAllThingObjects = ( thing: ThingPersisted, predicate: NamedNode, objects: Thing[], ): ThingPersisted => { return objects.reduce((thingAcc, object) => { return addUrl(thingAcc, predicate, object); }, thing); }; const mockMatcher = ( url: Url, content?: { agents?: Url[]; public?: boolean; authenticated?: boolean; creator?: boolean; clients?: (Url | string)[]; publicClient?: boolean; }, ): Matcher => { let mockedMatcher = createThing({ url: url.value, }); mockedMatcher = addUrl(mockedMatcher, RDF_TYPE, ACP_MATCHER); if (content?.agents) { mockedMatcher = addAllObjects(mockedMatcher, ACP_AGENT, content.agents); } if (content?.clients) { mockedMatcher = addAllObjects(mockedMatcher, ACP_CLIENT, content.clients); } if (content?.public) { mockedMatcher = addUrl(mockedMatcher, ACP_AGENT, ACP_PUBLIC); } if (content?.authenticated) { mockedMatcher = addUrl(mockedMatcher, ACP_AGENT, ACP_AUTHENTICATED); } if (content?.creator) { mockedMatcher = addUrl(mockedMatcher, ACP_AGENT, ACP_CREATOR); } if (content?.publicClient) { mockedMatcher = addUrl(mockedMatcher, ACP_CLIENT, SOLID_PUBLIC_CLIENT); } return mockedMatcher; }; const mockPolicy = ( url: NamedNode, matchers?: { allOf?: Matcher[]; anyOf?: Matcher[]; noneOf?: Matcher[] }, ): Policy => { let mockedPolicy = createThing({ url: url.value }); if (matchers?.noneOf) { mockedPolicy = addAllThingObjects(mockedPolicy, ACP_NONE, matchers.noneOf); } if (matchers?.anyOf) { mockedPolicy = addAllThingObjects(mockedPolicy, ACP_ANY, matchers.anyOf); } if (matchers?.allOf) { mockedPolicy = addAllThingObjects(mockedPolicy, ACP_ALL, matchers.allOf); } return mockedPolicy; }; describe("addNoneOfMatcherUrl", () => { it("adds the matcher in the noneOf matchers of the policy", () => { const myPolicy = addNoneOfMatcherUrl( mockPolicy(MOCKED_POLICY_IRI), mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(MOCKED_MATCHER_IRI.value); }); it("does not remove the existing noneOf matchers", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(OTHER_MOCKED_MATCHER_IRI)], }); const myPolicy = addNoneOfMatcherUrl( mockedPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_NONE)).toContain( OTHER_MOCKED_MATCHER_IRI.value, ); }); it("does not change the existing allOf and anyOf matchers", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const myPolicy = addNoneOfMatcherUrl( mockedPolicy, mockMatcher(NONEOF_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_MATCHER_IRI.value); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_MATCHER_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = addNoneOfMatcherUrl( myPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("addAnyOfMatcherUrl", () => { it("adds the matcher in the anyOf matchers of the policy", () => { const myPolicy = addAnyOfMatcherUrl( mockPolicy(MOCKED_POLICY_IRI), mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(MOCKED_MATCHER_IRI.value); }); it("does not remove the existing anyOf matchers", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockMatcher(OTHER_MOCKED_MATCHER_IRI)], }); const myPolicy = addAnyOfMatcherUrl( mockedPolicy, mockMatcher(MOCKED_POLICY_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain( OTHER_MOCKED_MATCHER_IRI.value, ); }); it("does not change the existing allOf and noneOf matchers", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const myPolicy = addAnyOfMatcherUrl( mockedPolicy, mockMatcher(ANYOF_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_MATCHER_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_MATCHER_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = addAnyOfMatcherUrl( myPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("addAllOfMatcherUrl", () => { it("adds the matcher in the allOf matchers of the policy", () => { const myPolicy = addAllOfMatcherUrl( mockPolicy(MOCKED_POLICY_IRI), mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(MOCKED_MATCHER_IRI.value); }); it("does not remove the existing allOf matchers", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockMatcher(OTHER_MOCKED_MATCHER_IRI)], }); const myPolicy = addAllOfMatcherUrl( mockedPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain( OTHER_MOCKED_MATCHER_IRI.value, ); }); it("does not change the existing anyOf and noneOf matchers", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], }); const myPolicy = addAllOfMatcherUrl( mockedPolicy, mockMatcher(ANYOF_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_MATCHER_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_MATCHER_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = addAnyOfMatcherUrl( myPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("setNoneOfMatcherUrl", () => { it("sets the provided matchers as the noneOf matchers for the policy", () => { const myPolicy = setNoneOfMatcherUrl( mockPolicy(MOCKED_POLICY_IRI), mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(MOCKED_MATCHER_IRI.value); }); it("removes any previous noneOf matchers for on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(OTHER_MOCKED_MATCHER_IRI)], }); const myPolicy = setNoneOfMatcherUrl( mockedPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_NONE)).not.toContain( OTHER_MOCKED_MATCHER_IRI.value, ); }); it("does not change the existing anyOf and allOf matchers on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const myPolicy = setNoneOfMatcherUrl( mockedPolicy, mockMatcher(NONEOF_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_MATCHER_IRI.value); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_MATCHER_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = setNoneOfMatcherUrl( myPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("setAnyOfMatcherUrl", () => { it("sets the provided matchers as the anyOf matchers for the policy", () => { const myPolicy = setAnyOfMatcherUrl( mockPolicy(MOCKED_POLICY_IRI), mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(MOCKED_MATCHER_IRI.value); }); it("removes any previous anyOf matchers for on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockMatcher(OTHER_MOCKED_MATCHER_IRI)], }); const myPolicy = setAnyOfMatcherUrl( mockedPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).not.toContain( OTHER_MOCKED_MATCHER_IRI.value, ); }); it("does not change the existing noneOf and allOf matchers on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const myPolicy = setAnyOfMatcherUrl( mockedPolicy, mockMatcher(ANYOF_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_MATCHER_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_MATCHER_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = setAnyOfMatcherUrl( myPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("setAllOfMatcherUrl", () => { it("sets the provided matchers as the allOf matchers for the policy", () => { const myPolicy = setAllOfMatcherUrl( mockPolicy(MOCKED_POLICY_IRI), mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(MOCKED_MATCHER_IRI.value); }); it("removes any previous allOf matchers for on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockMatcher(OTHER_MOCKED_MATCHER_IRI)], }); const myPolicy = setAllOfMatcherUrl( mockedPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).not.toContain( OTHER_MOCKED_MATCHER_IRI.value, ); }); it("does not change the existing noneOf and anyOf matchers on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], }); const myPolicy = setAllOfMatcherUrl( mockedPolicy, mockMatcher(ALLOF_MATCHER_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_MATCHER_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_MATCHER_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = setAllOfMatcherUrl( myPolicy, mockMatcher(MOCKED_MATCHER_IRI), ); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("getNoneOfMatcherUrlAll", () => { it("returns all the noneOf matchers for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [ mockMatcher(MOCKED_MATCHER_IRI), mockMatcher(OTHER_MOCKED_MATCHER_IRI), ], }); const noneOfMatchers = getNoneOfMatcherUrlAll(mockedPolicy); expect(noneOfMatchers).toContain(MOCKED_MATCHER_IRI.value); expect(noneOfMatchers).toContain(OTHER_MOCKED_MATCHER_IRI.value); expect(noneOfMatchers).toHaveLength(2); }); it("returns only the noneOf matchers for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const noneOfMatchers = getNoneOfMatcherUrlAll(mockedPolicy); expect(noneOfMatchers).not.toContain(ANYOF_MATCHER_IRI.value); expect(noneOfMatchers).not.toContain(ALLOF_MATCHER_IRI.value); expect(noneOfMatchers).toHaveLength(1); }); }); describe("getAnyOfMatcherUrlAll", () => { it("returns all the anyOf matchers for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [ mockMatcher(MOCKED_MATCHER_IRI), mockMatcher(OTHER_MOCKED_MATCHER_IRI), ], }); const anyOfMatchers = getAnyOfMatcherUrlAll(mockedPolicy); expect(anyOfMatchers).toContain(MOCKED_MATCHER_IRI.value); expect(anyOfMatchers).toContain(OTHER_MOCKED_MATCHER_IRI.value); expect(anyOfMatchers).toHaveLength(2); }); it("returns only the anyOf matchers for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const anyOfMatchers = getAnyOfMatcherUrlAll(mockedPolicy); expect(anyOfMatchers).not.toContain(NONEOF_MATCHER_IRI.value); expect(anyOfMatchers).not.toContain(ALLOF_MATCHER_IRI.value); expect(anyOfMatchers).toHaveLength(1); }); }); describe("getAllOfMatcherUrlAll", () => { it("returns all the allOf matchers for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [ mockMatcher(MOCKED_MATCHER_IRI), mockMatcher(OTHER_MOCKED_MATCHER_IRI), ], }); const allOfMatchers = getAllOfMatcherUrlAll(mockedPolicy); expect(allOfMatchers).toContain(MOCKED_MATCHER_IRI.value); expect(allOfMatchers).toContain(OTHER_MOCKED_MATCHER_IRI.value); expect(allOfMatchers).toHaveLength(2); }); it("returns only the allOf matchers for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockMatcher(NONEOF_MATCHER_IRI)], anyOf: [mockMatcher(ANYOF_MATCHER_IRI)], allOf: [mockMatcher(ALLOF_MATCHER_IRI)], }); const allOfMatchers = getAllOfMatcherUrlAll(mockedPolicy); expect(allOfMatchers).not.toContain(NONEOF_MATCHER_IRI.value); expect(allOfMatchers).not.toContain(ANYOF_MATCHER_IRI.value); expect(allOfMatchers).toHaveLength(1); }); }); describe("removeAllOfMatcherUrl", () => { it("removes the matcher from the allOf matchers for the given policy", () => { const mockedMatcher = mockMatcher(MOCKED_MATCHER_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockedMatcher], }); const result = removeAllOfMatcherUrl(mockedPolicy, mockedMatcher); expect(getUrlAll(result, ACP_ALL)).not.toContain(MOCKED_MATCHER_IRI.value); }); it("does not remove the matcher from the anyOf/noneOf matchers for the given policy", () => { const mockedMatcher = mockMatcher(MOCKED_MATCHER_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockedMatcher], noneOf: [mockedMatcher], }); const result = removeAllOfMatcherUrl(mockedPolicy, mockedMatcher); expect(getUrlAll(result, ACP_ANY)).toContain(MOCKED_MATCHER_IRI.value); expect(getUrlAll(result, ACP_NONE)).toContain(MOCKED_MATCHER_IRI.value); }); }); describe("removeAnyOfMatcherUrl", () => { it("removes the matcher from the allOf matchers for the given policy", () => { const mockedMatcher = mockMatcher(MOCKED_MATCHER_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockedMatcher], }); const result = removeAnyOfMatcherUrl(mockedPolicy, mockedMatcher); expect(getUrlAll(result, ACP_ANY)).not.toContain(MOCKED_MATCHER_IRI.value); }); it("does not remove the matcher from the allOf/noneOf matchers for the given policy", () => { const mockedMatcher = mockMatcher(MOCKED_MATCHER_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockedMatcher], noneOf: [mockedMatcher], }); const result = removeAnyOfMatcherUrl(mockedPolicy, mockedMatcher); expect(getUrlAll(result, ACP_ALL)).toContain(MOCKED_MATCHER_IRI.value); expect(getUrlAll(result, ACP_NONE)).toContain(MOCKED_MATCHER_IRI.value); }); }); describe("removeNoneOfMatcherUrl", () => { it("removes the matcher from the noneOf matchers for the given policy", () => { const mockedMatcher = mockMatcher(MOCKED_MATCHER_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockedMatcher], }); const result = removeNoneOfMatcherUrl(mockedPolicy, mockedMatcher); expect(getUrlAll(result, ACP_NONE)).not.toContain(MOCKED_MATCHER_IRI.value); }); it("does not remove the matcher from the allOf/anyOf matchers for the given policy", () => { const mockedMatcher = mockMatcher(MOCKED_MATCHER_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockedMatcher], anyOf: [mockedMatcher], }); const result = removeNoneOfMatcherUrl(mockedPolicy, mockedMatcher); expect(getUrlAll(result, ACP_ALL)).toContain(MOCKED_MATCHER_IRI.value); expect(getUrlAll(result, ACP_ANY)).toContain(MOCKED_MATCHER_IRI.value); }); }); describe("createMatcher", () => { it("returns a acp:Matcher", () => { const myMatcher = createMatcher(MOCKED_MATCHER_IRI.value); expect(getUrl(myMatcher, RDF_TYPE)).toBe(ACP_MATCHER.value); }); it("returns an **empty** matcher", () => { const myMatcher = createMatcher("https://my.pod/matcher-resource#matcher"); // The matcher should only contain a type triple. expect(Object.keys(myMatcher.predicates)).toHaveLength(1); }); }); describe("createResourceMatcherFor", () => { it("returns a acp:Matcher", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const myMatcher = createResourceMatcherFor( mockedResourceWithAcr, "myMatcher", ); expect(getIri(myMatcher, RDF_TYPE)).toBe(ACP_MATCHER.value); }); it("returns an **empty** matcher", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const myMatcher = createResourceMatcherFor( mockedResourceWithAcr, "myMatcher", ); // The matcher should only contain a type triple. expect(Object.keys(myMatcher.predicates)).toHaveLength(1); }); }); describe("getMatcher", () => { it("returns the matcher with a matching IRI", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const dataset = setThing(createSolidDataset(), matcher); const result = getMatcher(dataset, MOCKED_MATCHER_IRI.value); expect(result).not.toBeNull(); }); it("does not return a Thing with a matching IRI but the wrong type", () => { const notAMatcher = createThing({ url: "https://my.pod/matcher-resource#not-a-matcher", }); const dataset = setThing( createSolidDataset(), setUrl(notAMatcher, RDF_TYPE, "http://example.org/ns#NotMatcherType"), ); const result = getMatcher( dataset, "https://my.pod/matcher-resource#not-a-matcher", ); expect(result).toBeNull(); }); it("does not return a matcher with a mismatching IRI", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const dataset = setThing(createSolidDataset(), matcher); const result = getMatcher(dataset, OTHER_MOCKED_MATCHER_IRI); expect(result).toBeNull(); }); }); describe("getResourceMatcher", () => { it("returns the matcher with a matching name", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceMatcher(mockedResourceWithAcr, "matcher"); expect(result).not.toBeNull(); }); it("does not return a Thing with a matching IRI but the wrong type", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl( mockedMatcher, rdf.type, "http://example.org/ns#NotMatcherType", ); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceMatcher(mockedResourceWithAcr, "matcher"); expect(result).toBeNull(); }); it("does not return a matcher with a mismatching IRI", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceMatcher(mockedResourceWithAcr, "other-matcher"); expect(result).toBeNull(); }); }); describe("getMatcherAll", () => { it("returns an empty array if there are no matchers in the given Dataset", () => { expect(getMatcherAll(createSolidDataset())).toHaveLength(0); }); it("returns all the matchers in a matcher resource", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const dataset = setThing(createSolidDataset(), matcher); let result = getMatcherAll(dataset); expect(result).toHaveLength(1); const anotherMatcher = mockMatcher(OTHER_MOCKED_MATCHER_IRI); const newDataset = setThing(dataset, anotherMatcher); result = getMatcherAll(newDataset); expect(result).toHaveLength(2); }); }); describe("getResourceMatcherAll", () => { it("returns an empty array if there are no matchers in the given Resource's ACR", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); expect(getResourceMatcherAll(mockedResourceWithAcr)).toHaveLength(0); }); it("returns all the matchers in a Resource's ACR", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher1 = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher1`, }); mockedMatcher1 = setUrl(mockedMatcher1, rdf.type, acp.Matcher); let mockedMatcher2 = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher2`, }); mockedMatcher2 = setUrl(mockedMatcher2, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher1); mockedAcr = setThing(mockedAcr, mockedMatcher2); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceMatcherAll(mockedResourceWithAcr); expect(result).toHaveLength(2); }); }); describe("removeMatcher", () => { it("removes the matcher from the given empty Dataset", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const dataset = setThing(createSolidDataset(), matcher); const updatedDataset = removeMatcher(dataset, MOCKED_MATCHER_IRI); expect(getThingAll(updatedDataset)).toHaveLength(0); }); }); describe("removeResourceMatcher", () => { it("removes the matcher from the given Resource's Access control Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceMatcher( mockedResourceWithAcr, mockedMatcher, ); expect(getResourceMatcherAll(updatedDataset)).toHaveLength(0); }); it("accepts a plain name to remove a matcher", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceMatcher( mockedResourceWithAcr, "matcher", ); expect(getResourceMatcherAll(updatedDataset)).toHaveLength(0); }); it("accepts a full URL to remove a matcher", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceMatcher( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#matcher`, ); expect(getResourceMatcherAll(updatedDataset)).toHaveLength(0); }); it("accepts a Named Node to remove a matcher", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceMatcher( mockedResourceWithAcr, DataFactory.namedNode(`${getSourceUrl(mockedAcr)}#matcher`), ); expect(getResourceMatcherAll(updatedDataset)).toHaveLength(0); }); it("does not remove a non-matcher with the same name", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl( mockedMatcher, rdf.type, "https://example.vocab/not-a-matcher", ); mockedAcr = setThing(mockedAcr, mockedMatcher); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceMatcher( mockedResourceWithAcr, "matcher", ); const updatedAcr = internal_getAcr(updatedDataset); expect( getThing(updatedAcr, `${getSourceUrl(mockedAcr)}#matcher`), ).not.toBeNull(); }); }); describe("setMatcher", () => { it("sets the matcher in the given empty Dataset", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const dataset = setMatcher(createSolidDataset(), matcher); const result = getThing(dataset, MOCKED_MATCHER_IRI); expect(result).not.toBeNull(); expect(getIriAll(result as Thing, rdf.type)).toContain(acp.Matcher); }); }); describe("setResourceMatcher", () => { it("sets the matcher in the given Resource's ACR", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); let mockedMatcher = createThing({ url: `${getSourceUrl(mockedAcr)}#matcher`, }); mockedMatcher = setUrl(mockedMatcher, rdf.type, acp.Matcher); const updatedResource = setResourceMatcher( mockedResourceWithAcr, mockedMatcher, ); expect(getResourceMatcherAll(updatedResource)).toHaveLength(1); }); }); describe("getAgentAll", () => { it("returns all the agents a matcher applies to by WebID", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_ME, MOCK_WEBID_YOU], }); const agents = getAgentAll(matcher); expect(agents).toContain(MOCK_WEBID_ME.value); expect(agents).toContain(MOCK_WEBID_YOU.value); expect(agents).toHaveLength(2); }); it("does not return the public/authenticated/creator/clients a matcher applies to", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, authenticated: true, creator: true, clients: [MOCK_CLIENT_IDENTIFIER_1], }); const agents = getAgentAll(matcher); expect(agents).not.toContain(ACP_CREATOR.value); expect(agents).not.toContain(ACP_AUTHENTICATED.value); expect(agents).not.toContain(ACP_PUBLIC.value); expect(agents).toHaveLength(0); }); }); describe("setAgent", () => { it("sets the given agents for the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = setAgent(matcher, MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); it("deletes any agents previously set for the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_YOU], }); const result = setAgent(matcher, MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).not.toContain(MOCK_WEBID_YOU.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_YOU], }); setAgent(matcher, MOCK_WEBID_ME.value); expect(getUrlAll(matcher, ACP_AGENT)).not.toContain(MOCK_WEBID_ME.value); expect(getUrlAll(matcher, ACP_AGENT)).toContain(MOCK_WEBID_YOU.value); }); it("does not overwrite public, authenticated and creator agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, authenticated: true, creator: true, }); const result = setAgent(matcher, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_CREATOR.value); }); }); describe("addAgent", () => { it("adds the given agent to the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = addAgent(matcher, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_YOU.value); }); it("does not override existing agents/public/authenticated", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_ME], public: true, authenticated: true, }); const result = addAgent(matcher, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); }); }); describe("removeAgent", () => { it("removes the given agent from the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_YOU], }); const result = removeAgent(matcher, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).not.toContain(MOCK_WEBID_YOU.value); }); it("does not delete unrelated agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_ME, MOCK_WEBID_YOU], public: true, authenticated: true, }); const result = removeAgent(matcher, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).not.toContain(MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); }); }); describe("hasPublic", () => { it("returns true if the matcher applies to the public agent", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, }); expect(hasPublic(matcher)).toBe(true); }); it("returns false if the matcher only applies to other agent", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: false, authenticated: true, agents: [MOCK_WEBID_ME], }); expect(hasPublic(matcher)).toBe(false); }); }); describe("setPublic", () => { it("applies the given matcher to the public agent", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = setPublic(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); setPublic(matcher); expect(getUrlAll(matcher, ACP_AGENT)).not.toContain(ACP_PUBLIC.value); }); it("does not change the other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { authenticated: true, agents: [MOCK_WEBID_ME], }); const result = setPublic(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); it("throws an error when you attempt to use the deprecated API", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); expect( // @ts-expect-error The type signature should warn about passing a second argument: () => setPublic(matcher, true), ).toThrow( "The function `setPublic` no longer takes a second parameter. It is now used together with `removePublic` instead.", ); }); }); describe("removePublic", () => { it("prevents the matcher from applying to the public agent", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, }); const result = removePublic(matcher); expect(getUrlAll(result, ACP_AGENT)).not.toContain(ACP_PUBLIC.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true }); removePublic(matcher); expect(getUrlAll(matcher, ACP_AGENT)).toContain(ACP_PUBLIC.value); }); it("does not change the other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { authenticated: true, agents: [MOCK_WEBID_ME], public: true, }); const result = removePublic(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); }); describe("hasAuthenticated", () => { it("returns true if the matcher applies to authenticated agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { authenticated: true, }); expect(hasAuthenticated(matcher)).toBe(true); }); it("returns false if the matcher only applies to other agent", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, authenticated: false, agents: [MOCK_WEBID_ME], }); expect(hasAuthenticated(matcher)).toBe(false); }); }); describe("setAuthenticated", () => { it("applies to given matcher to authenticated agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = setAuthenticated(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); setAuthenticated(matcher); expect(getUrlAll(matcher, ACP_AGENT)).not.toContain( ACP_AUTHENTICATED.value, ); }); it("does not change the other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, agents: [MOCK_WEBID_ME], }); const result = setAuthenticated(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); it("throws an error when you attempt to use the deprecated API", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); expect( // @ts-expect-error The type signature should warn about passing a second argument: () => setAuthenticated(matcher, true), ).toThrow( "The function `setAuthenticated` no longer takes a second parameter. It is now used together with `removeAuthenticated` instead.", ); }); }); describe("removeAuthenticated", () => { it("prevents the matcher from applying to authenticated agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { authenticated: true, }); const result = removeAuthenticated(matcher); expect(getUrlAll(result, ACP_AGENT)).not.toContain(ACP_AUTHENTICATED.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { authenticated: true }); removeAuthenticated(matcher); expect(getUrlAll(matcher, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); }); it("does not change the other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, authenticated: true, agents: [MOCK_WEBID_ME], }); const result = removeAuthenticated(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); }); describe("hasCreator", () => { it("returns true if the matcher applies to the Resource's creator", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { creator: true, }); expect(hasCreator(matcher)).toBe(true); }); it("returns false if the matcher only applies to other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, creator: false, agents: [MOCK_WEBID_ME], }); expect(hasCreator(matcher)).toBe(false); }); }); describe("setCreator", () => { it("applies the given matcher to the Resource's creator", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = setCreator(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_CREATOR.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); setCreator(matcher); expect(getUrlAll(matcher, ACP_AGENT)).not.toContain(ACP_CREATOR.value); }); it("does not change the other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { public: true, agents: [MOCK_WEBID_ME], }); const result = setCreator(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); it("throws an error when you attempt to use the deprecated API", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); expect( // @ts-expect-error The type signature should warn about passing a second argument: () => setCreator(matcher, true), ).toThrow( "The function `setCreator` no longer takes a second parameter. It is now used together with `removeCreator` instead.", ); }); }); describe("removeCreator", () => { it("prevents the matcher from applying to the Resource's creator", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { creator: true, }); const result = removeCreator(matcher); expect(getUrlAll(result, ACP_AGENT)).not.toContain(ACP_CREATOR.value); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { creator: true }); removeCreator(matcher); expect(getUrlAll(matcher, ACP_AGENT)).toContain(ACP_CREATOR.value); }); it("does not change the other agents", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { creator: true, public: true, agents: [MOCK_WEBID_ME], }); const result = removeCreator(matcher); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); }); describe("getClientAll", () => { it("returns all the clients a matcher applies to by WebID", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { clients: [ MOCK_CLIENT_IDENTIFIER_1, MOCK_CLIENT_IDENTIFIER_2, MOCK_CLIENT_ID_3, ], }); const clients = getClientAll(matcher); expect(clients).toContain(MOCK_CLIENT_IDENTIFIER_1.value); expect(clients).toContain(MOCK_CLIENT_IDENTIFIER_2.value); expect(clients).toContain(MOCK_CLIENT_ID_3); expect(clients).toHaveLength(3); }); it("does not return the agents/public client a matcher applies to", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { agents: [MOCK_WEBID_ME], public: true, authenticated: true, creator: true, publicClient: true, }); const clients = getClientAll(matcher); expect(clients).not.toContain(ACP_CREATOR.value); expect(clients).not.toContain(ACP_AUTHENTICATED.value); expect(clients).not.toContain(ACP_PUBLIC.value); expect(clients).toHaveLength(0); }); }); describe("setClient", () => { it("sets the given clients for the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = setClient(matcher, MOCK_CLIENT_IDENTIFIER_1.value); expect(getUrlAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_1.value, ); }); it("deletes any clients previously set for the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { clients: [MOCK_CLIENT_IDENTIFIER_1], }); const result = setClient(matcher, MOCK_CLIENT_IDENTIFIER_2.value); expect(getUrlAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_2.value, ); expect(getUrlAll(result, ACP_CLIENT)).not.toContain( MOCK_CLIENT_IDENTIFIER_1.value, ); }); it("does not change the input matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { clients: [MOCK_CLIENT_IDENTIFIER_1], }); setClient(matcher, MOCK_CLIENT_IDENTIFIER_2.value); expect(getUrlAll(matcher, ACP_CLIENT)).not.toContain( MOCK_CLIENT_IDENTIFIER_2.value, ); expect(getUrlAll(matcher, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_1.value, ); }); it("does not overwrite the public client class", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { publicClient: true, }); const result = setClient(matcher, MOCK_CLIENT_IDENTIFIER_1.value); expect(getUrlAll(result, ACP_CLIENT)).toContain(SOLID_PUBLIC_CLIENT.value); }); }); describe("addClient", () => { it("adds the given client to the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = addClient(matcher, MOCK_CLIENT_IDENTIFIER_1.value); expect(getUrlAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_1.value, ); }); it("adds the given string client ID to the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI); const result = addClient(matcher, MOCK_CLIENT_ID_3); expect(getStringNoLocaleAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_ID_3, ); }); it("does not override existing clients/the public client class", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { clients: [MOCK_CLIENT_IDENTIFIER_1], publicClient: true, }); const result = addClient(matcher, MOCK_CLIENT_IDENTIFIER_2.value); expect(getUrlAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_1.value, ); expect(getUrlAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_2.value, ); expect(getUrlAll(result, ACP_CLIENT)).toContain(SOLID_PUBLIC_CLIENT.value); }); }); describe("removeClient", () => { it("removes the given client from the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { clients: [MOCK_CLIENT_IDENTIFIER_1, MOCK_CLIENT_IDENTIFIER_2], }); const result = removeClient(matcher, MOCK_CLIENT_IDENTIFIER_1.value); expect(getUrlAll(result, ACP_CLIENT)).not.toContain( MOCK_CLIENT_IDENTIFIER_1.value, ); expect(getUrlAll(result, ACP_CLIENT)).toContain( MOCK_CLIENT_IDENTIFIER_2.value, ); }); it("removes the given string client ID from the matcher", () => { const matcher = mockMatcher(MOCKED_MATCHER_IRI, { clients: [MOCK_CLIENT_ID_3, MOCK_CLIENT_ID_4], }); const result = removeClient(matcher, MOCK_CLIENT_ID_