Skip to content

Commit

Permalink
Merge branch 'main' into add-access-grant-query-support
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardsph authored Dec 10, 2024
2 parents 77c52e1 + 64af265 commit fe282e8
Show file tree
Hide file tree
Showing 16 changed files with 945 additions and 45 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ The following changes are pending, and will be applied on the next major release

## Unreleased

### New feature (alpha)

- Add support for custom fields. Applications are now able to read and write custom fields
into Access Credentials (both Access Requests and Access Grants).

## [3.1.1](https://github.com/inrupt/solid-client-access-grants-js/releases/tag/v3.1.1) - 2024-10-23

### Patch change
Expand Down
8 changes: 4 additions & 4 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ export default {
// The auto-pickup of fetch is no longer tested because of issues between
// jose (dependency of solid-client-authn) and ts-jest.
// FIXME: some unit tests do not cover node-specific code.
branches: 93,
functions: 93,
lines: 93,
statements: 93,
branches: 90,
functions: 90,
lines: 90,
statements: 90,
},
},
projects: [
Expand Down
14 changes: 11 additions & 3 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2022 Inrupt Inc.
// 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
Expand All @@ -20,6 +20,14 @@
//

import "@inrupt/jest-jsdom-polyfills";

globalThis.fetch = () => {
throw new Error('Global fetch should not be called without being mocked in unit tests')
}
throw new Error(
"Global fetch should not be called without being mocked in unit tests",
);
};

// Crude structuredClone polyfill (missing in JSDom), good enough for our purpose.
globalThis.structuredClone = (val: unknown) => {
return JSON.parse(JSON.stringify(val));
};
121 changes: 121 additions & 0 deletions src/common/getters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,23 @@ import {
import {
AccessGrantWrapper,
getAccessModes,
getCustomBoolean,
getConsent,
getCredentialSubject,
getCustomFields,
getCustomDouble,
getExpirationDate,
getId,
getInbox,
getInherit,
getCustomInteger,
getIssuanceDate,
getIssuer,
getPurposes,
getRequestor,
getResourceOwner,
getResources,
getCustomString,
getTypes,
} from "./getters";
import type { AccessGrant, AccessRequest } from "../gConsent";
Expand Down Expand Up @@ -536,6 +541,122 @@ describe("getters", () => {
});
});

describe("getCustomFields", () => {
it("gets all the custom fields from an access request", async () => {
const customFields = [
{
key: new URL("https://example.org/ns/customString"),
value: "customValue",
},
{
key: new URL("https://example.org/ns/customBoolean"),
value: true,
},
{
key: new URL("https://example.org/ns/customInt"),
value: 1,
},
{
key: new URL("https://example.org/ns/customFloat"),
value: 1.1,
},
];
const gConsentRequest = await mockGConsentRequest({
custom: customFields,
});
expect(getCustomFields(gConsentRequest)).toStrictEqual({
"https://example.org/ns/customString": "customValue",
"https://example.org/ns/customBoolean": true,
"https://example.org/ns/customInt": 1,
"https://example.org/ns/customFloat": 1.1,
});
});

it("returns an empty object if no custom fields are found", async () => {
expect(getCustomFields(await mockGConsentRequest())).toStrictEqual({});
});
});

describe("getCustomInteger", () => {
it("gets an integer value from an access request custom field", async () => {
const customFields = [
{
key: new URL("https://example.org/ns/customInt"),
value: 1,
},
];
const gConsentRequest = await mockGConsentRequest({
custom: customFields,
});
// This shows the typing of the return is correct.
const i: number | undefined = getCustomInteger(
gConsentRequest,
new URL("https://example.org/ns/customInt"),
);
expect(i).toBe(1);
});
});

describe("getCustomBoolean", () => {
it("gets a boolean value from an access request custom field", async () => {
const customFields = [
{
key: new URL("https://example.org/ns/customBoolean"),
value: true,
},
];
const gConsentRequest = await mockGConsentRequest({
custom: customFields,
});
// This shows the typing of the return is correct.
const bool: boolean | undefined = getCustomBoolean(
gConsentRequest,
new URL("https://example.org/ns/customBoolean"),
);
expect(bool).toBe(true);
});
});

describe("getCustomDouble", () => {
it("gets a double value from an access request custom field", async () => {
const customFields = [
{
key: new URL("https://example.org/ns/customDouble"),
value: 1.1,
},
];
const gConsentRequest = await mockGConsentRequest({
custom: customFields,
});
// This shows the typing of the return is correct.
const d: number | undefined = getCustomDouble(
gConsentRequest,
new URL("https://example.org/ns/customDouble"),
);
expect(d).toBe(1.1);
});
});

describe("getCustomString", () => {
it("gets a string value from an access request custom field", async () => {
const customFields = [
{
key: new URL("https://example.org/ns/customString"),
value: "some value",
},
];
const gConsentRequest = await mockGConsentRequest({
custom: customFields,
});
// This shows the typing of the return is correct.
const s: string | undefined = getCustomString(
gConsentRequest,
new URL("https://example.org/ns/customString"),
);
expect(s).toBe("some value");
});
});

describe("AccessGrant", () => {
it("wraps calls to the underlying functions", async () => {
const wrappedConsentRequest = new AccessGrantWrapper(
Expand Down
Loading

0 comments on commit fe282e8

Please sign in to comment.