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: Mocha testing configuration #23706

Merged
merged 23 commits into from
Nov 16, 2021
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
15009d9
Add helper for blob URLs in tests
tassoevan Nov 12, 2021
0d72823
Setup all chai plugins at once
tassoevan Nov 12, 2021
ddc6e01
Replace assert with chai
tassoevan Nov 12, 2021
da87bfa
Set eslint mocha env for test files
tassoevan Nov 12, 2021
8966da1
Replace import babel-polyfill with requiring runtime-generator
tassoevan Nov 12, 2021
7302bc6
Named-import chai functions
tassoevan Nov 12, 2021
dd3a2b0
Move Web API mocks
tassoevan Nov 12, 2021
c9c0286
Unify configurations
tassoevan Nov 12, 2021
5becbf2
Upgrade testing deps
tassoevan Nov 12, 2021
87f389b
Adjust URL.createObjectURL mock
tassoevan Nov 13, 2021
5933ce8
Force exit at the end to circumvent unresolved mongodb promises
tassoevan Nov 13, 2021
3302204
Split configuration for client tests
tassoevan Nov 14, 2021
64c9765
Add integration tests for NotFoundPage
tassoevan Nov 14, 2021
ef8c615
Fix cleanup invocation on Mocha
tassoevan Nov 15, 2021
f55e3fc
Transpile tests without type checking
tassoevan Nov 15, 2021
cdf65f3
Add some explanation on Mocha configuration files
tassoevan Nov 15, 2021
921e39d
Add eslint-plugin-testing-library and implement suggestions
tassoevan Nov 15, 2021
319c9c5
Replace all occurrences of a placeholder on string instead of just fi…
KevLehman Nov 15, 2021
99bc32d
Chore: Api definitions (#23701)
ggazzo Nov 15, 2021
462978d
Definition unit tests
ggazzo Nov 16, 2021
3757482
testunit-definition
ggazzo Nov 16, 2021
09a6d11
Change chai imports
ggazzo Nov 16, 2021
4d3ce79
Adjust comment at configuration file
tassoevan Nov 16, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"presets": [
"@babel/preset-env"
"@babel/preset-env",
"@babel/preset-react"
]
}
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ imports/client/**/*
!/.storybook/
ee/server/services/dist/**
!/.mocharc.js
!/.mocharc.*.js
!/client/.eslintrc.js
!/ee/client/.eslintrc.js
10 changes: 10 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@
"version": "detect"
}
}
},
{
"files": [
"**/*.tests.js",
"**/*.tests.ts",
"**/*.spec.ts"
],
"env": {
"mocha": true
}
}
]
}
6 changes: 6 additions & 0 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,15 @@ jobs:
run: |
npm install

- name: Unit Test (definitions)
run: npm run testunit-definition

- name: Unit Test
run: npm run testunit

- name: Unit Test (client)
run: npm run testunit-client

- name: E2E Test
env:
TEST_MODE: "true"
Expand Down
3 changes: 2 additions & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
meteor npm run lint && \
meteor npm run testunit
meteor npm run testunit && \
meteor npm run testunit-client
12 changes: 5 additions & 7 deletions mocha_end_to_end.opts.js → .mocharc.api.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
'use strict';

/**
* Mocha configuration for REST API integration tests.
*/

module.exports = {
require: [
'babel-mocha-es6-compiler',
'babel-polyfill',
],
reporter: 'spec',
ui: 'bdd',
extension: 'js,ts',
...require('./.mocharc.base.json'), // see https://github.com/mochajs/mocha/issues/3916
timeout: 10000,
bail: true,
file: 'tests/end-to-end/teardown.js',
Expand Down
16 changes: 16 additions & 0 deletions .mocharc.base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"ui": "bdd",
"reporter": "spec",
"extension": ["js", "ts", "tsx"],
"require": [
"@babel/register",
"regenerator-runtime/runtime",
"ts-node/register",
"./tests/setup/chaiPlugins.ts"
],
"watch-files": [
"./**/*.js",
"./**/*.ts",
"./**/*.tsx"
]
}
32 changes: 32 additions & 0 deletions .mocharc.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

/**
* Mocha configuration for client-side unit and integration tests.
*/

const base = require('./.mocharc.base.json');

/**
* Mocha will run `ts-node` without doing type checking to speed-up the tests. It should be fine as `npm run typecheck`
* covers test files too.
*/

Object.assign(process.env, {
TS_NODE_FILES: true,
TS_NODE_TRANSPILE_ONLY: true,
}, process.env);

module.exports = {
...base, // see https://github.com/mochajs/mocha/issues/3916
require: [
...base.require,
'./tests/setup/registerWebApiMocks.ts',
'./tests/setup/cleanupTestingLibrary.ts',
],
exit: false,
slow: 200,
spec: [
'client/**/*.spec.ts',
'client/**/*.spec.tsx',
],
};
29 changes: 29 additions & 0 deletions .mocharc.definition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

/**
* Mocha configuration for client-side unit and integration tests.
*/

const base = require('./.mocharc.base.json');

/**
* Mocha will run `ts-node` without doing type checking to speed-up the tests. It should be fine as `npm run typecheck`
* covers test files too.
*/

Object.assign(process.env, {
TS_NODE_FILES: true,
TS_NODE_TRANSPILE_ONLY: true,
}, process.env);

module.exports = {
...base, // see https://github.com/mochajs/mocha/issues/3916
require: [
...base.require,
],
exit: false,
slow: 200,
spec: [
'definition/**/*.spec.ts',
],
};
28 changes: 19 additions & 9 deletions .mocharc.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
'use strict';

/**
* Mocha configuration for general unit tests.
*/

const base = require('./.mocharc.base.json');

/**
* Mocha will run `ts-node` without doing type checking to speed-up the tests. It should be fine as `npm run typecheck`
* covers test files too.
*/

Object.assign(process.env, {
TS_NODE_FILES: true,
TS_NODE_TRANSPILE_ONLY: true,
}, process.env);

module.exports = {
require: [
'ts-node/register',
'@babel/register',
],
reporter: 'spec',
ui: 'bdd',
extension: ['js', 'ts'],
...base, // see https://github.com/mochajs/mocha/issues/3916
exit: true,
spec: [
'app/**/*.spec.ts',
'app/**/*.tests.js',
'app/**/*.tests.ts',
'app/**/*.spec.ts',
'server/**/*.tests.ts',
'client/**/*.spec.ts',
],
};
116 changes: 115 additions & 1 deletion app/api/server/api.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,118 @@
import { APIClass } from '.';
import { Endpoints } from '../../../definition/rest';
import { Awaited } from '../../../definition/utils';
import { IUser } from '../../../definition/IUser';


export type ChangeTypeOfKeys<
T extends object,
Keys extends keyof T,
NewType
> = {
[key in keyof T]: key extends Keys ? NewType : T[key]
}

type This = {
getPaginationItems(): ({
offset: number;
count: number;
});
parseJsonQuery(): ({
sort: Record<string, unknown>;
fields: Record<string, unknown>;
query: Record<string, unknown>;
});
readonly urlParams: Record<string, unknown>;
getUserFromParams(): IUser;
}

type ThisLoggedIn = {
readonly user: IUser;
readonly userId: string;
}

type ThisLoggedOut = {
readonly user: null;
readonly userId: null;
}

type EndpointWithExtraOptions<FN extends (this: any, ...args: any) => any, A> = WrappedFunction<FN> | ({ action: WrappedFunction<FN> } & (A extends true ? { twoFactorRequired: boolean } : {}));

export type Methods<T, A = false> = {
[K in keyof T as `${Lowercase<string & K>}`]: T[K] extends (...args: any) => any ? EndpointWithExtraOptions<(this: This & (A extends true ? ThisLoggedIn : ThisLoggedOut) & Params<K, Parameters<T[K]>[0]>) => ReturnType<T[K]>, A> : never;
};

type Params<K, P> = K extends 'GET' ? { readonly queryParams: Partial<P> } : K extends 'POST' ? { readonly bodyParams: Partial<P> } : never;

type SuccessResult<T = undefined> = {
statusCode: 200;
success: true;
} & T extends (undefined) ? {} : { body: T }

type UnauthorizedResult = {
statusCode: 403;
body: {
success: false;
error: string;
};
}

type FailureResult<T = undefined, ET = undefined, ST = undefined, E = undefined> = {
statusCode: 400;
} & FailureBody<T, ET, ST, { success: false }>;

type FailureBody<T, ET, ST, E> = Exclude<T, string> extends object ? { body: T & E } : {
body: E & { error: string } & E extends Error ? { details: string } : {} & ST extends undefined ? {} : { stack: string } & ET extends undefined ? {} : { errorType: string };
}

type Errors = FailureResult | FailureResult<object> | FailureResult<string, string, string, { error: string }> | UnauthorizedResult;

type WrappedFunction<T extends (this: any, ...args: any) => any> = (this: ThisParameterType<T>, ...args: Parameters<T>) => ReturnTypes<T>;

type ReturnTypes<T extends (this: any, ...args: any) => any> = PromisedOrNot<SuccessResult<ReturnType<T>> | PromisedOrNot<Errors>>;

type PromisedOrNot<T> = Promise<T> | T;

type Options = {
permissionsRequired?: string[];
twoFactorOptions?: unknown;
twoFactorRequired?: boolean;
authRequired?: boolean;
}

export type RestEndpoints<P extends keyof Endpoints, A = false> = Methods<Endpoints[P], A>;

type ToLowerCaseKeys<T> = {
[K in keyof T as `${Lowercase<string & K>}`]: T[K];
};
type ToResultType<T> = {
[K in keyof T]: T[K] extends (...args: any) => any ? Awaited<ReturnTypes<T[K]>> : never;
}
export type ResultTypeEndpoints<P extends keyof Endpoints, A = false> = ToResultType<ToLowerCaseKeys<Endpoints[P]>>;

declare class APIClass {
addRoute<P extends keyof Endpoints>(route: P, endpoints: RestEndpoints<P>): void;

addRoute<P extends keyof Endpoints, O extends Options>(route: P, options: O, endpoints: RestEndpoints<P, O['authRequired'] extends true ? true: false>): void;

unauthorized(msg?: string): UnauthorizedResult;

failure<ET = string | undefined, ST = string | undefined, E = Error | undefined>(result: string, errorType?: ET, stack?: ST, error?: E): FailureResult<string, ET, ST, E>;

failure(result: object): FailureResult<object>;

failure(): FailureResult;

success(): SuccessResult<void>;

success<T>(result: T): SuccessResult<T>;

defaultFieldsToExclude: {
joinCode: 0;
members: 0;
importIds: 0;
e2e: 0;
}
}

export declare const API: {
v1: APIClass;
Expand Down
2 changes: 1 addition & 1 deletion app/api/server/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ export class APIClass extends Restivus {
api.processTwoFactor({ userId: this.userId, request: this.request, invocation, options: _options.twoFactorOptions, connection });
}

result = DDP._CurrentInvocation.withValue(invocation, () => originalAction.apply(this)) || API.v1.success();
result = DDP._CurrentInvocation.withValue(invocation, () => Promise.await(originalAction.apply(this))) || API.v1.success();

log.http({
status: result.statusCode,
Expand Down
2 changes: 1 addition & 1 deletion app/api/server/helpers/getPaginationItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ API.helperMethods.set('getPaginationItems', function _getPaginationItems() {
const offset = this.queryParams.offset ? parseInt(this.queryParams.offset) : 0;
let count = defaultCount;

// Ensure count is an appropiate amount
// Ensure count is an appropriate amount
if (typeof this.queryParams.count !== 'undefined') {
count = parseInt(this.queryParams.count);
} else {
Expand Down
Loading