diff --git a/src/management/__generated/managers/branding-manager.ts b/src/management/__generated/managers/branding-manager.ts index 6b5bceaac7..bf548315e5 100644 --- a/src/management/__generated/managers/branding-manager.ts +++ b/src/management/__generated/managers/branding-manager.ts @@ -2,22 +2,34 @@ import * as runtime from '../../../lib/runtime.js'; import type { InitOverride, ApiResponse } from '../../../lib/runtime.js'; import type { CreatePhoneProviderRequest, + CreatePhoneTemplateRequestContent, + CreatePhoneTemplateResponseContent, GetBranding200Response, GetBrandingPhoneProviders200Response, GetBrandingPhoneProviders200ResponseProvidersInner, + GetPhoneTemplateResponseContent, GetUniversalLogin200Response, + ListPhoneTemplatesResponseContent, PatchBrandingRequest, PostBrandingTheme200Response, PostBrandingThemeRequest, PutUniversalLoginRequest, + ResetPhoneTemplateResponseContent, UpdatePhoneProviderRequest, + UpdatePhoneTemplateRequestContent, + UpdatePhoneTemplateResponseContent, DeleteBrandingThemeRequest, DeletePhoneProviderRequest, + DeletePhoneTemplateRequest, GetBrandingPhoneProvidersRequest, GetBrandingThemeRequest, GetPhoneProviderRequest, + GetPhoneTemplateRequest, + GetPhoneTemplatesRequest, PatchBrandingThemeRequest, + ResetPhoneTemplateRequest, UpdatePhoneProviderOperationRequest, + UpdatePhoneTemplateRequest, } from '../models/index.js'; const { BaseAPI } = runtime; @@ -55,6 +67,32 @@ export class BrandingManager extends BaseAPI { return runtime.JSONApiResponse.fromResponse(response); } + /** + * Create a phone notification template + * + * @throws {RequiredError} + */ + async createPhoneTemplate( + bodyParameters: CreatePhoneTemplateRequestContent, + initOverrides?: InitOverride + ): Promise> { + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request( + { + path: `/branding/phone/templates`, + method: 'POST', + headers: headerParameters, + body: bodyParameters, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } + /** * Delete branding theme. * Delete branding theme @@ -108,6 +146,31 @@ export class BrandingManager extends BaseAPI { return runtime.VoidApiResponse.fromResponse(response); } + /** + * Delete a phone notification template + * + * @throws {RequiredError} + */ + async deletePhoneTemplate( + requestParameters: DeletePhoneTemplateRequest, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const response = await this.request( + { + path: `/branding/phone/templates/{id}`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'DELETE', + }, + initOverrides + ); + + return runtime.VoidApiResponse.fromResponse(response); + } + /** * Delete template for New Universal Login Experience * @@ -246,6 +309,59 @@ export class BrandingManager extends BaseAPI { return runtime.JSONApiResponse.fromResponse(response); } + /** + * Get a phone notification template + * + * @throws {RequiredError} + */ + async getPhoneTemplate( + requestParameters: GetPhoneTemplateRequest, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const response = await this.request( + { + path: `/branding/phone/templates/{id}`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'GET', + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } + + /** + * Get a list of phone notification templates + * + * @throws {RequiredError} + */ + async getAllPhoneTemplates( + requestParameters: GetPhoneTemplatesRequest = {}, + initOverrides?: InitOverride + ): Promise> { + const queryParameters = runtime.applyQueryParams(requestParameters, [ + { + key: 'disabled', + config: {}, + }, + ]); + + const response = await this.request( + { + path: `/branding/phone/templates`, + method: 'GET', + query: queryParameters, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } + /** * Get template for New Universal Login Experience * @@ -404,6 +520,38 @@ export class BrandingManager extends BaseAPI { return runtime.VoidApiResponse.fromResponse(response); } + /** + * Resets a phone notification template values + * + * @throws {RequiredError} + */ + async resetTemplate( + requestParameters: ResetPhoneTemplateRequest, + bodyParameters: any | null, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request( + { + path: `/branding/phone/templates/{id}/reset`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'PATCH', + headers: headerParameters, + body: bodyParameters as any, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } + /** * Update a phone provider. * The credentials object requires different properties depending on the phone provider (which is specified using the name property). @@ -438,4 +586,36 @@ export class BrandingManager extends BaseAPI { return runtime.JSONApiResponse.fromResponse(response); } + + /** + * Update a phone notification template + * + * @throws {RequiredError} + */ + async updatePhoneTemplate( + requestParameters: UpdatePhoneTemplateRequest, + bodyParameters: UpdatePhoneTemplateRequestContent, + initOverrides?: InitOverride + ): Promise> { + runtime.validateRequiredRequestParams(requestParameters, ['id']); + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request( + { + path: `/branding/phone/templates/{id}`.replace( + '{id}', + encodeURIComponent(String(requestParameters.id)) + ), + method: 'PATCH', + headers: headerParameters, + body: bodyParameters, + }, + initOverrides + ); + + return runtime.JSONApiResponse.fromResponse(response); + } } diff --git a/src/management/__generated/models/index.ts b/src/management/__generated/models/index.ts index 0a47f140b4..7c0b6761bc 100644 --- a/src/management/__generated/models/index.ts +++ b/src/management/__generated/models/index.ts @@ -3763,6 +3763,72 @@ export interface CreatePhoneProviderRequestCredentialsAnyOf { */ auth_token: string; } +/** + * + */ +export interface CreatePhoneTemplateRequestContent { + /** + */ + type?: CreatePhoneTemplateRequestContentTypeEnum; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled?: boolean; + /** + */ + content?: PhoneTemplateContent; +} + +export const CreatePhoneTemplateRequestContentTypeEnum = { + otp_verify: 'otp_verify', + otp_enroll: 'otp_enroll', + change_password: 'change_password', + blocked_account: 'blocked_account', + password_breach: 'password_breach', +} as const; +export type CreatePhoneTemplateRequestContentTypeEnum = + (typeof CreatePhoneTemplateRequestContentTypeEnum)[keyof typeof CreatePhoneTemplateRequestContentTypeEnum]; + +/** + * + */ +export interface CreatePhoneTemplateResponseContent { + /** + */ + id: string; + /** + */ + channel?: string; + /** + */ + customizable?: boolean; + /** + */ + tenant?: string; + /** + */ + content: PhoneTemplateContent; + /** + */ + type: CreatePhoneTemplateResponseContentTypeEnum; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled: boolean; +} + +export const CreatePhoneTemplateResponseContentTypeEnum = { + otp_verify: 'otp_verify', + otp_enroll: 'otp_enroll', + change_password: 'change_password', + blocked_account: 'blocked_account', + password_breach: 'password_breach', +} as const; +export type CreatePhoneTemplateResponseContentTypeEnum = + (typeof CreatePhoneTemplateResponseContentTypeEnum)[keyof typeof CreatePhoneTemplateResponseContentTypeEnum]; + /** * */ @@ -8042,6 +8108,45 @@ export const GetPhoneProviders200ResponseProviderEnum = { export type GetPhoneProviders200ResponseProviderEnum = (typeof GetPhoneProviders200ResponseProviderEnum)[keyof typeof GetPhoneProviders200ResponseProviderEnum]; +/** + * + */ +export interface GetPhoneTemplateResponseContent { + /** + */ + id: string; + /** + */ + channel?: string; + /** + */ + customizable?: boolean; + /** + */ + tenant?: string; + /** + */ + content: PhoneTemplateContent; + /** + */ + type: GetPhoneTemplateResponseContentTypeEnum; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled: boolean; +} + +export const GetPhoneTemplateResponseContentTypeEnum = { + otp_verify: 'otp_verify', + otp_enroll: 'otp_enroll', + change_password: 'change_password', + blocked_account: 'blocked_account', + password_breach: 'password_breach', +} as const; +export type GetPhoneTemplateResponseContentTypeEnum = + (typeof GetPhoneTemplateResponseContentTypeEnum)[keyof typeof GetPhoneTemplateResponseContentTypeEnum]; + /** * */ @@ -9523,6 +9628,14 @@ export const JobFormatEnum = { } as const; export type JobFormatEnum = (typeof JobFormatEnum)[keyof typeof JobFormatEnum]; +/** + * + */ +export interface ListPhoneTemplatesResponseContent { + /** + */ + templates?: Array; +} /** * */ @@ -9675,6 +9788,19 @@ export interface LogLocationInfo { */ continent_code: string; } +/** + * + */ +export interface PartialPhoneTemplateContent { + /** + * Default phone number to be used as 'from' when sending a phone notification + * + */ + from?: string; + /** + */ + body?: PhoneTemplateBody; +} /** * */ @@ -10663,6 +10789,76 @@ export interface Permission { */ description?: string; } +/** + * + */ +export interface PhoneTemplate { + /** + */ + id: string; + /** + */ + channel?: string; + /** + */ + customizable?: boolean; + /** + */ + tenant?: string; + /** + */ + content: PhoneTemplateContent; + /** + */ + type: PhoneTemplateTypeEnum; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled: boolean; +} + +export const PhoneTemplateTypeEnum = { + otp_verify: 'otp_verify', + otp_enroll: 'otp_enroll', + change_password: 'change_password', + blocked_account: 'blocked_account', + password_breach: 'password_breach', +} as const; +export type PhoneTemplateTypeEnum = + (typeof PhoneTemplateTypeEnum)[keyof typeof PhoneTemplateTypeEnum]; + +/** + * + */ +export interface PhoneTemplateBody { + /** + * Content of the phone template for text notifications + * + */ + text?: string; + /** + * Content of the phone template for voice notifications + * + */ + voice?: string; +} +/** + * + */ +export interface PhoneTemplateContent { + /** + */ + syntax?: string; + /** + * Default phone number to be used as 'from' when sending a phone notification + * + */ + from?: string; + /** + */ + body?: PhoneTemplateBody; +} /** * */ @@ -15849,6 +16045,45 @@ export interface PutUniversalLoginRequestOneOf { */ template: string; } +/** + * + */ +export interface ResetPhoneTemplateResponseContent { + /** + */ + id: string; + /** + */ + channel?: string; + /** + */ + customizable?: boolean; + /** + */ + tenant?: string; + /** + */ + content: PhoneTemplateContent; + /** + */ + type: ResetPhoneTemplateResponseContentTypeEnum; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled: boolean; +} + +export const ResetPhoneTemplateResponseContentTypeEnum = { + otp_verify: 'otp_verify', + otp_enroll: 'otp_enroll', + change_password: 'change_password', + blocked_account: 'blocked_account', + password_breach: 'password_breach', +} as const; +export type ResetPhoneTemplateResponseContentTypeEnum = + (typeof ResetPhoneTemplateResponseContentTypeEnum)[keyof typeof ResetPhoneTemplateResponseContentTypeEnum]; + /** * */ @@ -17762,6 +17997,58 @@ export const UpdatePhoneProviderRequestNameEnum = { export type UpdatePhoneProviderRequestNameEnum = (typeof UpdatePhoneProviderRequestNameEnum)[keyof typeof UpdatePhoneProviderRequestNameEnum]; +/** + * + */ +export interface UpdatePhoneTemplateRequestContent { + /** + */ + content?: PartialPhoneTemplateContent; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled?: boolean; +} +/** + * + */ +export interface UpdatePhoneTemplateResponseContent { + /** + */ + id: string; + /** + */ + channel?: string; + /** + */ + customizable?: boolean; + /** + */ + tenant?: string; + /** + */ + content: PhoneTemplateContent; + /** + */ + type: UpdatePhoneTemplateResponseContentTypeEnum; + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled: boolean; +} + +export const UpdatePhoneTemplateResponseContentTypeEnum = { + otp_verify: 'otp_verify', + otp_enroll: 'otp_enroll', + change_password: 'change_password', + blocked_account: 'blocked_account', + password_breach: 'password_breach', +} as const; +export type UpdatePhoneTemplateResponseContentTypeEnum = + (typeof UpdatePhoneTemplateResponseContentTypeEnum)[keyof typeof UpdatePhoneTemplateResponseContentTypeEnum]; + /** * */ @@ -18455,6 +18742,14 @@ export interface DeletePhoneProviderRequest { */ id: string; } +/** + * + */ +export interface DeletePhoneTemplateRequest { + /** + */ + id: string; +} /** * */ @@ -18483,6 +18778,24 @@ export interface GetPhoneProviderRequest { */ id: string; } +/** + * + */ +export interface GetPhoneTemplateRequest { + /** + */ + id: string; +} +/** + * + */ +export interface GetPhoneTemplatesRequest { + /** + * Whether the template is enabled (false) or disabled (true). + * + */ + disabled?: boolean; +} /** * */ @@ -18493,6 +18806,14 @@ export interface PatchBrandingThemeRequest { */ themeId: string; } +/** + * + */ +export interface ResetPhoneTemplateRequest { + /** + */ + id: string; +} /** * */ @@ -18501,6 +18822,14 @@ export interface UpdatePhoneProviderOperationRequest { */ id: string; } +/** + * + */ +export interface UpdatePhoneTemplateRequest { + /** + */ + id: string; +} /** * */ diff --git a/test/management/branding.test.ts b/test/management/branding.test.ts index 5fe27d5a4f..62ac92f9cc 100644 --- a/test/management/branding.test.ts +++ b/test/management/branding.test.ts @@ -25,6 +25,12 @@ import { DeletePhoneProviderRequest, GetPhoneProviderRequest, GetBrandingPhoneProviders200ResponseProvidersInnerConfigurationAnyOf, + CreatePhoneTemplateRequestContent, + CreatePhoneTemplateResponseContent, + CreatePhoneTemplateRequestContentTypeEnum, + CreatePhoneTemplateResponseContentTypeEnum, + UpdatePhoneTemplateResponseContent, + UpdatePhoneTemplateRequestContent, } from '../../src/index.js'; describe('BrandingManager', () => { @@ -1111,4 +1117,638 @@ describe('BrandingManager', () => { .catch(done); }); }); + + describe('#createPhoneTemplate', () => { + const data: CreatePhoneTemplateRequestContent = { + type: 'otp_verify' as CreatePhoneTemplateRequestContentTypeEnum, + disabled: false, + content: { + syntax: 'liquid', + from: '+1234567890', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + }; + const response: CreatePhoneTemplateResponseContent = { + id: 'template_id', + channel: 'sms', + customizable: true, + tenant: 'tenant_id', + type: 'otp_verify' as CreatePhoneTemplateResponseContentTypeEnum, + disabled: false, + content: { + syntax: 'liquid', + from: '+1234567890', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + }; + let request: nock.Scope; + + beforeEach(() => { + request = nock(API_URL) + .post('/branding/phone/templates', (body) => { + return JSON.stringify(body) === JSON.stringify(data); + }) + .reply(201, response); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should return a promise if no callback is given', (done) => { + branding + .createPhoneTemplate(data) + .then(() => done()) + .catch((err) => done(err)); + }); + + it('should pass any errors to the promise catch handler', (done) => { + nock.cleanAll(); + + nock(API_URL).post('/branding/phone/templates').reply(500, {}); + + branding.createPhoneTemplate(data).catch((err) => { + expect(err).toBeDefined(); + done(); + }); + }); + + it('should perform a POST request to /api/v2/branding/phone/templates', (done) => { + branding.createPhoneTemplate(data).then(() => { + expect(request.isDone()).toBe(true); + done(); + }); + }); + + it('should include the token in the Authorization header', (done) => { + nock.cleanAll(); + + const request = nock(API_URL) + .post('/branding/phone/templates', (body) => JSON.stringify(body) === JSON.stringify(data)) + .matchHeader('Authorization', `Bearer ${token}`) + .reply(201, response); + + branding.createPhoneTemplate(data).then(() => { + expect(request.isDone()).toBe(true); + done(); + }); + }); + + it('should include Content-Type application/json header', (done) => { + nock.cleanAll(); + + const request = nock(API_URL) + .post('/branding/phone/templates', (body) => JSON.stringify(body) === JSON.stringify(data)) + .matchHeader('Content-Type', 'application/json') + .reply(201, response); + + branding.createPhoneTemplate(data).then(() => { + expect(request.isDone()).toBe(true); + done(); + }); + }); + + it('should pass the body of the response to the "then" handler', (done) => { + branding.createPhoneTemplate(data).then((result) => { + expect(result.data.id).toBe(response.id); + expect(result.data.type).toBe(response.type); + expect(result.data.disabled).toBe(response.disabled); + expect(result.data.channel).toBe(response.channel); + expect(result.data.customizable).toBe(response.customizable); + expect(result.data.tenant).toBe(response.tenant); + expect(result.data.content.syntax).toBe(response.content.syntax); + expect(result.data.content.from).toBe(response.content.from); + expect(result.data.content.body?.text).toBe(response.content.body?.text); + expect(result.data.content.body?.voice).toBe(response.content.body?.voice); + done(); + }); + }); + }); + + describe('#getPhoneTemplate', () => { + const params = { id: '5' }; + + const data = { + id: 'template_id', + channel: 'sms', + customizable: true, + tenant: 'tenant_id', + type: 'otp_verify' as CreatePhoneTemplateResponseContentTypeEnum, + disabled: false, + content: { + syntax: 'liquid', + from: '+1234567890', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + }; + + let request: nock.Scope; + + beforeEach(() => { + nock.cleanAll(); + + request = nock(API_URL).get(`/branding/phone/templates/${params.id}`).reply(200, data); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should return a promise if no callback is given', (done) => { + branding + .getPhoneTemplate(params) + .then(() => done()) + .catch((err) => done(err)); + }); + + it('should pass any errors to the promise catch handler', (done) => { + nock.cleanAll(); + + nock(API_URL).get(`/branding/phone/templates/${params.id}`).reply(500, {}); + + branding + .getPhoneTemplate(params) + .then(() => done(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err).toBeDefined(); + done(); + }); + }); + + it('should pass the body of the response to the "then" handler', (done) => { + branding + .getPhoneTemplate(params) + .then((response) => { + const result = response.data ?? response; + expect(result.id).toBe(data.id); + expect(result.channel).toBe(data.channel); + expect(result.customizable).toBe(data.customizable); + expect(result.tenant).toBe(data.tenant); + expect(result.type).toBe(data.type); + expect(result.disabled).toBe(data.disabled); + expect(result.content.syntax).toBe(data.content.syntax); + expect(result.content.from).toBe(data.content.from); + expect(result.content.body?.text).toBe(data.content.body?.text); + expect(result.content.body?.voice).toBe(data.content.body?.voice); + done(); + }) + .catch(done); + }); + + it('should perform a GET request to /branding/phone/templates/:id', (done) => { + branding + .getPhoneTemplate(params) + .then(() => { + expect(request.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should include the token in the Authorization header', (done) => { + nock.cleanAll(); + + const authRequest = nock(API_URL) + .get(`/branding/phone/templates/${params.id}`) + .matchHeader('Authorization', `Bearer ${token}`) + .reply(200, data); + + branding + .getPhoneTemplate(params) + .then(() => { + expect(authRequest.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + }); + + describe('#getAllPhoneTemplates', () => { + const data = { + templates: [ + { + id: 'template_id', + channel: 'sms', + customizable: true, + tenant: 'tenant_id', + type: 'otp_verify' as CreatePhoneTemplateResponseContentTypeEnum, + disabled: false, + content: { + syntax: 'liquid', + from: '+1234567890', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + }, + ], + }; + + let request: nock.Scope; + + beforeEach(() => { + nock.cleanAll(); + request = nock(API_URL).get('/branding/phone/templates').reply(200, data); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should return a promise if no callback is given', (done) => { + branding + .getAllPhoneTemplates() + .then(() => done()) + .catch((err) => done(err)); + }); + + it('should perform a GET request to /branding/phone/templates', (done) => { + branding + .getAllPhoneTemplates() + .then(() => { + expect(request.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should pass the body of the response to the "then" handler', (done) => { + nock.cleanAll(); + + nock(API_URL).get('/branding/phone/templates').reply(200, data); + + branding + .getAllPhoneTemplates() + .then((response) => { + expect(response.data.templates?.[0].id).toBe(data.templates?.[0].id); + expect(response.data.templates?.[0].channel).toBe(data.templates[0].channel); + expect(response.data.templates?.[0].customizable).toBe(data.templates[0].customizable); + expect(response.data.templates?.[0].tenant).toBe(data.templates[0].tenant); + expect(response.data.templates?.[0].type).toBe(data.templates[0].type); + expect(response.data.templates?.[0].disabled).toBe(data.templates[0].disabled); + expect(response.data.templates?.[0].content.from).toBe(data.templates[0].content.from); + expect(response.data.templates?.[0].content.body?.text).toBe( + data.templates[0].content.body?.text + ); + expect(response.data.templates?.[0].content.body?.voice).toBe( + data.templates[0].content.body?.voice + ); + + done(); + }) + .catch(done); + }); + + it('should include the token in the Authorization header', (done) => { + nock.cleanAll(); + + const authRequest = nock(API_URL) + .get('/branding/phone/templates') + .matchHeader('Authorization', `Bearer ${token}`) + .reply(200, data); + + branding + .getAllPhoneTemplates() + .then(() => { + expect(authRequest.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should pass any errors to the promise catch handler', (done) => { + nock.cleanAll(); + + nock(API_URL).get('/branding/phone/templates').reply(500, {}); + + branding + .getAllPhoneTemplates() + .then(() => done(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err).toBeDefined(); + done(); + }); + }); + }); + describe('#updatePhoneTemplate', () => { + const params = { id: '5' }; + const data: UpdatePhoneTemplateRequestContent = { + content: { + from: '+123456789', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + disabled: false, + }; + + const response: UpdatePhoneTemplateResponseContent = { + id: 'template_id', + channel: 'sms', + customizable: true, + tenant: 'tenant_id', + type: 'otp_verify' as CreatePhoneTemplateResponseContentTypeEnum, + disabled: false, + content: { + syntax: 'liquid', + from: '+1234567890', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + }; + + let request: nock.Scope; + + beforeEach(() => { + nock.cleanAll(); + request = nock(API_URL) + .patch(`/branding/phone/templates/${params.id}`, (body) => { + return JSON.stringify(body) === JSON.stringify(data); + }) + .reply(200, response); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should return a promise if no callback is given', (done) => { + branding + .updatePhoneTemplate(params, data) + .then(() => done()) + .catch((err) => done(err)); + }); + + it('should pass any errors to the promise catch handler', (done) => { + nock.cleanAll(); + + nock(API_URL).patch(`/branding/phone/templates/${params.id}`).reply(500, {}); + + branding + .updatePhoneTemplate(params, data) + .then(() => done(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err).toBeDefined(); + done(); + }); + }); + + it('should perform a PATCH request to /branding/phone/templates/:id', (done) => { + branding + .updatePhoneTemplate(params, data) + .then(() => { + expect(request.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should include the token in the Authorization header', (done) => { + nock.cleanAll(); + + const authRequest = nock(API_URL) + .patch( + `/branding/phone/templates/${params.id}`, + (body) => JSON.stringify(body) === JSON.stringify(data) + ) + .matchHeader('Authorization', `Bearer ${token}`) + .reply(200, response); + + branding + .updatePhoneTemplate(params, data) + .then(() => { + expect(authRequest.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should include Content-Type application/json header', (done) => { + nock.cleanAll(); + + const contentTypeRequest = nock(API_URL) + .patch( + `/branding/phone/templates/${params.id}`, + (body) => JSON.stringify(body) === JSON.stringify(data) + ) + .matchHeader('Content-Type', 'application/json') + .reply(200, response); + + branding + .updatePhoneTemplate(params, data) + .then(() => { + expect(contentTypeRequest.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should pass the body of the response to the "then" handler', (done) => { + branding + .updatePhoneTemplate(params, data) + .then((result) => { + expect(result.data.id).toBe(response.id); + expect(result.data.type).toBe(response.type); + expect(result.data.disabled).toBe(response.disabled); + expect(result.data.channel).toBe(response.channel); + expect(result.data.customizable).toBe(response.customizable); + expect(result.data.tenant).toBe(response.tenant); + expect(result.data.content.syntax).toBe(response.content.syntax); + expect(result.data.content.from).toBe(response.content.from); + expect(result.data.content.body?.text).toBe(response.content.body?.text); + expect(result.data.content.body?.voice).toBe(response.content.body?.voice); + done(); + }) + .catch(done); + }); + }); + describe('#deletePhoneTemplate', () => { + const id = '5'; + + afterEach(() => { + nock.cleanAll(); + }); + + it('should return a promise if no callback is given', async () => { + const request = nock(API_URL).delete(`/branding/phone/templates/${id}`).reply(204, {}); + + const promise = branding.deletePhoneTemplate({ id }); + expect(typeof promise.then).toBe('function'); + expect(typeof promise.catch).toBe('function'); + await promise; + expect(request.isDone()).toBe(true); + }); + + it('should pass any errors to the promise catch handler', async () => { + const request = nock(API_URL) + .delete(`/branding/phone/templates/${id}`) + .reply(404, { message: 'Not Found' }); + + try { + await branding.deletePhoneTemplate({ id }); + throw new Error('Expected method to reject.'); + } catch (err: any) { + expect(err).toBeDefined(); + expect(err.statusCode).toBe(404); + expect(request.isDone()).toBe(true); + } + }); + + it('should perform a DELETE request to /branding/phone/templates/:id', async () => { + const request = nock(API_URL).delete(`/branding/phone/templates/${id}`).reply(204, {}); + + await branding.deletePhoneTemplate({ id }); + expect(request.isDone()).toBe(true); + }); + + it('should include the token in the Authorization header', async () => { + const request = nock(API_URL) + .delete(`/branding/phone/templates/${id}`) + .matchHeader('Authorization', `Bearer ${token}`) + .reply(204, {}); + + await branding.deletePhoneTemplate({ id }); + expect(request.isDone()).toBe(true); + }); + }); + + describe('#resetTemplate', () => { + const params = { id: '5' }; + const data = {}; + + const response: UpdatePhoneTemplateResponseContent = { + id: 'template_id', + channel: 'sms', + customizable: true, + tenant: 'tenant_id', + type: 'otp_verify' as CreatePhoneTemplateResponseContentTypeEnum, + disabled: false, + content: { + syntax: 'liquid', + from: '+1234567890', + body: { + text: 'Your verification code is: {{code}}', + voice: 'Your verification code is {{code}}', + }, + }, + }; + + let request: nock.Scope; + + beforeEach(() => { + nock.cleanAll(); + request = nock(API_URL) + .patch(`/branding/phone/templates/${params.id}/reset`, (body) => { + return JSON.stringify(body) === JSON.stringify(data); + }) + .reply(200, response); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should return a promise if no callback is given', (done) => { + branding + .resetTemplate(params, data) + .then(() => done()) + .catch((err) => done(err)); + }); + + it('should pass any errors to the promise catch handler', (done) => { + nock.cleanAll(); + + nock(API_URL).patch(`/branding/phone/templates/${params.id}/reset`).reply(500, {}); + + branding + .resetTemplate(params, data) + .then(() => done(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err).toBeDefined(); + done(); + }); + }); + + it('should perform a PATCH request to /branding/phone/templates/:id/reset', (done) => { + branding + .resetTemplate(params, data) + .then(() => { + expect(request.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should include the token in the Authorization header', (done) => { + nock.cleanAll(); + + const authRequest = nock(API_URL) + .patch( + `/branding/phone/templates/${params.id}/reset`, + (body) => JSON.stringify(body) === JSON.stringify(data) + ) + .matchHeader('Authorization', `Bearer ${token}`) + .reply(200, response); + + branding + .resetTemplate(params, data) + .then(() => { + expect(authRequest.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should include Content-Type application/json header', (done) => { + nock.cleanAll(); + + const contentTypeRequest = nock(API_URL) + .patch( + `/branding/phone/templates/${params.id}/reset`, + (body) => JSON.stringify(body) === JSON.stringify(data) + ) + .matchHeader('Content-Type', 'application/json') + .reply(200, response); + + branding + .resetTemplate(params, data) + .then(() => { + expect(contentTypeRequest.isDone()).toBe(true); + done(); + }) + .catch(done); + }); + + it('should pass the body of the response to the "then" handler', (done) => { + branding + .resetTemplate(params, data) + .then((result) => { + expect(result.data.id).toBe(response.id); + expect(result.data.type).toBe(response.type); + expect(result.data.disabled).toBe(response.disabled); + expect(result.data.channel).toBe(response.channel); + expect(result.data.customizable).toBe(response.customizable); + expect(result.data.tenant).toBe(response.tenant); + expect(result.data.content.syntax).toBe(response.content.syntax); + expect(result.data.content.from).toBe(response.content.from); + expect(result.data.content.body?.text).toBe(response.content.body?.text); + expect(result.data.content.body?.voice).toBe(response.content.body?.voice); + done(); + }) + .catch(done); + }); + }); });