cumulocity-cypress
Version:
Cypress commands for Cumulocity IoT
156 lines (155 loc) • 6.55 kB
JavaScript
import { FetchClient, } from "@c8y/client";
import { getCookieValue, toWindowFetchResponse, wrapFetchResponse, } from "../../shared/c8yclient";
import { isAuthOptions } from "../../shared/auth";
import { getAuthOptions, getBaseUrlFromEnv, getC8yClientAuthentication, } from "../utils";
import { get_i } from "../../shared/util";
const { _ } = Cypress;
export class C8yPactFetchClient extends FetchClient {
constructor(options) {
const auth = getC8yClientAuthentication(options.auth);
const url = options.baseUrl || getBaseUrlFromEnv();
let authOptions;
if (_.isString(auth)) {
authOptions = getAuthOptions(auth);
}
else if (isAuthOptions(auth)) {
authOptions = auth;
}
if (!url) {
throw new Error("C8yPactFetchClient Error. No baseUrl provided.");
}
const [user, userAlias] = [
// @ts-expect-error
authOptions?.user || auth?.user || Cypress.env("C8Y_LOGGED_IN_USER"),
authOptions?.userAlias || Cypress.env("C8Y_LOGGED_IN_USER_ALIAS"),
];
super(auth, url);
this.authOptions = authOptions;
this.authentication = auth;
this.cypresspact = options?.cypresspact;
this.user = user;
this.userAlias = userAlias;
}
getUser() {
return [this.user, this.userAlias];
}
async fetch(url, fetchOptions) {
const setUserEnv = () => {
Cypress.env("C8Y_LOGGED_IN_USER_ALIAS", this.userAlias);
Cypress.env("C8Y_LOGGED_IN_USER", this.user);
};
const isRecordingEnabled = this.cypresspact?.isRecordingEnabled() === true;
const isMockingEnabled = this.cypresspact?.isMockingEnabled() === true;
const currentPact = this.cypresspact?.current;
if (!isRecordingEnabled && isMockingEnabled) {
const fullUrl = this.getUrl(url, fetchOptions);
const relativeUrl = fullUrl.replace(this.baseUrl || "", "");
let strictMocking = this.cypresspact?.getConfigValue("strictMocking") === true;
const consoleProps = {
pact: currentPact,
url: fullUrl,
relativeUrl,
strictMocking,
fetchOptions,
baseUrl: this.baseUrl,
authentication: this.authentication,
};
let logger = undefined;
if (this.cypresspact?.debugLog === true) {
logger = Cypress.log({
autoEnd: false,
name: "c8ypact",
message: `mock ${relativeUrl || null}`,
consoleProps: () => consoleProps,
});
}
if (currentPact) {
let record = currentPact.nextRecordMatchingRequest({
url: fullUrl?.replace(this.baseUrl || "", ""),
method: fetchOptions?.method,
});
consoleProps.record = record;
if (record) {
if (_.isFunction(this.cypresspact?.on.mockRecord)) {
record = this.cypresspact?.on.mockRecord(record) || null;
consoleProps.record = record;
}
if (record) {
const response = toWindowFetchResponse(record);
consoleProps.mockedResponse = response || null;
if (response) {
logger?.end();
return Promise.resolve(response);
}
}
else {
strictMocking = false;
}
}
}
logger?.end();
if (strictMocking) {
const error = new Error(`Mocking failed in C8yPactFetchClient. No recording found for request "${relativeUrl}". Do re-recording or disable Cypress.c8ypact.config.strictMocking.`);
error.name = "C8yPactError";
throw error;
}
else if (this.authentication == null) {
const error = new Error(`Mocking failed in C8yPactFetchClient. No recording found for request "${relativeUrl}". If strictMocking is disabled, authentication is required.`);
error.name = "C8yPactError";
throw error;
}
}
try {
const response = await super.fetch(url, fetchOptions);
if (this.cypresspact == null || !isRecordingEnabled) {
return Promise.resolve(response);
}
const result = await this.savePact(response, url, fetchOptions);
return Promise.resolve(result);
}
catch (failure) {
if (this.cypresspact == null || !isRecordingEnabled) {
setUserEnv();
return Promise.reject(failure);
}
const result = await this.savePact(failure, url, fetchOptions);
return Promise.reject(result);
}
}
getFetchOptions(options) {
const result = super.getFetchOptions(options);
// for full authentication xsrf token and bearer token are required
// always add Bearer token if no authorization header is set
if (!get_i(result, "headers.Authorization")) {
const bearer = this.authOptions?.bearer || getCookieValue("Authorization");
if (bearer) {
// xsrf token header is set in CookieAuth
result.headers = Object.assign({ Authorization: `Bearer ${bearer}` }, result.headers);
}
}
return result;
}
async savePact(response, url, fetchOptions) {
let result = response;
let responseObj = response.responseObj;
if (!response.responseObj) {
const fullUrl = this.getUrl(url, fetchOptions);
result = await wrapFetchResponse(response, {
url: new URL(fullUrl, this.baseUrl),
fetchOptions: this.getFetchOptions(fetchOptions),
});
responseObj = result.responseObj;
}
else {
delete response.responseObj;
}
await this.cypresspact?.savePact(responseObj, {
_auth: this.authentication,
}, {
noqueue: true,
loggedInUser: this.user,
loggedInUserAlias: this.userAlias,
});
return result;
}
}