passbolt-styleguide
Version:
Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.
796 lines (700 loc) • 29.7 kB
JavaScript
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 2.13.0
*/
import { ApiClient } from "./apiClient";
import { ApiClientOptions } from "./apiClientOptions";
import { enableFetchMocks } from "jest-fetch-mock";
import each from "jest-each";
import { v4 as uuid } from "uuid";
import PassboltBadResponseError from "../Error/PassboltBadResponseError";
import PassboltServiceUnavailableError from "../Error/PassboltServiceUnavailableError";
import PassboltApiFetchError from "../Error/PassboltApiFetchError";
beforeEach(() => {
jest.clearAllMocks();
enableFetchMocks();
});
//@todo: put in a mock lib like it is done in passbolt-browser-extension
const mockApiResponseError = (status, errorMessage, body = {}) =>
Promise.resolve({
status: status,
body: JSON.stringify({
header: {
message: errorMessage,
status: status,
},
body: body,
}),
});
const mockApiResponse = (body = {}, header = {}) => Promise.resolve(JSON.stringify({ header: header, body: body }));
describe("Unit testing apiClient with mocked fetch", () => {
const responseHtml = "<html><head></head><body></body></html>";
const responseJson = JSON.stringify({
header: {
test: "test",
},
body: {
resource: {},
},
});
const url = "https://test.passbolt.com/passbolt-unit-test";
const resourceName = "fake-resource";
const options = new ApiClientOptions().setBaseUrl(url).setResourceName(resourceName);
each([
{ responseBody: responseHtml, method: "GET" },
{ responseBody: responseHtml, method: "POST" },
{ responseBody: responseJson, method: "GET" },
{ responseBody: responseJson, method: "POST" },
]).describe(`Should call the endpoint and return the response as-is with sendRequest`, (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(4);
const testClient = new ApiClient(options);
const currentUrl = new URL(url);
const spyOnAssertUrl = jest.spyOn(testClient, "assertUrl");
const spyOnAssertMethod = jest.spyOn(testClient, "assertMethod");
const spyOnAssertBody = jest.spyOn(testClient, "assertBody");
fetch.mockResponseOnce(async () => scenario.responseBody);
const result = await testClient.sendRequest(scenario.method, currentUrl);
expect(result.text()).resolves.toStrictEqual(scenario.responseBody);
expect(spyOnAssertUrl).toHaveBeenLastCalledWith(currentUrl);
expect(spyOnAssertMethod).toHaveBeenLastCalledWith(scenario.method);
expect(spyOnAssertBody).not.toHaveBeenCalled();
});
});
it("Should call the endpoint with form data body and return the response as-is with sendRequest", async () => {
expect.assertions(4);
const testClient = new ApiClient(options);
const currentUrl = new URL(url);
const spyOnAssertUrl = jest.spyOn(testClient, "assertUrl");
const spyOnAssertMethod = jest.spyOn(testClient, "assertMethod");
const spyOnAssertBody = jest.spyOn(testClient, "assertBody");
const body = new FormData();
body.append("data[test]", "test");
fetch.mockResponseOnce(async () => responseJson);
const result = await testClient.sendRequest("POST", currentUrl, body);
expect(result.text()).resolves.toStrictEqual(responseJson);
expect(spyOnAssertUrl).toHaveBeenLastCalledWith(currentUrl);
expect(spyOnAssertMethod).toHaveBeenLastCalledWith("POST");
expect(spyOnAssertBody).toHaveBeenCalledWith(body);
});
each([
{ responseBody: responseJson, method: "GET" },
{ responseBody: responseJson, method: "POST" },
]).describe(`should call the endpoint and parse the response as JSON with fetchAndHandleResponse`, (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(4);
const testClient = new ApiClient(options);
const currentUrl = new URL(url);
const spyOnAssertUrl = jest.spyOn(testClient, "assertUrl");
const spyOnAssertMethod = jest.spyOn(testClient, "assertMethod");
const spyOnAssertBody = jest.spyOn(testClient, "assertBody");
fetch.mockResponseOnce(async () => scenario.responseBody);
const result = await testClient.fetchAndHandleResponse(scenario.method, currentUrl);
expect(result).toStrictEqual(JSON.parse(scenario.responseBody));
expect(spyOnAssertUrl).toHaveBeenLastCalledWith(currentUrl);
expect(spyOnAssertMethod).toHaveBeenLastCalledWith(scenario.method);
expect(spyOnAssertBody).not.toHaveBeenCalled();
});
});
it("should throw an exception if server respond with an error", async () => {
expect.assertions(1);
const testClient = new ApiClient(options);
const currentUrl = new URL(url);
const errorMessage = "Something went wrong!";
fetch.mockResponse(() => {
throw new Error(errorMessage);
});
expect(testClient.fetchAndHandleResponse("POST", currentUrl)).rejects.toThrowError(PassboltServiceUnavailableError);
});
it("should throw an exception if server respond with an error", async () => {
expect.assertions(1);
const testClient = new ApiClient(options);
const currentUrl = new URL(url);
const errorMessage = "Something went wrong!";
fetch.mockResponse(() => mockApiResponseError(500, errorMessage));
expect(testClient.fetchAndHandleResponse("POST", currentUrl)).rejects.toThrowError(
new PassboltApiFetchError(errorMessage),
);
});
it("should throw an exception if response is not JSON but JSON is expected", async () => {
expect.assertions(1);
const testClient = new ApiClient(options);
const currentUrl = new URL(url);
fetch.mockResponse(async () => responseHtml);
expect(testClient.fetchAndHandleResponse("POST", currentUrl)).rejects.toThrowError(PassboltBadResponseError);
});
const assertUrlEmptyError = new TypeError("ApliClient.assertUrl error: url is required.");
const assertUrlInvalidError = new TypeError("ApliClient.assertUrl error: url should be a valid URL object.");
const assertUrlInvalidProtocolError = new TypeError(
"ApliClient.assertUrl error: url protocol should only be https or http.",
);
each([
{ url: null, error: assertUrlEmptyError },
{ url: undefined, error: assertUrlEmptyError },
{ url: false, error: assertUrlEmptyError },
{ url: 0, error: assertUrlEmptyError },
{ url: 1, error: assertUrlInvalidError },
{ url: "test", error: assertUrlInvalidError },
{ url: "file:///etc/", error: assertUrlInvalidError },
{ url: "https://www.passbolt.com", error: assertUrlInvalidError },
{ url: new URL("file:///etc/"), error: assertUrlInvalidProtocolError },
{ url: new URL("ssh://passbolt.com"), error: assertUrlInvalidProtocolError },
{ url: new URL("chrome-extension://passbolt.com"), error: assertUrlInvalidProtocolError },
]).describe("should throw an Error if the URL can't be asserted", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertUrl");
fetch.mockResponse(async () => responseJson);
try {
await testClient.sendRequest("GET", scenario.url);
} catch (e) {
expect(e).toStrictEqual(scenario.error);
}
try {
await testClient.fetchAndHandleResponse("GET", scenario.url);
} catch (e) {
expect(e).toStrictEqual(scenario.error);
}
expect(spy).toHaveBeenCalledTimes(2);
});
});
each([
{ url: new URL("https://www.passbolt.com") },
{ url: new URL("https://www.passbolt.com/sub-folder/") },
{ url: new URL("https://www.google.com") },
]).describe("should successfully assert the URL if it's correct", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertUrl");
fetch.mockResponse(async () => responseJson);
expect(testClient.sendRequest("GET", scenario.url)).resolves.not.toThrow();
expect(testClient.fetchAndHandleResponse("GET", scenario.url)).resolves.not.toThrow();
expect(spy).toHaveBeenCalledTimes(2);
});
});
const assertMethodTypeError = new TypeError("ApiClient.assertValidMethod method should be a string.");
each([
{ method: null, error: assertMethodTypeError },
{ method: undefined, error: assertMethodTypeError },
{ method: false, error: assertMethodTypeError },
{ method: 0, error: assertMethodTypeError },
{ method: 1, error: assertMethodTypeError },
]).describe("should throw an Error if the method is not a string", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertMethod");
const currentUrl = new URL(url);
fetch.mockResponse(async () => responseJson);
try {
await testClient.sendRequest(scenario.method, currentUrl);
} catch (e) {
expect(e).toStrictEqual(scenario.error);
}
try {
await testClient.fetchAndHandleResponse(scenario.method, currentUrl);
} catch (e) {
expect(e).toStrictEqual(scenario.error);
}
expect(spy).toHaveBeenCalledTimes(2);
});
});
each([{ method: "HEAD" }, { method: "OPTION" }, { method: "head" }, { method: "option" }]).describe(
"should throw an Error if the method is not unsupported",
(scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertMethod");
const assertMethodUnsupportedError = new TypeError(
`ApiClient.assertValidMethod error: method ${scenario.method} is not supported.`,
);
const currentUrl = new URL(url);
fetch.mockResponse(async () => responseJson);
try {
await testClient.sendRequest(scenario.method, currentUrl);
} catch (e) {
expect(e).toStrictEqual(assertMethodUnsupportedError);
}
try {
await testClient.fetchAndHandleResponse(scenario.method, currentUrl);
} catch (e) {
expect(e).toStrictEqual(assertMethodUnsupportedError);
}
expect(spy).toHaveBeenCalledTimes(2);
});
},
);
each([
{ method: "GET" },
{ method: "POST" },
{ method: "PUT" },
{ method: "DELETE" },
{ method: "get" },
{ method: "post" },
{ method: "put" },
{ method: "delete" },
]).describe("should successfully assert the method if it's correct", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertMethod");
const currentUrl = new URL(url);
fetch.mockResponse(async () => responseJson);
expect(testClient.sendRequest(scenario.method, currentUrl)).resolves.not.toThrow();
expect(testClient.fetchAndHandleResponse(scenario.method, currentUrl)).resolves.not.toThrow();
expect(spy).toHaveBeenCalledTimes(2);
});
});
const assertIdEmptyError = new TypeError("ApiClient.assertValidId error: id cannot be empty");
const assertIdTypeError = new TypeError("ApiClient.assertValidId error: id should be a string");
each([
{ id: null, error: assertIdEmptyError },
{ id: undefined, error: assertIdEmptyError },
{ id: false, error: assertIdEmptyError },
{ id: 0, error: assertIdEmptyError },
{ id: {}, error: assertIdTypeError },
]).describe("should throw an Error if the ID can't be asserted", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(1);
const testClient = new ApiClient(options);
try {
testClient.assertValidId(scenario.id);
} catch (e) {
expect(e).toStrictEqual(scenario.error);
}
});
});
each([{ id: "https://www.passbolt.com" }, { id: uuid() }, { id: "me" }, { id: "test.json" }]).describe(
"should successfully assert the ID if it's correct",
(scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, () => {
expect.assertions(1);
const testClient = new ApiClient(options);
expect(() => testClient.assertValidId(scenario.id)).not.toThrow();
});
},
);
const assertBodyError = new TypeError(`ApiClient.assertBody error: body should be a string or a FormData.`);
each([
{ body: 1, error: assertBodyError },
{ body: true, error: assertBodyError },
{ body: [], error: assertBodyError },
{ body: {}, error: assertBodyError },
]).describe("should throw an Error if the body is not a string", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertBody");
const currentUrl = new URL(url);
fetch.mockResponse(async () => responseJson);
try {
await testClient.sendRequest("POST", currentUrl, scenario.body);
} catch (e) {
expect(e).toStrictEqual(assertBodyError);
}
try {
await testClient.fetchAndHandleResponse("POST", currentUrl, scenario.body);
} catch (e) {
expect(e).toStrictEqual(assertBodyError);
}
expect(spy).toHaveBeenCalledTimes(2);
});
});
each([{ body: null }, { body: undefined }, { body: 0 }]).describe(
"should ignore the body if it has a falsy value",
(scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertBody");
const currentUrl = new URL(url);
fetch.mockResponse(async (req) => {
const body = await req.text();
expect(body).toStrictEqual("");
return responseJson;
});
expect(testClient.sendRequest("POST", currentUrl, scenario.body)).resolves.not.toThrow();
expect(testClient.fetchAndHandleResponse("POST", currentUrl, scenario.body)).resolves.not.toThrow();
expect(spy).not.toHaveBeenCalled();
});
},
);
each([{ body: JSON.stringify({ string: "string", object: {}, array: [] }) }, { body: uuid() }]).describe(
"should send the given body if it is a string or a form data",
(scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "assertBody");
const currentUrl = new URL(url);
fetch.mockResponse(async (req) => {
const body = await req.text();
expect(body).toStrictEqual(scenario.body);
return responseJson;
});
expect(testClient.sendRequest("POST", currentUrl, scenario.body)).resolves.not.toThrow();
expect(testClient.fetchAndHandleResponse("POST", currentUrl, scenario.body)).resolves.not.toThrow();
expect(spy).toHaveBeenCalledTimes(2);
});
},
);
const userUuid = uuid();
each([
{
expectedUrl: "https://test.passbolt.com/resource.json?api-version=v2",
url: "https://test.passbolt.com/resource",
options: undefined,
},
{
expectedUrl: `https://test.passbolt.com/resource.json?api-version=v2&filter%5Bhas-users%5D=${userUuid}`,
url: "https://test.passbolt.com/resource",
options: { "filter[has-users]": userUuid },
},
{
expectedUrl: `https://test.passbolt.com/resource.json?api-version=v2&filter%5Bhas-users%5D=${userUuid}&filter%5Bsearch%5D=something`,
url: "https://test.passbolt.com/resource",
options: {
"filter[has-users]": userUuid,
"filter[search]": "something",
},
},
{
expectedUrl: "https://test.passbolt.com/resource.json?api-version=v2&contain%5Bpermissions.user.profile%5D=1",
url: "https://test.passbolt.com/resource",
options: {
"contain[permissions.user.profile]": "1",
},
},
{
expectedUrl:
"https://test.passbolt.com/resource.json?api-version=v2&contain%5Bpermissions.user.profile%5D=1&contain%5Bpermissions.group%5D=1",
url: "https://test.passbolt.com/resource",
options: {
"contain[permissions.user.profile]": "1",
"contain[permissions.group]": "1",
},
},
{
expectedUrl: `https://test.passbolt.com/resource.json?api-version=v2&filter%5Bhas-users%5D=${userUuid}&contain%5Bpermissions.user.profile%5D=1`,
url: "https://test.passbolt.com/resource",
options: {
"filter[has-users]": userUuid,
"contain[permissions.user.profile]": "1",
},
},
{
expectedUrl: `https://test.passbolt.com/resource.json?api-version=v2&filter%5Bhas-users%5D=${userUuid}&filter%5Bsearch%5D=something&contain%5Bpermissions.user.profile%5D=1&contain%5Bpermissions.group%5D=1`,
url: "https://test.passbolt.com/resource",
options: {
"filter[has-users]": userUuid,
"filter[search]": "something",
"contain[permissions.user.profile]": "1",
"contain[permissions.group]": "1",
},
},
]).describe("should run the build URL properly", (scenario) => {
it(`scenario: ${JSON.stringify(scenario)}`, async () => {
expect.assertions(1);
const testClient = new ApiClient(options);
const url = testClient.buildUrl(scenario.url, scenario.options);
expect(url.toString()).toStrictEqual(scenario.expectedUrl);
});
});
it("should call GET with an id for a resource", async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spyFetch = jest.spyOn(testClient, "fetchAndHandleResponse");
const spyAssertId = jest.spyOn(testClient, "assertValidId");
const resourceId = uuid();
const responseData = {
id: resourceId,
data: "fake-data",
};
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.get(resourceId);
expect(result).toStrictEqual(expectedResponse);
expect(spyFetch).toHaveBeenCalledTimes(1);
expect(spyFetch).toHaveBeenCalledWith("GET", new URL(`${url}/${resourceName}/${resourceId}.json?api-version=v2`));
expect(spyAssertId).toHaveBeenCalledTimes(1);
expect(spyAssertId).toHaveBeenCalledWith(resourceId);
});
it("should call DELETE with an id for a resource", async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spyFetch = jest.spyOn(testClient, "fetchAndHandleResponse");
const spyAssertId = jest.spyOn(testClient, "assertValidId");
const resourceId = uuid();
const responseData = {
id: resourceId,
data: "fake-data",
};
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.delete(resourceId);
expect(result).toStrictEqual(expectedResponse);
expect(spyFetch).toHaveBeenCalledTimes(1);
expect(spyFetch).toHaveBeenCalledWith(
"DELETE",
new URL(`${url}/${resourceName}/${resourceId}.json?api-version=v2`),
null,
);
expect(spyAssertId).toHaveBeenCalledTimes(1);
expect(spyAssertId).toHaveBeenCalledWith(resourceId);
});
it("should call DELETE (dry-run) with an id for a resource", async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spyFetch = jest.spyOn(testClient, "fetchAndHandleResponse");
const spyAssertId = jest.spyOn(testClient, "assertValidId");
const resourceId = uuid();
const responseData = {
id: resourceId,
data: "fake-data",
};
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.delete(resourceId, null, {}, true);
expect(result).toStrictEqual(expectedResponse);
expect(spyFetch).toHaveBeenCalledTimes(1);
expect(spyFetch).toHaveBeenCalledWith(
"DELETE",
new URL(`${url}/${resourceName}/${resourceId}/dry-run.json?api-version=v2`),
null,
);
expect(spyAssertId).toHaveBeenCalledTimes(1);
expect(spyAssertId).toHaveBeenCalledWith(resourceId);
});
it("should call GET (find all) without id", async () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "fetchAndHandleResponse");
const responseData = [
{
id: uuid(),
data: "fake-data",
},
{
id: uuid(),
data: "fake-data",
},
];
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.findAll();
expect(result).toStrictEqual(expectedResponse);
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith("GET", new URL(`${url}/${resourceName}.json?api-version=v2`));
});
it("should call POST (create) without id", async () => {
expect.assertions(3);
const testClient = new ApiClient(options);
const spy = jest.spyOn(testClient, "fetchAndHandleResponse");
const resourceId = uuid();
const body = {
data: "fake-data",
};
const responseData = { id: resourceId, ...body };
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.create(body);
expect(result).toStrictEqual(expectedResponse);
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith(
"POST",
new URL(`${url}/${resourceName}.json?api-version=v2`),
JSON.stringify(body),
);
});
it("should call PUT (update) with an id for a resource", async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spyFetch = jest.spyOn(testClient, "fetchAndHandleResponse");
const spyAssertId = jest.spyOn(testClient, "assertValidId");
const resourceId = uuid();
const body = {
id: resourceId,
data: "fake-data",
};
const responseData = { id: resourceId, ...body };
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.update(resourceId, body);
expect(result).toStrictEqual(expectedResponse);
expect(spyFetch).toHaveBeenCalledTimes(1);
expect(spyFetch).toHaveBeenCalledWith(
"PUT",
new URL(`${url}/${resourceName}/${resourceId}.json?api-version=v2`),
JSON.stringify(body),
);
expect(spyAssertId).toHaveBeenCalledTimes(1);
expect(spyAssertId).toHaveBeenCalledWith(resourceId);
});
it("should call PUT (update dry-run) with an id for a resource", async () => {
expect.assertions(5);
const testClient = new ApiClient(options);
const spyFetch = jest.spyOn(testClient, "fetchAndHandleResponse");
const spyAssertId = jest.spyOn(testClient, "assertValidId");
const resourceId = uuid();
const body = {
id: resourceId,
data: "fake-data",
};
const responseData = { id: resourceId, ...body };
const expectedResponse = JSON.parse(await mockApiResponse(responseData));
fetch.mockResponse(() => mockApiResponse(responseData));
const result = await testClient.update(resourceId, null, {}, true);
expect(result).toStrictEqual(expectedResponse);
expect(spyFetch).toHaveBeenCalledTimes(1);
expect(spyFetch).toHaveBeenCalledWith(
"PUT",
new URL(`${url}/${resourceName}/${resourceId}/dry-run.json?api-version=v2`),
null,
);
expect(spyAssertId).toHaveBeenCalledTimes(1);
expect(spyAssertId).toHaveBeenCalledWith(resourceId);
});
each([
{ baseUrl: "http://local.passbolt.dev", resourceName: "/resource", expected: "http://local.passbolt.dev/resource" },
{
baseUrl: "http://local.passbolt.dev/",
resourceName: "/resource",
expected: "http://local.passbolt.dev/resource",
},
{ baseUrl: "http://local.passbolt.dev", resourceName: "resource", expected: "http://local.passbolt.dev/resource" },
{ baseUrl: "http://local.passbolt.dev/", resourceName: "resource", expected: "http://local.passbolt.dev/resource" },
{
baseUrl: "http://local.passbolt.dev",
resourceName: "/resource/other",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/",
resourceName: "/resource/other",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev",
resourceName: "resource/other",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/",
resourceName: "resource/other",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev",
resourceName: "/resource/other/",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/",
resourceName: "/resource/other/",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev",
resourceName: "resource/other/",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/",
resourceName: "resource/other/",
expected: "http://local.passbolt.dev/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder",
resourceName: "/resource",
expected: "http://local.passbolt.dev/subfolder/resource",
},
{
baseUrl: "http://local.passbolt.dev/subfolder/",
resourceName: "/resource",
expected: "http://local.passbolt.dev/subfolder/resource",
},
{
baseUrl: "http://local.passbolt.dev/subfolder",
resourceName: "resource",
expected: "http://local.passbolt.dev/subfolder/resource",
},
{
baseUrl: "http://local.passbolt.dev/subfolder/",
resourceName: "resource",
expected: "http://local.passbolt.dev/subfolder/resource",
},
{
baseUrl: "http://local.passbolt.dev/subfolder",
resourceName: "/resource/other",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder/",
resourceName: "/resource/other",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder",
resourceName: "resource/other",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder/",
resourceName: "resource/other",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder",
resourceName: "/resource/other/",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder/",
resourceName: "/resource/other/",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder",
resourceName: "resource/other/",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
{
baseUrl: "http://local.passbolt.dev/subfolder/",
resourceName: "resource/other/",
expected: "http://local.passbolt.dev/subfolder/resource/other",
},
]).describe(
"Should set a proper baseUrl with ending slashes in baseUrl and starting slash in resource name",
(scenario) => {
it(`with the URL: ${scenario.baseUrl}/${scenario.resourceName}`, async () => {
expect.assertions(1);
const options = new ApiClientOptions().setBaseUrl(scenario.baseUrl).setResourceName(scenario.resourceName);
const apiClient = new ApiClient(options);
expect(apiClient.baseUrl.toString()).toStrictEqual(scenario.expected);
});
},
);
it("should use a custom fetch strategy if provided.", async () => {
expect.assertions(2);
global.customApiClientFetch = jest.fn();
const url = "https://test.passbolt.com/passbolt-unit-test";
const resourceName = "fake-resource";
const options = new ApiClientOptions().setBaseUrl(url).setResourceName(resourceName);
const apiClient = new ApiClient(options);
await expect(apiClient.sendRequest("GET", new URL(`${url}/test.json`))).resolves.not.toThrow();
expect(global.customApiClientFetch).toHaveBeenCalled();
delete global.customApiClientFetch;
});
});