Skip to content

Commit

Permalink
coverage and lint
Browse files Browse the repository at this point in the history
  • Loading branch information
garciafdezpatricia committed Apr 23, 2024
1 parent 071d6fe commit ed727b0
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 11 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ The following changes are pending, and will be applied on the next major release
## Unreleased changes

### Patch changes
- Fixed #2339: Unnamed policies are now returned by `getResourcePolicyAll` if an optional argument

- Fixed #2339: Unnamed policies are now returned by `getResourcePolicyAll` if an optional argument
`{ acceptBlankNodes: true }` is specified. This additional argument makes this a non-breaking change,
as the current type signature isn't changed.
- `getThing` now supports Blank Node identifiers in addition to IRIs and skolems to refer to a subject.
Expand Down
167 changes: 163 additions & 4 deletions src/acp/control.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,22 @@ import {
} from "./control";
import {
internal_createControl,
internal_getAcr,
internal_getControl,
internal_getControlAll,
internal_setAcr,
internal_setControl,
} from "./control.internal";
import { acp, rdf } from "../constants";
import type { WithServerResourceInfo } from "../interfaces";
import { getIri, getUrl, getUrlAll } from "../thing/get";
import {
asIri,
asUrl,
createThing,
getThing,
getThingAll,
removeThing,
setThing,
} from "../thing/thing";
import { addMockAcrTo, mockAcrFor } from "./mock";
Expand Down Expand Up @@ -527,6 +531,24 @@ describe("getAcrPolicyUrlAll", () => {

expect(policyUrls).toEqual([]);
});

it("does not return policies if acr does not have an anchor node", () => {
const accessControlResource = mockAcrFor("https://some.pod/resource");
const existingControl = addUrl(
createThing({ url: getSourceUrl(accessControlResource) }),
acp.accessMembers,
"https://some.pod/policy-resource#policy",
);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
setThing(accessControlResource, existingControl),
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(getAcrPolicyUrlAll(updatedResource)).toHaveLength(0);
});
});

describe("getMemberAcrPolicyUrlAll", () => {
Expand Down Expand Up @@ -575,6 +597,24 @@ describe("getMemberAcrPolicyUrlAll", () => {

expect(policyUrls).toEqual([]);
});

it("does not return policies if acr does not have an anchor node", () => {
const accessControlResource = mockAcrFor("https://some.pod/resource");
const existingControl = addUrl(
createThing({ url: getSourceUrl(accessControlResource) }),
acp.accessMembers,
"https://some.pod/policy-resource#policy",
);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
setThing(accessControlResource, existingControl),
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(getMemberAcrPolicyUrlAll(updatedResource)).toHaveLength(0);
});
});

describe("removeAcrPolicyUrl", () => {
Expand Down Expand Up @@ -705,6 +745,29 @@ describe("removeAcrPolicyUrl", () => {
"https://some.pod/policy-resource#policy",
);
});

it("returns the resource unchanged if acr does not have an anchor node", () => {
const accessControlResource = mockAcrFor("https://some.pod/resource");
const existingControl = addUrl(
createThing({ url: getSourceUrl(accessControlResource) }),
acp.accessMembers,
"https://some.pod/policy-resource#policy",
);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
setThing(accessControlResource, existingControl),
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(
removeAcrPolicyUrl(
updatedResource,
"https://some.pod/policy-resource#policy",
),
).toEqual(updatedResource);
});
});

describe("removeMemberAcrPolicyUrl", () => {
Expand Down Expand Up @@ -835,6 +898,33 @@ describe("removeMemberAcrPolicyUrl", () => {
"https://some.pod/policy-resource#policy",
);
});

it("returns the resource unchanged if acr does not have an anchor node", () => {
let accessControlResource = mockAcrFor("https://some.pod/resource");
let existingControl = createThing({
url: getSourceUrl(accessControlResource),
});
existingControl = addUrl(
existingControl,
acp.accessMembers,
"https://some.pod/policy-resource#policy",
);
accessControlResource = setThing(accessControlResource, existingControl);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
accessControlResource,
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(
removeMemberAcrPolicyUrl(
updatedResource,
"https://some.pod/policy-resource#policy",
),
).toEqual(updatedResource);
});
});

describe("removeAcrPolicyUrlAll", () => {
Expand Down Expand Up @@ -929,6 +1019,24 @@ describe("removeAcrPolicyUrlAll", () => {
"https://some.pod/policy-resource#policy",
);
});

it("returns the resource unchanged if acr does not have an anchor node", () => {
const accessControlResource = mockAcrFor("https://some.pod/resource");
const existingControl = addUrl(
createThing({ url: getSourceUrl(accessControlResource) }),
acp.accessMembers,
"https://some.pod/policy-resource#policy",
);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
setThing(accessControlResource, existingControl),
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(removeAcrPolicyUrlAll(updatedResource)).toEqual(updatedResource);
});
});

describe("removeMemberAcrPolicyUrlAll", () => {
Expand Down Expand Up @@ -1023,6 +1131,26 @@ describe("removeMemberAcrPolicyUrlAll", () => {
"https://some.pod/policy-resource#policy",
);
});

it("returns the resource unchanged if acr does not have an anchor node", () => {
const accessControlResource = mockAcrFor("https://some.pod/resource");
const existingControl = addUrl(
createThing({ url: getSourceUrl(accessControlResource) }),
acp.accessMembers,
"https://some.pod/policy-resource#policy",
);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
setThing(accessControlResource, existingControl),
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(removeMemberAcrPolicyUrlAll(updatedResource)).toEqual(
updatedResource,
);
});
});

describe("addPolicyUrl", () => {
Expand All @@ -1042,8 +1170,14 @@ describe("addPolicyUrl", () => {
updatedResourceWithAcr.internal_acp.acr,
);

const difference = updatedControls.filter((control) => {
return !oldControls.some((oldControl) => {
return asUrl(control) === asUrl(oldControl);
});
})[0];

expect(updatedControls).toHaveLength(oldControls.length + 1);
expect(getUrl(updatedControls[updatedControls.length - 1], acp.apply)).toBe(
expect(getUrl(difference, acp.apply)).toBe(
"https://some.pod/policy-resource#policy",
);
});
Expand Down Expand Up @@ -1110,10 +1244,17 @@ describe("addMemberPolicyUrl", () => {
const updatedControls = getThingAll(
updatedResourceWithAcr.internal_acp.acr,
);

const difference = updatedControls.filter((control) => {
return !oldControls.some((oldControl) => {
return asUrl(control) === asUrl(oldControl);
});
})[0];

expect(updatedControls).toHaveLength(oldControls.length + 1);
expect(
getUrl(updatedControls[updatedControls.length - 1], acp.applyMembers),
).toBe("https://some.pod/policy-resource#policy");
expect(getUrl(difference, acp.applyMembers)).toBe(
"https://some.pod/policy-resource#policy",
);
});

it("does not remove existing Policy URLs", () => {
Expand Down Expand Up @@ -1276,6 +1417,24 @@ describe("getMemberPolicyUrlAll", () => {

expect(policyUrls).toEqual([]);
});

it("returns the resource unchanged if acr does not have an anchor node", () => {
const accessControlResource = mockAcrFor("https://some.pod/resource");
const existingControl = addUrl(
createThing({ url: getSourceUrl(accessControlResource) }),
acp.applyMembers,
"https://some.pod/policy-resource#policy",
);
const resourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
setThing(accessControlResource, existingControl),
);
const acr = internal_getAcr(resourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(resourceWithAcr, updatedAcr);
expect(getMemberPolicyUrlAll(updatedResource)).toHaveLength(0);
});
});

describe("removePolicyUrl", () => {
Expand Down
24 changes: 23 additions & 1 deletion src/acp/policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
createThing,
getThing,
getThingAll,
removeThing,
setThing,
} from "../thing/thing";
import {
Expand All @@ -45,7 +46,7 @@ import {
getAcrPolicyUrlAll,
getPolicyUrlAll,
} from "./control";
import { internal_getAcr } from "./control.internal";
import { internal_getAcr, internal_setAcr } from "./control.internal";
import { addMockAcrTo, mockAcrFor } from "./mock";
import {
createPolicy,
Expand All @@ -68,6 +69,7 @@ import {
setResourcePolicy,
} from "./policy";
import { fromRdfJsDataset } from "../rdfjs";
import { SolidClientError } from "../interfaces";

jest.spyOn(globalThis, "fetch").mockImplementation(
async () =>
Expand Down Expand Up @@ -1141,6 +1143,26 @@ describe("removeResourceAcrPolicy", () => {

expect(getResourceAcrPolicyAll(updatedPolicyDataset)).toHaveLength(1);
});

it("errors if the acr does not have an anchor node matching its url", () => {
let mockedAcr = mockAcrFor("https://some.pod/resource");
let mockedPolicy1 = createThing({
url: `${getSourceUrl(mockedAcr)}#policy1`,
});
mockedPolicy1 = setUrl(mockedPolicy1, rdf.type, acp.Policy);
mockedAcr = setThing(mockedAcr, mockedPolicy1);
const mockedResourceWithAcr = addMockAcrTo(
mockSolidDatasetFrom("https://some.pod/resource"),
mockedAcr,
);
const acr = internal_getAcr(mockedResourceWithAcr);
const acrUrl = getSourceUrl(acr);
const updatedAcr = removeThing(acr, acrUrl);
const updatedResource = internal_setAcr(mockedResourceWithAcr, updatedAcr);
expect(() => getResourcePolicyAll(updatedResource)).toThrow(
SolidClientError,
);
});
});

describe("setAllowModes", () => {
Expand Down
6 changes: 1 addition & 5 deletions src/acp/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,7 @@ export function getResourcePolicyAll(
return (
getTermAll(acrSubj, acp.accessControl)
.reduce((prev, accessControlId) => {
const accessControl = getThing(acr, accessControlId.value);
if (accessControl === null) {
// If the access control isn't found, there are no policies to add.
return prev;
}
const accessControl = getThing(acr, accessControlId.value)!;
const accessControlPolicies = getTermAll(
accessControl,
acp.apply,
Expand Down

0 comments on commit ed727b0

Please sign in to comment.