From 2d0edb0a4a1530ffbacd7585a610c3ce010908c2 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Mon, 15 Jun 2026 11:03:35 +0300 Subject: [PATCH 1/6] Add reports endpoints for phase 2. --- lib/reports/index.ts | 71 ++++++ lib/reports/types.ts | 236 +++++++++++++++++- test/functional/client.spec.ts | 8 +- .../reports/delete_report_column.spec.ts | 98 ++++++++ .../reports/get_report_column.spec.ts | 134 ++++++++++ .../reports/get_report_definition.spec.ts | 219 ++++++++++++++++ .../reports/list_report_columns.spec.ts | 183 ++++++++++++++ .../reports/list_report_scope.spec.ts | 127 ++++++++++ .../reports/update_report_column.spec.ts | 160 ++++++++++++ 9 files changed, 1234 insertions(+), 2 deletions(-) create mode 100644 test/mock-api/reports/delete_report_column.spec.ts create mode 100644 test/mock-api/reports/get_report_column.spec.ts create mode 100644 test/mock-api/reports/get_report_definition.spec.ts create mode 100644 test/mock-api/reports/list_report_columns.spec.ts create mode 100644 test/mock-api/reports/list_report_scope.spec.ts create mode 100644 test/mock-api/reports/update_report_column.spec.ts diff --git a/lib/reports/index.ts b/lib/reports/index.ts index fe1b47e..e937313 100644 --- a/lib/reports/index.ts +++ b/lib/reports/index.ts @@ -25,6 +25,17 @@ import type { AddReportColumnsResponse, CreateReportOptions, CreateReportResponse, + ListReportScopeOptions, + ListReportScopeResponse, + ListReportColumnsOptions, + ListReportColumnsResponse, + GetReportColumnOptions, + ReportColumn, + UpdateReportColumnOptions, + UpdateReportColumnResponse, + DeleteReportColumnOptions, + GetReportDefinitionOptions, + ReportDefinition, } from './types'; import * as constants from '../utils/constants'; @@ -140,6 +151,60 @@ export function create(options: CreateOptions): ReportsApi { return requestor.post({ ...optionsToSend, ...urlOptions, ...postOptions }, callback); }; + const listReportScope = ( + getOptions: ListReportScopeOptions, + callback?: RequestCallback + ): Promise => { + const urlOptions = { url: options.apiUrls.reports + '/' + getOptions.reportId + '/scope' }; + return requestor.get({ ...optionsToSend, ...urlOptions, ...getOptions }, callback); + }; + + const listReportColumns = ( + getOptions: ListReportColumnsOptions, + callback?: RequestCallback + ): Promise => { + const urlOptions = { url: options.apiUrls.reports + '/' + getOptions.reportId + '/columns' }; + return requestor.get({ ...optionsToSend, ...urlOptions, ...getOptions }, callback); + }; + + const getReportColumn = ( + getOptions: GetReportColumnOptions, + callback?: RequestCallback + ): Promise => { + const urlOptions = { + url: options.apiUrls.reports + '/' + getOptions.reportId + '/columns/' + getOptions.columnVirtualId, + }; + return requestor.get({ ...optionsToSend, ...urlOptions, ...getOptions }, callback); + }; + + const updateReportColumn = ( + putOptions: UpdateReportColumnOptions, + callback?: RequestCallback + ): Promise => { + const urlOptions = { + url: options.apiUrls.reports + '/' + putOptions.reportId + '/columns/' + putOptions.columnVirtualId, + }; + return requestor.put({ ...optionsToSend, ...urlOptions, ...putOptions }, callback); + }; + + const deleteReportColumn = ( + deleteOptions: DeleteReportColumnOptions, + callback?: RequestCallback + ): Promise => { + const urlOptions = { + url: options.apiUrls.reports + '/' + deleteOptions.reportId + '/columns/' + deleteOptions.columnVirtualId, + }; + return requestor.delete({ ...optionsToSend, ...urlOptions, ...deleteOptions }, callback); + }; + + const getReportDefinition = ( + getOptions: GetReportDefinitionOptions, + callback?: RequestCallback + ): Promise => { + const urlOptions = { url: options.apiUrls.reports + '/' + getOptions.reportId + '/definition' }; + return requestor.get({ ...optionsToSend, ...urlOptions, ...getOptions }, callback); + }; + return { listReports, getReport, @@ -154,5 +219,11 @@ export function create(options: CreateOptions): ReportsApi { removeReportScope, addReportColumns, createReport, + listReportScope, + listReportColumns, + getReportColumn, + updateReportColumn, + deleteReportColumn, + getReportDefinition, }; } diff --git a/lib/reports/types.ts b/lib/reports/types.ts index 380dc3e..e4e82af 100644 --- a/lib/reports/types.ts +++ b/lib/reports/types.ts @@ -1,6 +1,8 @@ import type { RequestCallback } from '../types/RequestCallback'; import type { RequestOptions } from '../types/RequestOptions'; import type { BaseResponseStatus } from '../types/BaseResponseStatus'; +import type { TokenPaginationQueryParameters } from '../types/TokenPaginationQueryParameters'; +import type { TokenPaginationResponse } from '../types/TokenPaginationResponse'; import type { FailedItem } from '../types/FailedItem'; import type { Attachment } from '../attachments/types'; import type { Column } from '../columns/types'; @@ -430,6 +432,130 @@ export interface ReportsApi { options: CreateReportOptions, callback?: RequestCallback ) => Promise; + + /** + * Gets the scope of a Report. + * + * @param options - {@link ListReportScopeOptions} - Configuration options for the request + * @param callback - {@link RequestCallback}\<{@link ListReportScopeResponse}\> - Optional callback function + * @returns Promise\<{@link ListReportScopeResponse}\> + * + * @remarks + * It mirrors to the following Smartsheet REST API method: `GET /reports/{reportId}/scope` + * + * @example + * ```typescript + * const scope = await client.reports.listReportScope({ reportId: 4583173393803140 }); + * ``` + */ + listReportScope: ( + options: ListReportScopeOptions, + callback?: RequestCallback + ) => Promise; + + /** + * Gets the columns of a Report. + * + * @param options - {@link ListReportColumnsOptions} - Configuration options for the request + * @param callback - {@link RequestCallback}\<{@link ListReportColumnsResponse}\> - Optional callback function + * @returns Promise\<{@link ListReportColumnsResponse}\> + * + * @remarks + * It mirrors to the following Smartsheet REST API method: `GET /reports/{reportId}/columns` + * + * @example + * ```typescript + * const columns = await client.reports.listReportColumns({ reportId: 4583173393803140 }); + * ``` + */ + listReportColumns: ( + options: ListReportColumnsOptions, + callback?: RequestCallback + ) => Promise; + + /** + * Gets a single column of a Report. + * + * @param options - {@link GetReportColumnOptions} - Configuration options for the request + * @param callback - {@link RequestCallback}\<{@link ReportColumn}\> - Optional callback function + * @returns Promise\<{@link ReportColumn}\> + * + * @remarks + * It mirrors to the following Smartsheet REST API method: `GET /reports/{reportId}/columns/{columnVirtualId}` + * + * @example + * ```typescript + * const column = await client.reports.getReportColumn({ reportId: 4583173393803140, columnVirtualId: 123 }); + * ``` + */ + getReportColumn: ( + options: GetReportColumnOptions, + callback?: RequestCallback + ) => Promise; + + /** + * Updates a column of a Report. + * + * @param options - {@link UpdateReportColumnOptions} - Configuration options for the request + * @param callback - {@link RequestCallback}\<{@link UpdateReportColumnResponse}\> - Optional callback function + * @returns Promise\<{@link UpdateReportColumnResponse}\> + * + * @remarks + * It mirrors to the following Smartsheet REST API method: `PUT /reports/{reportId}/columns/{columnVirtualId}` + * + * @example + * ```typescript + * const result = await client.reports.updateReportColumn({ + * reportId: 4583173393803140, + * columnVirtualId: 123, + * body: { title: 'New Title', hidden: false } + * }); + * ``` + */ + updateReportColumn: ( + options: UpdateReportColumnOptions, + callback?: RequestCallback + ) => Promise; + + /** + * Deletes a column from a Report. + * + * @param options - {@link DeleteReportColumnOptions} - Configuration options for the request + * @param callback - {@link RequestCallback}\<{@link BaseResponseStatus}\> - Optional callback function + * @returns Promise\<{@link BaseResponseStatus}\> + * + * @remarks + * It mirrors to the following Smartsheet REST API method: `DELETE /reports/{reportId}/columns/{columnVirtualId}` + * + * @example + * ```typescript + * const result = await client.reports.deleteReportColumn({ reportId: 4583173393803140, columnVirtualId: 123 }); + * ``` + */ + deleteReportColumn: ( + options: DeleteReportColumnOptions, + callback?: RequestCallback + ) => Promise; + + /** + * Gets the definition of a Report. + * + * @param options - {@link GetReportDefinitionOptions} - Configuration options for the request + * @param callback - {@link RequestCallback}\<{@link ReportDefinition}\> - Optional callback function + * @returns Promise\<{@link ReportDefinition}\> + * + * @remarks + * It mirrors to the following Smartsheet REST API method: `GET /reports/{reportId}/definition` + * + * @example + * ```typescript + * const definition = await client.reports.getReportDefinition({ reportId: 4583173393803140 }); + * ``` + */ + getReportDefinition: ( + options: GetReportDefinitionOptions, + callback?: RequestCallback + ) => Promise; } // ============================================================================ @@ -1231,7 +1357,7 @@ export interface ReportFilterObjectValue { * For DATE objects, this would be a date string. * For CURRENT_USER, this represents the user identifier. */ - value: string; + value?: string; } /** @@ -1639,3 +1765,111 @@ export interface CreateReportResponse extends BaseResponseStatus { */ result: CreateReportResult; } + +// ============================================================================ +// Get Report Scope +// ============================================================================ + +export interface ListReportScopeOptions extends RequestOptions { + /** + * Report ID. + */ + reportId: number; +} + +export type ListReportScopeResponse = TokenPaginationResponse; + +// ============================================================================ +// Get Report Columns +// ============================================================================ + +export interface ListReportColumnsOptions extends RequestOptions { + /** + * Report ID. + */ + reportId: number; +} + +export type ListReportColumnsResponse = TokenPaginationResponse; + +// ============================================================================ +// Get Report Column +// ============================================================================ + +export interface GetReportColumnOptions extends RequestOptions { + /** + * Report ID. + */ + reportId: number; + /** + * The virtual ID of the report column. + */ + columnVirtualId: number; +} + +// ============================================================================ +// Update Report Column +// ============================================================================ + +export interface UpdateReportColumnRequest { + /** + * Column title. + */ + title?: string; + /** + * Column index or position. + */ + index?: number; + /** + * Indicates whether the column is hidden. + */ + hidden?: boolean; + /** + * Display width of the column in pixels. + */ + width?: number; +} + +export interface UpdateReportColumnOptions extends RequestOptions { + /** + * Report ID. + */ + reportId: number; + /** + * The virtual ID of the report column. + */ + columnVirtualId: number; +} + +export interface UpdateReportColumnResponse extends BaseResponseStatus { + /** + * The updated report column. + */ + result: ReportColumn; +} + +// ============================================================================ +// Delete Report Column +// ============================================================================ + +export interface DeleteReportColumnOptions extends RequestOptions { + /** + * Report ID. + */ + reportId: number; + /** + * The virtual ID of the report column. + */ + columnVirtualId: number; +} + +// ============================================================================ +// Get Report Definition +// ============================================================================ + +export interface GetReportDefinitionOptions extends RequestOptions { + /** + * Report ID. + */ + reportId: number; +} diff --git a/test/functional/client.spec.ts b/test/functional/client.spec.ts index 164b8d1..66d012c 100644 --- a/test/functional/client.spec.ts +++ b/test/functional/client.spec.ts @@ -178,7 +178,7 @@ describe('Client Unit Tests', () => { describe('#reports', () => { it('should have reports object', () => { expect(smartsheet).toHaveProperty('reports'); - expect(Object.keys(smartsheet.reports)).toHaveLength(13); + expect(Object.keys(smartsheet.reports)).toHaveLength(19); }); it('should have get methods', () => { @@ -187,6 +187,10 @@ describe('Client Unit Tests', () => { expect(smartsheet.reports).toHaveProperty('getReportAsExcel'); expect(smartsheet.reports).toHaveProperty('getReportAsCSV'); expect(smartsheet.reports).toHaveProperty('getReportPublishStatus'); + expect(smartsheet.reports).toHaveProperty('listReportScope'); + expect(smartsheet.reports).toHaveProperty('listReportColumns'); + expect(smartsheet.reports).toHaveProperty('getReportColumn'); + expect(smartsheet.reports).toHaveProperty('getReportDefinition'); }); it('should have create methods', () => { @@ -198,11 +202,13 @@ describe('Client Unit Tests', () => { it('should have update methods', () => { expect(smartsheet.reports).toHaveProperty('setReportPublishStatus'); expect(smartsheet.reports).toHaveProperty('sendReportViaEmail'); + expect(smartsheet.reports).toHaveProperty('updateReportColumn'); }); it('should have delete methods', () => { expect(smartsheet.reports).toHaveProperty('deleteReport'); expect(smartsheet.reports).toHaveProperty('removeReportScope'); + expect(smartsheet.reports).toHaveProperty('deleteReportColumn'); }); }); diff --git a/test/mock-api/reports/delete_report_column.spec.ts b/test/mock-api/reports/delete_report_column.spec.ts new file mode 100644 index 0000000..7640224 --- /dev/null +++ b/test/mock-api/reports/delete_report_column.spec.ts @@ -0,0 +1,98 @@ +import crypto from 'crypto'; +import { createClient, findWireMockRequest } from '../utils/utils'; +import { expect } from '@jest/globals'; +import { + TEST_REPORT_ID, + TEST_SUCCESS_MESSAGE, + TEST_SUCCESS_RESULT_CODE, + ERROR_500_STATUS_CODE, + ERROR_500_MESSAGE, + ERROR_400_STATUS_CODE, + ERROR_400_MESSAGE, +} from './common_test_constants'; + +describe('Reports - deleteReportColumn endpoint tests', () => { + const client = createClient(); + + const TEST_COLUMN_VIRTUAL_ID = 7001; + + const expectedAllResponseProperties = { + message: TEST_SUCCESS_MESSAGE, + resultCode: TEST_SUCCESS_RESULT_CODE, + }; + + it('deleteReportColumn generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/delete-report-column/all-response-body-properties', + }, + }; + await client.reports.deleteReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/columns/${TEST_COLUMN_VIRTUAL_ID}`); + expect(matchedRequest.method).toEqual('DELETE'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({}); + }); + + it('deleteReportColumn all response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/delete-report-column/all-response-body-properties', + }, + }; + const response = await client.reports.deleteReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedAllResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('deleteReportColumn error 500 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/500-response', + }, + }; + try { + await client.reports.deleteReportColumn(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); + } + }); + + it('deleteReportColumn error 400 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/400-response', + }, + }; + try { + await client.reports.deleteReportColumn(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); + } + }); +}); diff --git a/test/mock-api/reports/get_report_column.spec.ts b/test/mock-api/reports/get_report_column.spec.ts new file mode 100644 index 0000000..e9c8ee7 --- /dev/null +++ b/test/mock-api/reports/get_report_column.spec.ts @@ -0,0 +1,134 @@ +import crypto from 'crypto'; +import { createClient, findWireMockRequest } from '../utils/utils'; +import { expect } from '@jest/globals'; +import { + TEST_REPORT_ID, + ERROR_500_STATUS_CODE, + ERROR_500_MESSAGE, + ERROR_400_STATUS_CODE, + ERROR_400_MESSAGE, +} from './common_test_constants'; +import { ReportColumnType } from '@smartsheet/reports/types'; + +describe('Reports - getReportColumn endpoint tests', () => { + const client = createClient(); + + const TEST_COLUMN_VIRTUAL_ID = 7001; + + const expectedAllResponseProperties = { + virtualId: 7001, + index: 0, + title: 'Task Name', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + width: 150, + hidden: false, + validation: true, + version: 0, + autoNumberFormat: { + fill: '0001', + prefix: 'TASK-', + startingNumber: 1, + suffix: '', + }, + }; + + const expectedRequiredResponseProperties = { + index: 0, + title: 'Task Name', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }; + + it('getReportColumn generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-column/all-response-body-properties', + }, + }; + await client.reports.getReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/columns/${TEST_COLUMN_VIRTUAL_ID}`); + expect(matchedRequest.method).toEqual('GET'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({}); + }); + + it('getReportColumn all response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-column/all-response-body-properties', + }, + }; + const response = await client.reports.getReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedAllResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('getReportColumn required response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-column/required-response-body-properties', + }, + }; + const response = await client.reports.getReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedRequiredResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('getReportColumn error 500 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/500-response', + }, + }; + try { + await client.reports.getReportColumn(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); + } + }); + + it('getReportColumn error 400 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/400-response', + }, + }; + try { + await client.reports.getReportColumn(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); + } + }); +}); diff --git a/test/mock-api/reports/get_report_definition.spec.ts b/test/mock-api/reports/get_report_definition.spec.ts new file mode 100644 index 0000000..47e4fda --- /dev/null +++ b/test/mock-api/reports/get_report_definition.spec.ts @@ -0,0 +1,219 @@ +import crypto from 'crypto'; +import { createClient, findWireMockRequest } from '../utils/utils'; +import { expect } from '@jest/globals'; +import { + TEST_REPORT_ID, + ERROR_500_STATUS_CODE, + ERROR_500_MESSAGE, + ERROR_400_STATUS_CODE, + ERROR_400_MESSAGE, +} from './common_test_constants'; +import { + ReportFilterOperator, + ReportFilterConditionOperator, + ReportColumnType, + ReportSortingDirection, + ReportAggregationType, + SystemColumnType, +} from '@smartsheet/reports/types'; + +describe('Reports - getReportDefinition endpoint tests', () => { + const client = createClient(); + + const expectedAllResponseProperties = { + filters: { + operator: ReportFilterOperator.AND, + criteria: [ + { + column: { + title: 'Primary Column', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }, + operator: ReportFilterConditionOperator.EQUAL, + values: ['Test Value'], + }, + { + column: { + title: 'Status', + type: ReportColumnType.PICKLIST, + }, + operator: ReportFilterConditionOperator.NOT_EQUAL, + values: ['Complete'], + }, + { + column: { + title: 'Amount', + type: ReportColumnType.TEXT_NUMBER, + }, + operator: ReportFilterConditionOperator.GREATER_THAN, + values: [42], + }, + { + column: { + type: ReportColumnType.DATETIME, + systemColumnType: SystemColumnType.MODIFIED_DATE, + }, + operator: ReportFilterConditionOperator.LESS_THAN, + values: [{ objectType: 'DATE', value: '2025-01-14' }], + }, + { + column: { + title: 'Assigned To', + type: ReportColumnType.CONTACT_LIST, + }, + operator: ReportFilterConditionOperator.EQUAL, + values: [{ objectType: 'CURRENT_USER' }], + }, + { + column: { + title: 'Notes', + type: ReportColumnType.TEXT_NUMBER, + }, + operator: ReportFilterConditionOperator.EQUAL, + values: [null], + }, + ], + }, + groupingCriteria: [ + { + column: { + title: 'Primary Column', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }, + sortingDirection: ReportSortingDirection.ASCENDING, + isExpanded: true, + }, + { + column: { + title: 'Category', + type: ReportColumnType.TEXT_NUMBER, + }, + sortingDirection: ReportSortingDirection.DESCENDING, + isExpanded: false, + }, + ], + summarizingCriteria: [ + { + column: { + title: 'Primary Column', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }, + aggregationType: ReportAggregationType.COUNT, + }, + { + column: { + title: 'Amount', + type: ReportColumnType.TEXT_NUMBER, + }, + aggregationType: ReportAggregationType.SUM, + }, + ], + sortingCriteria: [ + { + column: { + title: 'Primary Column', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }, + sortingDirection: ReportSortingDirection.ASCENDING, + }, + { + column: { + type: ReportColumnType.DATETIME, + systemColumnType: SystemColumnType.MODIFIED_DATE, + }, + sortingDirection: ReportSortingDirection.DESCENDING, + }, + ], + }; + + it('getReportDefinition generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-definition/all-response-body-properties', + }, + }; + await client.reports.getReportDefinition(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/definition`); + expect(matchedRequest.method).toEqual('GET'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({}); + }); + + it('getReportDefinition all response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-definition/all-response-body-properties', + }, + }; + const response = await client.reports.getReportDefinition(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedAllResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('getReportDefinition required response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-definition/required-response-body-properties', + }, + }; + const response = await client.reports.getReportDefinition(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual({}); + expect(matchedRequest.body).toEqual(''); + }); + + it('getReportDefinition error 500 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/500-response', + }, + }; + try { + await client.reports.getReportDefinition(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); + } + }); + + it('getReportDefinition error 400 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/400-response', + }, + }; + try { + await client.reports.getReportDefinition(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); + } + }); +}); diff --git a/test/mock-api/reports/list_report_columns.spec.ts b/test/mock-api/reports/list_report_columns.spec.ts new file mode 100644 index 0000000..446dbf2 --- /dev/null +++ b/test/mock-api/reports/list_report_columns.spec.ts @@ -0,0 +1,183 @@ +import crypto from 'crypto'; +import { createClient, findWireMockRequest } from '../utils/utils'; +import { expect } from '@jest/globals'; +import { + TEST_REPORT_ID, + ERROR_500_STATUS_CODE, + ERROR_500_MESSAGE, + ERROR_400_STATUS_CODE, + ERROR_400_MESSAGE, +} from './common_test_constants'; +import { ReportColumnType, SystemColumnType } from '@smartsheet/reports/types'; + +describe('Reports - listReportColumns endpoint tests', () => { + const client = createClient(); + + const TEST_LAST_KEY = 'someLastKey'; + const TEST_MAX_ITEMS = 50; + + const expectedAllResponseProperties = { + data: [ + { + virtualId: 7001, + index: 0, + title: 'Task Name', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + width: 150, + hidden: false, + validation: true, + version: 0, + autoNumberFormat: { + fill: '0001', + prefix: 'TASK-', + startingNumber: 1, + suffix: '', + }, + }, + { + virtualId: 7002, + index: 1, + title: 'Status', + type: ReportColumnType.PICKLIST, + width: 120, + hidden: false, + validation: false, + version: 0, + }, + { + virtualId: 7003, + index: 2, + title: 'Created By', + type: ReportColumnType.CONTACT_LIST, + systemColumnType: SystemColumnType.CREATED_BY, + width: 150, + hidden: false, + validation: false, + version: 1, + }, + { + virtualId: 7004, + index: 3, + title: 'Sheet Name', + type: ReportColumnType.TEXT_NUMBER, + sheetNameColumn: true, + width: 200, + hidden: false, + validation: false, + version: 0, + }, + ], + lastKey: null, + }; + + const expectedRequiredResponseProperties = { + data: [ + { + index: 0, + title: 'Task Name', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }, + { + index: 1, + type: ReportColumnType.DATETIME, + systemColumnType: SystemColumnType.CREATED_DATE, + }, + ], + }; + + it('listReportColumns generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + queryParameters: { + lastKey: TEST_LAST_KEY, + maxItems: TEST_MAX_ITEMS, + }, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-columns/all-response-body-properties', + }, + }; + await client.reports.listReportColumns(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/columns`); + expect(matchedRequest.method).toEqual('GET'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({ + lastKey: TEST_LAST_KEY, + maxItems: TEST_MAX_ITEMS.toString(), + }); + }); + + it('listReportColumns all response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-columns/all-response-body-properties', + }, + }; + const response = await client.reports.listReportColumns(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedAllResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('listReportColumns required response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-columns/required-response-body-properties', + }, + }; + const response = await client.reports.listReportColumns(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedRequiredResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('listReportColumns error 500 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/500-response', + }, + }; + try { + await client.reports.listReportColumns(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); + } + }); + + it('listReportColumns error 400 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/400-response', + }, + }; + try { + await client.reports.listReportColumns(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); + } + }); +}); diff --git a/test/mock-api/reports/list_report_scope.spec.ts b/test/mock-api/reports/list_report_scope.spec.ts new file mode 100644 index 0000000..5e9f3b1 --- /dev/null +++ b/test/mock-api/reports/list_report_scope.spec.ts @@ -0,0 +1,127 @@ +import crypto from 'crypto'; +import { createClient, findWireMockRequest } from '../utils/utils'; +import { expect } from '@jest/globals'; +import { + TEST_REPORT_ID, + ERROR_500_STATUS_CODE, + ERROR_500_MESSAGE, + ERROR_400_STATUS_CODE, + ERROR_400_MESSAGE, +} from './common_test_constants'; +import { ReportAssetType } from '@smartsheet/reports/types'; + +describe('Reports - listReportScope endpoint tests', () => { + const client = createClient(); + + const TEST_LAST_KEY = 'someLastKey'; + const TEST_MAX_ITEMS = 50; + + const expectedAllResponseProperties = { + data: [ + { assetType: ReportAssetType.SHEET, assetId: 2331373580117892 }, + { assetType: ReportAssetType.WORKSPACE, assetId: Number('7879278542455688') }, + { assetType: ReportAssetType.SHEET, assetId: 1234567890123456 }, + ], + lastKey: null, + }; + + const expectedRequiredResponseProperties = { + data: [ + { assetType: ReportAssetType.SHEET, assetId: 2331373580117892 }, + ], + }; + + it('listReportScope generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + queryParameters: { + lastKey: TEST_LAST_KEY, + maxItems: TEST_MAX_ITEMS, + }, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-scope/all-response-body-properties', + }, + }; + await client.reports.listReportScope(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/scope`); + expect(matchedRequest.method).toEqual('GET'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({ + lastKey: TEST_LAST_KEY, + maxItems: TEST_MAX_ITEMS.toString(), + }); + }); + + it('listReportScope all response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-scope/all-response-body-properties', + }, + }; + const response = await client.reports.listReportScope(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedAllResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('listReportScope required response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-scope/required-response-body-properties', + }, + }; + const response = await client.reports.listReportScope(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedRequiredResponseProperties); + expect(matchedRequest.body).toEqual(''); + }); + + it('listReportScope error 500 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/500-response', + }, + }; + try { + await client.reports.listReportScope(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); + } + }); + + it('listReportScope error 400 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/400-response', + }, + }; + try { + await client.reports.listReportScope(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); + } + }); +}); diff --git a/test/mock-api/reports/update_report_column.spec.ts b/test/mock-api/reports/update_report_column.spec.ts new file mode 100644 index 0000000..dd34aa8 --- /dev/null +++ b/test/mock-api/reports/update_report_column.spec.ts @@ -0,0 +1,160 @@ +import crypto from 'crypto'; +import { createClient, findWireMockRequest } from '../utils/utils'; +import { expect } from '@jest/globals'; +import { + TEST_REPORT_ID, + TEST_SUCCESS_MESSAGE, + TEST_SUCCESS_RESULT_CODE, + ERROR_500_STATUS_CODE, + ERROR_500_MESSAGE, + ERROR_400_STATUS_CODE, + ERROR_400_MESSAGE, +} from './common_test_constants'; +import { ReportColumnType } from '@smartsheet/reports/types'; + +describe('Reports - updateReportColumn endpoint tests', () => { + const client = createClient(); + + const TEST_COLUMN_VIRTUAL_ID = 7001; + + const testRequestBody = { + index: 2, + title: 'Updated Task Name', + width: 200, + hidden: false, + }; + + const expectedAllResponseProperties = { + message: TEST_SUCCESS_MESSAGE, + resultCode: TEST_SUCCESS_RESULT_CODE, + result: { + virtualId: 7001, + index: 2, + title: 'Updated Task Name', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + width: 200, + hidden: false, + validation: true, + version: 0, + autoNumberFormat: { + fill: '0001', + prefix: 'TASK-', + startingNumber: 1, + suffix: '', + }, + }, + }; + + const expectedRequiredResponseProperties = { + message: TEST_SUCCESS_MESSAGE, + resultCode: TEST_SUCCESS_RESULT_CODE, + result: { + index: 1, + title: 'Updated Column', + type: ReportColumnType.TEXT_NUMBER, + primary: true, + }, + }; + + it('updateReportColumn generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + body: testRequestBody, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/update-report-column/all-response-body-properties', + }, + }; + await client.reports.updateReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/columns/${TEST_COLUMN_VIRTUAL_ID}`); + expect(matchedRequest.method).toEqual('PUT'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({}); + }); + + it('updateReportColumn all response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + body: testRequestBody, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/update-report-column/all-response-body-properties', + }, + }; + const response = await client.reports.updateReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedAllResponseProperties); + + const body = JSON.parse(matchedRequest.body); + expect(body).toEqual(testRequestBody); + }); + + it('updateReportColumn required response body properties', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + body: testRequestBody, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/update-report-column/required-response-body-properties', + }, + }; + const response = await client.reports.updateReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + expect(response).toEqual(expectedRequiredResponseProperties); + + const body = JSON.parse(matchedRequest.body); + expect(body).toEqual(testRequestBody); + }); + + it('updateReportColumn error 500 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + body: testRequestBody, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/500-response', + }, + }; + try { + await client.reports.updateReportColumn(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); + } + }); + + it('updateReportColumn error 400 response', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + body: testRequestBody, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/errors/400-response', + }, + }; + try { + await client.reports.updateReportColumn(options); + expect(true).toBe(false); // Expected an error to be thrown + } catch (error: any) { + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); + } + }); +}); From e7869714d7de9aec2dbc605b0b1a84005eb6664a Mon Sep 17 00:00:00 2001 From: George Goranov Date: Mon, 15 Jun 2026 11:08:11 +0300 Subject: [PATCH 2/6] Re-order tests. --- .../reports/delete_report_column.spec.ts | 16 ++++++++-------- test/mock-api/reports/get_report_column.spec.ts | 16 ++++++++-------- .../reports/get_report_definition.spec.ts | 16 ++++++++-------- .../mock-api/reports/list_report_columns.spec.ts | 16 ++++++++-------- test/mock-api/reports/list_report_scope.spec.ts | 16 ++++++++-------- .../reports/update_report_column.spec.ts | 16 ++++++++-------- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/test/mock-api/reports/delete_report_column.spec.ts b/test/mock-api/reports/delete_report_column.spec.ts index 7640224..3341fd1 100644 --- a/test/mock-api/reports/delete_report_column.spec.ts +++ b/test/mock-api/reports/delete_report_column.spec.ts @@ -58,41 +58,41 @@ describe('Reports - deleteReportColumn endpoint tests', () => { expect(matchedRequest.body).toEqual(''); }); - it('deleteReportColumn error 500 response', async () => { + it('deleteReportColumn error 400 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, columnVirtualId: TEST_COLUMN_VIRTUAL_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/500-response', + 'x-test-name': '/errors/400-response', }, }; try { await client.reports.deleteReportColumn(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); - expect(error.message).toBe(ERROR_500_MESSAGE); + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); } }); - it('deleteReportColumn error 400 response', async () => { + it('deleteReportColumn error 500 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, columnVirtualId: TEST_COLUMN_VIRTUAL_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/400-response', + 'x-test-name': '/errors/500-response', }, }; try { await client.reports.deleteReportColumn(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); - expect(error.message).toBe(ERROR_400_MESSAGE); + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); } }); }); diff --git a/test/mock-api/reports/get_report_column.spec.ts b/test/mock-api/reports/get_report_column.spec.ts index e9c8ee7..c4a28a8 100644 --- a/test/mock-api/reports/get_report_column.spec.ts +++ b/test/mock-api/reports/get_report_column.spec.ts @@ -94,41 +94,41 @@ describe('Reports - getReportColumn endpoint tests', () => { expect(matchedRequest.body).toEqual(''); }); - it('getReportColumn error 500 response', async () => { + it('getReportColumn error 400 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, columnVirtualId: TEST_COLUMN_VIRTUAL_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/500-response', + 'x-test-name': '/errors/400-response', }, }; try { await client.reports.getReportColumn(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); - expect(error.message).toBe(ERROR_500_MESSAGE); + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); } }); - it('getReportColumn error 400 response', async () => { + it('getReportColumn error 500 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, columnVirtualId: TEST_COLUMN_VIRTUAL_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/400-response', + 'x-test-name': '/errors/500-response', }, }; try { await client.reports.getReportColumn(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); - expect(error.message).toBe(ERROR_400_MESSAGE); + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); } }); }); diff --git a/test/mock-api/reports/get_report_definition.spec.ts b/test/mock-api/reports/get_report_definition.spec.ts index 47e4fda..f6525b5 100644 --- a/test/mock-api/reports/get_report_definition.spec.ts +++ b/test/mock-api/reports/get_report_definition.spec.ts @@ -181,39 +181,39 @@ describe('Reports - getReportDefinition endpoint tests', () => { expect(matchedRequest.body).toEqual(''); }); - it('getReportDefinition error 500 response', async () => { + it('getReportDefinition error 400 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/500-response', + 'x-test-name': '/errors/400-response', }, }; try { await client.reports.getReportDefinition(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); - expect(error.message).toBe(ERROR_500_MESSAGE); + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); } }); - it('getReportDefinition error 400 response', async () => { + it('getReportDefinition error 500 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/400-response', + 'x-test-name': '/errors/500-response', }, }; try { await client.reports.getReportDefinition(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); - expect(error.message).toBe(ERROR_400_MESSAGE); + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); } }); }); diff --git a/test/mock-api/reports/list_report_columns.spec.ts b/test/mock-api/reports/list_report_columns.spec.ts index 446dbf2..28e6964 100644 --- a/test/mock-api/reports/list_report_columns.spec.ts +++ b/test/mock-api/reports/list_report_columns.spec.ts @@ -145,39 +145,39 @@ describe('Reports - listReportColumns endpoint tests', () => { expect(matchedRequest.body).toEqual(''); }); - it('listReportColumns error 500 response', async () => { + it('listReportColumns error 400 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/500-response', + 'x-test-name': '/errors/400-response', }, }; try { await client.reports.listReportColumns(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); - expect(error.message).toBe(ERROR_500_MESSAGE); + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); } }); - it('listReportColumns error 400 response', async () => { + it('listReportColumns error 500 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/400-response', + 'x-test-name': '/errors/500-response', }, }; try { await client.reports.listReportColumns(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); - expect(error.message).toBe(ERROR_400_MESSAGE); + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); } }); }); diff --git a/test/mock-api/reports/list_report_scope.spec.ts b/test/mock-api/reports/list_report_scope.spec.ts index 5e9f3b1..b0b6452 100644 --- a/test/mock-api/reports/list_report_scope.spec.ts +++ b/test/mock-api/reports/list_report_scope.spec.ts @@ -89,39 +89,39 @@ describe('Reports - listReportScope endpoint tests', () => { expect(matchedRequest.body).toEqual(''); }); - it('listReportScope error 500 response', async () => { + it('listReportScope error 400 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/500-response', + 'x-test-name': '/errors/400-response', }, }; try { await client.reports.listReportScope(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); - expect(error.message).toBe(ERROR_500_MESSAGE); + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); } }); - it('listReportScope error 400 response', async () => { + it('listReportScope error 500 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/400-response', + 'x-test-name': '/errors/500-response', }, }; try { await client.reports.listReportScope(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); - expect(error.message).toBe(ERROR_400_MESSAGE); + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); } }); }); diff --git a/test/mock-api/reports/update_report_column.spec.ts b/test/mock-api/reports/update_report_column.spec.ts index dd34aa8..0964a82 100644 --- a/test/mock-api/reports/update_report_column.spec.ts +++ b/test/mock-api/reports/update_report_column.spec.ts @@ -118,7 +118,7 @@ describe('Reports - updateReportColumn endpoint tests', () => { expect(body).toEqual(testRequestBody); }); - it('updateReportColumn error 500 response', async () => { + it('updateReportColumn error 400 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, @@ -126,19 +126,19 @@ describe('Reports - updateReportColumn endpoint tests', () => { body: testRequestBody, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/500-response', + 'x-test-name': '/errors/400-response', }, }; try { await client.reports.updateReportColumn(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); - expect(error.message).toBe(ERROR_500_MESSAGE); + expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); + expect(error.message).toBe(ERROR_400_MESSAGE); } }); - it('updateReportColumn error 400 response', async () => { + it('updateReportColumn error 500 response', async () => { const requestId = crypto.randomUUID(); const options = { reportId: TEST_REPORT_ID, @@ -146,15 +146,15 @@ describe('Reports - updateReportColumn endpoint tests', () => { body: testRequestBody, customProperties: { 'x-request-id': requestId, - 'x-test-name': '/errors/400-response', + 'x-test-name': '/errors/500-response', }, }; try { await client.reports.updateReportColumn(options); expect(true).toBe(false); // Expected an error to be thrown } catch (error: any) { - expect(error.statusCode).toBe(ERROR_400_STATUS_CODE); - expect(error.message).toBe(ERROR_400_MESSAGE); + expect(error.statusCode).toBe(ERROR_500_STATUS_CODE); + expect(error.message).toBe(ERROR_500_MESSAGE); } }); }); From 966372b3e60b9da546fab8da31d610b3c6889571 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Mon, 15 Jun 2026 11:09:19 +0300 Subject: [PATCH 3/6] Fix lint issues. --- lib/reports/types.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/reports/types.ts b/lib/reports/types.ts index e4e82af..04269bf 100644 --- a/lib/reports/types.ts +++ b/lib/reports/types.ts @@ -488,10 +488,7 @@ export interface ReportsApi { * const column = await client.reports.getReportColumn({ reportId: 4583173393803140, columnVirtualId: 123 }); * ``` */ - getReportColumn: ( - options: GetReportColumnOptions, - callback?: RequestCallback - ) => Promise; + getReportColumn: (options: GetReportColumnOptions, callback?: RequestCallback) => Promise; /** * Updates a column of a Report. From 6bddb92d95b27108760ebfa773123da05899859e Mon Sep 17 00:00:00 2001 From: George Goranov Date: Mon, 15 Jun 2026 13:06:51 +0300 Subject: [PATCH 4/6] Add changelog entry. --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8238cb7..5a21eba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [X.X.X] - Unreleased +### Added +- Added support for GET /2.0/reports/{reportId}/scope endpoint (`listReportScope`) +- Added support for GET /2.0/reports/{reportId}/columns endpoint (`listReportColumns`) +- Added support for GET /2.0/reports/{reportId}/columns/{columnVirtualId} endpoint (`getReportColumn`) +- Added support for PUT /2.0/reports/{reportId}/columns/{columnVirtualId} endpoint (`updateReportColumn`) +- Added support for DELETE /2.0/reports/{reportId}/columns/{columnVirtualId} endpoint (`deleteReportColumn`) +- Added support for GET /2.0/reports/{reportId}/definition endpoint (`getReportDefinition`) + ## [5.0.1] - 2026-06-10 ### Fixed From 5cb318032fce79b1830c3ba3438e80d9a5a77445 Mon Sep 17 00:00:00 2001 From: Georgi Gyurchev Date: Fri, 3 Jul 2026 18:13:55 +0300 Subject: [PATCH 5/6] Add compatibility level parameter for getReportColumn and listReportColumns --- lib/reports/types.ts | 18 ++++++++++-- .../reports/get_report_column.spec.ts | 25 +++++++++++++++++ .../reports/list_report_columns.spec.ts | 28 +++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/lib/reports/types.ts b/lib/reports/types.ts index 04269bf..8ed4157 100644 --- a/lib/reports/types.ts +++ b/lib/reports/types.ts @@ -1780,7 +1780,14 @@ export type ListReportScopeResponse = TokenPaginationResponse; // Get Report Columns // ============================================================================ -export interface ListReportColumnsOptions extends RequestOptions { +export interface ListReportColumnsQueryParameters extends TokenPaginationQueryParameters { + /** + * Compatibility level. + */ + level?: number; +} + +export interface ListReportColumnsOptions extends RequestOptions { /** * Report ID. */ @@ -1793,7 +1800,14 @@ export type ListReportColumnsResponse = TokenPaginationResponse; // Get Report Column // ============================================================================ -export interface GetReportColumnOptions extends RequestOptions { +export interface GetReportColumnQueryParameters { + /** + * Compatibility level. + */ + level?: number; +} + +export interface GetReportColumnOptions extends RequestOptions { /** * Report ID. */ diff --git a/test/mock-api/reports/get_report_column.spec.ts b/test/mock-api/reports/get_report_column.spec.ts index c4a28a8..dbddeb7 100644 --- a/test/mock-api/reports/get_report_column.spec.ts +++ b/test/mock-api/reports/get_report_column.spec.ts @@ -60,6 +60,31 @@ describe('Reports - getReportColumn endpoint tests', () => { expect(queryParamsObject).toEqual({}); }); + it('getReportColumn with level generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + columnVirtualId: TEST_COLUMN_VIRTUAL_ID, + queryParameters: { + level: 3 + }, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/get-report-column/all-response-body-properties', + }, + }; + await client.reports.getReportColumn(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/columns/${TEST_COLUMN_VIRTUAL_ID}`); + expect(matchedRequest.method).toEqual('GET'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({ + level: '3' + }); + }); + it('getReportColumn all response body properties', async () => { const requestId = crypto.randomUUID(); const options = { diff --git a/test/mock-api/reports/list_report_columns.spec.ts b/test/mock-api/reports/list_report_columns.spec.ts index 28e6964..2c1079f 100644 --- a/test/mock-api/reports/list_report_columns.spec.ts +++ b/test/mock-api/reports/list_report_columns.spec.ts @@ -113,6 +113,34 @@ describe('Reports - listReportColumns endpoint tests', () => { }); }); + it('listReportColumns with level generated url is correct', async () => { + const requestId = crypto.randomUUID(); + const options = { + reportId: TEST_REPORT_ID, + queryParameters: { + lastKey: TEST_LAST_KEY, + maxItems: TEST_MAX_ITEMS, + level: 3 + }, + customProperties: { + 'x-request-id': requestId, + 'x-test-name': '/reports/list-report-columns/all-response-body-properties', + }, + }; + await client.reports.listReportColumns(options); + const matchedRequest = await findWireMockRequest(requestId); + + const parsedUrl = new URL(matchedRequest.absoluteUrl); + expect(parsedUrl.pathname).toEqual(`/2.0/reports/${TEST_REPORT_ID}/columns`); + expect(matchedRequest.method).toEqual('GET'); + const queryParamsObject = Object.fromEntries(parsedUrl.searchParams); + expect(queryParamsObject).toEqual({ + lastKey: TEST_LAST_KEY, + maxItems: TEST_MAX_ITEMS.toString(), + level: '3' + }); + }); + it('listReportColumns all response body properties', async () => { const requestId = crypto.randomUUID(); const options = { From 7f9ae58a5bee1b6c30cf77df1eb37c5d6ff2cc47 Mon Sep 17 00:00:00 2001 From: Georgi Gyurchev Date: Thu, 9 Jul 2026 16:17:23 +0300 Subject: [PATCH 6/6] Fix test --- test/functional/client.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/client.spec.ts b/test/functional/client.spec.ts index 60c3ba6..51e179a 100644 --- a/test/functional/client.spec.ts +++ b/test/functional/client.spec.ts @@ -179,7 +179,7 @@ describe('Client Unit Tests', () => { describe('#reports', () => { it('should have reports object', () => { expect(smartsheet).toHaveProperty('reports'); - expect(Object.keys(smartsheet.reports)).toHaveLength(19); + expect(Object.keys(smartsheet.reports)).toHaveLength(20); }); it('should have get methods', () => {