diff --git a/.gitignore b/.gitignore index e65109bc..3499b2f3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ iam-identity/*.js iam-policy-management/*.js ibm-cloud-shell/*.js open-service-broker/*.js +partner-billing-units/*.js resource-manager/*.js resource-controller/*.js usage-metering/*.js diff --git a/README.md b/README.md index e7007041..d8cce2ab 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Service Name | Import Path [IAM Policy Management](https://cloud.ibm.com/apidocs/iam-policy-management?code=node) | @ibm-cloud/platform-services/iam-policy-management/v1 [IBM Cloud Shell](https://cloud.ibm.com/apidocs/cloudshell?code=node) | @ibm-cloud/platform-services/ibm-cloud-shell/v1 [Open Service Broker](https://cloud.ibm.com/apidocs/resource-controller/ibm-cloud-osb-api?code=node) | @ibm-cloud/platform-services/open-service-broker/v1 +[Partner Billing Units](https://cloud.ibm.com/apidocs/partner-apis/billing-unit?code=node) | @ibm-cloud/platform-services/partner-billing-units/v1 [Resource Controller](https://cloud.ibm.com/apidocs/resource-controller/resource-controller?code=node) | @ibm-cloud/platform-services/resource-controller/v2 [Resource Manager](https://cloud.ibm.com/apidocs/resource-controller/resource-manager?code=node) | @ibm-cloud/platform-services/resource-manager/v2 [Usage Metering](https://cloud.ibm.com/apidocs/usage-metering?code=node) | @ibm-cloud/platform-services/usage-metering/v4 diff --git a/examples/partner-billing-units.v1.test.js b/examples/partner-billing-units.v1.test.js new file mode 100644 index 00000000..19bde78a --- /dev/null +++ b/examples/partner-billing-units.v1.test.js @@ -0,0 +1,134 @@ +/** + * @jest-environment node + */ +/** + * (C) Copyright IBM Corp. 2024. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + */ + +/* eslint-disable no-console */ + +const PartnerBillingUnitsV1 = require('../dist/partner-billing-units/v1'); +// eslint-disable-next-line node/no-unpublished-require +const authHelper = require('../test/resources/auth-helper.js'); +const { readExternalSources } = require('ibm-cloud-sdk-core'); + +// +// This file provides an example of how to use the Partner Billing Units service. +// +// The following configuration properties are assumed to be defined: +// PARTNER_BILLING_UNITS_URL= +// PARTNER_BILLING_UNITS_AUTH_TYPE=iam +// PARTNER_BILLING_UNITS_APIKEY= +// PARTNER_BILLING_UNITS_AUTH_URL= +// PARTNER_BILLING_UNITS_PARTNER_ID= +// PARTNER_BILLING_UNITS_CUSTOMER_ID= +// PARTNER_BILLING_UNITS_RESELLER_ID= +// PARTNER_BILLING_UNITS_BILLING_MONTH= +// +// These configuration properties can be exported as environment variables, or stored +// in a configuration file and then: +// export IBM_CREDENTIALS_FILE= +// +const configFile = 'partner_billing_units_v1.env'; + +const describe = authHelper.prepareTests(configFile); + +// Save original console.log +const originalLog = console.log; +const originalWarn = console.warn; + +// Mocks for console.log and console.warn +const consoleLogMock = jest.spyOn(console, 'log'); +const consoleWarnMock = jest.spyOn(console, 'warn'); + +describe('PartnerBillingUnitsV1', () => { + jest.setTimeout(30000); + // Service instance + let partnerBillingUnitsService; + + let partnerId; + let billingMonth; + + test('Initialize service', async () => { + // begin-common + + partnerBillingUnitsService = PartnerBillingUnitsV1.newInstance(); + + const config = readExternalSources(PartnerBillingUnitsV1.DEFAULT_SERVICE_NAME); + + partnerId = config.partnerId; + billingMonth = config.billingMonth; + + // end-common + }); + + test('getBillingOptions request example', async () => { + consoleLogMock.mockImplementation((output) => { + originalLog(output); + }); + consoleWarnMock.mockImplementation((output) => { + // if an error occurs, display the message and then fail the test + originalWarn(output); + expect(true).toBeFalsy(); + }); + + originalLog('getBillingOptions() result:'); + // begin-get_billing_options + + const params = { + partnerId, + date: billingMonth, + }; + + let res; + try { + res = await partnerBillingUnitsService.getBillingOptions(params); + console.log(JSON.stringify(res.result, null, 2)); + } catch (err) { + console.warn(err); + } + + // end-get_billing_options + }); + + test('getCreditPoolsReport request example', async () => { + consoleLogMock.mockImplementation((output) => { + originalLog(output); + }); + consoleWarnMock.mockImplementation((output) => { + // if an error occurs, display the message and then fail the test + originalWarn(output); + expect(true).toBeFalsy(); + }); + + originalLog('getCreditPoolsReport() result:'); + // begin-get_credit_pools_report + + const params = { + partnerId, + date: billingMonth, + }; + + let res; + try { + res = await partnerBillingUnitsService.getCreditPoolsReport(params); + console.log(JSON.stringify(res.result, null, 2)); + } catch (err) { + console.warn(err); + } + + // end-get_credit_pools_report + }); +}); diff --git a/partner-billing-units/v1.ts b/partner-billing-units/v1.ts new file mode 100644 index 00000000..473e8a2a --- /dev/null +++ b/partner-billing-units/v1.ts @@ -0,0 +1,505 @@ +/** + * (C) Copyright IBM Corp. 2024. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + */ + +/** + * IBM OpenAPI SDK Code Generator Version: 3.85.0-75c38f8f-20240206-210220 + */ + +import * as extend from 'extend'; +import { IncomingHttpHeaders, OutgoingHttpHeaders } from 'http'; +import { + Authenticator, + BaseService, + UserOptions, + getAuthenticatorFromEnvironment, + validateParams, +} from 'ibm-cloud-sdk-core'; +import { getSdkHeaders } from '../lib/common'; + +/** + * Billing units for IBM Cloud partners + * + * API Version: 1.0.0 + */ + +class PartnerBillingUnitsV1 extends BaseService { + static DEFAULT_SERVICE_URL: string = 'https://partner.cloud.ibm.com'; + + static DEFAULT_SERVICE_NAME: string = 'partner_billing_units'; + + /************************* + * Factory method + ************************/ + + /** + * Constructs an instance of PartnerBillingUnitsV1 with passed in options and external configuration. + * + * @param {UserOptions} [options] - The parameters to send to the service. + * @param {string} [options.serviceName] - The name of the service to configure + * @param {Authenticator} [options.authenticator] - The Authenticator object used to authenticate requests to the service + * @param {string} [options.serviceUrl] - The base URL for the service + * @returns {PartnerBillingUnitsV1} + */ + + public static newInstance(options: UserOptions): PartnerBillingUnitsV1 { + options = options || {}; + + if (!options.serviceName) { + options.serviceName = this.DEFAULT_SERVICE_NAME; + } + if (!options.authenticator) { + options.authenticator = getAuthenticatorFromEnvironment(options.serviceName); + } + const service = new PartnerBillingUnitsV1(options); + service.configureService(options.serviceName); + if (options.serviceUrl) { + service.setServiceUrl(options.serviceUrl); + } + return service; + } + + /** + * Construct a PartnerBillingUnitsV1 object. + * + * @param {Object} options - Options for the service. + * @param {string} [options.serviceUrl] - The base URL for the service + * @param {OutgoingHttpHeaders} [options.headers] - Default headers that shall be included with every request to the service. + * @param {Authenticator} options.authenticator - The Authenticator object used to authenticate requests to the service + * @constructor + * @returns {PartnerBillingUnitsV1} + */ + constructor(options: UserOptions) { + options = options || {}; + + super(options); + if (options.serviceUrl) { + this.setServiceUrl(options.serviceUrl); + } else { + this.setServiceUrl(PartnerBillingUnitsV1.DEFAULT_SERVICE_URL); + } + } + + /************************* + * billingOptions + ************************/ + + /** + * Get customers billing options. + * + * Returns the billing options for the requested customer for a given month. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.partnerId - Enterprise ID of the distributor or reseller for which the report is requested. + * @param {string} [params.customerId] - Enterprise ID of the customer for which the report is requested. + * @param {string} [params.resellerId] - Enterprise ID of the reseller for which the report is requested. + * @param {string} [params.date] - The billing month for which the usage report is requested. Format is yyyy-mm. + * Defaults to current month. + * @param {number} [params.limit] - Number of usage records returned. The default value is 30. Maximum value is 200. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public getBillingOptions( + params: PartnerBillingUnitsV1.GetBillingOptionsParams + ): Promise> { + const _params = { ...params }; + const _requiredParams = ['partnerId']; + const _validParams = ['partnerId', 'customerId', 'resellerId', 'date', 'limit', 'headers']; + const _validationErrors = validateParams(_params, _requiredParams, _validParams); + if (_validationErrors) { + return Promise.reject(_validationErrors); + } + + const query = { + 'partner_id': _params.partnerId, + 'customer_id': _params.customerId, + 'reseller_id': _params.resellerId, + 'date': _params.date, + '_limit': _params.limit, + }; + + const sdkHeaders = getSdkHeaders( + PartnerBillingUnitsV1.DEFAULT_SERVICE_NAME, + 'v1', + 'getBillingOptions' + ); + + const parameters = { + options: { + url: '/v1/billing-options', + method: 'GET', + qs: query, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend( + true, + sdkHeaders, + { + 'Accept': 'application/json', + }, + _params.headers + ), + }), + }; + + return this.createRequest(parameters); + } + /************************* + * creditPools + ************************/ + + /** + * Get subscription burn-down report. + * + * Returns the subscription or commitment burn-down reports for the end customers for a given month. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.partnerId - Enterprise ID of the distributor or reseller for which the report is requested. + * @param {string} [params.customerId] - Enterprise ID of the customer for which the report is requested. + * @param {string} [params.resellerId] - Enterprise ID of the reseller for which the report is requested. + * @param {string} [params.date] - The billing month for which the usage report is requested. Format is yyyy-mm. + * Defaults to current month. + * @param {number} [params.limit] - Number of usage records returned. The default value is 30. Maximum value is 200. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public getCreditPoolsReport( + params: PartnerBillingUnitsV1.GetCreditPoolsReportParams + ): Promise> { + const _params = { ...params }; + const _requiredParams = ['partnerId']; + const _validParams = ['partnerId', 'customerId', 'resellerId', 'date', 'limit', 'headers']; + const _validationErrors = validateParams(_params, _requiredParams, _validParams); + if (_validationErrors) { + return Promise.reject(_validationErrors); + } + + const query = { + 'partner_id': _params.partnerId, + 'customer_id': _params.customerId, + 'reseller_id': _params.resellerId, + 'date': _params.date, + '_limit': _params.limit, + }; + + const sdkHeaders = getSdkHeaders( + PartnerBillingUnitsV1.DEFAULT_SERVICE_NAME, + 'v1', + 'getCreditPoolsReport' + ); + + const parameters = { + options: { + url: '/v1/credit-pools', + method: 'GET', + qs: query, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend( + true, + sdkHeaders, + { + 'Accept': 'application/json', + }, + _params.headers + ), + }), + }; + + return this.createRequest(parameters); + } +} + +/************************* + * interfaces + ************************/ + +namespace PartnerBillingUnitsV1 { + /** An operation response. */ + export interface Response { + result: T; + status: number; + statusText: string; + headers: IncomingHttpHeaders; + } + + /** The callback for a service request. */ + export type Callback = (error: any, response?: Response) => void; + + /** The body of a service request that returns no response data. */ + export interface EmptyObject {} + + /** A standard JS object, defined to avoid the limitations of `Object` and `object` */ + export interface JsonObject { + [key: string]: any; + } + + /************************* + * request interfaces + ************************/ + + /** Parameters for the `getBillingOptions` operation. */ + export interface GetBillingOptionsParams { + /** Enterprise ID of the distributor or reseller for which the report is requested. */ + partnerId: string; + /** Enterprise ID of the customer for which the report is requested. */ + customerId?: string; + /** Enterprise ID of the reseller for which the report is requested. */ + resellerId?: string; + /** The billing month for which the usage report is requested. Format is yyyy-mm. Defaults to current month. */ + date?: string; + /** Number of usage records returned. The default value is 30. Maximum value is 200. */ + limit?: number; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `getCreditPoolsReport` operation. */ + export interface GetCreditPoolsReportParams { + /** Enterprise ID of the distributor or reseller for which the report is requested. */ + partnerId: string; + /** Enterprise ID of the customer for which the report is requested. */ + customerId?: string; + /** Enterprise ID of the reseller for which the report is requested. */ + resellerId?: string; + /** The billing month for which the usage report is requested. Format is yyyy-mm. Defaults to current month. */ + date?: string; + /** Number of usage records returned. The default value is 30. Maximum value is 200. */ + limit?: number; + headers?: OutgoingHttpHeaders; + } + + /************************* + * model interfaces + ************************/ + + /** The link to the first page of the search query. */ + export interface BillingOptionsSummaryFirst { + /** A link to a page of query results. */ + href?: string; + } + + /** The link to the next page of the search query. */ + export interface BillingOptionsSummaryNext { + /** A link to a page of query results. */ + href?: string; + /** The value of the `_start` query parameter to fetch the next page. */ + offset?: string; + } + + /** Billing options report for the end customers. */ + export interface BillingOption { + /** The ID of the billing option. */ + id?: string; + /** The ID of the billing unit that's associated with the billing option. */ + billing_unit_id?: string; + /** Account ID of the customer. */ + customer_id?: string; + /** The customer type. The valid values are `ENTERPRISE`, `ACCOUNT`, and `ACCOUNT_GROUP`. */ + customer_type?: BillingOption.Constants.CustomerType | string; + /** A user-defined name for the customer. */ + customer_name?: string; + /** ID of the reseller in the heirarchy of the requested customer. */ + reseller_id?: string; + /** Name of the reseller in the heirarchy of the requested customer. */ + reseller_name?: string; + /** The billing month for which the burn-down report is requested. Format is yyyy-mm. Defaults to current month. */ + month?: string; + /** Errors in the billing. */ + errors?: JsonObject[]; + /** The type of billing option. The valid values are `SUBSCRIPTION` and `OFFER`. */ + type?: BillingOption.Constants.Type | string; + /** The start date of billing option. */ + start_date?: string; + /** The end date of billing option. */ + end_date?: string; + /** The state of the billing option. The valid values include `ACTIVE, `SUSPENDED`, and `CANCELED`. */ + state?: BillingOption.Constants.State | string; + /** The category of the billing option. The valid values are `PLATFORM`, `SERVICE`, and `SUPPORT`. */ + category?: BillingOption.Constants.Category | string; + /** The payment method for support. */ + payment_instrument?: JsonObject; + /** Part number of the offering. */ + part_number?: string; + /** ID of the catalog containing this offering. */ + catalog_id?: string; + /** ID of the order containing this offering. */ + order_id?: string; + /** PO Number of the offering. */ + po_number?: string; + /** Subscription model. */ + subscription_model?: string; + /** The duration of the billing options in months. */ + duration_in_months?: number; + /** Amount billed monthly for this offering. */ + monthly_amount?: number; + /** The support billing system. */ + billing_system?: JsonObject; + /** The country code for the billing unit. */ + country_code?: string; + /** The currency code of the billing unit. */ + currency_code?: string; + } + export namespace BillingOption { + export namespace Constants { + /** The customer type. The valid values are `ENTERPRISE`, `ACCOUNT`, and `ACCOUNT_GROUP`. */ + export enum CustomerType { + ENTERPRISE = 'ENTERPRISE', + ACCOUNT = 'ACCOUNT', + ACCOUNT_GROUP = 'ACCOUNT_GROUP', + } + /** The type of billing option. The valid values are `SUBSCRIPTION` and `OFFER`. */ + export enum Type { + SUBSCRIPTION = 'SUBSCRIPTION', + OFFER = 'OFFER', + } + /** The state of the billing option. The valid values include `ACTIVE, `SUSPENDED`, and `CANCELED`. */ + export enum State { + ACTIVE = 'ACTIVE', + SUSPENDED = 'SUSPENDED', + CANCELED = 'CANCELED', + } + /** The category of the billing option. The valid values are `PLATFORM`, `SERVICE`, and `SUPPORT`. */ + export enum Category { + PLATFORM = 'PLATFORM', + SERVICE = 'SERVICE', + SUPPORT = 'SUPPORT', + } + } + } + + /** The billing options report for the customer. */ + export interface BillingOptionsSummary { + /** The max number of reports in the response. */ + limit?: number; + /** The link to the first page of the search query. */ + first?: BillingOptionsSummaryFirst; + /** The link to the next page of the search query. */ + next?: BillingOptionsSummaryNext; + /** Aggregated usage report of all requested partners. */ + resources?: BillingOption[]; + } + + /** The link to the first page of the search query. */ + export interface CreditPoolsReportSummaryFirst { + /** A link to a page of query results. */ + href?: string; + } + + /** The link to the next page of the search query. */ + export interface CreditPoolsReportSummaryNext { + /** A link to a page of query results. */ + href?: string; + /** The value of the `_start` query parameter to fetch the next page. */ + offset?: string; + } + + /** Aggregated subscription burn-down report for the end customers. */ + export interface CreditPoolsReport { + /** The category of the billing option. The valid values are `PLATFORM`, `SERVICE` and `SUPPORT`. */ + type?: CreditPoolsReport.Constants.Type | string; + /** The ID of the billing unit that's associated with the billing option. */ + billing_unit_id?: string; + /** Account ID of the customer. */ + customer_id?: string; + /** The customer type. The valid values are `ENTERPRISE`, `ACCOUNT`, and `ACCOUNT_GROUP`. */ + customer_type?: CreditPoolsReport.Constants.CustomerType | string; + /** A user-defined name for the customer. */ + customer_name?: string; + /** ID of the reseller in the heirarchy of the requested customer. */ + reseller_id?: string; + /** Name of the reseller in the heirarchy of the requested customer. */ + reseller_name?: string; + /** The billing month for which the burn-down report is requested. Format is yyyy-mm. Defaults to current month. */ + month?: string; + /** The currency code of the billing unit. */ + currency_code?: string; + /** A list of active subscription terms available within a credit. */ + term_credits?: TermCredits[]; + /** Overage that was generated on the credit pool. */ + overage?: Overage; + } + export namespace CreditPoolsReport { + export namespace Constants { + /** The category of the billing option. The valid values are `PLATFORM`, `SERVICE` and `SUPPORT`. */ + export enum Type { + PLATFORM = 'PLATFORM', + SERVICE = 'SERVICE', + SUPPORT = 'SUPPORT', + } + /** The customer type. The valid values are `ENTERPRISE`, `ACCOUNT`, and `ACCOUNT_GROUP`. */ + export enum CustomerType { + ENTERPRISE = 'ENTERPRISE', + ACCOUNT = 'ACCOUNT', + ACCOUNT_GROUP = 'ACCOUNT_GROUP', + } + } + } + + /** The aggregated credit pools report. */ + export interface CreditPoolsReportSummary { + /** The max number of reports in the response. */ + limit?: number; + /** The link to the first page of the search query. */ + first?: CreditPoolsReportSummaryFirst; + /** The link to the next page of the search query. */ + next?: CreditPoolsReportSummaryNext; + /** Aggregated usage report of all requested partners. */ + resources?: CreditPoolsReport[]; + } + + /** Overage that was generated on the credit pool. */ + export interface Overage { + /** The number of credits used as overage. */ + cost?: number; + /** A list of resources that generated overage. */ + resources?: JsonObject[]; + } + + /** The subscription term that is active in the requested month. */ + export interface TermCredits { + /** The ID of the billing option from which the subscription term is derived. */ + billing_option_id?: string; + /** Billing option model. */ + billing_option_model?: string; + /** The category of the billing option. The valid values are `PLATFORM`, `SERVICE`, and `SUPPORT`. */ + category?: TermCredits.Constants.Category | string; + /** The start date of the term in ISO format. */ + start_date?: string; + /** The end date of the term in ISO format. */ + end_date?: string; + /** The total credit available in this term. */ + total_credits?: number; + /** The balance of available credit at the start of the current month. */ + starting_balance?: number; + /** The amount of credit used during the current month. */ + used_credits?: number; + /** The balance of remaining credit in the subscription term. */ + current_balance?: number; + /** A list of resources that used credit during the month. */ + resources?: JsonObject[]; + } + export namespace TermCredits { + export namespace Constants { + /** The category of the billing option. The valid values are `PLATFORM`, `SERVICE`, and `SUPPORT`. */ + export enum Category { + PLATFORM = 'PLATFORM', + SERVICE = 'SERVICE', + SUPPORT = 'SUPPORT', + } + } + } +} + +export = PartnerBillingUnitsV1; diff --git a/test/integration/partner-billing-units.v1.test.js b/test/integration/partner-billing-units.v1.test.js new file mode 100644 index 00000000..5b319d3f --- /dev/null +++ b/test/integration/partner-billing-units.v1.test.js @@ -0,0 +1,142 @@ +/** + * (C) Copyright IBM Corp. 2024. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + */ + +/* eslint-disable no-console */ + +const { readExternalSources } = require('ibm-cloud-sdk-core'); +const PartnerBillingUnitsV1 = require('../../dist/partner-billing-units/v1'); +const authHelper = require('../resources/auth-helper.js'); + +// testcase timeout value (200s). +const timeout = 200000; + +// Location of our config file. +const configFile = 'partner_billing_units_v1.env'; + +const describe = authHelper.prepareTests(configFile); + +describe('PartnerBillingUnitsV1_integration', () => { + jest.setTimeout(timeout); + + // Service instance + let partnerBillingUnitsService; + let partnerId; + let customerId; + let resellerId; + let billingMonth; + + test('Initialize service', async () => { + partnerBillingUnitsService = PartnerBillingUnitsV1.newInstance(); + + expect(partnerBillingUnitsService).not.toBeNull(); + + const config = readExternalSources(PartnerBillingUnitsV1.DEFAULT_SERVICE_NAME); + expect(config).not.toBeNull(); + + partnerId = config.partnerId; + customerId = config.customerId; + resellerId = config.resellerId; + billingMonth = config.billingMonth; + expect(partnerId).not.toBeNull(); + expect(customerId).not.toBeNull(); + expect(resellerId).not.toBeNull(); + expect(billingMonth).not.toBeNull(); + + partnerBillingUnitsService.enableRetries(); + }); + + test('getBillingOptions() - Get customers billing options of a partner', async () => { + const params = { + partnerId, + date: billingMonth, + limit: 30, + }; + + const res = await partnerBillingUnitsService.getBillingOptions(params); + expect(res).toBeDefined(); + expect(res.status).toBe(200); + expect(res.result).toBeDefined(); + }); + + test('getBillingOptions() - Get customers billing options of a Reseller for a specific partner', async () => { + const params = { + partnerId, + resellerId, + date: billingMonth, + limit: 30, + }; + + const res = await partnerBillingUnitsService.getBillingOptions(params); + expect(res).toBeDefined(); + expect(res.status).toBe(200); + expect(res.result).toBeDefined(); + }); + + test('getBillingOptions() - Get customers billing options of an end customer for a specific partner', async () => { + const params = { + partnerId, + customerId, + date: billingMonth, + limit: 30, + }; + + const res = await partnerBillingUnitsService.getBillingOptions(params); + expect(res).toBeDefined(); + expect(res.status).toBe(200); + expect(res.result).toBeDefined(); + }); + + test('getCreditPoolsReport() - Get subscription burn-down report of a partner', async () => { + const params = { + partnerId, + date: billingMonth, + limit: 30, + }; + + const res = await partnerBillingUnitsService.getCreditPoolsReport(params); + expect(res).toBeDefined(); + expect(res.status).toBe(200); + expect(res.result).toBeDefined(); + }); + + test('getCreditPoolsReport() - Get subscription burn-down report of a Reseller for a specific partner', async () => { + const params = { + partnerId, + resellerId, + date: billingMonth, + limit: 30, + }; + + const res = await partnerBillingUnitsService.getCreditPoolsReport(params); + expect(res).toBeDefined(); + expect(res.status).toBe(200); + expect(res.result).toBeDefined(); + }); + + test('getCreditPoolsReport() - Get subscription burn-down report of an end customer for a specific partner', async () => { + const params = { + partnerId, + customerId, + date: billingMonth, + limit: 30, + }; + + const res = await partnerBillingUnitsService.getCreditPoolsReport(params); + expect(res).toBeDefined(); + expect(res.status).toBe(200); + expect(res.result).toBeDefined(); + }); +}); diff --git a/test/unit/partner-billing-units.v1.test.js b/test/unit/partner-billing-units.v1.test.js new file mode 100644 index 00000000..6273012f --- /dev/null +++ b/test/unit/partner-billing-units.v1.test.js @@ -0,0 +1,303 @@ +/** + * (C) Copyright IBM Corp. 2024. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + */ + +// need to import the whole package to mock getAuthenticatorFromEnvironment +const sdkCorePackage = require('ibm-cloud-sdk-core'); + +const { NoAuthAuthenticator, unitTestUtils } = sdkCorePackage; +const PartnerBillingUnitsV1 = require('../../dist/partner-billing-units/v1'); + +const { + getOptions, + checkUrlAndMethod, + checkMediaHeaders, + expectToBePromise, +} = unitTestUtils; + +const partnerBillingUnitsServiceOptions = { + authenticator: new NoAuthAuthenticator(), + url: 'https://partner.cloud.ibm.com', +}; + +const partnerBillingUnitsService = new PartnerBillingUnitsV1(partnerBillingUnitsServiceOptions); + +let createRequestMock = null; +function mock_createRequest() { + if (!createRequestMock) { + createRequestMock = jest.spyOn(partnerBillingUnitsService, 'createRequest'); + createRequestMock.mockImplementation(() => Promise.resolve()); + } +} + +// dont actually construct an authenticator +const getAuthenticatorMock = jest.spyOn(sdkCorePackage, 'getAuthenticatorFromEnvironment'); +getAuthenticatorMock.mockImplementation(() => new NoAuthAuthenticator()); + +describe('PartnerBillingUnitsV1', () => { + beforeEach(() => { + mock_createRequest(); + }); + + afterEach(() => { + if (createRequestMock) { + createRequestMock.mockClear(); + } + getAuthenticatorMock.mockClear(); + }); + + describe('the newInstance method', () => { + test('should use defaults when options not provided', () => { + const testInstance = PartnerBillingUnitsV1.newInstance(); + + expect(getAuthenticatorMock).toHaveBeenCalled(); + expect(testInstance.baseOptions.authenticator).toBeInstanceOf(NoAuthAuthenticator); + expect(testInstance.baseOptions.serviceName).toBe(PartnerBillingUnitsV1.DEFAULT_SERVICE_NAME); + expect(testInstance.baseOptions.serviceUrl).toBe(PartnerBillingUnitsV1.DEFAULT_SERVICE_URL); + expect(testInstance).toBeInstanceOf(PartnerBillingUnitsV1); + }); + + test('should set serviceName, serviceUrl, and authenticator when provided', () => { + const options = { + authenticator: new NoAuthAuthenticator(), + serviceUrl: 'custom.com', + serviceName: 'my-service', + }; + + const testInstance = PartnerBillingUnitsV1.newInstance(options); + + expect(getAuthenticatorMock).not.toHaveBeenCalled(); + expect(testInstance.baseOptions.authenticator).toBeInstanceOf(NoAuthAuthenticator); + expect(testInstance.baseOptions.serviceUrl).toBe('custom.com'); + expect(testInstance.baseOptions.serviceName).toBe('my-service'); + expect(testInstance).toBeInstanceOf(PartnerBillingUnitsV1); + }); + }); + + describe('the constructor', () => { + test('use user-given service url', () => { + const options = { + authenticator: new NoAuthAuthenticator(), + serviceUrl: 'custom.com', + }; + + const testInstance = new PartnerBillingUnitsV1(options); + + expect(testInstance.baseOptions.serviceUrl).toBe('custom.com'); + }); + + test('use default service url', () => { + const options = { + authenticator: new NoAuthAuthenticator(), + }; + + const testInstance = new PartnerBillingUnitsV1(options); + + expect(testInstance.baseOptions.serviceUrl).toBe(PartnerBillingUnitsV1.DEFAULT_SERVICE_URL); + }); + }); + + describe('getBillingOptions', () => { + describe('positive tests', () => { + function __getBillingOptionsTest() { + // Construct the params object for operation getBillingOptions + const partnerId = 'testString'; + const customerId = 'testString'; + const resellerId = 'testString'; + const date = '2024-01'; + const limit = 30; + const getBillingOptionsParams = { + partnerId, + customerId, + resellerId, + date, + limit, + }; + + const getBillingOptionsResult = partnerBillingUnitsService.getBillingOptions(getBillingOptionsParams); + + // all methods should return a Promise + expectToBePromise(getBillingOptionsResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const mockRequestOptions = getOptions(createRequestMock); + + checkUrlAndMethod(mockRequestOptions, '/v1/billing-options', 'GET'); + const expectedAccept = 'application/json'; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + expect(mockRequestOptions.qs.partner_id).toEqual(partnerId); + expect(mockRequestOptions.qs.customer_id).toEqual(customerId); + expect(mockRequestOptions.qs.reseller_id).toEqual(resellerId); + expect(mockRequestOptions.qs.date).toEqual(date); + expect(mockRequestOptions.qs._limit).toEqual(limit); + } + + test('should pass the right params to createRequest with enable and disable retries', () => { + // baseline test + __getBillingOptionsTest(); + + // enable retries and test again + createRequestMock.mockClear(); + partnerBillingUnitsService.enableRetries(); + __getBillingOptionsTest(); + + // disable retries and test again + createRequestMock.mockClear(); + partnerBillingUnitsService.disableRetries(); + __getBillingOptionsTest(); + }); + + test('should prioritize user-given headers', () => { + // parameters + const partnerId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const getBillingOptionsParams = { + partnerId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + partnerBillingUnitsService.getBillingOptions(getBillingOptionsParams); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async () => { + let err; + try { + await partnerBillingUnitsService.getBillingOptions({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + }); + + test('should reject promise when required params are not given', async () => { + let err; + try { + await partnerBillingUnitsService.getBillingOptions(); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + }); + }); + }); + + describe('getCreditPoolsReport', () => { + describe('positive tests', () => { + function __getCreditPoolsReportTest() { + // Construct the params object for operation getCreditPoolsReport + const partnerId = 'testString'; + const customerId = 'testString'; + const resellerId = 'testString'; + const date = '2024-01'; + const limit = 30; + const getCreditPoolsReportParams = { + partnerId, + customerId, + resellerId, + date, + limit, + }; + + const getCreditPoolsReportResult = partnerBillingUnitsService.getCreditPoolsReport(getCreditPoolsReportParams); + + // all methods should return a Promise + expectToBePromise(getCreditPoolsReportResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const mockRequestOptions = getOptions(createRequestMock); + + checkUrlAndMethod(mockRequestOptions, '/v1/credit-pools', 'GET'); + const expectedAccept = 'application/json'; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + expect(mockRequestOptions.qs.partner_id).toEqual(partnerId); + expect(mockRequestOptions.qs.customer_id).toEqual(customerId); + expect(mockRequestOptions.qs.reseller_id).toEqual(resellerId); + expect(mockRequestOptions.qs.date).toEqual(date); + expect(mockRequestOptions.qs._limit).toEqual(limit); + } + + test('should pass the right params to createRequest with enable and disable retries', () => { + // baseline test + __getCreditPoolsReportTest(); + + // enable retries and test again + createRequestMock.mockClear(); + partnerBillingUnitsService.enableRetries(); + __getCreditPoolsReportTest(); + + // disable retries and test again + createRequestMock.mockClear(); + partnerBillingUnitsService.disableRetries(); + __getCreditPoolsReportTest(); + }); + + test('should prioritize user-given headers', () => { + // parameters + const partnerId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const getCreditPoolsReportParams = { + partnerId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + partnerBillingUnitsService.getCreditPoolsReport(getCreditPoolsReportParams); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async () => { + let err; + try { + await partnerBillingUnitsService.getCreditPoolsReport({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + }); + + test('should reject promise when required params are not given', async () => { + let err; + try { + await partnerBillingUnitsService.getCreditPoolsReport(); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + }); + }); + }); +});