UNPKG

@inrupt/solid-client

Version:

Make your web apps work with Solid Pods.

1,414 lines (1,286 loc) • 55.1 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 { Rule } from "./rule"; import { addAgent, addNoneOfRuleUrl, addGroup, addAnyOfRuleUrl, addAllOfRuleUrl, createRule, getAgentAll, getNoneOfRuleUrlAll, getGroupAll, getAnyOfRuleUrlAll, getAllOfRuleUrlAll, removeNoneOfRuleUrl, removeAnyOfRuleUrl, removeAllOfRuleUrl, getRule, hasAuthenticated, hasPublic, removeAgent, removeGroup, setAgent, setAuthenticated, setNoneOfRuleUrl, setGroup, setAnyOfRuleUrl, setPublic, setAllOfRuleUrl, getRuleAll, setRule, hasCreator, setCreator, ruleAsMarkdown, removeRule, getClientAll, setClient, addClient, removeClient, hasAnyClient, setAnyClient, removePublic, removeAuthenticated, removeCreator, removeAnyClient, getResourceRule, getResourceRuleAll, removeResourceRule, setResourceRule, createResourceRuleFor, } from "./rule"; 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 { addUrl } from "../thing/add"; import { getUrl, getUrlAll } from "../thing/get"; // 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_RULE = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#Rule"); const ACP_AGENT = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#agent"); const ACP_GROUP = DataFactory.namedNode("http://www.w3.org/ns/solid/acp#group"); 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_RULE_IRI = DataFactory.namedNode( "https://some.pod/rule-resource#a-rule", ); const OTHER_MOCKED_RULE_IRI = DataFactory.namedNode( "https://some.pod/rule-resource#another-rule", ); const ALLOF_RULE_IRI = DataFactory.namedNode( "https://some.pod/rule-resource#allOf-rule", ); const ANYOF_RULE_IRI = DataFactory.namedNode( "https://some.pod/rule-resource#anyOf-rule", ); const NONEOF_RULE_IRI = DataFactory.namedNode( "https://some.pod/rule-resource#noneOf-rule", ); const MOCK_WEBID_ME = DataFactory.namedNode("https://my.pod/profile#me"); const MOCK_WEBID_YOU = DataFactory.namedNode("https://your.pod/profile#you"); const MOCK_GROUP_IRI = DataFactory.namedNode("https://my.pod/group#a-group"); const MOCK_GROUP_OTHER_IRI = DataFactory.namedNode( "https://my.pod/group#another-group", ); const MOCK_CLIENT_WEBID_1 = DataFactory.namedNode( "https://my.app/registration#it", ); const MOCK_CLIENT_WEBID_2 = DataFactory.namedNode( "https://your.app/registration#it", ); const addAllObjects = ( thing: ThingPersisted, predicate: NamedNode, objects: Url[], ): ThingPersisted => { return objects.reduce((thingAcc, object) => { return addUrl(thingAcc, predicate, object); }, thing); }; const addAllThingObjects = ( thing: ThingPersisted, predicate: NamedNode, objects: Thing[], ): ThingPersisted => { return objects.reduce((thingAcc, object) => { return addUrl(thingAcc, predicate, object); }, thing); }; const mockRule = ( url: Url, content?: { agents?: Url[]; groups?: Url[]; public?: boolean; authenticated?: boolean; creator?: boolean; clients?: Url[]; publicClient?: boolean; }, ): Rule => { let mockedRule = createThing({ url: url.value, }); mockedRule = addUrl(mockedRule, RDF_TYPE, ACP_RULE); if (content?.agents) { mockedRule = addAllObjects(mockedRule, ACP_AGENT, content.agents); } if (content?.groups) { mockedRule = addAllObjects(mockedRule, ACP_GROUP, content.groups); } if (content?.clients) { mockedRule = addAllObjects(mockedRule, ACP_CLIENT, content.clients); } if (content?.public) { mockedRule = addUrl(mockedRule, ACP_AGENT, ACP_PUBLIC); } if (content?.authenticated) { mockedRule = addUrl(mockedRule, ACP_AGENT, ACP_AUTHENTICATED); } if (content?.creator) { mockedRule = addUrl(mockedRule, ACP_AGENT, ACP_CREATOR); } if (content?.publicClient) { mockedRule = addUrl(mockedRule, ACP_CLIENT, SOLID_PUBLIC_CLIENT); } return mockedRule; }; const mockPolicy = ( url: NamedNode, rules?: { allOf?: Rule[]; anyOf?: Rule[]; noneOf?: Rule[] }, ): Policy => { let mockedPolicy = createThing({ url: url.value }); if (rules?.noneOf) { mockedPolicy = addAllThingObjects(mockedPolicy, ACP_NONE, rules.noneOf); } if (rules?.anyOf) { mockedPolicy = addAllThingObjects(mockedPolicy, ACP_ANY, rules.anyOf); } if (rules?.allOf) { mockedPolicy = addAllThingObjects(mockedPolicy, ACP_ALL, rules.allOf); } return mockedPolicy; }; describe("addNoneOfRuleUrl", () => { it("adds the rule in the noneOf rules of the policy", () => { const myPolicy = addNoneOfRuleUrl( mockPolicy(MOCKED_POLICY_IRI), mockRule(MOCKED_RULE_IRI), ); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(MOCKED_RULE_IRI.value); }); it("does not remove the existing noneOf rules", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(OTHER_MOCKED_RULE_IRI)], }); const myPolicy = addNoneOfRuleUrl(mockedPolicy, mockRule(MOCKED_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_NONE)).toContain( OTHER_MOCKED_RULE_IRI.value, ); }); it("does not change the existing allOf and anyOf rules", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockRule(ANYOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const myPolicy = addNoneOfRuleUrl(mockedPolicy, mockRule(NONEOF_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_RULE_IRI.value); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_RULE_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = addNoneOfRuleUrl(myPolicy, mockRule(MOCKED_RULE_IRI)); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("addAnyOfRuleUrl", () => { it("adds the rule in the anyOf rules of the policy", () => { const myPolicy = addAnyOfRuleUrl( mockPolicy(MOCKED_POLICY_IRI), mockRule(MOCKED_RULE_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(MOCKED_RULE_IRI.value); }); it("does not remove the existing anyOf rules", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockRule(OTHER_MOCKED_RULE_IRI)], }); const myPolicy = addAnyOfRuleUrl(mockedPolicy, mockRule(MOCKED_POLICY_IRI)); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(OTHER_MOCKED_RULE_IRI.value); }); it("does not change the existing allOf and noneOf rules", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const myPolicy = addAnyOfRuleUrl(mockedPolicy, mockRule(ANYOF_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_RULE_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_RULE_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = addAnyOfRuleUrl(myPolicy, mockRule(MOCKED_RULE_IRI)); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("addAllOfRule", () => { it("adds the rule in the allOf rules of the policy", () => { const myPolicy = addAllOfRuleUrl( mockPolicy(MOCKED_POLICY_IRI), mockRule(MOCKED_RULE_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(MOCKED_RULE_IRI.value); }); it("does not remove the existing allOf rules", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockRule(OTHER_MOCKED_RULE_IRI)], }); const myPolicy = addAllOfRuleUrl(mockedPolicy, mockRule(MOCKED_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(OTHER_MOCKED_RULE_IRI.value); }); it("does not change the existing anyOf and noneOf rules", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], anyOf: [mockRule(ANYOF_RULE_IRI)], }); const myPolicy = addAllOfRuleUrl(mockedPolicy, mockRule(ANYOF_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_RULE_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_RULE_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = addAnyOfRuleUrl(myPolicy, mockRule(MOCKED_RULE_IRI)); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("setNoneOfRuleUrl", () => { it("sets the provided rules as the noneOf rules for the policy", () => { const myPolicy = setNoneOfRuleUrl( mockPolicy(MOCKED_POLICY_IRI), mockRule(MOCKED_RULE_IRI), ); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(MOCKED_RULE_IRI.value); }); it("removes any previous noneOf rules for on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(OTHER_MOCKED_RULE_IRI)], }); const myPolicy = setNoneOfRuleUrl(mockedPolicy, mockRule(MOCKED_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_NONE)).not.toContain( OTHER_MOCKED_RULE_IRI.value, ); }); it("does not change the existing anyOf and allOf rules on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockRule(ANYOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const myPolicy = setNoneOfRuleUrl(mockedPolicy, mockRule(NONEOF_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_RULE_IRI.value); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_RULE_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = setNoneOfRuleUrl(myPolicy, mockRule(MOCKED_RULE_IRI)); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("setAnyOfRuleUrl", () => { it("sets the provided rules as the anyOf rules for the policy", () => { const myPolicy = setAnyOfRuleUrl( mockPolicy(MOCKED_POLICY_IRI), mockRule(MOCKED_RULE_IRI), ); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(MOCKED_RULE_IRI.value); }); it("removes any previous anyOf rules for on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockRule(OTHER_MOCKED_RULE_IRI)], }); const myPolicy = setAnyOfRuleUrl(mockedPolicy, mockRule(MOCKED_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ANY)).not.toContain( OTHER_MOCKED_RULE_IRI.value, ); }); it("does not change the existing noneOf and allOf rules on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const myPolicy = setAnyOfRuleUrl(mockedPolicy, mockRule(ANYOF_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(ALLOF_RULE_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_RULE_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = setAnyOfRuleUrl(myPolicy, mockRule(MOCKED_RULE_IRI)); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("setAllOfRuleUrl", () => { it("sets the provided rules as the allOf rules for the policy", () => { const myPolicy = setAllOfRuleUrl( mockPolicy(MOCKED_POLICY_IRI), mockRule(MOCKED_RULE_IRI), ); expect(getUrlAll(myPolicy, ACP_ALL)).toContain(MOCKED_RULE_IRI.value); }); it("removes any previous allOf rules for on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockRule(OTHER_MOCKED_RULE_IRI)], }); const myPolicy = setAllOfRuleUrl(mockedPolicy, mockRule(MOCKED_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ALL)).not.toContain( OTHER_MOCKED_RULE_IRI.value, ); }); it("does not change the existing noneOf and anyOf rules on the policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], anyOf: [mockRule(ANYOF_RULE_IRI)], }); const myPolicy = setAllOfRuleUrl(mockedPolicy, mockRule(ALLOF_RULE_IRI)); expect(getUrlAll(myPolicy, ACP_ANY)).toContain(ANYOF_RULE_IRI.value); expect(getUrlAll(myPolicy, ACP_NONE)).toContain(NONEOF_RULE_IRI.value); }); it("does not change the input policy", () => { const myPolicy = mockPolicy(MOCKED_POLICY_IRI); const updatedPolicy = setAllOfRuleUrl(myPolicy, mockRule(MOCKED_RULE_IRI)); expect(myPolicy).not.toStrictEqual(updatedPolicy); }); }); describe("getNoneOfRuleurlAll", () => { it("returns all the noneOf rules for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(MOCKED_RULE_IRI), mockRule(OTHER_MOCKED_RULE_IRI)], }); const noneOfRules = getNoneOfRuleUrlAll(mockedPolicy); expect(noneOfRules).toContain(MOCKED_RULE_IRI.value); expect(noneOfRules).toContain(OTHER_MOCKED_RULE_IRI.value); expect(noneOfRules).toHaveLength(2); }); it("returns only the noneOf rules for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], anyOf: [mockRule(ANYOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const noneOfRules = getNoneOfRuleUrlAll(mockedPolicy); expect(noneOfRules).not.toContain(ANYOF_RULE_IRI.value); expect(noneOfRules).not.toContain(ALLOF_RULE_IRI.value); expect(noneOfRules).toHaveLength(1); }); }); describe("getAnyOfRulesOnPolicyAll", () => { it("returns all the anyOf rules for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockRule(MOCKED_RULE_IRI), mockRule(OTHER_MOCKED_RULE_IRI)], }); const anyOfRules = getAnyOfRuleUrlAll(mockedPolicy); expect(anyOfRules).toContain(MOCKED_RULE_IRI.value); expect(anyOfRules).toContain(OTHER_MOCKED_RULE_IRI.value); expect(anyOfRules).toHaveLength(2); }); it("returns only the anyOf rules for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], anyOf: [mockRule(ANYOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const anyOfRules = getAnyOfRuleUrlAll(mockedPolicy); expect(anyOfRules).not.toContain(NONEOF_RULE_IRI.value); expect(anyOfRules).not.toContain(ALLOF_RULE_IRI.value); expect(anyOfRules).toHaveLength(1); }); }); describe("getAllOfRulesOnPolicyAll", () => { it("returns all the allOf rules for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockRule(MOCKED_RULE_IRI), mockRule(OTHER_MOCKED_RULE_IRI)], }); const allOfRules = getAllOfRuleUrlAll(mockedPolicy); expect(allOfRules).toContain(MOCKED_RULE_IRI.value); expect(allOfRules).toContain(OTHER_MOCKED_RULE_IRI.value); expect(allOfRules).toHaveLength(2); }); it("returns only the allOf rules for the given policy", () => { const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockRule(NONEOF_RULE_IRI)], anyOf: [mockRule(ANYOF_RULE_IRI)], allOf: [mockRule(ALLOF_RULE_IRI)], }); const allOfRules = getAllOfRuleUrlAll(mockedPolicy); expect(allOfRules).not.toContain(NONEOF_RULE_IRI.value); expect(allOfRules).not.toContain(ANYOF_RULE_IRI.value); expect(allOfRules).toHaveLength(1); }); }); describe("removeAllOfRule", () => { it("removes the rule from the allOf rules for the given policy", () => { const mockedRule = mockRule(MOCKED_RULE_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockedRule], }); const result = removeAllOfRuleUrl(mockedPolicy, mockedRule); expect(getUrlAll(result, ACP_ALL)).not.toContain(MOCKED_RULE_IRI.value); }); it("does not remove the rule from the anyOf/noneOf rules for the given policy", () => { const mockedRule = mockRule(MOCKED_RULE_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockedRule], noneOf: [mockedRule], }); const result = removeAllOfRuleUrl(mockedPolicy, mockedRule); expect(getUrlAll(result, ACP_ANY)).toContain(MOCKED_RULE_IRI.value); expect(getUrlAll(result, ACP_NONE)).toContain(MOCKED_RULE_IRI.value); }); }); describe("removeAnyOfRuleUrl", () => { it("removes the rule from the allOf rules for the given policy", () => { const mockedRule = mockRule(MOCKED_RULE_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { anyOf: [mockedRule], }); const result = removeAnyOfRuleUrl(mockedPolicy, mockedRule); expect(getUrlAll(result, ACP_ANY)).not.toContain(MOCKED_RULE_IRI.value); }); it("does not remove the rule from the allOf/noneOf rules for the given policy", () => { const mockedRule = mockRule(MOCKED_RULE_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockedRule], noneOf: [mockedRule], }); const result = removeAnyOfRuleUrl(mockedPolicy, mockedRule); expect(getUrlAll(result, ACP_ALL)).toContain(MOCKED_RULE_IRI.value); expect(getUrlAll(result, ACP_NONE)).toContain(MOCKED_RULE_IRI.value); }); }); describe("removeNoneOfRuleUrl", () => { it("removes the rule from the noneOf rules for the given policy", () => { const mockedRule = mockRule(MOCKED_RULE_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { noneOf: [mockedRule], }); const result = removeNoneOfRuleUrl(mockedPolicy, mockedRule); expect(getUrlAll(result, ACP_NONE)).not.toContain(MOCKED_RULE_IRI.value); }); it("does not remove the rule from the allOf/anyOf rules for the given policy", () => { const mockedRule = mockRule(MOCKED_RULE_IRI); const mockedPolicy = mockPolicy(MOCKED_POLICY_IRI, { allOf: [mockedRule], anyOf: [mockedRule], }); const result = removeNoneOfRuleUrl(mockedPolicy, mockedRule); expect(getUrlAll(result, ACP_ALL)).toContain(MOCKED_RULE_IRI.value); expect(getUrlAll(result, ACP_ANY)).toContain(MOCKED_RULE_IRI.value); }); }); describe("createRule", () => { it("returns a acp:Rule", () => { const myRule = createRule(MOCKED_RULE_IRI.value); expect(getUrl(myRule, RDF_TYPE)).toBe(ACP_RULE.value); }); it("returns an **empty** rule", () => { const myRule = createRule("https://my.pod/rule-resource#rule"); // The rule should only contain a type triple. expect(Object.keys(myRule.predicates)).toHaveLength(1); }); }); describe("createResourceRuleFor", () => { it("returns a acp:Rule", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const myRule = createResourceRuleFor(mockedResourceWithAcr, "myRule"); expect(getIri(myRule, RDF_TYPE)).toBe(ACP_RULE.value); }); it("returns an **empty** rule", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const myRule = createResourceRuleFor(mockedResourceWithAcr, "myRule"); // The rule should only contain a type triple. expect(Object.keys(myRule.predicates)).toHaveLength(1); }); }); describe("getRule", () => { it("returns the rule with a matching IRI", () => { const rule = mockRule(MOCKED_RULE_IRI); const dataset = setThing(createSolidDataset(), rule); const result = getRule(dataset, MOCKED_RULE_IRI.value); expect(result).not.toBeNull(); }); it("does not return a Thing with a matching IRI but the wrong type", () => { const notARule = createThing({ url: "https://my.pod/rule-resource#not-a-rule", }); const dataset = setThing( createSolidDataset(), setUrl(notARule, RDF_TYPE, "http://example.org/ns#NotRuleType"), ); const result = getRule(dataset, "https://my.pod/rule-resource#not-a-rule"); expect(result).toBeNull(); }); it("does not return a rule with a mismatching IRI", () => { const rule = mockRule(MOCKED_RULE_IRI); const dataset = setThing(createSolidDataset(), rule); const result = getRule(dataset, OTHER_MOCKED_RULE_IRI); expect(result).toBeNull(); }); }); describe("getResourceRule", () => { it("returns the rule with a matching name", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceRule(mockedResourceWithAcr, "rule"); 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 mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl( mockedRule, rdf.type, "http://example.org/ns#NotRuleType", ); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceRule(mockedResourceWithAcr, "rule"); expect(result).toBeNull(); }); it("does not return a rule with a mismatching IRI", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceRule(mockedResourceWithAcr, "other-rule"); expect(result).toBeNull(); }); }); describe("getRuleAll", () => { it("returns an empty array if there are no Rules in the given Dataset", () => { expect(getRuleAll(createSolidDataset())).toHaveLength(0); }); it("returns all the rules in a rule resource", () => { const rule = mockRule(MOCKED_RULE_IRI); const dataset = setThing(createSolidDataset(), rule); let result = getRuleAll(dataset); expect(result).toHaveLength(1); const anotherRule = mockRule(OTHER_MOCKED_RULE_IRI); const newDataset = setThing(dataset, anotherRule); result = getRuleAll(newDataset); expect(result).toHaveLength(2); }); }); describe("getResourceRuleAll", () => { it("returns an empty array if there are no Rules in the given Resource's ACR", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); expect(getResourceRuleAll(mockedResourceWithAcr)).toHaveLength(0); }); it("returns all the rules in a Resource's ACR", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule1 = createThing({ url: `${getSourceUrl(mockedAcr)}#rule1`, }); mockedRule1 = setUrl(mockedRule1, rdf.type, acp.Rule); let mockedRule2 = createThing({ url: `${getSourceUrl(mockedAcr)}#rule2`, }); mockedRule2 = setUrl(mockedRule2, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule1); mockedAcr = setThing(mockedAcr, mockedRule2); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const result = getResourceRuleAll(mockedResourceWithAcr); expect(result).toHaveLength(2); }); }); describe("removeRule", () => { it("removes the Rule from the given empty Dataset", () => { const rule = mockRule(MOCKED_RULE_IRI); const dataset = setThing(createSolidDataset(), rule); const updatedDataset = removeRule(dataset, MOCKED_RULE_IRI); expect(getThingAll(updatedDataset)).toHaveLength(0); }); }); describe("removeResourceRule", () => { it("removes the Rule from the given Resource's Access control Resource", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceRule( mockedResourceWithAcr, mockedRule, ); expect(getResourceRuleAll(updatedDataset)).toHaveLength(0); }); it("accepts a plain name to remove a Rule", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceRule(mockedResourceWithAcr, "rule"); expect(getResourceRuleAll(updatedDataset)).toHaveLength(0); }); it("accepts a full URL to remove a Rule", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceRule( mockedResourceWithAcr, `${getSourceUrl(mockedAcr)}#rule`, ); expect(getResourceRuleAll(updatedDataset)).toHaveLength(0); }); it("accepts a Named Node to remove a Rule", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceRule( mockedResourceWithAcr, DataFactory.namedNode(`${getSourceUrl(mockedAcr)}#rule`), ); expect(getResourceRuleAll(updatedDataset)).toHaveLength(0); }); it("does not remove a non-Rule with the same name", () => { let mockedAcr = mockAcrFor("https://some.pod/resource"); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl( mockedRule, rdf.type, "https://example.vocab/not-a-rule", ); mockedAcr = setThing(mockedAcr, mockedRule); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); const updatedDataset = removeResourceRule(mockedResourceWithAcr, "rule"); const updatedAcr = internal_getAcr(updatedDataset); expect( getThing(updatedAcr, `${getSourceUrl(mockedAcr)}#rule`), ).not.toBeNull(); }); }); describe("setRule", () => { it("sets the Rule in the given empty Dataset", () => { const rule = mockRule(MOCKED_RULE_IRI); const dataset = setRule(createSolidDataset(), rule); const result = getThing(dataset, MOCKED_RULE_IRI); expect(result).not.toBeNull(); expect(getIriAll(result as Thing, rdf.type)).toContain(acp.Rule); }); }); describe("setResourceRule", () => { it("sets the Rule in the given Resource's ACR", () => { const mockedAcr = mockAcrFor("https://some.pod/resource"); const mockedResourceWithAcr = addMockAcrTo( mockSolidDatasetFrom("https://some.pod/resource"), mockedAcr, ); let mockedRule = createThing({ url: `${getSourceUrl(mockedAcr)}#rule`, }); mockedRule = setUrl(mockedRule, rdf.type, acp.Rule); const updatedResource = setResourceRule(mockedResourceWithAcr, mockedRule); expect(getResourceRuleAll(updatedResource)).toHaveLength(1); }); }); describe("getAgentAll", () => { it("returns all the agents a rule applies to by WebID", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME, MOCK_WEBID_YOU], }); const agents = getAgentAll(rule); expect(agents).toContain(MOCK_WEBID_ME.value); expect(agents).toContain(MOCK_WEBID_YOU.value); expect(agents).toHaveLength(2); }); it("does not return the groups/public/authenticated/creator/clients a rule applies to", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_IRI], public: true, authenticated: true, creator: true, clients: [MOCK_CLIENT_WEBID_1], }); const agents = getAgentAll(rule); expect(agents).not.toContain(MOCK_GROUP_IRI.value); 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 rule", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = setAgent(rule, MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); it("deletes any agents previously set for the rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_YOU], }); const result = setAgent(rule, 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 rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_YOU], }); setAgent(rule, MOCK_WEBID_ME.value); expect(getUrlAll(rule, ACP_AGENT)).not.toContain(MOCK_WEBID_ME.value); expect(getUrlAll(rule, ACP_AGENT)).toContain(MOCK_WEBID_YOU.value); }); it("does not overwrite public, authenticated and creator agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, authenticated: true, creator: true, }); const result = setAgent(rule, 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 rule", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = addAgent(rule, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_YOU.value); }); it("does not override existing agents/public/authenticated/groups", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME], groups: [MOCK_GROUP_IRI], public: true, authenticated: true, }); const result = addAgent(rule, 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); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_IRI.value); }); }); describe("removeAgent", () => { it("removes the given agent from the rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_YOU], }); const result = removeAgent(rule, MOCK_WEBID_YOU.value); expect(getUrlAll(result, ACP_AGENT)).not.toContain(MOCK_WEBID_YOU.value); }); it("does not delete unrelated agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME, MOCK_WEBID_YOU], public: true, authenticated: true, }); const result = removeAgent(rule, 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); }); it("does not remove groups, even with matching IRI", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_IRI], }); const result = removeAgent(rule, MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_IRI.value); }); }); describe("getGroupAll", () => { it("returns all the groups a rule applies to", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_IRI, MOCK_GROUP_OTHER_IRI], }); const groups = getGroupAll(rule); expect(groups).toContain(MOCK_GROUP_IRI.value); expect(groups).toContain(MOCK_GROUP_OTHER_IRI.value); expect(groups).toHaveLength(2); }); it("does not return the agents/public/authenticated/clients a rule applies to", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME], public: true, authenticated: true, clients: [MOCK_CLIENT_WEBID_1], }); const groups = getGroupAll(rule); expect(groups).not.toContain(MOCK_WEBID_ME.value); expect(groups).not.toContain(ACP_AUTHENTICATED.value); expect(groups).not.toContain(ACP_PUBLIC.value); expect(groups).toHaveLength(0); }); }); describe("setGroup", () => { it("sets the given groups for the rule", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = setGroup(rule, MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_IRI.value); }); it("deletes any groups previously set for the rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_OTHER_IRI], }); const result = setGroup(rule, MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).not.toContain( MOCK_GROUP_OTHER_IRI.value, ); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_OTHER_IRI], }); setGroup(rule, MOCK_GROUP_IRI.value); expect(getUrlAll(rule, ACP_GROUP)).not.toContain(MOCK_GROUP_IRI.value); expect(getUrlAll(rule, ACP_GROUP)).toContain(MOCK_GROUP_OTHER_IRI.value); }); }); describe("addGroup", () => { it("adds the given group to the rule", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = addGroup(rule, "https://your.pod/groups#a-group"); expect(getUrlAll(result, ACP_GROUP)).toContain( "https://your.pod/groups#a-group", ); }); it("does not override existing agents/public/authenticated/groups", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME], groups: [MOCK_GROUP_IRI], public: true, authenticated: true, }); const result = addGroup(rule, MOCK_GROUP_OTHER_IRI.value); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_OTHER_IRI.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); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_IRI.value); }); }); describe("removeGroup", () => { it("removes the given group from the rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_IRI], }); const result = removeGroup(rule, MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).not.toContain(MOCK_GROUP_IRI.value); }); it("does not delete unrelated groups", () => { const rule = mockRule(MOCKED_RULE_IRI, { groups: [MOCK_GROUP_IRI, MOCK_GROUP_OTHER_IRI], }); const result = removeGroup(rule, MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).not.toContain(MOCK_GROUP_IRI.value); expect(getUrlAll(result, ACP_GROUP)).toContain(MOCK_GROUP_OTHER_IRI.value); }); it("does not remove agents, even with matching IRI", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME], }); const result = removeGroup(rule, MOCK_WEBID_ME.value); expect(getUrlAll(result, ACP_AGENT)).toContain(MOCK_WEBID_ME.value); }); }); describe("hasPublic", () => { it("returns true if the rule applies to the public agent", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, }); expect(hasPublic(rule)).toBe(true); }); it("returns false if the rule only applies to other agent", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: false, authenticated: true, agents: [MOCK_WEBID_ME], }); expect(hasPublic(rule)).toBe(false); }); }); describe("setPublic", () => { it("applies the given rule to the public agent", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = setPublic(rule); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_PUBLIC.value); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI); setPublic(rule); expect(getUrlAll(rule, ACP_AGENT)).not.toContain(ACP_PUBLIC.value); }); it("does not change the other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { authenticated: true, agents: [MOCK_WEBID_ME], }); const result = setPublic(rule); 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 rule = mockRule(MOCKED_RULE_IRI); expect( // @ts-expect-error The type signature should warn about passing a second argument: () => setPublic(rule, true), ).toThrow( "The function `setPublic` no longer takes a second parameter. It is now used together with `removePublic` instead.", ); }); }); describe("removePublic", () => { it("prevents the rule from applying to the public agent", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, }); const result = removePublic(rule); expect(getUrlAll(result, ACP_AGENT)).not.toContain(ACP_PUBLIC.value); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true }); removePublic(rule); expect(getUrlAll(rule, ACP_AGENT)).toContain(ACP_PUBLIC.value); }); it("does not change the other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { authenticated: true, agents: [MOCK_WEBID_ME], public: true, }); const result = removePublic(rule); 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 rule applies to authenticated agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { authenticated: true, }); expect(hasAuthenticated(rule)).toBe(true); }); it("returns false if the rule only applies to other agent", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, authenticated: false, agents: [MOCK_WEBID_ME], }); expect(hasAuthenticated(rule)).toBe(false); }); }); describe("setAuthenticated", () => { it("applies to given rule to authenticated agents", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = setAuthenticated(rule); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI); setAuthenticated(rule); expect(getUrlAll(rule, ACP_AGENT)).not.toContain(ACP_AUTHENTICATED.value); }); it("does not change the other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, agents: [MOCK_WEBID_ME], }); const result = setAuthenticated(rule); 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 rule = mockRule(MOCKED_RULE_IRI); expect( // @ts-expect-error The type signature should warn about passing a second argument: () => setAuthenticated(rule, true), ).toThrow( "The function `setAuthenticated` no longer takes a second parameter. It is now used together with `removeAuthenticated` instead.", ); }); }); describe("removeAuthenticated", () => { it("prevents the rule from applying to authenticated agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { authenticated: true, }); const result = removeAuthenticated(rule); expect(getUrlAll(result, ACP_AGENT)).not.toContain(ACP_AUTHENTICATED.value); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { authenticated: true }); removeAuthenticated(rule); expect(getUrlAll(rule, ACP_AGENT)).toContain(ACP_AUTHENTICATED.value); }); it("does not change the other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, authenticated: true, agents: [MOCK_WEBID_ME], }); const result = removeAuthenticated(rule); 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 rule applies to the Resource's creator", () => { const rule = mockRule(MOCKED_RULE_IRI, { creator: true, }); expect(hasCreator(rule)).toBe(true); }); it("returns false if the rule only applies to other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, creator: false, agents: [MOCK_WEBID_ME], }); expect(hasCreator(rule)).toBe(false); }); }); describe("setCreator", () => { it("applies the given rule to the Resource's creator", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = setCreator(rule); expect(getUrlAll(result, ACP_AGENT)).toContain(ACP_CREATOR.value); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI); setCreator(rule); expect(getUrlAll(rule, ACP_AGENT)).not.toContain(ACP_CREATOR.value); }); it("does not change the other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { public: true, agents: [MOCK_WEBID_ME], }); const result = setCreator(rule); 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 rule = mockRule(MOCKED_RULE_IRI); expect( // @ts-expect-error The type signature should warn about passing a second argument: () => setCreator(rule, true), ).toThrow( "The function `setCreator` no longer takes a second parameter. It is now used together with `removeCreator` instead.", ); }); }); describe("removeCreator", () => { it("prevents the rule from applying to the Resource's creator", () => { const rule = mockRule(MOCKED_RULE_IRI, { creator: true, }); const result = removeCreator(rule); expect(getUrlAll(result, ACP_AGENT)).not.toContain(ACP_CREATOR.value); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { creator: true }); removeCreator(rule); expect(getUrlAll(rule, ACP_AGENT)).toContain(ACP_CREATOR.value); }); it("does not change the other agents", () => { const rule = mockRule(MOCKED_RULE_IRI, { creator: true, public: true, agents: [MOCK_WEBID_ME], }); const result = removeCreator(rule); 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 rule applies to by WebID", () => { const rule = mockRule(MOCKED_RULE_IRI, { clients: [MOCK_CLIENT_WEBID_1, MOCK_CLIENT_WEBID_2], }); const clients = getClientAll(rule); expect(clients).toContain(MOCK_CLIENT_WEBID_1.value); expect(clients).toContain(MOCK_CLIENT_WEBID_2.value); expect(clients).toHaveLength(2); }); it("does not return the agents/groups/public client a rule applies to", () => { const rule = mockRule(MOCKED_RULE_IRI, { agents: [MOCK_WEBID_ME], groups: [MOCK_GROUP_IRI], public: true, authenticated: true, creator: true, publicClient: true, }); const clients = getClientAll(rule); expect(clients).not.toContain(MOCK_GROUP_IRI.value); 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 rule", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = setClient(rule, MOCK_CLIENT_WEBID_1.value); expect(getUrlAll(result, ACP_CLIENT)).toContain(MOCK_CLIENT_WEBID_1.value); }); it("deletes any clients previously set for the rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { clients: [MOCK_CLIENT_WEBID_1], }); const result = setClient(rule, MOCK_CLIENT_WEBID_2.value); expect(getUrlAll(result, ACP_CLIENT)).toContain(MOCK_CLIENT_WEBID_2.value); expect(getUrlAll(result, ACP_CLIENT)).not.toContain( MOCK_CLIENT_WEBID_1.value, ); }); it("does not change the input rule", () => { const rule = mockRule(MOCKED_RULE_IRI, { clients: [MOCK_CLIENT_WEBID_1], }); setClient(rule, MOCK_CLIENT_WEBID_2.value); expect(getUrlAll(rule, ACP_CLIENT)).not.toContain( MOCK_CLIENT_WEBID_2.value, ); expect(getUrlAll(rule, ACP_CLIENT)).toContain(MOCK_CLIENT_WEBID_1.value); }); it("does not overwrite the public client class", () => { const rule = mockRule(MOCKED_RULE_IRI, { publicClient: true, }); const result = setClient(rule, MOCK_CLIENT_WEBID_1.value); expect(getUrlAll(result, ACP_CLIENT)).toContain(SOLID_PUBLIC_CLIENT.value); }); }); describe("addClient", () => { it("adds the given client to the rule", () => { const rule = mockRule(MOCKED_RULE_IRI); const result = addClient(rule, MOCK_CLIENT_WEBID_1.value); expect(getUrlAll(result, ACP_CLIENT)).toContain(MOCK_CLIENT_WEBID_1.value); }); it("does not override existing clients/the public client class", () => { const rule = mockRule(MOCKED_RULE_IRI, { clients: [MOCK_CLIENT_WEBID_1], publicClie