Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor test filters to typescript #4054

Merged
merged 4 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion test/mocha_mongodb.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"source-map-support/register",
"ts-node/register",
"test/tools/runner/chai-addons.js",
"test/tools/runner/hooks/configuration.js",
"test/tools/runner/hooks/configuration.ts",
"test/tools/runner/hooks/unhandled_checker.ts",
"test/tools/runner/hooks/leak_checker.ts",
"test/tools/runner/hooks/legacy_crud_shims.ts"
Expand Down
1 change: 1 addition & 0 deletions test/tools/runner/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export class TestConfiguration {
serverApi: ServerApi;
activeResources: number;
isSrv: boolean;
serverlessCredentials: { username: string | undefined; password: string | undefined };

constructor(private uri: string, private context: Record<string, any>) {
const url = new ConnectionString(uri);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
'use strict';
import { Filter } from './filter';

/**
* Filter for the MongoDB API Version required for the test
*
* example:
* @example
* ```js
* metadata: {
* requires: {
* apiVersion: '1'
* }
* }
* ```
*/
class ApiVersionFilter {
export class ApiVersionFilter extends Filter {
apiVersion: string | undefined;
constructor() {
super();
// Get environmental variables that are known
this.apiVersion = process.env.MONGODB_API_VERSION;
}

filter(test) {
filter(test: { metadata?: MongoDBMetadataUI }) {
if (!test.metadata) return true;
if (!test.metadata.requires) return true;
const apiVersion = test.metadata.requires.apiVersion;
Expand All @@ -33,5 +37,3 @@ class ApiVersionFilter {
return apiVersion === this.apiVersion;
}
}

module.exports = ApiVersionFilter;
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
'use strict';
import { Filter } from './filter';

/**
* Filter for authorization enabled or disabled on the server
*
* example:
* @example
* ```js
* metadata: {
* requires: {
* auth: 'enabled' | 'disabled'
* }
* }
* ```
*/
class AuthFilter {
export class AuthFilter extends Filter {
isAuthEnabled: boolean;
constructor() {
super();
this.isAuthEnabled = process.env.AUTH === 'auth';
}

filter(test) {
filter(test: { metadata?: MongoDBMetadataUI }) {
if (!test.metadata) return true;
if (!test.metadata.requires) return true;
if (!test.metadata.requires.auth) return true;
Expand All @@ -33,5 +37,3 @@ class AuthFilter {
);
}
}

module.exports = AuthFilter;
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
'use strict';
import { readFile } from 'fs/promises';
import { dirname, resolve } from 'path';
import * as process from 'process';

const { readFileSync } = require('fs');
const { resolve } = require('path');
const process = require('process');
import { type MongoClient } from '../../../mongodb';
import { Filter } from './filter';

/**
* Filter for whether or not a test needs / doesn't need Client Side Encryption
*
* example:
* @example
* ```js
* metadata: {
* requires: {
* clientSideEncryption: true|false
* }
* }
* ```
*/

class ClientSideEncryptionFilter {
initializeFilter(client, context, callback) {
export class ClientSideEncryptionFilter extends Filter {
enabled: boolean;
static version = null;

override async initializeFilter(client: MongoClient, context: Record<string, any>) {
const CSFLE_KMS_PROVIDERS = process.env.CSFLE_KMS_PROVIDERS;
let mongodbClientEncryption;
try {
Expand All @@ -27,11 +33,12 @@ class ClientSideEncryptionFilter {
}
}

const { version } = JSON.parse(
readFileSync(
resolve(__dirname, '../../../../node_modules/mongodb-client-encryption', 'package.json')
ClientSideEncryptionFilter.version ??= JSON.parse(
await readFile(
resolve(dirname(require.resolve('mongodb-client-encryption')), '..', 'package.json'),
'utf8'
)
);
).version;

this.enabled = !!(CSFLE_KMS_PROVIDERS && mongodbClientEncryption);

Expand All @@ -40,13 +47,11 @@ class ClientSideEncryptionFilter {
enabled: this.enabled,
mongodbClientEncryption,
CSFLE_KMS_PROVIDERS,
version
version: ClientSideEncryptionFilter.version
};

callback();
}

filter(test) {
filter(test: { metadata?: MongoDBMetadataUI }) {
const clientSideEncryption =
test.metadata && test.metadata.requires && test.metadata.requires.clientSideEncryption;

Expand All @@ -66,5 +71,3 @@ class ClientSideEncryptionFilter {
return this.enabled;
}
}

module.exports = ClientSideEncryptionFilter;
11 changes: 11 additions & 0 deletions test/tools/runner/filters/filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { type Test } from 'mocha';

import { type MongoClient } from '../../../mongodb';

export abstract class Filter {
async initializeFilter(_client: MongoClient, _context: Record<string, any>): Promise<void> {
return;
}

abstract filter(test: Test): string | boolean;
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
'use strict';

/**
* Generic filter than can run predicates.
*
* Predicates cannot be async. The test is skipped if the predicate returns
* a string. The string returned should be a skip reason.
*
* example:
* @example
* ```js
* metadata: {
* requires: {
* predicate: (test: Mocha.Test) => true | string
* }
* }
* ```
*/

class GenericPredicateFilter {
filter(test) {
/** @type{ ((test?: Mocha.Test) => string | true) | undefined } */
const predicate = test?.metadata?.requires?.predicate;
import { type Test } from 'mocha';

import { Filter } from './filter';

export class GenericPredicateFilter extends Filter {
filter(test: Test & { metadata?: MongoDBMetadataUI }) {
const predicate = test?.metadata?.requires?.predicate;
return predicate?.(test) ?? true;
}
}

module.exports = GenericPredicateFilter;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
import { get } from 'http';

const { get } = require('http');
import { Filter } from './filter';

async function isMockServerSetup() {
const url = (() => {
Expand All @@ -11,7 +11,7 @@ async function isMockServerSetup() {
url.searchParams.append('resource', 'https://vault.azure.net');
return url;
})();
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
get(url, res => {
if (res.statusCode === 200) {
return resolve();
Expand All @@ -26,24 +26,28 @@ async function isMockServerSetup() {
/**
* Filter for tests that require the mock idms server to be running.
*
* example:
* @example
* ```js
* metadata: {
* requires: {
* idmsMockServer: true
* }
* }
* ```
*/
class IDMSMockServerFilter {
initializeFilter(client, context, callback) {
isMockServerSetup()
.then(
() => (this.isRunning = true),
() => (this.isRunning = false)
)
.then(() => callback());
export class IDMSMockServerFilter extends Filter {
isRunning: boolean;

override async initializeFilter() {
try {
await isMockServerSetup();
this.isRunning = true;
} catch (error) {
this.isRunning = false;
}
}

filter(test) {
filter(test: { metadata?: MongoDBMetadataUI }) {
if (!test.metadata) return true;
if (!test.metadata.requires) return true;
if (!test.metadata.requires.idmsMockServer) return true;
Expand All @@ -58,5 +62,3 @@ class IDMSMockServerFilter {
return this.isRunning;
}
}

module.exports = IDMSMockServerFilter;
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
'use strict';
const { TopologyType } = require('../../../mongodb');
import { type MongoClient, TopologyType } from '../../../mongodb';
import { Filter } from './filter';

/**
* Filter for the MongoDB topology required for the test
*
* example:
* @example
* ```js
* metadata: {
* requires: {
* topology: 'single' | 'replicaset' | 'sharded'
* }
* }
* ```
*/
class MongoDBTopologyFilter {
initializeFilter(client, context, callback) {
let type = client.topology.description.type;
export class MongoDBTopologyFilter extends Filter {
runtimeTopology: string;

override async initializeFilter(client: MongoClient, context: Record<string, any>) {
const type = client.topology?.description.type;
if (type == null) throw new Error('unexpected nullish type' + client.topology?.description);
context.topologyType = type;
this.runtimeTopology = topologyTypeToString(type);
callback();
}

filter(test) {
filter(test: { metadata?: MongoDBMetadataUI }) {
if (!test.metadata) return true;
if (!test.metadata.requires) return true;
if (!test.metadata.requires.topology) return true;
Expand Down Expand Up @@ -72,5 +76,3 @@ function topologyTypeToString(topologyType) {

return 'single';
}

module.exports = MongoDBTopologyFilter;
47 changes: 0 additions & 47 deletions test/tools/runner/filters/mongodb_version_filter.js

This file was deleted.