camunda-external-task-client-js
Version:
Implement your [BPMN Service Task](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/) in NodeJS.
213 lines (189 loc) • 6.5 kB
JavaScript
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { jest } from "@jest/globals";
import got from "got";
import KeycloakAuthInterceptor from "./KeycloakAuthInterceptor.js";
import {
MISSING_KEYCLOAK_AUTH_PARAMS,
UNEXPECTED_KEYCLOAK_TOKEN_RESULT,
} from "./__internal/errors.js";
describe("KeycloakAuthInterceptor", () => {
afterEach(() => {
got.mockClear();
});
test("should throw error if tokenEndpoint, clientId or clientSecret are missing", () => {
expect(() => new KeycloakAuthInterceptor()).toThrowError(
MISSING_KEYCLOAK_AUTH_PARAMS
);
expect(
() => new KeycloakAuthInterceptor({ tokenEndpoint: "some endpoint" })
).toThrowError(MISSING_KEYCLOAK_AUTH_PARAMS);
expect(
() => new KeycloakAuthInterceptor({ clientId: "some id" })
).toThrowError(MISSING_KEYCLOAK_AUTH_PARAMS);
expect(
() => new KeycloakAuthInterceptor({ clientSecret: "some secret" })
).toThrowError(MISSING_KEYCLOAK_AUTH_PARAMS);
expect(
() =>
new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
})
).toThrowError(MISSING_KEYCLOAK_AUTH_PARAMS);
expect(
() =>
new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientSecret: "some secret",
})
).toThrowError(MISSING_KEYCLOAK_AUTH_PARAMS);
expect(
() =>
new KeycloakAuthInterceptor({
clientId: "some password",
clientSecret: "some secret",
})
).toThrowError(MISSING_KEYCLOAK_AUTH_PARAMS);
});
test("should throw error if token endpoint returns unexpected HTTP response", async () => {
// given
const response = {
body: "Some keycloak error",
statusCode: 400,
statusMessage: "Bad request",
};
const error = new got.HTTPError(response);
error.response = response;
got.mockReturnValue({ json: () => Promise.reject(error) });
const keycloakAuthInterceptor = new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
clientSecret: "some secret",
});
// when
const { hooks } = keycloakAuthInterceptor({});
const hook = hooks.beforeRequest[0];
// then
try {
await hook({});
} catch (e) {
expect(e).toEqual(
new Error(
`${UNEXPECTED_KEYCLOAK_TOKEN_RESULT} status: 400; body: Some keycloak error`
)
);
}
});
test("should throw error if token doesn't contains the access token", async () => {
// given
got.mockReturnValue({ json: () => Promise.resolve({}) });
const keycloakAuthInterceptor = new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
clientSecret: "some secret",
});
// when
const { hooks } = keycloakAuthInterceptor({});
const hook = hooks.beforeRequest[0];
// then
try {
await hook({});
} catch (e) {
expect(e).toEqual(
new Error(
`${UNEXPECTED_KEYCLOAK_TOKEN_RESULT} token without access_token property: {}`
)
);
}
});
test("should add auth token to intercepted config", async () => {
// given
got.mockReturnValue({
json: () => Promise.resolve({ access_token: "1234567890" }),
});
const keycloakAuthInterceptor = new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
clientSecret: "some secret",
});
const options = { key: "some value" };
// when
const { hooks } = keycloakAuthInterceptor({});
const hook = hooks.beforeRequest[0];
await hook(options);
// then
expect(options).toMatchSnapshot();
});
test("should cache the token response if token expiry is greater than cacheOffset", async () => {
// given
const tokenResponse = { access_token: "1234567890", expires_in: 5 };
got.mockReturnValue({ json: () => Promise.resolve(tokenResponse) });
const keycloakAuthInterceptor = new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
clientSecret: "some secret",
cacheOffset: 0,
});
// when
const { hooks } = keycloakAuthInterceptor({});
const hook = hooks.beforeRequest[0];
await hook({});
await hook({});
// then
expect(got).toHaveBeenCalledTimes(1);
});
test("should not cache the token response if token expiry is less than cacheOffset", async () => {
// given
const tokenResponse = { access_token: "1234567890", expires_in: 5 };
got.mockReturnValue({ json: () => Promise.resolve(tokenResponse) });
const keycloakAuthInterceptor = new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
clientSecret: "some secret",
cacheOffset: 10,
});
// when
const { hooks } = keycloakAuthInterceptor({});
const hook = hooks.beforeRequest[0];
await hook({});
await hook({});
// then
expect(got).toHaveBeenCalledTimes(2);
});
test("should clear the token cache", async () => {
jest.useFakeTimers();
// given
const tokenResponse = { access_token: "1234567890", expires_in: 5 };
got.mockReturnValue({ json: () => Promise.resolve(tokenResponse) });
const keycloakAuthInterceptor = new KeycloakAuthInterceptor({
tokenEndpoint: "some endpoint",
clientId: "some id",
clientSecret: "some secret",
cacheOffset: 0,
});
// when
const { hooks } = keycloakAuthInterceptor({});
const hook = hooks.beforeRequest[0];
await hook({});
jest.runAllTimers();
await hook({});
// then
expect(got).toHaveBeenCalledTimes(2);
jest.useRealTimers();
});
});