From 275bdbf57be103ce41ced2f1151753cad11ee6b5 Mon Sep 17 00:00:00 2001 From: Levko Kravets Date: Tue, 21 May 2024 13:50:07 +0300 Subject: [PATCH] Polish & cleanup Signed-off-by: Levko Kravets --- lib/DBSQLClient.ts | 16 +- lib/DBSQLOperation.ts | 18 +- lib/DBSQLSession.ts | 4 +- .../auth/DatabricksOAuth/AuthorizationCode.ts | 2 +- lib/connection/auth/DatabricksOAuth/index.ts | 16 +- .../auth/PlainHttpAuthentication.ts | 8 +- lib/connection/connections/HttpConnection.ts | 2 +- lib/connection/connections/HttpRetryPolicy.ts | 6 +- lib/result/ArrowResultConverter.ts | 4 +- lib/result/ArrowResultHandler.ts | 6 +- lib/result/CloudFetchResultHandler.ts | 8 +- lib/result/JsonResultHandler.ts | 4 +- lib/result/ResultSlicer.ts | 2 +- lib/utils/CloseableCollection.ts | 2 +- tests/unit/.stubs/ClientContextStub.ts | 3 +- tests/unit/DBSQLClient.test.ts | 226 +++++-------- tests/unit/DBSQLOperation.test.ts | 317 ++++++++---------- tests/unit/DBSQLSession.test.ts | 119 +++---- .../DatabricksOAuth/AuthorizationCode.test.ts | 80 ++--- .../auth/DatabricksOAuth/OAuthManager.test.ts | 2 +- .../auth/DatabricksOAuth/index.test.ts | 88 ++--- .../auth/PlainHttpAuthentication.test.ts | 30 +- .../connections/HttpConnection.test.ts | 24 +- .../connections/HttpRetryPolicy.test.ts | 141 +++----- tests/unit/hive/commands/BaseCommand.test.ts | 24 +- tests/unit/result/ArrowResultHandler.test.ts | 30 +- .../result/CloudFetchResultHandler.test.ts | 100 ++---- tests/unit/result/JsonResultHandler.test.ts | 22 +- tests/unit/utils/CloseableCollection.test.ts | 62 ++-- 29 files changed, 598 insertions(+), 768 deletions(-) diff --git a/lib/DBSQLClient.ts b/lib/DBSQLClient.ts index 54c44cf1..d3d9427c 100644 --- a/lib/DBSQLClient.ts +++ b/lib/DBSQLClient.ts @@ -51,11 +51,11 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I private readonly config: ClientConfig; - protected connectionProvider?: IConnectionProvider; + private connectionProvider?: IConnectionProvider; - protected authProvider?: IAuthentication; + private authProvider?: IAuthentication; - protected client?: IThriftClient; + private client?: IThriftClient; private readonly driver = new HiveDriver({ context: this, @@ -63,9 +63,9 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I private readonly logger: IDBSQLLogger; - protected thrift: ThriftLibrary = thrift; + private thrift: ThriftLibrary = thrift; - protected sessions = new CloseableCollection(); + private readonly sessions = new CloseableCollection(); private static getDefaultLogger(): IDBSQLLogger { if (!this.defaultLogger) { @@ -102,7 +102,7 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I this.logger.log(LogLevel.info, 'Created DBSQLClient'); } - protected getConnectionOptions(options: ConnectionOptions): IConnectionOptions { + private getConnectionOptions(options: ConnectionOptions): IConnectionOptions { return { host: options.host, port: options.port || 443, @@ -116,7 +116,7 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I }; } - protected createAuthProvider(options: ConnectionOptions, authProvider?: IAuthentication): IAuthentication { + private createAuthProvider(options: ConnectionOptions, authProvider?: IAuthentication): IAuthentication { if (authProvider) { return authProvider; } @@ -146,7 +146,7 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I } } - protected createConnectionProvider(options: ConnectionOptions): IConnectionProvider { + private createConnectionProvider(options: ConnectionOptions): IConnectionProvider { return new HttpConnection(this.getConnectionOptions(options), this); } diff --git a/lib/DBSQLOperation.ts b/lib/DBSQLOperation.ts index f9cebb94..50d22709 100644 --- a/lib/DBSQLOperation.ts +++ b/lib/DBSQLOperation.ts @@ -48,21 +48,21 @@ async function delay(ms?: number): Promise { } export default class DBSQLOperation implements IOperation { - protected readonly context: IClientContext; + private readonly context: IClientContext; - protected readonly operationHandle: TOperationHandle; + private readonly operationHandle: TOperationHandle; - protected readonly _data: RowSetProvider; + private readonly _data: RowSetProvider; - protected readonly closeOperation?: TCloseOperationResp; + private readonly closeOperation?: TCloseOperationResp; - protected closed: boolean = false; + private closed: boolean = false; - protected cancelled: boolean = false; + private cancelled: boolean = false; - protected metadata?: TGetResultSetMetadataResp; + private metadata?: TGetResultSetMetadataResp; - protected state: number = TOperationState.INITIALIZED_STATE; + private state: TOperationState = TOperationState.INITIALIZED_STATE; public onClose?: () => void; @@ -376,7 +376,7 @@ export default class DBSQLOperation implements IOperation { return this.metadata; } - protected async getResultHandler(): Promise> { + private async getResultHandler(): Promise> { const metadata = await this.fetchMetadata(); const resultFormat = definedOrError(metadata.resultFormat); diff --git a/lib/DBSQLSession.ts b/lib/DBSQLSession.ts index 2e445543..2f9e1fcc 100644 --- a/lib/DBSQLSession.ts +++ b/lib/DBSQLSession.ts @@ -143,9 +143,9 @@ export default class DBSQLSession implements IDBSQLSession { private readonly sessionHandle: TSessionHandle; - protected isOpen = true; + private isOpen = true; - protected operations = new CloseableCollection(); + private operations = new CloseableCollection(); public onClose?: () => void; diff --git a/lib/connection/auth/DatabricksOAuth/AuthorizationCode.ts b/lib/connection/auth/DatabricksOAuth/AuthorizationCode.ts index eaf655e6..58560857 100644 --- a/lib/connection/auth/DatabricksOAuth/AuthorizationCode.ts +++ b/lib/connection/auth/DatabricksOAuth/AuthorizationCode.ts @@ -129,7 +129,7 @@ export default class AuthorizationCode { throw new AuthenticationError('Failed to start server: all ports are in use'); } - protected createHttpServer(requestHandler: (req: IncomingMessage, res: ServerResponse) => void) { + private createHttpServer(requestHandler: (req: IncomingMessage, res: ServerResponse) => void) { return http.createServer(requestHandler); } diff --git a/lib/connection/auth/DatabricksOAuth/index.ts b/lib/connection/auth/DatabricksOAuth/index.ts index feaec2ed..fa855af4 100644 --- a/lib/connection/auth/DatabricksOAuth/index.ts +++ b/lib/connection/auth/DatabricksOAuth/index.ts @@ -16,16 +16,15 @@ export interface DatabricksOAuthOptions extends OAuthManagerOptions { export default class DatabricksOAuth implements IAuthentication { private readonly context: IClientContext; - protected readonly options: DatabricksOAuthOptions; + private readonly options: DatabricksOAuthOptions; - protected readonly manager: OAuthManager; + private manager?: OAuthManager; private readonly defaultPersistence = new OAuthPersistenceCache(); constructor(options: DatabricksOAuthOptions) { this.context = options.context; this.options = options; - this.manager = this.createManager(this.options); } public async authenticate(): Promise { @@ -35,10 +34,10 @@ export default class DatabricksOAuth implements IAuthentication { let token = await persistence.read(host); if (!token) { - token = await this.manager.getToken(scopes ?? defaultOAuthScopes); + token = await this.getManager().getToken(scopes ?? defaultOAuthScopes); } - token = await this.manager.refreshAccessToken(token); + token = await this.getManager().refreshAccessToken(token); await persistence.persist(host, token); return { @@ -47,7 +46,10 @@ export default class DatabricksOAuth implements IAuthentication { }; } - protected createManager(options: OAuthManagerOptions): OAuthManager { - return OAuthManager.getManager(options); + private getManager(): OAuthManager { + if (!this.manager) { + this.manager = OAuthManager.getManager(this.options); + } + return this.manager; } } diff --git a/lib/connection/auth/PlainHttpAuthentication.ts b/lib/connection/auth/PlainHttpAuthentication.ts index 4fb84151..977f1cc5 100644 --- a/lib/connection/auth/PlainHttpAuthentication.ts +++ b/lib/connection/auth/PlainHttpAuthentication.ts @@ -10,13 +10,13 @@ interface PlainHttpAuthenticationOptions { } export default class PlainHttpAuthentication implements IAuthentication { - protected readonly context: IClientContext; + private readonly context: IClientContext; - protected readonly username: string; + private readonly username: string; - protected readonly password: string; + private readonly password: string; - protected readonly headers: HeadersInit; + private readonly headers: HeadersInit; constructor(options: PlainHttpAuthenticationOptions) { this.context = options.context; diff --git a/lib/connection/connections/HttpConnection.ts b/lib/connection/connections/HttpConnection.ts index a1bdec94..dc9c3902 100644 --- a/lib/connection/connections/HttpConnection.ts +++ b/lib/connection/connections/HttpConnection.ts @@ -17,7 +17,7 @@ export default class HttpConnection implements IConnectionProvider { private readonly context: IClientContext; - protected headers: HeadersInit = {}; + private headers: HeadersInit = {}; private connection?: ThriftHttpConnection; diff --git a/lib/connection/connections/HttpRetryPolicy.ts b/lib/connection/connections/HttpRetryPolicy.ts index fb1a9f8d..c28d0efc 100644 --- a/lib/connection/connections/HttpRetryPolicy.ts +++ b/lib/connection/connections/HttpRetryPolicy.ts @@ -10,11 +10,11 @@ function delay(milliseconds: number): Promise { } export default class HttpRetryPolicy implements IRetryPolicy { - protected context: IClientContext; + private context: IClientContext; - protected startTime: number; // in milliseconds + private startTime: number; // in milliseconds - protected attempt: number; + private attempt: number; constructor(context: IClientContext) { this.context = context; diff --git a/lib/result/ArrowResultConverter.ts b/lib/result/ArrowResultConverter.ts index a6de359c..57fa02af 100644 --- a/lib/result/ArrowResultConverter.ts +++ b/lib/result/ArrowResultConverter.ts @@ -24,9 +24,9 @@ type ArrowSchema = Schema; type ArrowSchemaField = Field>; export default class ArrowResultConverter implements IResultsProvider> { - protected readonly context: IClientContext; + private readonly context: IClientContext; - public readonly source: IResultsProvider; + private readonly source: IResultsProvider; private readonly schema: Array; diff --git a/lib/result/ArrowResultHandler.ts b/lib/result/ArrowResultHandler.ts index 75f461d7..a67cd617 100644 --- a/lib/result/ArrowResultHandler.ts +++ b/lib/result/ArrowResultHandler.ts @@ -6,11 +6,11 @@ import { ArrowBatch, hiveSchemaToArrowSchema } from './utils'; import { LZ4 } from '../utils'; export default class ArrowResultHandler implements IResultsProvider { - protected readonly context: IClientContext; + private readonly context: IClientContext; - public readonly source: IResultsProvider; + private readonly source: IResultsProvider; - protected readonly arrowSchema?: Buffer; + private readonly arrowSchema?: Buffer; private readonly isLZ4Compressed: boolean; diff --git a/lib/result/CloudFetchResultHandler.ts b/lib/result/CloudFetchResultHandler.ts index fa0c590c..081eb134 100644 --- a/lib/result/CloudFetchResultHandler.ts +++ b/lib/result/CloudFetchResultHandler.ts @@ -7,15 +7,15 @@ import { ArrowBatch } from './utils'; import { LZ4 } from '../utils'; export default class CloudFetchResultHandler implements IResultsProvider { - protected readonly context: IClientContext; + private readonly context: IClientContext; - public readonly source: IResultsProvider; + private readonly source: IResultsProvider; private readonly isLZ4Compressed: boolean; - protected pendingLinks: Array = []; + private pendingLinks: Array = []; - protected downloadTasks: Array> = []; + private downloadTasks: Array> = []; constructor( context: IClientContext, diff --git a/lib/result/JsonResultHandler.ts b/lib/result/JsonResultHandler.ts index 71fedd75..2286b6dd 100644 --- a/lib/result/JsonResultHandler.ts +++ b/lib/result/JsonResultHandler.ts @@ -6,7 +6,7 @@ import { getSchemaColumns, convertThriftValue, getColumnValue } from './utils'; export default class JsonResultHandler implements IResultsProvider> { private readonly context: IClientContext; - public readonly source: IResultsProvider; + private readonly source: IResultsProvider; private readonly schema: Array; @@ -72,7 +72,7 @@ export default class JsonResultHandler implements IResultsProvider> { }); } - protected isNull(nulls: Buffer, i: number): boolean { + private isNull(nulls: Buffer, i: number): boolean { const byte = nulls[Math.floor(i / 8)]; const ofs = 2 ** (i % 8); diff --git a/lib/result/ResultSlicer.ts b/lib/result/ResultSlicer.ts index dff7768a..11a2a15f 100644 --- a/lib/result/ResultSlicer.ts +++ b/lib/result/ResultSlicer.ts @@ -10,7 +10,7 @@ export interface ResultSlicerFetchNextOptions extends ResultsProviderFetchNextOp export default class ResultSlicer implements IResultsProvider> { private readonly context: IClientContext; - public readonly source: IResultsProvider>; + private readonly source: IResultsProvider>; private remainingResults: Array = []; diff --git a/lib/utils/CloseableCollection.ts b/lib/utils/CloseableCollection.ts index 20b19eee..91b8bfcf 100644 --- a/lib/utils/CloseableCollection.ts +++ b/lib/utils/CloseableCollection.ts @@ -5,7 +5,7 @@ export interface ICloseable { } export default class CloseableCollection { - protected items = new Set(); + private items = new Set(); public add(item: T) { item.onClose = () => { diff --git a/tests/unit/.stubs/ClientContextStub.ts b/tests/unit/.stubs/ClientContextStub.ts index 8a5c327d..519316ff 100644 --- a/tests/unit/.stubs/ClientContextStub.ts +++ b/tests/unit/.stubs/ClientContextStub.ts @@ -26,8 +26,7 @@ export default class ClientContextStub implements IClientContext { } public getConfig(): ClientConfig { - // @ts-expect-error TS2341: Property getDefaultConfig is private and only accessible within class DBSQLClient - const defaultConfig = DBSQLClient.getDefaultConfig(); + const defaultConfig = DBSQLClient['getDefaultConfig'](); return { ...defaultConfig, ...this.configOverrides, diff --git a/tests/unit/DBSQLClient.test.ts b/tests/unit/DBSQLClient.test.ts index 6fdb3cd7..5caf8420 100644 --- a/tests/unit/DBSQLClient.test.ts +++ b/tests/unit/DBSQLClient.test.ts @@ -17,38 +17,6 @@ import IAuthentication from '../../lib/connection/contracts/IAuthentication'; import AuthProviderStub from './.stubs/AuthProviderStub'; import ConnectionProviderStub from './.stubs/ConnectionProviderStub'; -interface DBSQLClientInternals { - client: IThriftClient | null; - authProvider: IAuthentication | null; - connectionProvider: IConnectionProvider | null; - thrift: ThriftLibrary; -} - -class DBSQLClientTest extends DBSQLClient { - public getConnectionOptions = super.getConnectionOptions; - - public createAuthProvider = super.createAuthProvider; - - public createConnectionProvider = super.createConnectionProvider; - - public inspectInternals() { - return { - client: this.client, - authProvider: this.authProvider, - connectionProvider: this.connectionProvider, - sessions: this.sessions, - }; - } - - public updateInternals(values: Partial) { - this.client = values.client === null ? undefined : values.client ?? this.client; - this.authProvider = values.authProvider === null ? undefined : values.authProvider ?? this.authProvider; - this.connectionProvider = - values.connectionProvider === null ? undefined : values.connectionProvider ?? this.connectionProvider; - this.thrift = values.thrift ?? this.thrift; - } -} - const connectOptions = { host: '127.0.0.1', port: 80, @@ -58,45 +26,47 @@ const connectOptions = { describe('DBSQLClient.connect', () => { it('should prepend "/" to path if it is missing', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const path = 'example/path'; - const connectionOptions = client.getConnectionOptions({ ...connectOptions, path }); + const connectionOptions = client['getConnectionOptions']({ ...connectOptions, path }); expect(connectionOptions.path).to.equal(`/${path}`); }); it('should not prepend "/" to path if it is already available', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const path = '/example/path'; - const connectionOptions = client.getConnectionOptions({ ...connectOptions, path }); + const connectionOptions = client['getConnectionOptions']({ ...connectOptions, path }); expect(connectionOptions.path).to.equal(path); }); it('should initialize connection state', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); - expect(client.inspectInternals().client).to.be.undefined; - expect(client.inspectInternals().authProvider).to.be.undefined; - expect(client.inspectInternals().connectionProvider).to.be.undefined; + expect(client['client']).to.be.undefined; + expect(client['authProvider']).to.be.undefined; + expect(client['connectionProvider']).to.be.undefined; await client.connect(connectOptions); - expect(client.inspectInternals().client).to.be.undefined; // it should not be initialized at this point - expect(client.inspectInternals().authProvider).to.be.instanceOf(PlainHttpAuthentication); - expect(client.inspectInternals().connectionProvider).to.be.instanceOf(HttpConnection); + expect(client['client']).to.be.undefined; // it should not be initialized at this point + expect(client['authProvider']).to.be.instanceOf(PlainHttpAuthentication); + expect(client['connectionProvider']).to.be.instanceOf(HttpConnection); }); it('should listen for Thrift connection events', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const thriftConnectionStub = { on: sinon.stub(), }; - sinon.stub(client, 'createConnectionProvider').returns({ + // This method is private, so we cannot easily `sinon.stub` it. + // But in this case we can just replace it + client['createConnectionProvider'] = () => ({ getThriftConnection: async () => thriftConnectionStub, getAgent: async () => undefined, setHeaders: () => {}, @@ -113,7 +83,7 @@ describe('DBSQLClient.connect', () => { describe('DBSQLClient.openSession', () => { it('should successfully open session', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const thriftClient = new ThriftClientStub(); sinon.stub(client, 'getClient').returns(Promise.resolve(thriftClient)); @@ -122,7 +92,7 @@ describe('DBSQLClient.openSession', () => { }); it('should use initial namespace options', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const thriftClient = new ThriftClientStub(); sinon.stub(client, 'getClient').returns(Promise.resolve(thriftClient)); @@ -153,10 +123,8 @@ describe('DBSQLClient.openSession', () => { }); it('should throw an exception when not connected', async () => { - const client = new DBSQLClientTest(); - client.updateInternals({ - connectionProvider: null, - }); + const client = new DBSQLClient(); + client['connectionProvider'] = undefined; try { await client.openSession(); @@ -172,7 +140,7 @@ describe('DBSQLClient.openSession', () => { describe('DBSQLClient.getClient', () => { it('should throw an error if not connected', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); try { await client.getClient(); expect.fail('It should throw an error'); @@ -185,18 +153,16 @@ describe('DBSQLClient.getClient', () => { }); it('should create client if was not initialized yet', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const thriftClient = new ThriftClientStub(); const createThriftClient = sinon.stub().returns(thriftClient); - client.updateInternals({ - authProvider: new AuthProviderStub(), - connectionProvider: new ConnectionProviderStub(), - thrift: { - createClient: createThriftClient, - }, - }); + client['authProvider'] = new AuthProviderStub(); + client['connectionProvider'] = new ConnectionProviderStub(); + client['thrift'] = { + createClient: createThriftClient, + }; const result = await client.getClient(); expect(createThriftClient.called).to.be.true; @@ -204,30 +170,26 @@ describe('DBSQLClient.getClient', () => { }); it('should update auth credentials each time when client is requested', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const thriftClient = new ThriftClientStub(); const createThriftClient = sinon.stub().returns(thriftClient); const authProvider = sinon.spy(new AuthProviderStub()); const connectionProvider = sinon.spy(new ConnectionProviderStub()); - client.updateInternals({ - connectionProvider, - thrift: { - createClient: createThriftClient, - }, - }); + client['connectionProvider'] = connectionProvider; + client['thrift'] = { + createClient: createThriftClient, + }; // just a sanity check - authProvider should not be initialized until `getClient()` call - expect(client.inspectInternals().authProvider).to.be.undefined; + expect(client['authProvider']).to.be.undefined; expect(connectionProvider.setHeaders.callCount).to.be.equal(0); await client.getClient(); expect(authProvider.authenticate.callCount).to.be.equal(0); expect(connectionProvider.setHeaders.callCount).to.be.equal(0); - client.updateInternals({ - authProvider, - }); + client['authProvider'] = authProvider; // initialize client firstCall: { @@ -245,7 +207,7 @@ describe('DBSQLClient.getClient', () => { expect(result).to.be.equal(thriftClient); } - // change credentials mock - client should be re-created + // change credentials stub - client should be re-created thirdCall: { authProvider.headers = { test: 'test' }; @@ -259,41 +221,37 @@ describe('DBSQLClient.getClient', () => { describe('DBSQLClient.close', () => { it('should close the connection if it was initiated', async () => { - const client = new DBSQLClientTest(); - client.updateInternals({ - client: new ThriftClientStub(), - connectionProvider: new ConnectionProviderStub(), - authProvider: new AuthProviderStub(), - }); + const client = new DBSQLClient(); + client['client'] = new ThriftClientStub(); + client['connectionProvider'] = new ConnectionProviderStub(); + client['authProvider'] = new AuthProviderStub(); await client.close(); - expect(client.inspectInternals().client).to.be.undefined; - expect(client.inspectInternals().connectionProvider).to.be.undefined; - expect(client.inspectInternals().authProvider).to.be.undefined; + expect(client['client']).to.be.undefined; + expect(client['connectionProvider']).to.be.undefined; + expect(client['authProvider']).to.be.undefined; }); it('should do nothing if the connection does not exist', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); - expect(client.inspectInternals().client).to.be.undefined; - expect(client.inspectInternals().connectionProvider).to.be.undefined; - expect(client.inspectInternals().authProvider).to.be.undefined; + expect(client['client']).to.be.undefined; + expect(client['connectionProvider']).to.be.undefined; + expect(client['authProvider']).to.be.undefined; await client.close(); - expect(client.inspectInternals().client).to.be.undefined; - expect(client.inspectInternals().connectionProvider).to.be.undefined; - expect(client.inspectInternals().authProvider).to.be.undefined; + expect(client['client']).to.be.undefined; + expect(client['connectionProvider']).to.be.undefined; + expect(client['authProvider']).to.be.undefined; }); it('should close sessions that belong to it', async () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const thriftClient = sinon.spy(new ThriftClientStub()); - client.updateInternals({ - client: thriftClient, - connectionProvider: new ConnectionProviderStub(), - authProvider: new AuthProviderStub(), - }); + client['client'] = thriftClient; + client['connectionProvider'] = new ConnectionProviderStub(); + client['authProvider'] = new AuthProviderStub(); const session = await client.openSession(); if (!(session instanceof DBSQLSession)) { @@ -301,32 +259,28 @@ describe('DBSQLClient.close', () => { } expect(session.onClose).to.be.not.undefined; - // @ts-expect-error TS2445: Property isOpen is protected - expect(session.isOpen).to.be.true; - // @ts-expect-error TS2445: Property items is protected - expect(client.inspectInternals().sessions.items.size).to.eq(1); + expect(session['isOpen']).to.be.true; + expect(client['sessions']['items'].size).to.eq(1); - const closeAllSessionsSpy = sinon.spy(client.inspectInternals().sessions, 'closeAll'); + const closeAllSessionsSpy = sinon.spy(client['sessions'], 'closeAll'); const sessionCloseSpy = sinon.spy(session, 'close'); await client.close(); expect(closeAllSessionsSpy.called).to.be.true; expect(sessionCloseSpy.called).to.be.true; expect(session.onClose).to.be.undefined; - // @ts-expect-error TS2445: Property isOpen is protected - expect(session.isOpen).to.be.false; - // @ts-expect-error TS2445: Property items is protected - expect(client.inspectInternals().sessions.items.size).to.eq(0); + expect(session['isOpen']).to.be.false; + expect(client['sessions']['items'].size).to.eq(0); expect(thriftClient.CloseSession.called).to.be.true; }); }); describe('DBSQLClient.createAuthProvider', () => { it('should use access token auth method', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const testAccessToken = 'token'; - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'access-token', token: testAccessToken, @@ -336,15 +290,14 @@ describe('DBSQLClient.createAuthProvider', () => { if (!(provider instanceof PlainHttpAuthentication)) { throw new Error('Assertion error: expected provider to be PlainHttpAuthentication'); } - // @ts-expect-error TS2445: Property password is protected - expect(provider.password).to.be.equal(testAccessToken); + expect(provider['password']).to.be.equal(testAccessToken); }); it('should use access token auth method by default (compatibility)', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const testAccessToken = 'token'; - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, // note: no `authType` provided token: testAccessToken, @@ -354,14 +307,13 @@ describe('DBSQLClient.createAuthProvider', () => { if (!(provider instanceof PlainHttpAuthentication)) { throw new Error('Assertion error: expected provider to be PlainHttpAuthentication'); } - // @ts-expect-error TS2445: Property password is protected - expect(provider.password).to.be.equal(testAccessToken); + expect(provider['password']).to.be.equal(testAccessToken); }); it('should use Databricks OAuth method (AWS)', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'databricks-oauth', // host is used when creating OAuth manager, so make it look like a real AWS instance @@ -373,14 +325,13 @@ describe('DBSQLClient.createAuthProvider', () => { if (!(provider instanceof DatabricksOAuth)) { throw new Error('Assertion error: expected provider to be DatabricksOAuth'); } - // @ts-expect-error TS2445: Property manager is protected - expect(provider.manager).to.be.instanceOf(DatabricksOAuthManager); + expect(provider['getManager']()).to.be.instanceOf(DatabricksOAuthManager); }); it('should use Databricks OAuth method (Azure)', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'databricks-oauth', // host is used when creating OAuth manager, so make it look like a real Azure instance @@ -391,14 +342,13 @@ describe('DBSQLClient.createAuthProvider', () => { if (!(provider instanceof DatabricksOAuth)) { throw new Error('Assertion error: expected provider to be DatabricksOAuth'); } - // @ts-expect-error TS2445: Property manager is protected - expect(provider.manager).to.be.instanceOf(AzureOAuthManager); + expect(provider['getManager']()).to.be.instanceOf(AzureOAuthManager); }); it('should use Databricks OAuth method (GCP)', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'databricks-oauth', // host is used when creating OAuth manager, so make it look like a real AWS instance @@ -409,18 +359,17 @@ describe('DBSQLClient.createAuthProvider', () => { if (!(provider instanceof DatabricksOAuth)) { throw new Error('Assertion error: expected provider to be DatabricksOAuth'); } - // @ts-expect-error TS2445: Property manager is protected - expect(provider.manager).to.be.instanceOf(DatabricksOAuthManager); + expect(provider['getManager']()).to.be.instanceOf(DatabricksOAuthManager); }); it('should use Databricks InHouse OAuth method (Azure)', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); // When `useDatabricksOAuthInAzure = true`, it should use Databricks OAuth method // only for supported Azure hosts, and fail for others case1: { - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'databricks-oauth', // host is used when creating OAuth manager, so make it look like a real Azure instance @@ -432,44 +381,53 @@ describe('DBSQLClient.createAuthProvider', () => { if (!(provider instanceof DatabricksOAuth)) { throw new Error('Assertion error: expected provider to be DatabricksOAuth'); } - // @ts-expect-error TS2445: Property manager is protected - expect(provider.manager).to.be.instanceOf(DatabricksOAuthManager); + expect(provider['getManager']()).to.be.instanceOf(DatabricksOAuthManager); } case2: { expect(() => { - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'databricks-oauth', // host is used when creating OAuth manager, so make it look like a real Azure instance host: 'example.databricks.azure.us', useDatabricksOAuthInAzure: true, }); + + if (!(provider instanceof DatabricksOAuth)) { + throw new Error('Expected `provider` to be `DatabricksOAuth`'); + } + provider['getManager'](); // just call the method }).to.throw(); } }); it('should throw error when OAuth not supported for host', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); expect(() => { - client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'databricks-oauth', // use host which is not supported for sure host: 'example.com', }); + + if (!(provider instanceof DatabricksOAuth)) { + throw new Error('Expected `provider` to be `DatabricksOAuth`'); + } + provider['getManager'](); // just call the method }).to.throw(); }); it('should use custom auth method', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const customProvider = { authenticate: () => Promise.resolve({}), }; - const provider = client.createAuthProvider({ + const provider = client['createAuthProvider']({ ...connectOptions, authType: 'custom', provider: customProvider, @@ -479,13 +437,13 @@ describe('DBSQLClient.createAuthProvider', () => { }); it('should use custom auth method (legacy way)', () => { - const client = new DBSQLClientTest(); + const client = new DBSQLClient(); const customProvider = { authenticate: () => Promise.resolve({}), }; - const provider = client.createAuthProvider( + const provider = client['createAuthProvider']( // custom provider from second arg should be used no matter what's specified in config { ...connectOptions, authType: 'access-token', token: 'token' }, customProvider, diff --git a/tests/unit/DBSQLOperation.test.ts b/tests/unit/DBSQLOperation.test.ts index 5a29aa27..94224455 100644 --- a/tests/unit/DBSQLOperation.test.ts +++ b/tests/unit/DBSQLOperation.test.ts @@ -21,6 +21,7 @@ import CloudFetchResultHandler from '../../lib/result/CloudFetchResultHandler'; import ResultSlicer from '../../lib/result/ResultSlicer'; import ClientContextStub from './.stubs/ClientContextStub'; +import { Type } from 'apache-arrow'; function operationHandleStub(overrides: Partial): TOperationHandle { return { @@ -42,33 +43,19 @@ async function expectFailure(fn: () => Promise) { } } -class DBSQLOperationTest extends DBSQLOperation { - public getResultHandler = super.getResultHandler; - - public inspectInternals() { - return { - state: this.state, - operationHandle: this.operationHandle, - _data: this._data, - closed: this.closed, - cancelled: this.cancelled, - }; - } -} - describe('DBSQLOperation', () => { describe('status', () => { it('should pick up state from operation handle', async () => { const context = new ClientContextStub(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().state).to.equal(TOperationState.INITIALIZED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.true; + expect(operation['state']).to.equal(TOperationState.INITIALIZED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.true; }); it('should pick up state from directResults', async () => { const context = new ClientContextStub(); - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context, directResults: { @@ -80,8 +67,8 @@ describe('DBSQLOperation', () => { }, }); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.true; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.true; }); it('should fetch status and update internal state', async () => { @@ -90,17 +77,17 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: false }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context }); - expect(operation.inspectInternals().state).to.equal(TOperationState.INITIALIZED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.false; + expect(operation['state']).to.equal(TOperationState.INITIALIZED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.false; const status = await operation.status(); expect(driver.getOperationStatus.called).to.be.true; expect(status.operationState).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.true; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.true; }); it('should request progress', async () => { @@ -108,7 +95,7 @@ describe('DBSQLOperation', () => { const driver = sinon.spy(context.driver); driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: false }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context }); await operation.status(true); expect(driver.getOperationStatus.called).to.be.true; @@ -121,10 +108,10 @@ describe('DBSQLOperation', () => { const driver = sinon.spy(context.driver); driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: false }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context }); - expect(operation.inspectInternals().state).to.equal(TOperationState.INITIALIZED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.false; + expect(operation['state']).to.equal(TOperationState.INITIALIZED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.false; // First call - should fetch data and cache driver.getOperationStatusResp = { @@ -135,8 +122,8 @@ describe('DBSQLOperation', () => { expect(driver.getOperationStatus.callCount).to.equal(1); expect(status1.operationState).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.true; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.true; // Second call - should return cached data driver.getOperationStatusResp = { @@ -147,8 +134,8 @@ describe('DBSQLOperation', () => { expect(driver.getOperationStatus.callCount).to.equal(1); expect(status2.operationState).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.true; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.true; }); it('should fetch status if directResults status is not finished', async () => { @@ -157,7 +144,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context, directResults: { @@ -169,15 +156,15 @@ describe('DBSQLOperation', () => { }, }); - expect(operation.inspectInternals().state).to.equal(TOperationState.RUNNING_STATE); // from directResults - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.false; + expect(operation['state']).to.equal(TOperationState.RUNNING_STATE); // from directResults + expect(operation['operationHandle'].hasResultSet).to.be.false; const status = await operation.status(false); expect(driver.getOperationStatus.called).to.be.true; expect(status.operationState).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.true; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.true; }); it('should not fetch status if directResults status is finished', async () => { @@ -186,7 +173,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.RUNNING_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context, directResults: { @@ -198,21 +185,21 @@ describe('DBSQLOperation', () => { }, }); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); // from directResults - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.false; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); // from directResults + expect(operation['operationHandle'].hasResultSet).to.be.false; const status = await operation.status(false); expect(driver.getOperationStatus.called).to.be.false; expect(status.operationState).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); - expect(operation.inspectInternals().operationHandle.hasResultSet).to.be.false; + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); + expect(operation['operationHandle'].hasResultSet).to.be.false; }); it('should throw an error in case of a status error', async () => { const context = new ClientContextStub(); context.driver.getOperationStatusResp.status.statusCode = TStatusCode.ERROR_STATUS; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); try { await operation.status(false); @@ -230,63 +217,63 @@ describe('DBSQLOperation', () => { it('should cancel operation and update state', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.cancel(); expect(driver.cancelOperation.called).to.be.true; - expect(operation.inspectInternals().cancelled).to.be.true; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.true; + expect(operation['closed']).to.be.false; }); it('should return immediately if already cancelled', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.cancel(); expect(driver.cancelOperation.callCount).to.be.equal(1); - expect(operation.inspectInternals().cancelled).to.be.true; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.true; + expect(operation['closed']).to.be.false; await operation.cancel(); expect(driver.cancelOperation.callCount).to.be.equal(1); - expect(operation.inspectInternals().cancelled).to.be.true; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.true; + expect(operation['closed']).to.be.false; }); it('should return immediately if already closed', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.close(); expect(driver.closeOperation.callCount).to.be.equal(1); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.true; await operation.cancel(); expect(driver.cancelOperation.callCount).to.be.equal(0); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.true; }); it('should throw an error in case of a status error and keep state', async () => { const context = new ClientContextStub(); context.driver.cancelOperationResp.status.statusCode = TStatusCode.ERROR_STATUS; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; try { await operation.cancel(); @@ -296,17 +283,17 @@ describe('DBSQLOperation', () => { throw e; } expect(e).to.be.instanceOf(StatusError); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; } }); it('should reject all methods once cancelled', async () => { const context = new ClientContextStub(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); await operation.cancel(); - expect(operation.inspectInternals().cancelled).to.be.true; + expect(operation['cancelled']).to.be.true; await expectFailure(() => operation.fetchAll()); await expectFailure(() => operation.fetchChunk({ disableBuffering: true })); @@ -320,61 +307,61 @@ describe('DBSQLOperation', () => { it('should close operation and update state', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.close(); expect(driver.closeOperation.called).to.be.true; - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.true; }); it('should return immediately if already closed', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.close(); expect(driver.closeOperation.callCount).to.be.equal(1); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.true; await operation.close(); expect(driver.closeOperation.callCount).to.be.equal(1); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.true; }); it('should return immediately if already cancelled', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.cancel(); expect(driver.cancelOperation.callCount).to.be.equal(1); - expect(operation.inspectInternals().cancelled).to.be.true; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.true; + expect(operation['closed']).to.be.false; await operation.close(); expect(driver.closeOperation.callCount).to.be.equal(0); - expect(operation.inspectInternals().cancelled).to.be.true; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.true; + expect(operation['closed']).to.be.false; }); it('should initialize from directResults', async () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context, directResults: { @@ -384,24 +371,24 @@ describe('DBSQLOperation', () => { }, }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; await operation.close(); expect(driver.closeOperation.called).to.be.false; - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.true; expect(driver.closeOperation.callCount).to.be.equal(0); }); it('should throw an error in case of a status error and keep state', async () => { const context = new ClientContextStub(); context.driver.closeOperationResp.status.statusCode = TStatusCode.ERROR_STATUS; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; try { await operation.close(); @@ -411,17 +398,17 @@ describe('DBSQLOperation', () => { throw e; } expect(e).to.be.instanceOf(StatusError); - expect(operation.inspectInternals().cancelled).to.be.false; - expect(operation.inspectInternals().closed).to.be.false; + expect(operation['cancelled']).to.be.false; + expect(operation['closed']).to.be.false; } }); it('should reject all methods once closed', async () => { const context = new ClientContextStub(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); await operation.close(); - expect(operation.inspectInternals().closed).to.be.true; + expect(operation['closed']).to.be.true; await expectFailure(() => operation.fetchAll()); await expectFailure(() => operation.fetchChunk({ disableBuffering: true })); @@ -450,14 +437,14 @@ describe('DBSQLOperation', () => { return getOperationStatusStub.wrappedMethod.apply(context.driver, args); }); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); - expect(operation.inspectInternals().state).to.equal(TOperationState.INITIALIZED_STATE); + expect(operation['state']).to.equal(TOperationState.INITIALIZED_STATE); await operation.finished(); expect(getOperationStatusStub.callCount).to.be.equal(attemptsUntilFinished); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); }); }, ); @@ -476,7 +463,7 @@ describe('DBSQLOperation', () => { return getOperationStatusStub.wrappedMethod.apply(context.driver, args); }); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); await operation.finished({ progress: true }); expect(getOperationStatusStub.called).to.be.true; @@ -500,7 +487,7 @@ describe('DBSQLOperation', () => { return getOperationStatusStub.wrappedMethod.apply(context.driver, args); }); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const callback = sinon.stub(); @@ -516,7 +503,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.status.statusCode = TStatusCode.SUCCESS_STATUS; driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context, directResults: { @@ -539,7 +526,7 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.status.statusCode = TStatusCode.ERROR_STATUS; context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); try { await operation.finished(); @@ -564,7 +551,7 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.status.statusCode = TStatusCode.SUCCESS_STATUS; context.driver.getOperationStatusResp.operationState = operationState; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); try { await operation.finished(); @@ -586,7 +573,7 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; context.driver.getOperationStatusResp.hasResultSet = false; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: false }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context }); const schema = await operation.getSchema(); @@ -610,13 +597,13 @@ describe('DBSQLOperation', () => { context.driver.getResultSetMetadataResp.schema = { columns: [] }; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const schema = await operation.getSchema(); expect(getOperationStatusStub.called).to.be.true; expect(schema).to.deep.equal(context.driver.getResultSetMetadataResp.schema); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); }); it('should request progress', async () => { @@ -633,7 +620,7 @@ describe('DBSQLOperation', () => { return getOperationStatusStub.wrappedMethod.apply(context.driver, args); }); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); await operation.getSchema({ progress: true }); expect(getOperationStatusStub.called).to.be.true; @@ -657,7 +644,7 @@ describe('DBSQLOperation', () => { return getOperationStatusStub.wrappedMethod.apply(context.driver, args); }); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const callback = sinon.stub(); @@ -673,7 +660,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const schema = await operation.getSchema(); expect(schema).to.deep.equal(driver.getResultSetMetadataResp.schema); @@ -686,7 +673,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const schema1 = await operation.getSchema(); expect(schema1).to.deep.equal(context.driver.getResultSetMetadataResp.schema); @@ -723,7 +710,7 @@ describe('DBSQLOperation', () => { }, }, }; - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context, directResults, @@ -741,7 +728,7 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.hasResultSet = true; context.driver.getResultSetMetadataResp.status.statusCode = TStatusCode.ERROR_STATUS; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); try { await operation.getSchema(); @@ -764,39 +751,41 @@ describe('DBSQLOperation', () => { driver.getResultSetMetadataResp.resultFormat = TSparkRowSetType.COLUMN_BASED_SET; driver.getResultSetMetadata.resetHistory(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); - const resultHandler = await operation.getResultHandler(); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); + const resultHandler = await operation['getResultHandler'](); expect(driver.getResultSetMetadata.called).to.be.true; expect(resultHandler).to.be.instanceOf(ResultSlicer); - expect(resultHandler.source).to.be.instanceOf(JsonResultHandler); + expect(resultHandler['source']).to.be.instanceOf(JsonResultHandler); } arrowHandler: { driver.getResultSetMetadataResp.resultFormat = TSparkRowSetType.ARROW_BASED_SET; driver.getResultSetMetadata.resetHistory(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); - const resultHandler = await operation.getResultHandler(); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); + const resultHandler = await operation['getResultHandler'](); expect(driver.getResultSetMetadata.called).to.be.true; expect(resultHandler).to.be.instanceOf(ResultSlicer); - expect(resultHandler.source).to.be.instanceOf(ArrowResultConverter); - if (resultHandler.source instanceof ArrowResultConverter) { - expect(resultHandler.source.source).to.be.instanceOf(ArrowResultHandler); + expect(resultHandler['source']).to.be.instanceOf(ArrowResultConverter); + if (!(resultHandler['source'] instanceof ArrowResultConverter)) { + throw new Error('Expected `resultHandler.source` to be `ArrowResultConverter`'); } + expect(resultHandler['source']['source']).to.be.instanceOf(ArrowResultHandler); } cloudFetchHandler: { driver.getResultSetMetadataResp.resultFormat = TSparkRowSetType.URL_BASED_SET; driver.getResultSetMetadata.resetHistory(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); - const resultHandler = await operation.getResultHandler(); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); + const resultHandler = await operation['getResultHandler'](); expect(driver.getResultSetMetadata.called).to.be.true; expect(resultHandler).to.be.instanceOf(ResultSlicer); - expect(resultHandler.source).to.be.instanceOf(ArrowResultConverter); - if (resultHandler.source instanceof ArrowResultConverter) { - expect(resultHandler.source.source).to.be.instanceOf(CloudFetchResultHandler); + expect(resultHandler['source']).to.be.instanceOf(ArrowResultConverter); + if (!(resultHandler['source'] instanceof ArrowResultConverter)) { + throw new Error('Expected `resultHandler.source` to be `ArrowResultConverter`'); } + expect(resultHandler['source']['source']).to.be.instanceOf(CloudFetchResultHandler); } }); }); @@ -806,7 +795,7 @@ describe('DBSQLOperation', () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: false }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: false }), context }); const results = await operation.fetchChunk({ disableBuffering: true }); @@ -833,13 +822,13 @@ describe('DBSQLOperation', () => { context.driver.fetchResultsResp.hasMoreRows = false; context.driver.fetchResultsResp.results!.columns = []; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const results = await operation.fetchChunk({ disableBuffering: true }); expect(getOperationStatusStub.called).to.be.true; expect(results).to.deep.equal([]); - expect(operation.inspectInternals().state).to.equal(TOperationState.FINISHED_STATE); + expect(operation['state']).to.equal(TOperationState.FINISHED_STATE); }); it('should request progress', async () => { @@ -860,7 +849,7 @@ describe('DBSQLOperation', () => { context.driver.fetchResultsResp.hasMoreRows = false; context.driver.fetchResultsResp.results!.columns = []; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); await operation.fetchChunk({ progress: true, disableBuffering: true }); expect(getOperationStatusStub.called).to.be.true; @@ -888,7 +877,7 @@ describe('DBSQLOperation', () => { context.driver.fetchResultsResp.hasMoreRows = false; context.driver.fetchResultsResp.results!.columns = []; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const callback = sinon.stub(); @@ -904,7 +893,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const results = await operation.fetchChunk({ disableBuffering: true }); @@ -918,7 +907,7 @@ describe('DBSQLOperation', () => { const driver = sinon.spy(context.driver); driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context, directResults: { @@ -954,7 +943,7 @@ describe('DBSQLOperation', () => { driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; driver.getOperationStatusResp.hasResultSet = true; - const operation = new DBSQLOperationTest({ + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context, directResults: { @@ -997,7 +986,7 @@ describe('DBSQLOperation', () => { context.driver.getResultSetMetadataResp.resultFormat = TSparkRowSetType.ROW_BASED_SET; context.driver.getResultSetMetadataResp.schema = { columns: [] }; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); try { await operation.fetchChunk({ disableBuffering: true }); @@ -1014,7 +1003,7 @@ describe('DBSQLOperation', () => { describe('fetchAll', () => { it('should fetch data while available and return it all', async () => { const context = new ClientContextStub(); - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); const originalData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; @@ -1031,7 +1020,7 @@ describe('DBSQLOperation', () => { // Warning: this check is implementation-specific // `fetchAll` should wait for operation to complete. In current implementation // it does so by calling `fetchChunk` at least once, which internally does - // all the job. But since here we mock `fetchChunk` it won't really wait, + // all the job. But since here we stub `fetchChunk` it won't really wait, // therefore here we ensure it was called at least once expect(fetchChunkStub.callCount).to.be.gte(1); @@ -1049,15 +1038,13 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = false; context.driver.fetchResultsResp.results = undefined; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.undefined; + expect(operation['_data']['hasMoreRowsFlag']).to.be.undefined; await operation.fetchChunk({ disableBuffering: true }); expect(await operation.hasMoreRows()).to.be.false; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.false; + expect(operation['_data']['hasMoreRowsFlag']).to.be.false; }); it('should return False if operation was closed', async () => { @@ -1066,7 +1053,7 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; await operation.fetchChunk({ disableBuffering: true }); @@ -1081,7 +1068,7 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; await operation.fetchChunk({ disableBuffering: true }); @@ -1096,15 +1083,13 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = true; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.undefined; + expect(operation['_data']['hasMoreRowsFlag']).to.be.undefined; await operation.fetchChunk({ disableBuffering: true }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.true; + expect(operation['_data']['hasMoreRowsFlag']).to.be.true; }); it('should return True if hasMoreRows flag is False but there is actual data', async () => { @@ -1113,15 +1098,13 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = false; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.undefined; + expect(operation['_data']['hasMoreRowsFlag']).to.be.undefined; await operation.fetchChunk({ disableBuffering: true }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.true; + expect(operation['_data']['hasMoreRowsFlag']).to.be.true; }); it('should return True if hasMoreRows flag is unset but there is actual data', async () => { @@ -1130,15 +1113,13 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.operationState = TOperationState.FINISHED_STATE; context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = undefined; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.undefined; + expect(operation['_data']['hasMoreRowsFlag']).to.be.undefined; await operation.fetchChunk({ disableBuffering: true }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.true; + expect(operation['_data']['hasMoreRowsFlag']).to.be.true; }); it('should return False if hasMoreRows flag is False and there is no data', async () => { @@ -1148,15 +1129,13 @@ describe('DBSQLOperation', () => { context.driver.getOperationStatusResp.hasResultSet = true; context.driver.fetchResultsResp.hasMoreRows = false; context.driver.fetchResultsResp.results = undefined; - const operation = new DBSQLOperationTest({ handle: operationHandleStub({ hasResultSet: true }), context }); + const operation = new DBSQLOperation({ handle: operationHandleStub({ hasResultSet: true }), context }); expect(await operation.hasMoreRows()).to.be.true; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.undefined; + expect(operation['_data']['hasMoreRowsFlag']).to.be.undefined; await operation.fetchChunk({ disableBuffering: true }); expect(await operation.hasMoreRows()).to.be.false; - // @ts-expect-error TS2341: Property hasMoreRowsFlag is private and only accessible within class RowSetProvider - expect(operation.inspectInternals()._data.hasMoreRowsFlag).to.be.false; + expect(operation['_data']['hasMoreRowsFlag']).to.be.false; }); }); }); diff --git a/tests/unit/DBSQLSession.test.ts b/tests/unit/DBSQLSession.test.ts index f0567332..460047f5 100644 --- a/tests/unit/DBSQLSession.test.ts +++ b/tests/unit/DBSQLSession.test.ts @@ -12,15 +12,6 @@ const sessionHandleStub: TSessionHandle = { sessionId: { guid: Buffer.alloc(16), secret: Buffer.alloc(16) }, }; -class DBSQLSessionTest extends DBSQLSession { - public inspectInternals() { - return { - isOpen: this.isOpen, - operations: this.operations, - }; - } -} - async function expectFailure(fn: () => Promise) { try { await fn(); @@ -59,7 +50,7 @@ describe('DBSQLSession', () => { describe('getInfo', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getInfo(1); expect(result).instanceOf(InfoValue); }); @@ -67,26 +58,26 @@ describe('DBSQLSession', () => { describe('executeStatement', () => { it('should execute statement', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.executeStatement('SELECT * FROM table'); expect(result).instanceOf(DBSQLOperation); }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.executeStatement('SELECT * FROM table', { maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.executeStatement('SELECT * FROM table', { maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); describe('Arrow support', () => { it('should not use Arrow if disabled in options', async () => { - const session = new DBSQLSessionTest({ + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub({ arrowEnabled: false }), }); @@ -96,7 +87,7 @@ describe('DBSQLSession', () => { it('should apply defaults for Arrow options', async () => { case1: { - const session = new DBSQLSessionTest({ + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub({ arrowEnabled: true }), }); @@ -105,7 +96,7 @@ describe('DBSQLSession', () => { } case2: { - const session = new DBSQLSessionTest({ + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub({ arrowEnabled: true, useArrowNativeTypes: false }), }); @@ -118,19 +109,19 @@ describe('DBSQLSession', () => { describe('getTypeInfo', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTypeInfo(); expect(result).instanceOf(DBSQLOperation); }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTypeInfo({ maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTypeInfo({ maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); @@ -138,19 +129,19 @@ describe('DBSQLSession', () => { describe('getCatalogs', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getCatalogs(); expect(result).instanceOf(DBSQLOperation); }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getCatalogs({ maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getCatalogs({ maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); @@ -158,13 +149,13 @@ describe('DBSQLSession', () => { describe('getSchemas', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getSchemas(); expect(result).instanceOf(DBSQLOperation); }); it('should use filters', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getSchemas({ catalogName: 'catalog', schemaName: 'schema', @@ -173,13 +164,13 @@ describe('DBSQLSession', () => { }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getSchemas({ maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getSchemas({ maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); @@ -187,13 +178,13 @@ describe('DBSQLSession', () => { describe('getTables', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTables(); expect(result).instanceOf(DBSQLOperation); }); it('should use filters', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTables({ catalogName: 'catalog', schemaName: 'default', @@ -204,13 +195,13 @@ describe('DBSQLSession', () => { }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTables({ maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTables({ maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); @@ -218,19 +209,19 @@ describe('DBSQLSession', () => { describe('getTableTypes', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTableTypes(); expect(result).instanceOf(DBSQLOperation); }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTableTypes({ maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getTableTypes({ maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); @@ -238,13 +229,13 @@ describe('DBSQLSession', () => { describe('getColumns', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getColumns(); expect(result).instanceOf(DBSQLOperation); }); it('should use filters', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getColumns({ catalogName: 'catalog', schemaName: 'schema', @@ -255,13 +246,13 @@ describe('DBSQLSession', () => { }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getColumns({ maxRows: 10 }); expect(result).instanceOf(DBSQLOperation); }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getColumns({ maxRows: null }); expect(result).instanceOf(DBSQLOperation); }); @@ -269,7 +260,7 @@ describe('DBSQLSession', () => { describe('getFunctions', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getFunctions({ catalogName: 'catalog', schemaName: 'schema', @@ -279,7 +270,7 @@ describe('DBSQLSession', () => { }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getFunctions({ catalogName: 'catalog', schemaName: 'schema', @@ -290,7 +281,7 @@ describe('DBSQLSession', () => { }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getFunctions({ catalogName: 'catalog', schemaName: 'schema', @@ -303,7 +294,7 @@ describe('DBSQLSession', () => { describe('getPrimaryKeys', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getPrimaryKeys({ catalogName: 'catalog', schemaName: 'schema', @@ -313,7 +304,7 @@ describe('DBSQLSession', () => { }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getPrimaryKeys({ catalogName: 'catalog', schemaName: 'schema', @@ -324,7 +315,7 @@ describe('DBSQLSession', () => { }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getPrimaryKeys({ catalogName: 'catalog', schemaName: 'schema', @@ -337,7 +328,7 @@ describe('DBSQLSession', () => { describe('getCrossReference', () => { it('should run operation', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getCrossReference({ parentCatalogName: 'parentCatalogName', parentSchemaName: 'parentSchemaName', @@ -350,7 +341,7 @@ describe('DBSQLSession', () => { }); it('should use direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getCrossReference({ parentCatalogName: 'parentCatalogName', parentSchemaName: 'parentSchemaName', @@ -364,7 +355,7 @@ describe('DBSQLSession', () => { }); it('should disable direct results', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const result = await session.getCrossReference({ parentCatalogName: 'parentCatalogName', parentSchemaName: 'parentSchemaName', @@ -383,12 +374,12 @@ describe('DBSQLSession', () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context }); - expect(session.inspectInternals().isOpen).to.be.true; + const session = new DBSQLSession({ handle: sessionHandleStub, context }); + expect(session['isOpen']).to.be.true; const result = await session.close(); expect(result).instanceOf(Status); - expect(session.inspectInternals().isOpen).to.be.false; + expect(session['isOpen']).to.be.false; expect(driver.closeSession.callCount).to.eq(1); }); @@ -396,50 +387,46 @@ describe('DBSQLSession', () => { const context = new ClientContextStub(); const driver = sinon.spy(context.driver); - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context }); - expect(session.inspectInternals().isOpen).to.be.true; + const session = new DBSQLSession({ handle: sessionHandleStub, context }); + expect(session['isOpen']).to.be.true; const result = await session.close(); expect(result).instanceOf(Status); - expect(session.inspectInternals().isOpen).to.be.false; + expect(session['isOpen']).to.be.false; expect(driver.closeSession.callCount).to.eq(1); const result2 = await session.close(); expect(result2).instanceOf(Status); - expect(session.inspectInternals().isOpen).to.be.false; + expect(session['isOpen']).to.be.false; expect(driver.closeSession.callCount).to.eq(1); // second time it should not be called }); it('should close operations that belong to it', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); const operation = await session.executeStatement('SELECT * FROM table'); if (!(operation instanceof DBSQLOperation)) { expect.fail('Assertion error: operation is not a DBSQLOperation'); } expect(operation.onClose).to.be.not.undefined; - // @ts-expect-error TS2445: Property closed is protected and only accessible within class DBSQLOperation and its subclasses - expect(operation.closed).to.be.false; - // @ts-expect-error TS2445: Property items is protected and only accessible within class CloseableCollection and its subclasses - expect(session.inspectInternals().operations.items.size).to.eq(1); + expect(operation['closed']).to.be.false; + expect(session['operations']['items'].size).to.eq(1); - sinon.spy(session.inspectInternals().operations, 'closeAll'); + sinon.spy(session['operations'], 'closeAll'); sinon.spy(operation, 'close'); await session.close(); expect((operation.close as SinonSpy).called).to.be.true; - expect((session.inspectInternals().operations.closeAll as SinonSpy).called).to.be.true; + expect((session['operations'].closeAll as SinonSpy).called).to.be.true; expect(operation.onClose).to.be.undefined; - // @ts-expect-error TS2445: Property closed is protected and only accessible within class DBSQLOperation and its subclasses - expect(operation.closed).to.be.true; - // @ts-expect-error TS2445: Property items is protected and only accessible within class CloseableCollection and its subclasses - expect(session.inspectInternals().operations.items.size).to.eq(0); + expect(operation['closed']).to.be.true; + expect(session['operations']['items'].size).to.eq(0); }); it('should reject all methods once closed', async () => { - const session = new DBSQLSessionTest({ handle: sessionHandleStub, context: new ClientContextStub() }); + const session = new DBSQLSession({ handle: sessionHandleStub, context: new ClientContextStub() }); await session.close(); - expect(session.inspectInternals().isOpen).to.be.false; + expect(session['isOpen']).to.be.false; await expectFailure(() => session.getInfo(1)); await expectFailure(() => session.executeStatement('SELECT * FROM table')); diff --git a/tests/unit/connection/auth/DatabricksOAuth/AuthorizationCode.test.ts b/tests/unit/connection/auth/DatabricksOAuth/AuthorizationCode.test.ts index 7dcc7110..9b109f1c 100644 --- a/tests/unit/connection/auth/DatabricksOAuth/AuthorizationCode.test.ts +++ b/tests/unit/connection/auth/DatabricksOAuth/AuthorizationCode.test.ts @@ -76,35 +76,35 @@ class OpenIDClientStub implements BaseClient { [key: string]: unknown; } -class AuthorizationCodeTest extends AuthorizationCode { - public httpServer = new OAuthCallbackServerStub(); - - public createHttpServer(requestHandler: (req: IncomingMessage, res: ServerResponse) => void) { - this.httpServer.requestHandler = requestHandler; - return this.httpServer; - } -} - function prepareTestInstances(options: Partial) { const oauthClient = new OpenIDClientStub(); + const httpServer = new OAuthCallbackServerStub(); + const openAuthUrl = sinon.stub<[string], Promise>(); - const authCode = sinon.spy( - new AuthorizationCodeTest({ - client: oauthClient, - context: new ClientContextStub(), - ports: [], - ...options, - openAuthUrl, - }), - ); + const authCode = new AuthorizationCode({ + client: oauthClient, + context: new ClientContextStub(), + ports: [], + ...options, + openAuthUrl, + }); + + const authCodeSpy = sinon.spy(authCode); + + const createHttpServer = sinon.spy((requestHandler: (req: IncomingMessage, res: ServerResponse) => void) => { + httpServer.requestHandler = requestHandler; + return httpServer; + }); + + authCode['createHttpServer'] = createHttpServer; openAuthUrl.callsFake(async (authUrl) => { const params = JSON.parse(authUrl); const req = new IncomingMessageStub(params); const resp = new ServerResponseStub(req); - authCode.httpServer.requestHandler(req, resp); + httpServer.requestHandler(req, resp); }); function reloadUrl() { @@ -114,17 +114,17 @@ function prepareTestInstances(options: Partial) { }, 10); } - return { oauthClient, authCode, openAuthUrl, reloadUrl }; + return { oauthClient, authCode: authCodeSpy, httpServer, openAuthUrl, reloadUrl, createHttpServer }; } describe('AuthorizationCode', () => { it('should fetch authorization code', async () => { - const { authCode, oauthClient, openAuthUrl } = prepareTestInstances({ + const { authCode, oauthClient, openAuthUrl, createHttpServer } = prepareTestInstances({ ports: [80, 8000], }); const result = await authCode.fetch([]); - expect(authCode.createHttpServer.callCount).to.be.equal(2); + expect(createHttpServer.callCount).to.be.equal(2); expect(openAuthUrl.callCount).to.be.equal(1); expect(result.code).to.be.equal(oauthClient.code); @@ -133,7 +133,7 @@ describe('AuthorizationCode', () => { }); it('should throw error if cannot start server on any port', async () => { - const { authCode, openAuthUrl } = prepareTestInstances({ + const { authCode, openAuthUrl, createHttpServer } = prepareTestInstances({ ports: [80, 443], }); @@ -144,7 +144,7 @@ describe('AuthorizationCode', () => { if (error instanceof AssertionError || !(error instanceof Error)) { throw error; } - expect(authCode.createHttpServer.callCount).to.be.equal(2); + expect(createHttpServer.callCount).to.be.equal(2); expect(openAuthUrl.callCount).to.be.equal(0); expect(error.message).to.contain('all ports are in use'); @@ -152,12 +152,12 @@ describe('AuthorizationCode', () => { }); it('should re-throw unhandled server start errors', async () => { - const { authCode, openAuthUrl } = prepareTestInstances({ + const { authCode, openAuthUrl, httpServer, createHttpServer } = prepareTestInstances({ ports: [80], }); const testError = new Error('Test'); - authCode.httpServer.listenError = testError; + httpServer.listenError = testError; try { await authCode.fetch([]); @@ -166,7 +166,7 @@ describe('AuthorizationCode', () => { if (error instanceof AssertionError || !(error instanceof Error)) { throw error; } - expect(authCode.createHttpServer.callCount).to.be.equal(1); + expect(createHttpServer.callCount).to.be.equal(1); expect(openAuthUrl.callCount).to.be.equal(0); expect(error).to.be.equal(testError); @@ -174,12 +174,12 @@ describe('AuthorizationCode', () => { }); it('should re-throw unhandled server stop errors', async () => { - const { authCode, openAuthUrl } = prepareTestInstances({ + const { authCode, openAuthUrl, httpServer, createHttpServer } = prepareTestInstances({ ports: [8000], }); const testError = new Error('Test'); - authCode.httpServer.closeError = testError; + httpServer.closeError = testError; try { await authCode.fetch([]); @@ -188,7 +188,7 @@ describe('AuthorizationCode', () => { if (error instanceof AssertionError || !(error instanceof Error)) { throw error; } - expect(authCode.createHttpServer.callCount).to.be.equal(1); + expect(createHttpServer.callCount).to.be.equal(1); expect(openAuthUrl.callCount).to.be.equal(1); expect(error).to.be.equal(testError); @@ -196,7 +196,7 @@ describe('AuthorizationCode', () => { }); it('should throw an error if no code was returned', async () => { - const { authCode, oauthClient, openAuthUrl } = prepareTestInstances({ + const { authCode, oauthClient, openAuthUrl, createHttpServer } = prepareTestInstances({ ports: [8000], }); @@ -213,7 +213,7 @@ describe('AuthorizationCode', () => { if (error instanceof AssertionError || !(error instanceof Error)) { throw error; } - expect(authCode.createHttpServer.callCount).to.be.equal(1); + expect(createHttpServer.callCount).to.be.equal(1); expect(openAuthUrl.callCount).to.be.equal(1); expect(error.message).to.contain('No path parameters were returned to the callback'); @@ -221,7 +221,7 @@ describe('AuthorizationCode', () => { }); it('should use error details from callback params', async () => { - const { authCode, oauthClient, openAuthUrl } = prepareTestInstances({ + const { authCode, oauthClient, openAuthUrl, createHttpServer } = prepareTestInstances({ ports: [8000], }); @@ -242,7 +242,7 @@ describe('AuthorizationCode', () => { if (error instanceof AssertionError || !(error instanceof Error)) { throw error; } - expect(authCode.createHttpServer.callCount).to.be.equal(1); + expect(createHttpServer.callCount).to.be.equal(1); expect(openAuthUrl.callCount).to.be.equal(1); expect(error.message).to.contain('Test error'); @@ -250,7 +250,7 @@ describe('AuthorizationCode', () => { }); it('should serve 404 for unrecognized requests', async () => { - const { authCode, oauthClient, reloadUrl, openAuthUrl } = prepareTestInstances({ + const { authCode, oauthClient, reloadUrl, openAuthUrl, createHttpServer } = prepareTestInstances({ ports: [8000], }); @@ -268,26 +268,26 @@ describe('AuthorizationCode', () => { await authCode.fetch([]); - expect(authCode.createHttpServer.callCount).to.be.equal(1); + expect(createHttpServer.callCount).to.be.equal(1); expect(openAuthUrl.callCount).to.be.equal(2); }); it('should not attempt to stop server if not running', async () => { - const { authCode, oauthClient, openAuthUrl } = prepareTestInstances({ + const { authCode, oauthClient, openAuthUrl, httpServer, createHttpServer } = prepareTestInstances({ ports: [8000], }); const promise = authCode.fetch([]); - authCode.httpServer.listening = false; - authCode.httpServer.closeError = new Error('Test'); + httpServer.listening = false; + httpServer.closeError = new Error('Test'); const result = await promise; // We set up server to throw an error on close. If nothing happened - it means // that `authCode` never tried to stop it expect(result.code).to.be.equal(oauthClient.code); - expect(authCode.createHttpServer.callCount).to.be.equal(1); + expect(createHttpServer.callCount).to.be.equal(1); expect(openAuthUrl.callCount).to.be.equal(1); }); }); diff --git a/tests/unit/connection/auth/DatabricksOAuth/OAuthManager.test.ts b/tests/unit/connection/auth/DatabricksOAuth/OAuthManager.test.ts index 4bec931d..c2367971 100644 --- a/tests/unit/connection/auth/DatabricksOAuth/OAuthManager.test.ts +++ b/tests/unit/connection/auth/DatabricksOAuth/OAuthManager.test.ts @@ -92,7 +92,7 @@ class OpenIDClientStub implements BaseClient { case 'none': return this.grantU2M(params); } - throw new Error(`OAuthClientMock: unrecognized auth method: ${this.clientOptions.token_endpoint_auth_method}`); + throw new Error(`OAuthClientStub: unrecognized auth method: ${this.clientOptions.token_endpoint_auth_method}`); } async refresh(refreshToken: string) { diff --git a/tests/unit/connection/auth/DatabricksOAuth/index.test.ts b/tests/unit/connection/auth/DatabricksOAuth/index.test.ts index 28bc7909..77c4d22f 100644 --- a/tests/unit/connection/auth/DatabricksOAuth/index.test.ts +++ b/tests/unit/connection/auth/DatabricksOAuth/index.test.ts @@ -1,8 +1,7 @@ import { expect } from 'chai'; import sinon from 'sinon'; -import DatabricksOAuth, { DatabricksOAuthOptions, OAuthFlow } from '../../../../../lib/connection/auth/DatabricksOAuth'; +import DatabricksOAuth, { OAuthFlow } from '../../../../../lib/connection/auth/DatabricksOAuth'; import OAuthToken from '../../../../../lib/connection/auth/DatabricksOAuth/OAuthToken'; -import { OAuthManagerOptions } from '../../../../../lib/connection/auth/DatabricksOAuth/OAuthManager'; import { createExpiredAccessToken, @@ -12,82 +11,91 @@ import { } from '../../../.stubs/OAuth'; import ClientContextStub from '../../../.stubs/ClientContextStub'; -class DatabricksOAuthTest extends DatabricksOAuth { - public manager: OAuthManagerStub; - - constructor(options: Partial = {}) { - super({ - context: new ClientContextStub(), - flow: OAuthFlow.M2M, - host: 'localhost', - ...options, - }); - - this.manager = this.createManager(this.options); - } - - protected createManager(options: OAuthManagerOptions): OAuthManagerStub { - return new OAuthManagerStub(options); - } -} +const optionsStub = { + context: new ClientContextStub(), + flow: OAuthFlow.M2M, + host: 'localhost', +}; describe('DatabricksOAuth', () => { it('should get persisted token if available', async () => { const persistence = sinon.spy(new OAuthPersistenceStub()); persistence.token = new OAuthToken(createValidAccessToken()); - const provider = new DatabricksOAuthTest({ persistence }); + const options = { ...optionsStub, persistence }; + const provider = new DatabricksOAuth(options); + provider['manager'] = new OAuthManagerStub(options); await provider.authenticate(); expect(persistence.read.called).to.be.true; }); it('should get new token if storage not available', async () => { - const provider = new DatabricksOAuthTest(); - const oauthManager = sinon.spy(provider.manager); + const options = { ...optionsStub }; + + const oauthManager = new OAuthManagerStub(options); + const oauthManagerSpy = sinon.spy(oauthManager); + + const provider = new DatabricksOAuth(options); + provider['manager'] = oauthManager; await provider.authenticate(); - expect(oauthManager.getToken.called).to.be.true; + expect(oauthManagerSpy.getToken.called).to.be.true; }); it('should get new token if persisted token not available, and store valid token', async () => { const persistence = sinon.spy(new OAuthPersistenceStub()); persistence.token = undefined; - const provider = new DatabricksOAuthTest({ persistence }); - const oauthManager = sinon.spy(provider.manager); + const options = { ...optionsStub, persistence }; + + const oauthManager = new OAuthManagerStub(options); + const oauthManagerSpy = sinon.spy(oauthManager); + + const provider = new DatabricksOAuth(options); + provider['manager'] = oauthManager; await provider.authenticate(); - expect(oauthManager.getToken.called).to.be.true; + expect(oauthManagerSpy.getToken.called).to.be.true; expect(persistence.persist.called).to.be.true; - expect(persistence.token).to.be.equal(oauthManager.getTokenResult); + expect(persistence.token).to.be.equal(oauthManagerSpy.getTokenResult); }); it('should refresh expired token and store new token', async () => { const persistence = sinon.spy(new OAuthPersistenceStub()); persistence.token = undefined; - const provider = new DatabricksOAuthTest({ persistence }); - const oauthManager = sinon.spy(provider.manager); + const options = { ...optionsStub, persistence }; + + const oauthManager = new OAuthManagerStub(options); + const oauthManagerSpy = sinon.spy(oauthManager); + + const provider = new DatabricksOAuth(options); + provider['manager'] = oauthManager; - oauthManager.getTokenResult = new OAuthToken(createExpiredAccessToken()); - oauthManager.refreshTokenResult = new OAuthToken(createValidAccessToken()); + oauthManagerSpy.getTokenResult = new OAuthToken(createExpiredAccessToken()); + oauthManagerSpy.refreshTokenResult = new OAuthToken(createValidAccessToken()); await provider.authenticate(); - expect(oauthManager.getToken.called).to.be.true; - expect(oauthManager.refreshAccessToken.called).to.be.true; - expect(oauthManager.refreshAccessToken.firstCall.firstArg).to.be.equal(oauthManager.getTokenResult); - expect(persistence.token).to.be.equal(oauthManager.refreshTokenResult); + expect(oauthManagerSpy.getToken.called).to.be.true; + expect(oauthManagerSpy.refreshAccessToken.called).to.be.true; + expect(oauthManagerSpy.refreshAccessToken.firstCall.firstArg).to.be.equal(oauthManagerSpy.getTokenResult); + expect(persistence.token).to.be.equal(oauthManagerSpy.refreshTokenResult); expect(persistence.persist.called).to.be.true; - expect(persistence.token).to.be.equal(oauthManager.refreshTokenResult); + expect(persistence.token).to.be.equal(oauthManagerSpy.refreshTokenResult); }); it('should configure transport using valid token', async () => { - const provider = new DatabricksOAuthTest(); - const oauthManager = sinon.spy(provider.manager); + const options = { ...optionsStub }; + + const oauthManager = new OAuthManagerStub(options); + const oauthManagerSpy = sinon.spy(oauthManager); + + const provider = new DatabricksOAuth(options); + provider['manager'] = oauthManager; const authHeaders = await provider.authenticate(); - expect(oauthManager.getToken.called).to.be.true; + expect(oauthManagerSpy.getToken.called).to.be.true; expect(Object.keys(authHeaders)).to.deep.equal(['Authorization']); }); }); diff --git a/tests/unit/connection/auth/PlainHttpAuthentication.test.ts b/tests/unit/connection/auth/PlainHttpAuthentication.test.ts index 5c682eb3..9b69029f 100644 --- a/tests/unit/connection/auth/PlainHttpAuthentication.test.ts +++ b/tests/unit/connection/auth/PlainHttpAuthentication.test.ts @@ -3,48 +3,38 @@ import PlainHttpAuthentication from '../../../../lib/connection/auth/PlainHttpAu import ClientContextStub from '../../.stubs/ClientContextStub'; -class PlainHttpAuthenticationTest extends PlainHttpAuthentication { - public inspectInternals() { - return { - username: this.username, - password: this.password, - headers: this.headers, - }; - } -} - describe('PlainHttpAuthentication', () => { it('username and password must be anonymous if nothing passed', () => { - const auth = new PlainHttpAuthenticationTest({ context: new ClientContextStub() }); + const auth = new PlainHttpAuthentication({ context: new ClientContextStub() }); - expect(auth.inspectInternals().username).to.be.eq('anonymous'); - expect(auth.inspectInternals().password).to.be.eq('anonymous'); + expect(auth['username']).to.be.eq('anonymous'); + expect(auth['password']).to.be.eq('anonymous'); }); it('username and password must be defined correctly', () => { - const auth = new PlainHttpAuthenticationTest({ + const auth = new PlainHttpAuthentication({ context: new ClientContextStub(), username: 'user', password: 'pass', }); - expect(auth.inspectInternals().username).to.be.eq('user'); - expect(auth.inspectInternals().password).to.be.eq('pass'); + expect(auth['username']).to.be.eq('user'); + expect(auth['password']).to.be.eq('pass'); }); it('empty password must be set', () => { - const auth = new PlainHttpAuthenticationTest({ + const auth = new PlainHttpAuthentication({ context: new ClientContextStub(), username: 'user', password: '', }); - expect(auth.inspectInternals().username).to.be.eq('user'); - expect(auth.inspectInternals().password).to.be.eq(''); + expect(auth['username']).to.be.eq('user'); + expect(auth['password']).to.be.eq(''); }); it('auth token must be set to header', async () => { - const auth = new PlainHttpAuthenticationTest({ context: new ClientContextStub() }); + const auth = new PlainHttpAuthentication({ context: new ClientContextStub() }); const headers = await auth.authenticate(); expect(headers).to.deep.equal({ Authorization: 'Bearer anonymous', diff --git a/tests/unit/connection/connections/HttpConnection.test.ts b/tests/unit/connection/connections/HttpConnection.test.ts index 3358ed38..c7b39972 100644 --- a/tests/unit/connection/connections/HttpConnection.test.ts +++ b/tests/unit/connection/connections/HttpConnection.test.ts @@ -5,17 +5,9 @@ import ThriftHttpConnection from '../../../../lib/connection/connections/ThriftH import ClientContextStub from '../../.stubs/ClientContextStub'; -class HttpConnectionTest extends HttpConnection { - public inspectInternals() { - return { - headers: this.headers, - }; - } -} - describe('HttpConnection.connect', () => { it('should create Thrift connection', async () => { - const connection = new HttpConnectionTest( + const connection = new HttpConnection( { host: 'localhost', port: 10001, @@ -35,7 +27,7 @@ describe('HttpConnection.connect', () => { }); it('should set SSL certificates and disable rejectUnauthorized', async () => { - const connection = new HttpConnectionTest( + const connection = new HttpConnection( { host: 'localhost', port: 10001, @@ -57,7 +49,7 @@ describe('HttpConnection.connect', () => { }); it('should initialize http agents', async () => { - const connection = new HttpConnectionTest( + const connection = new HttpConnection( { host: 'localhost', port: 10001, @@ -78,7 +70,7 @@ describe('HttpConnection.connect', () => { b: 'test header B', }; - const connection = new HttpConnectionTest( + const connection = new HttpConnection( { host: 'localhost', port: 10001, @@ -93,7 +85,7 @@ describe('HttpConnection.connect', () => { c: 'test header C', }; connection.setHeaders(extraHeaders); - expect(connection.inspectInternals().headers).to.deep.equal(extraHeaders); + expect(connection['headers']).to.deep.equal(extraHeaders); const thriftConnection = await connection.getThriftConnection(); @@ -109,7 +101,7 @@ describe('HttpConnection.connect', () => { b: 'test header B', }; - const connection = new HttpConnectionTest( + const connection = new HttpConnection( { host: 'localhost', port: 10001, @@ -121,7 +113,7 @@ describe('HttpConnection.connect', () => { const thriftConnection = await connection.getThriftConnection(); - expect(connection.inspectInternals().headers).to.deep.equal({}); + expect(connection['headers']).to.deep.equal({}); expect(thriftConnection.config.headers).to.deep.equal(initialHeaders); const extraHeaders = { @@ -129,7 +121,7 @@ describe('HttpConnection.connect', () => { c: 'test header C', }; connection.setHeaders(extraHeaders); - expect(connection.inspectInternals().headers).to.deep.equal(extraHeaders); + expect(connection['headers']).to.deep.equal(extraHeaders); expect(thriftConnection.config.headers).to.deep.equal({ ...initialHeaders, ...extraHeaders, diff --git a/tests/unit/connection/connections/HttpRetryPolicy.test.ts b/tests/unit/connection/connections/HttpRetryPolicy.test.ts index c6aac2b4..50ba0bf5 100644 --- a/tests/unit/connection/connections/HttpRetryPolicy.test.ts +++ b/tests/unit/connection/connections/HttpRetryPolicy.test.ts @@ -6,50 +6,25 @@ import RetryError, { RetryErrorCode } from '../../../../lib/errors/RetryError'; import ClientContextStub from '../../.stubs/ClientContextStub'; -interface HttpRetryPolicyInternals { - startTime: number; - attempt: number; -} - -class HttpRetryPolicyTest extends HttpRetryPolicy { - public getBackoffDelay = super.getBackoffDelay; - - public getRetryAfterHeader = super.getRetryAfterHeader; - - public isRetryable = super.isRetryable; - - public inspectInternals() { - return { - startTime: this.startTime, - attempt: this.attempt, - }; - } - - public updateInternals(values: Partial) { - this.startTime = values.startTime ?? this.startTime; - this.attempt = values.attempt ?? this.attempt; - } -} - describe('HttpRetryPolicy', () => { it('should properly compute backoff delay', async () => { const context = new ClientContextStub({ retryDelayMin: 3, retryDelayMax: 20 }); const { retryDelayMin, retryDelayMax } = context.getConfig(); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - expect(policy.getBackoffDelay(0, retryDelayMin, retryDelayMax)).to.equal(3); - expect(policy.getBackoffDelay(1, retryDelayMin, retryDelayMax)).to.equal(6); - expect(policy.getBackoffDelay(2, retryDelayMin, retryDelayMax)).to.equal(12); - expect(policy.getBackoffDelay(3, retryDelayMin, retryDelayMax)).to.equal(retryDelayMax); - expect(policy.getBackoffDelay(4, retryDelayMin, retryDelayMax)).to.equal(retryDelayMax); + expect(policy['getBackoffDelay'](0, retryDelayMin, retryDelayMax)).to.equal(3); + expect(policy['getBackoffDelay'](1, retryDelayMin, retryDelayMax)).to.equal(6); + expect(policy['getBackoffDelay'](2, retryDelayMin, retryDelayMax)).to.equal(12); + expect(policy['getBackoffDelay'](3, retryDelayMin, retryDelayMax)).to.equal(retryDelayMax); + expect(policy['getBackoffDelay'](4, retryDelayMin, retryDelayMax)).to.equal(retryDelayMax); }); it('should extract delay from `Retry-After` header', async () => { const context = new ClientContextStub({ retryDelayMin: 3, retryDelayMax: 20 }); const { retryDelayMin } = context.getConfig(); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - function createMock(headers: HeadersInit) { + function createStub(headers: HeadersInit) { return { request: new Request('http://localhost'), response: new Response(undefined, { headers }), @@ -57,26 +32,26 @@ describe('HttpRetryPolicy', () => { } // Missing `Retry-After` header - expect(policy.getRetryAfterHeader(createMock({}), retryDelayMin)).to.be.undefined; + expect(policy['getRetryAfterHeader'](createStub({}), retryDelayMin)).to.be.undefined; // Valid `Retry-After`, several header name variants - expect(policy.getRetryAfterHeader(createMock({ 'Retry-After': '10' }), retryDelayMin)).to.equal(10); - expect(policy.getRetryAfterHeader(createMock({ 'retry-after': '10' }), retryDelayMin)).to.equal(10); - expect(policy.getRetryAfterHeader(createMock({ 'RETRY-AFTER': '10' }), retryDelayMin)).to.equal(10); + expect(policy['getRetryAfterHeader'](createStub({ 'Retry-After': '10' }), retryDelayMin)).to.equal(10); + expect(policy['getRetryAfterHeader'](createStub({ 'retry-after': '10' }), retryDelayMin)).to.equal(10); + expect(policy['getRetryAfterHeader'](createStub({ 'RETRY-AFTER': '10' }), retryDelayMin)).to.equal(10); // Invalid header values (non-numeric, negative) - expect(policy.getRetryAfterHeader(createMock({ 'Retry-After': 'test' }), retryDelayMin)).to.be.undefined; - expect(policy.getRetryAfterHeader(createMock({ 'Retry-After': '-10' }), retryDelayMin)).to.be.undefined; + expect(policy['getRetryAfterHeader'](createStub({ 'Retry-After': 'test' }), retryDelayMin)).to.be.undefined; + expect(policy['getRetryAfterHeader'](createStub({ 'Retry-After': '-10' }), retryDelayMin)).to.be.undefined; // It should not be smaller than min value, but can be greater than max value - expect(policy.getRetryAfterHeader(createMock({ 'Retry-After': '1' }), retryDelayMin)).to.equal(retryDelayMin); - expect(policy.getRetryAfterHeader(createMock({ 'Retry-After': '200' }), retryDelayMin)).to.equal(200); + expect(policy['getRetryAfterHeader'](createStub({ 'Retry-After': '1' }), retryDelayMin)).to.equal(retryDelayMin); + expect(policy['getRetryAfterHeader'](createStub({ 'Retry-After': '200' }), retryDelayMin)).to.equal(200); }); it('should check if HTTP transaction is safe to retry', async () => { - const policy = new HttpRetryPolicyTest(new ClientContextStub()); + const policy = new HttpRetryPolicy(new ClientContextStub()); - function createMock(status: number) { + function createStub(status: number) { return { request: new Request('http://localhost'), response: new Response(undefined, { status }), @@ -85,20 +60,20 @@ describe('HttpRetryPolicy', () => { // Status codes below 100 can be retried for (let status = 1; status < 100; status += 1) { - expect(policy.isRetryable(createMock(status))).to.be.true; + expect(policy['isRetryable'](createStub(status))).to.be.true; } // Status codes between 100 (including) and 500 (excluding) should not be retried // The only exception is 429 (Too many requests) for (let status = 100; status < 500; status += 1) { const expectedResult = status === 429 ? true : false; - expect(policy.isRetryable(createMock(status))).to.equal(expectedResult); + expect(policy['isRetryable'](createStub(status))).to.equal(expectedResult); } // Status codes above 500 can be retried, except for 501 for (let status = 500; status < 1000; status += 1) { const expectedResult = status === 501 ? false : true; - expect(policy.isRetryable(createMock(status))).to.equal(expectedResult); + expect(policy['isRetryable'](createStub(status))).to.equal(expectedResult); } }); @@ -106,9 +81,9 @@ describe('HttpRetryPolicy', () => { it('should not retry if transaction succeeded', async () => { const context = new ClientContextStub({ retryMaxAttempts: 3 }); const clientConfig = context.getConfig(); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - function createMock(status: number) { + function createStub(status: number) { return { request: new Request('http://localhost'), response: new Response(undefined, { status }), @@ -117,46 +92,42 @@ describe('HttpRetryPolicy', () => { // Try several times to make sure it doesn't increment an attempts counter for (let attempt = 1; attempt <= clientConfig.retryMaxAttempts + 1; attempt += 1) { - const result = await policy.shouldRetry(createMock(200)); + const result = await policy.shouldRetry(createStub(200)); expect(result.shouldRetry).to.be.false; - expect(policy.inspectInternals().attempt).to.equal(0); + expect(policy['attempt']).to.equal(0); } // Make sure it doesn't trigger timeout when not needed - policy.updateInternals({ - startTime: Date.now() - clientConfig.retriesTimeout * 2, - }); - const result = await policy.shouldRetry(createMock(200)); + policy['startTime'] = Date.now() - clientConfig.retriesTimeout * 2; + const result = await policy.shouldRetry(createStub(200)); expect(result.shouldRetry).to.be.false; }); it('should use `Retry-After` header as a base for backoff', async () => { const context = new ClientContextStub({ retryDelayMin: 3, retryDelayMax: 100, retryMaxAttempts: 10 }); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - function createMock(headers: HeadersInit) { + function createStub(headers: HeadersInit) { return { request: new Request('http://localhost'), response: new Response(undefined, { status: 500, headers }), }; } - const result1 = await policy.shouldRetry(createMock({ 'Retry-After': '5' })); + const result1 = await policy.shouldRetry(createStub({ 'Retry-After': '5' })); expect(result1.shouldRetry).to.be.true; if (result1.shouldRetry) { expect(result1.retryAfter).to.equal(10); } - const result2 = await policy.shouldRetry(createMock({ 'Retry-After': '8' })); + const result2 = await policy.shouldRetry(createStub({ 'Retry-After': '8' })); expect(result2.shouldRetry).to.be.true; if (result2.shouldRetry) { expect(result2.retryAfter).to.equal(32); } - policy.updateInternals({ - attempt: 4, - }); - const result3 = await policy.shouldRetry(createMock({ 'Retry-After': '10' })); + policy['attempt'] = 4; + const result3 = await policy.shouldRetry(createStub({ 'Retry-After': '10' })); expect(result3.shouldRetry).to.be.true; if (result3.shouldRetry) { expect(result3.retryAfter).to.equal(100); @@ -170,25 +141,23 @@ describe('HttpRetryPolicy', () => { retryMaxAttempts: Number.POSITIVE_INFINITY, // remove limit on max attempts }); const clientConfig = context.getConfig(); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - function createMock(headers: HeadersInit) { + function createStub(headers: HeadersInit) { return { request: new Request('http://localhost'), response: new Response(undefined, { status: 500, headers }), }; } - const result1 = await policy.shouldRetry(createMock({})); + const result1 = await policy.shouldRetry(createStub({})); expect(result1.shouldRetry).to.be.true; if (result1.shouldRetry) { expect(result1.retryAfter).to.equal(6); } - policy.updateInternals({ - attempt: 4, - }); - const result2 = await policy.shouldRetry(createMock({ 'Retry-After': 'test' })); + policy['attempt'] = 4; + const result2 = await policy.shouldRetry(createStub({ 'Retry-After': 'test' })); expect(result2.shouldRetry).to.be.true; if (result2.shouldRetry) { expect(result2.retryAfter).to.equal(clientConfig.retryDelayMax); @@ -198,24 +167,22 @@ describe('HttpRetryPolicy', () => { it('should check if retry timeout reached', async () => { const context = new ClientContextStub(); const clientConfig = context.getConfig(); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - function createMock() { + function createStub() { return { request: new Request('http://localhost', { method: 'POST' }), response: new Response(undefined, { status: 500 }), }; } - const result = await policy.shouldRetry(createMock()); + const result = await policy.shouldRetry(createStub()); expect(result.shouldRetry).to.be.true; // Modify start time to be in the past so the next `shouldRetry` would fail - policy.updateInternals({ - startTime: Date.now() - clientConfig.retriesTimeout * 2, - }); + policy['startTime'] = Date.now() - clientConfig.retriesTimeout * 2; try { - await policy.shouldRetry(createMock()); + await policy.shouldRetry(createStub()); expect.fail('It should throw an error'); } catch (error) { if (error instanceof AssertionError || !(error instanceof Error)) { @@ -229,9 +196,9 @@ describe('HttpRetryPolicy', () => { it('should check if retry attempts exceeded', async () => { const context = new ClientContextStub({ retryMaxAttempts: 3 }); const clientConfig = context.getConfig(); - const policy = new HttpRetryPolicyTest(context); + const policy = new HttpRetryPolicy(context); - function createMock() { + function createStub() { return { request: new Request('http://localhost', { method: 'POST' }), response: new Response(undefined, { status: 500 }), @@ -240,13 +207,13 @@ describe('HttpRetryPolicy', () => { // First attempts should succeed for (let attempt = 1; attempt < clientConfig.retryMaxAttempts; attempt += 1) { - const result = await policy.shouldRetry(createMock()); + const result = await policy.shouldRetry(createStub()); expect(result.shouldRetry).to.be.true; } // Modify start time to be in the past so the next `shouldRetry` would fail try { - await policy.shouldRetry(createMock()); + await policy.shouldRetry(createStub()); expect.fail('It should throw an error'); } catch (error) { if (error instanceof AssertionError || !(error instanceof Error)) { @@ -265,9 +232,9 @@ describe('HttpRetryPolicy', () => { retryDelayMax: 2, retryMaxAttempts: 20, }); - const policy = sinon.spy(new HttpRetryPolicyTest(context)); + const policy = sinon.spy(new HttpRetryPolicy(context)); - function createMock(status: number) { + function createStub(status: number) { return { request: new Request('http://localhost'), response: new Response(undefined, { status }), @@ -278,9 +245,9 @@ describe('HttpRetryPolicy', () => { const operation = sinon .stub() - .returns(createMock(500)) + .returns(createStub(500)) .onCall(expectedAttempts - 1) // call numbers are zero-based - .returns(createMock(200)); + .returns(createStub(200)); const result = await policy.invokeWithRetry(operation); expect(policy.shouldRetry.callCount).to.equal(expectedAttempts); @@ -295,9 +262,9 @@ describe('HttpRetryPolicy', () => { retryMaxAttempts: 3, }); const clientConfig = context.getConfig(); - const policy = sinon.spy(new HttpRetryPolicyTest(context)); + const policy = sinon.spy(new HttpRetryPolicy(context)); - function createMock(status: number) { + function createStub(status: number) { return { request: new Request('http://localhost'), response: new Response(undefined, { status }), @@ -306,7 +273,7 @@ describe('HttpRetryPolicy', () => { const expectedAttempts = clientConfig.retryMaxAttempts; - const operation = sinon.stub().returns(createMock(500)); + const operation = sinon.stub().returns(createStub(500)); try { await policy.invokeWithRetry(operation); diff --git a/tests/unit/hive/commands/BaseCommand.test.ts b/tests/unit/hive/commands/BaseCommand.test.ts index 752f3fd5..b1514775 100644 --- a/tests/unit/hive/commands/BaseCommand.test.ts +++ b/tests/unit/hive/commands/BaseCommand.test.ts @@ -15,7 +15,7 @@ class TCustomReq {} class TCustomResp {} -class ThriftClientMock { +class ThriftClientStub { static defaultResponse = { status: { statusCode: 0 }, }; @@ -47,7 +47,7 @@ class ThriftClientMock { } } -class CustomCommand extends BaseCommand { +class CustomCommand extends BaseCommand { public async execute(request: TCustomReq): Promise { return this.executeCommand(request, this.client.CustomMethod); } @@ -60,7 +60,7 @@ describe('BaseCommand', () => { // Here we have a special test condition - when invalid Thrift client is passed to // a command. Normally TS should catch this (and therefore we have a type cast here), // but there is an additional check in the code, which we need to verify as well - const command = new CustomCommand({} as ThriftClientMock, context); + const command = new CustomCommand({} as ThriftClientStub, context); try { await command.execute({}); @@ -79,7 +79,7 @@ describe('BaseCommand', () => { const context = new ClientContextStub(); - const thriftClient = new ThriftClientMock(context, async () => { + const thriftClient = new ThriftClientStub(context, async () => { throw new Error('Not implemented'); }); sinon.stub(thriftClient, 'CustomMethod').callsFake(() => { @@ -112,7 +112,7 @@ describe('BaseCommand', () => { let methodCallCount = 0; const command = new CustomCommand( - new ThriftClientMock(context, async () => { + new ThriftClientStub(context, async () => { methodCallCount += 1; const request = new Request('http://localhost/', { method: 'POST' }); const response = new Response(undefined, { @@ -147,7 +147,7 @@ describe('BaseCommand', () => { let methodCallCount = 0; const command = new CustomCommand( - new ThriftClientMock(context, async () => { + new ThriftClientStub(context, async () => { methodCallCount += 1; const request = new Request('http://localhost/', { method: 'POST' }); const response = new Response(undefined, { @@ -185,7 +185,7 @@ describe('BaseCommand', () => { let methodCallCount = 0; const command = new CustomCommand( - new ThriftClientMock(context, async () => { + new ThriftClientStub(context, async () => { const request = new Request('http://localhost/', { method: 'POST' }); methodCallCount += 1; @@ -196,7 +196,7 @@ describe('BaseCommand', () => { return { request, response }; } - const response = new Response(JSON.stringify(ThriftClientMock.defaultResponse), { + const response = new Response(JSON.stringify(ThriftClientStub.defaultResponse), { status: 200, }); return { request, response }; @@ -205,7 +205,7 @@ describe('BaseCommand', () => { ); const response = await command.execute({}); - expect(response).to.deep.equal(ThriftClientMock.defaultResponse); + expect(response).to.deep.equal(ThriftClientStub.defaultResponse); expect(methodCallCount).to.equal(4); // 3 failed attempts + 1 succeeded }); }); @@ -215,7 +215,7 @@ describe('BaseCommand', () => { const context = new ClientContextStub(); const command = new CustomCommand( - new ThriftClientMock(context, async () => { + new ThriftClientStub(context, async () => { throw new THTTPException( new Response(undefined, { status: 500, @@ -243,7 +243,7 @@ describe('BaseCommand', () => { const context = new ClientContextStub(); const command = new CustomCommand( - new ThriftClientMock(context, async () => { + new ThriftClientStub(context, async () => { throw new Thrift.TApplicationException(undefined, errorMessage); }), context, @@ -267,7 +267,7 @@ describe('BaseCommand', () => { const context = new ClientContextStub(); const command = new CustomCommand( - new ThriftClientMock(context, async () => { + new ThriftClientStub(context, async () => { throw new Error(errorMessage); }), context, diff --git a/tests/unit/result/ArrowResultHandler.test.ts b/tests/unit/result/ArrowResultHandler.test.ts index 105ae993..c657b16b 100644 --- a/tests/unit/result/ArrowResultHandler.test.ts +++ b/tests/unit/result/ArrowResultHandler.test.ts @@ -7,14 +7,6 @@ import { TRowSet, TSparkArrowBatch, TStatusCode, TTableSchema } from '../../../t import ClientContextStub from '../.stubs/ClientContextStub'; -class ArrowResultHandlerTest extends ArrowResultHandler { - public inspectInternals() { - return { - arrowSchema: this.arrowSchema, - }; - } -} - const sampleArrowSchema = Buffer.from([ 255, 255, 255, 255, 208, 0, 0, 0, 16, 0, 0, 0, 0, 0, 10, 0, 14, 0, 6, 0, 13, 0, 8, 0, 10, 0, 0, 0, 0, 0, 4, 0, 16, 0, 0, 0, 0, 1, 10, 0, 12, 0, 0, 0, 8, 0, 4, 0, 10, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 24, 0, 0, 0, @@ -77,7 +69,7 @@ const sampleRowSet4: TRowSet = { describe('ArrowResultHandler', () => { it('should return data', async () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet1], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -92,7 +84,7 @@ describe('ArrowResultHandler', () => { it('should handle LZ4 compressed data', async () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet1LZ4Compressed], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, arrowSchema: sampleArrowSchema, lz4Compressed: true, @@ -108,7 +100,7 @@ describe('ArrowResultHandler', () => { it('should not buffer any data', async () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet1], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -128,7 +120,7 @@ describe('ArrowResultHandler', () => { case1: { const rowSetProvider = new ResultsProviderStub([], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -137,7 +129,7 @@ describe('ArrowResultHandler', () => { } case2: { const rowSetProvider = new ResultsProviderStub([sampleRowSet2], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -146,7 +138,7 @@ describe('ArrowResultHandler', () => { } case3: { const rowSetProvider = new ResultsProviderStub([sampleRowSet3], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -155,7 +147,7 @@ describe('ArrowResultHandler', () => { } case4: { const rowSetProvider = new ResultsProviderStub([sampleRowSet4], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -187,7 +179,7 @@ describe('ArrowResultHandler', () => { ], undefined, ); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { arrowSchema: sampleArrowSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -219,16 +211,16 @@ describe('ArrowResultHandler', () => { ], }; - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { schema: sampleThriftSchema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); - expect(result.inspectInternals().arrowSchema).to.not.be.undefined; + expect(result['arrowSchema']).to.not.be.undefined; }); it('should return empty array if no schema available', async () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet2], undefined); - const result = new ArrowResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new ArrowResultHandler(new ClientContextStub(), rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); expect(await result.fetchNext({ limit: 10000 })).to.be.deep.eq({ diff --git a/tests/unit/result/CloudFetchResultHandler.test.ts b/tests/unit/result/CloudFetchResultHandler.test.ts index bb5e4620..7927ee41 100644 --- a/tests/unit/result/CloudFetchResultHandler.test.ts +++ b/tests/unit/result/CloudFetchResultHandler.test.ts @@ -129,69 +129,43 @@ class ClientContextStub extends BaseClientContextStub { } } -interface CloudFetchResultHandlerInternals { - pendingLinks: Array; - - downloadTasks: Array>; -} - -class CloudFetchResultHandlerTest extends CloudFetchResultHandler { - public inspectInternals() { - return { - pendingLinks: this.pendingLinks, - downloadTasks: this.downloadTasks, - }; - } - - public updateInternals(values: Partial) { - this.pendingLinks = values.pendingLinks ?? super.pendingLinks; - this.downloadTasks = values.downloadTasks ?? super.downloadTasks; - } -} - describe('CloudFetchResultHandler', () => { it('should report pending data if there are any', async () => { const context = new ClientContextStub({ cloudFetchConcurrentDownloads: 1 }); const rowSetProvider = new ResultsProviderStub([], undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); case1: { - result.updateInternals({ - pendingLinks: [], - downloadTasks: [], - }); + result['pendingLinks'] = []; + result['downloadTasks'] = []; expect(await result.hasMore()).to.be.false; } case2: { - result.updateInternals({ - pendingLinks: [ - { - fileLink: '', - expiryTime: new Int64(0), - startRowOffset: new Int64(0), - rowCount: new Int64(0), - bytesNum: new Int64(0), - }, - ], - downloadTasks: [], - }); + result['pendingLinks'] = [ + { + fileLink: '', + expiryTime: new Int64(0), + startRowOffset: new Int64(0), + rowCount: new Int64(0), + bytesNum: new Int64(0), + }, + ]; + result['downloadTasks'] = []; expect(await result.hasMore()).to.be.true; } case3: { - result.updateInternals({ - pendingLinks: [], - downloadTasks: [ - Promise.resolve({ - batches: [], - rowCount: 0, - }), - ], - }); + result['pendingLinks'] = []; + result['downloadTasks'] = [ + Promise.resolve({ + batches: [], + rowCount: 0, + }), + ]; expect(await result.hasMore()).to.be.true; } }); @@ -204,7 +178,7 @@ describe('CloudFetchResultHandler', () => { const rowSetProvider = new ResultsProviderStub(rowSets, undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -217,8 +191,8 @@ describe('CloudFetchResultHandler', () => { await result.fetchNext({ limit: 100000 }); } while (await rowSetProvider.hasMore()); - expect(result.inspectInternals().pendingLinks.length).to.be.equal(expectedLinksCount); - expect(result.inspectInternals().downloadTasks.length).to.be.equal(0); + expect(result['pendingLinks'].length).to.be.equal(expectedLinksCount); + expect(result['downloadTasks'].length).to.be.equal(0); expect(context.invokeWithRetryStub.called).to.be.false; }); @@ -234,7 +208,7 @@ describe('CloudFetchResultHandler', () => { const expectedLinksCount = rowSet.resultLinks?.length ?? 0; // 5 const rowSetProvider = new ResultsProviderStub([rowSet], undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -255,12 +229,10 @@ describe('CloudFetchResultHandler', () => { // it should use retry policy for all requests expect((context.connectionProvider.getRetryPolicy as SinonStub).called).to.be.true; expect(context.invokeWithRetryStub.callCount).to.be.equal(clientConfig.cloudFetchConcurrentDownloads); - expect(result.inspectInternals().pendingLinks.length).to.be.equal( + expect(result['pendingLinks'].length).to.be.equal( expectedLinksCount - clientConfig.cloudFetchConcurrentDownloads, ); - expect(result.inspectInternals().downloadTasks.length).to.be.equal( - clientConfig.cloudFetchConcurrentDownloads - 1, - ); + expect(result['downloadTasks'].length).to.be.equal(clientConfig.cloudFetchConcurrentDownloads - 1); } secondFetch: { @@ -272,12 +244,10 @@ describe('CloudFetchResultHandler', () => { // it should use retry policy for all requests expect((context.connectionProvider.getRetryPolicy as SinonStub).called).to.be.true; expect(context.invokeWithRetryStub.callCount).to.be.equal(clientConfig.cloudFetchConcurrentDownloads + 1); - expect(result.inspectInternals().pendingLinks.length).to.be.equal( + expect(result['pendingLinks'].length).to.be.equal( expectedLinksCount - clientConfig.cloudFetchConcurrentDownloads - 1, ); - expect(result.inspectInternals().downloadTasks.length).to.be.equal( - clientConfig.cloudFetchConcurrentDownloads - 1, - ); + expect(result['downloadTasks'].length).to.be.equal(clientConfig.cloudFetchConcurrentDownloads - 1); } thirdFetch: { @@ -289,12 +259,10 @@ describe('CloudFetchResultHandler', () => { // it should use retry policy for all requests expect((context.connectionProvider.getRetryPolicy as SinonStub).called).to.be.true; expect(context.invokeWithRetryStub.callCount).to.be.equal(clientConfig.cloudFetchConcurrentDownloads + 2); - expect(result.inspectInternals().pendingLinks.length).to.be.equal( + expect(result['pendingLinks'].length).to.be.equal( expectedLinksCount - clientConfig.cloudFetchConcurrentDownloads - 2, ); - expect(result.inspectInternals().downloadTasks.length).to.be.equal( - clientConfig.cloudFetchConcurrentDownloads - 1, - ); + expect(result['downloadTasks'].length).to.be.equal(clientConfig.cloudFetchConcurrentDownloads - 1); } }); @@ -303,7 +271,7 @@ describe('CloudFetchResultHandler', () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet1], undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { lz4Compressed: false, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -329,7 +297,7 @@ describe('CloudFetchResultHandler', () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet1], undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { lz4Compressed: true, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -357,7 +325,7 @@ describe('CloudFetchResultHandler', () => { const rowSetProvider = new ResultsProviderStub([sampleRowSet1], undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -384,7 +352,7 @@ describe('CloudFetchResultHandler', () => { const context = new ClientContextStub(); const rowSetProvider = new ResultsProviderStub([sampleExpiredRowSet], undefined); - const result = new CloudFetchResultHandlerTest(context, rowSetProvider, { + const result = new CloudFetchResultHandler(context, rowSetProvider, { status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); diff --git a/tests/unit/result/JsonResultHandler.test.ts b/tests/unit/result/JsonResultHandler.test.ts index 957f832c..45ea1f34 100644 --- a/tests/unit/result/JsonResultHandler.test.ts +++ b/tests/unit/result/JsonResultHandler.test.ts @@ -30,10 +30,6 @@ const getColumnSchema = (columnName: string, type: TTypeId | undefined, position }; }; -class JsonResultHandlerTest extends JsonResultHandler { - public isNull = super.isNull; -} - describe('JsonResultHandler', () => { it('should not buffer any data', async () => { const schema: TTableSchema = { @@ -49,7 +45,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub(data, undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -150,7 +146,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub(data, undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -230,7 +226,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub(data, undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -254,7 +250,7 @@ describe('JsonResultHandler', () => { it('should detect nulls', () => { const rowSetProvider = new ResultsProviderStub([], undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema: undefined, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -286,7 +282,7 @@ describe('JsonResultHandler', () => { true, true, // 0xC3 ].forEach((value, i) => { - expect(result.isNull(buf, i)).to.be.eq(value); + expect(result['isNull'](buf, i)).to.be.eq(value); }); }); @@ -373,7 +369,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub(data, undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -407,7 +403,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub([], undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -429,7 +425,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub(data, undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema: undefined, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); @@ -472,7 +468,7 @@ describe('JsonResultHandler', () => { const rowSetProvider = new ResultsProviderStub(data, undefined); - const result = new JsonResultHandlerTest(new ClientContextStub(), rowSetProvider, { + const result = new JsonResultHandler(new ClientContextStub(), rowSetProvider, { schema, status: { statusCode: TStatusCode.SUCCESS_STATUS }, }); diff --git a/tests/unit/utils/CloseableCollection.test.ts b/tests/unit/utils/CloseableCollection.test.ts index ac4961fe..da7ab147 100644 --- a/tests/unit/utils/CloseableCollection.test.ts +++ b/tests/unit/utils/CloseableCollection.test.ts @@ -1,18 +1,10 @@ import { expect, AssertionError } from 'chai'; import CloseableCollection, { ICloseable } from '../../../lib/utils/CloseableCollection'; -class CloseableCollectionTest extends CloseableCollection { - public inspectInternals() { - return { - items: this.items, - }; - } -} - describe('CloseableCollection', () => { it('should add item if not already added', () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const item: ICloseable = { close: () => Promise.resolve(), @@ -20,12 +12,12 @@ describe('CloseableCollection', () => { collection.add(item); expect(item.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); }); it('should add item if it is already added', () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const item: ICloseable = { close: () => Promise.resolve(), @@ -33,16 +25,16 @@ describe('CloseableCollection', () => { collection.add(item); expect(item.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); collection.add(item); expect(item.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); }); it('should delete item if already added', () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const item: ICloseable = { close: () => Promise.resolve(), @@ -50,16 +42,16 @@ describe('CloseableCollection', () => { collection.add(item); expect(item.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); collection.delete(item); expect(item.onClose).to.be.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(0); + expect(collection['items'].size).to.be.eq(0); }); it('should delete item if not added', () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const item: ICloseable = { close: () => Promise.resolve(), @@ -67,7 +59,7 @@ describe('CloseableCollection', () => { collection.add(item); expect(item.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); const otherItem: ICloseable = { onClose: () => {}, @@ -76,12 +68,12 @@ describe('CloseableCollection', () => { collection.delete(otherItem); // if item is not in collection - it should be just skipped expect(otherItem.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); }); it('should delete item if it was closed', async () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const item: ICloseable = { close() { @@ -92,16 +84,16 @@ describe('CloseableCollection', () => { collection.add(item); expect(item.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(1); + expect(collection['items'].size).to.be.eq(1); await item.close(); expect(item.onClose).to.be.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(0); + expect(collection['items'].size).to.be.eq(0); }); it('should close all and delete all items', async () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const item1: ICloseable = { close() { @@ -121,17 +113,17 @@ describe('CloseableCollection', () => { collection.add(item2); expect(item1.onClose).to.be.not.undefined; expect(item2.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(2); + expect(collection['items'].size).to.be.eq(2); await collection.closeAll(); expect(item1.onClose).to.be.undefined; expect(item2.onClose).to.be.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(0); + expect(collection['items'].size).to.be.eq(0); }); it('should close all and delete only first successfully closed items', async () => { - const collection = new CloseableCollectionTest(); - expect(collection.inspectInternals().items.size).to.be.eq(0); + const collection = new CloseableCollection(); + expect(collection['items'].size).to.be.eq(0); const errorMessage = 'Error from item 2'; @@ -162,7 +154,7 @@ describe('CloseableCollection', () => { expect(item1.onClose).to.be.not.undefined; expect(item2.onClose).to.be.not.undefined; expect(item3.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(3); + expect(collection['items'].size).to.be.eq(3); try { await collection.closeAll(); @@ -175,7 +167,7 @@ describe('CloseableCollection', () => { expect(item1.onClose).to.be.undefined; expect(item2.onClose).to.be.not.undefined; expect(item3.onClose).to.be.not.undefined; - expect(collection.inspectInternals().items.size).to.be.eq(2); + expect(collection['items'].size).to.be.eq(2); } }); });