UNPKG

@sap_oss/wdio-qmate-service

Version:

[![REUSE status](https://api.reuse.software/badge/github.com/SAP/wdio-qmate-service)](https://api.reuse.software/info/github.com/SAP/wdio-qmate-service)[![Node.js CI](https://github.com/SAP/wdio-qmate-service/actions/workflows/node.js.yml/badge.svg)](http

436 lines 18.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OData = void 0; // =================================== CONSTANTS ================================ const SERVICE_INIT_ERROR = "Service instance not found. Make sure the service is initialized and passed to the request."; const entitySetError = (entitySet) => `Entity Set "${entitySet}" not found in service.`; // =================================== MAIN ===================================== /** * @class odata * @memberof service */ class OData { utilModule = require("util"); urlLib = require("url").URL; axios = require("axios"); Service; constructor() { try { this.Service = require("@sap_oss/odata-library").Service; } catch (error) { util.console.error("OData test client Service issue: Probably @sap_oss/odata-library was not installed as a npm module."); } } /** * @function init * @memberOf service.odata * @description Initializes the OData Service. * XCSRF-Token will be automatically fetched and stored in the service instance. * Cookies will also automatically assembled and stored in the service instance. * @param {String} url - The base url of the service. * @param {String} username - The username to authenticate the service. * @param {String} password - The password of the username. * @param {Boolean} [loggingEnabled=false] - The boolean param to control whether user wants to see logs during build run. * @param {Object} [params={}] - JSON object with key-value pairs of parameter names and corresponding values. * By default we send { * "client": "715", * "documentation": ["heading", "quickinfo"], * "language": "EN" * } * These can be overridden by sending params as JSON object with additional params as shown in example. * @param {String} [authType] - authentication type, in case you want to override the default * SAML authentication. Set this to "basic", to use basic authentication for communication users for whom SAML login doesn't work. * Or "none" for no authentication. * @param {Object} [headers=undefined] - JSON object with key-value pairs of optional headers. * @returns {Object} The initialized service object. * @example const url = "<urlToSystem>/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/"; * const params = { * "saml2": "disabled", * "language": "de" * } * const srv = await service.odata.init(url, user, password, false, params); * @example const base64Credentials = Buffer.from(`${user}:${password}`).toString("base64"); * const authHeaders = { * "Authorization": `Basic ${base64Credentials}`, * "DwC-Tenant": tenant * }; * * const srv = await service.odata.init(url, user, password, true, params, "headers", authHeaders); */ async init(url, username, password, loggingEnabled = false, params = {}, authType, headers) { const logger = { trace: () => { }, debug: console.debug, info: console.info, warn: console.warn, error: console.error }; const auth = createAuthObject(); const srv = new this.Service({ logger: loggingEnabled ? logger : "", url: url, auth: auth, parameters: params, strict: false }); await srv.init; return srv; function createAuthObject() { const auth = { username: username, password: password }; if (authType) auth.type = authType; if (headers && Object.entries(headers).length > 0) auth.headers = headers; return auth; } } /** * @function get * @memberOf service.odata * @description Sends a GET request to retrieve data from the specified OData entity set. * @param {Object} srv - An instance of the service. * @param {String} entitySet - The entity set from which data is to be retrieved. * @param {Object} keys - The required keys for the GET request. * @param {Boolean} [raw=false] - Specifies whether the response should include all header contents. * @param {Object} [headers] - Optional headers to be included in the request. * @param {Object} [queryParams] - JSON object of key value pairs of custom query parameters. * @returns {Promise} A Promise that resolves to the response data. * @example const url = "<baseUrl>/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/"; * const srv = await service.odata.init(url, user, password); * const keys = { * PurchaseOrder: "4100000000" * }; * const queryParams = { * "$top" : 5, * "$skip" : 10, * }; * const headers = { * 'X-Custom-Header': 'foobar' * } * const res = await service.odata.get(srv, "A_PurchaseOrder", keys, false, headers, queryParams); */ async get(srv, entitySet, keys, raw = false, headers, queryParams) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let entity = srv[entitySet]; if (!entity) throw new Error(entitySetError(entitySet)); if (headers) entity = this._applyHeaders(entity, headers); if (queryParams) entity = this._applyQueryParameters(entity, queryParams); if (raw) entity = entity.raw(); if (keys && Object.entries(keys).length > 0) { return entity.get(keys); } else { return entity.get(); } } /** * @function getEntitySet * @memberOf service.odata * @description GET's the EntitySet collection. * @param {Object} srv - Instance of the service * @param {String} entitySet - The entitySet you want to GET from. * @param {String} [filterString] - The filters to be applied on get query * @param {String} [selectionFields] - comma separated list of fields to be selected * @param {Object} [queryParams] - JSON object of key value pairs of custom query parameters. * @returns {Promise} A Promise that resolves to the response data. * @example * const url = "<baseUrl>/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/"; * srv = await service.odata.init(url, user, password); * * let filterString = "Status eq '01'"; * let res = await service.odata.getEntitySet(srv, "A_PurchaseOrder", filterString); * * let select = "CentralPurchaseContract,PurchasingProcessingStatus" ; * let res = await service.odata.getEntitySet(srv, "A_PurchaseOrder", filterString, select); * * let queryParams = { * "$top" : 5, * "$skip" : 10, * }; * let res = await service.odata.getEntitySet(srv, "A_PurchaseOrder", filterString, select, queryParams); */ async getEntitySet(srv, entitySet, filterString = "", selectionFields = "", queryParams) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let entity = srv[entitySet]; if (!entity) throw new Error(entitySetError(entitySet)); if (filterString) entity = entity.filter(filterString); if (selectionFields) entity = entity.select(selectionFields.split(",")); if (queryParams) entity = this._applyQueryParameters(entity, queryParams); return entity.get(); } /** * @function post * @memberOf service.odata * @description Sends a POST request to retrieve data from the specified OData entity set for the given payload. * @param {Object} srv - Instance of the service * @param {String} entitySet - The entitySet you want to POST against. * @param {Object} payload - The payload of the POST request. * @param {Boolean} [raw=false] - Specifies whether the response should include all header contents. * @param {Object} [headers] - Optional headers to be included in the request. * @param {Object} [queryParams] - JSON object of key value pairs of custom query parameters. * @returns {Promise} A Promise that resolves to the response data. * @example * const payload = { * "PurchaseOrder": "4500007108", * "DraftUUID": "00000000-0000-0000-0000-000000000000", * "IsActiveEntity": "true" * }; * const res = await service.odata.post(srv, "A_PurchaseOrder", payload); */ async post(srv, entitySet, payload, raw = false, headers, queryParams) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let entity = srv[entitySet]; if (!entity) throw new Error(entitySetError(entitySet)); if (headers) entity = this._applyHeaders(entity, headers); if (queryParams) entity = this._applyQueryParameters(entity, queryParams); if (raw) entity = entity.raw(); return entity.post(payload); } /** * @function merge * @memberOf service.odata * @description @description Sends a MERGE request to merge data from the specified OData entity set for the given payload. * @param {Object} srv - Instance of the service * @param {String} entitySet - The entitySet you want to MERGE in. * @param {Object} payload - The payload of the MERGE request. * @param {Object} [headers] - Optional headers to be included in the request. * @returns {Promise} A Promise that resolves to the response data. * @example * const res = await service.odata.merge(srv, "A_PurchaseOrderScheduleLine", { * "PurchasingDocument": "4500007108", * "PurchasingDocumentItem": "10", * "ScheduleLine": "1", * "ScheduleLineDeliveryDate": new Date() * }; */ async merge(srv, entitySet, payload, headers) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let entity = srv[entitySet]; if (!entity) throw new Error(entitySetError(entitySet)); if (headers) entity = this._applyHeaders(entity, headers); return await entity.merge(payload); } /** * @function patch * @memberOf service.odata * @description @description Sends a PATCH request to patch data from the specified OData entity set for the given payload. * @param {Object} srv - Instance of the service * @param {String} entitySet - The entitySet you want to PATCH in. * @param {Object} payload - The payload of the PATCH request. * @param {Object} [headers] - Optional headers to be included in the request. * @returns {Promise} A Promise that resolves to the response data. * @example * const res = await service.odata.patch(srv, "ContractAccountPartner", { * "ContractAccount": "", * "BusinessPartner": "", * "DraftUUID": "42010aef-80aa-1fd0-8ec3-a11a9c56c3d3", * "IsActiveEntity": "false", * "CACompanyCodeGroup": "3910", * "CAStandardCompanyCode": "3910" * }; */ async patch(srv, entitySet, payload, headers) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let entity = srv[entitySet]; if (!entity) throw new Error(entitySetError(entitySet)); if (headers) entity = this._applyHeaders(entity, headers); return await entity.patch(payload); } /** * @function delete * @memberOf service.odata * @description Sends a DELETE request to the specified OData entity set. * @param {Object} srv - Instance of the service. * @param {String} entitySet - The entitySet you want to DELETE. * @param {Object} options - The options for the DELETE request. * @param {Object} [headers] - Optional headers to be included in the request. * @returns {Promise} A Promise that resolves to the response data. * @example * const options = { * "PurchaseOrder": "", * "DraftUUID": draftUUID, * "IsActiveEntity": false * }; * const res = await service.odata.delete(srv, "C_PurchaseOrderTP", options); */ async delete(srv, entitySet, options, headers) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let entity = srv[entitySet]; if (!entity) throw new Error(entitySetError(entitySet)); if (headers) entity = this._applyHeaders(entity, headers); return await entity.delete(options); } /** * @function callFunctionImport * @memberOf service.odata * @description Sends a function import request to the OData service instance. * @param {Object} srv - Instance of the service. * @param {String} functionImportName - Name of Function Import. * @param {Object} options - Parameters for function import. * @returns {Promise} A Promise that resolves to the response data. * @example * const options = { * CentralRequestForQuotation : "7500000026", * Supplier : "100006" * }; * const res = await service.odata.callFunctionImport(srv, "Cancel", options); */ async callFunctionImport(srv, functionImportName, options, raw = false) { if (!srv) throw new Error(SERVICE_INIT_ERROR); let functionImport = srv.functionImports[functionImportName]; if (raw) functionImport = functionImport.raw(); return await functionImport.call(options); } /** * @function isFeatureToggleActivated * @memberOf service.odata * @description Checks if a feature toggle is switched on or off. * @param {Object} srv - Instance of the service * @param {String} featureName - The name of the feature you want know the status of. * @returns {Promise} A Promise that resolves to a bool value. * @example const url = browser.params.systemUrl + "/sap/opu/odata/SAP/CA_FM_FEATURE_TOGGLE_STATUS_SRV/"; * const srv = await service.odata.init(url, user, password); * let isFeatureActive = await service.odata.isFeatureToggleActivated(srv, "MM_PUR_PO_BATCHES_IN_MANAGE_PO"); */ async isFeatureToggleActivated(srv, featureName) { if (!srv) throw new Error(SERVICE_INIT_ERROR); const res = await this.getEntitySet(srv, "ToggleStatusSet"); for (const featureEntity of Object.values(res)) { // @ts-ignore if (featureEntity.Featureid === featureName) { //feature toggle is disabled if found util.console.info(`Feature Toggle "${featureName}" is disabled.`); return false; } } //feature toggle is enabled if NOT found util.console.info(`Feature Toggle "${featureName}" is enabled.`); return true; } // =================================== PDF ====================================== /** * @function getOutputManagementPdfStream * @memberOf service.odata * @description returns a stream of output management pdf file. * @param {Object} outputConf - Configuration for the output management pdf. * @param {String} url - system url * @param {String} username - username for login * @param {String} password - password for login * @example * const outputConf = * ApplObjectType: "REQUEST_FOR_QUOTATION", * ApplObjectId: "7000002653", * ItemId: "1" * }; * const pdfStream = await service.odata.getOutputManagementPdfStream(outputConf, url, user, password); */ async getOutputManagementPdfStream(outputConf, url, username, password) { if (arguments.length < 4) { throw new Error("getOutputManagementPdfStream Failed. Please send correct parameters"); } const uri = new this.urlLib(url); url = uri.origin + "/sap/opu/odata/sap/CA_OC_OUTPUT_REQUEST_SRV/"; const srv = await service.odata.init(url, username, password); const dataBuffer = await srv.Items.key(outputConf).GetDocument.get(); return dataBuffer; } /** * @function readPdfFromDirectUrl * @memberOf service.odata * @description returns a stream of pdf file which is part of attachment. * @param {String} url - system url * @param {String} [username] - username for login * @param {String} [password] - password for login * @param {Boolean} [isSaml=false] - use SAML login if true * @example * const url = "https://domain.com/getPdfFile"; * const pdfStream = await service.odata.readPdfFromDirectUrl(url, "username", "Password"); */ async readPdfFromDirectUrl(url, username, password, isSaml = false) { if (url === undefined || url === null) { throw new Error("Function 'readPdfFromDirectUrl' Failed. Please provide valid url as first parameter"); } return await this._doRequest(url, username, password, isSaml); } // =================================== HELPER =================================== async _doRequest(url, username, password, isSaml) { //const auth = new Buffer(username + ":" + password).toString("base64"); const options = { encoding: null, "content-type": "application/pdf" }; if (username && password) { if (isSaml) { // works only for SAP odata services const serviceUrl = url.match(/.*\/[a-zA-Z0-9_]+_SRV\//)?.[0]; if (serviceUrl) { let relativePath = "/" + url.substring(serviceUrl.length); const srv = await service.odata.init(serviceUrl, username, password); const pdfResp = await srv.agent.get(relativePath); return pdfResp.arrayBuffer(); } else { throw new Error("SAML login option is available only for SAP ODATA services"); } } else { options.auth = { user: username, pass: password }; } } return new Promise((resolve, reject) => { this.axios .get(url, options) .then((response) => resolve(response.data)) .catch((error) => reject(error)); }); } _applyHeaders(entity, headers) { for (const [key, value] of Object.entries(headers)) { entity.header(key, value); } return entity; } _applyQueryParameters(entity, params) { for (const [key, value] of Object.entries(params)) { entity.queryParameter(key, value); } return entity; } } exports.OData = OData; exports.default = new OData(); //# sourceMappingURL=odata.js.map