Skip to content

Commit

Permalink
[CHORE] adds infra for testing calls to Ember warn|deprecate|assert (#…
Browse files Browse the repository at this point in the history
…6626)

* [CHORE] adds infra for testing calls to Ember warn|deprecate|assert

* fix production tests

* address feedback

* feedback on labels

* remove id checks
  • Loading branch information
runspired authored Oct 24, 2019
1 parent 8c3dc88 commit 55cec65
Show file tree
Hide file tree
Showing 17 changed files with 557 additions and 36 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@
"ember-load-initializers": "^2.1.0",
"ember-maybe-import-regenerator": "^0.1.6",
"ember-qunit": "^4.5.1",
"ember-qunit-assert-helpers": "^0.2.2",
"ember-resolver": "^5.3.0",
"ember-simple-tree": "^0.7.0",
"ember-source": "^3.13.3",
Expand Down
1 change: 0 additions & 1 deletion packages/-ember-data/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
"ember-load-initializers": "^2.1.0",
"ember-maybe-import-regenerator": "^0.1.6",
"ember-qunit": "^4.5.1",
"ember-qunit-assert-helpers": "^0.2.2",
"ember-resolver": "^5.3.0",
"ember-source": "^3.13.3",
"ember-source-channel-url": "^2.0.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import QUnit from 'qunit';
import { checkMatcher } from './check-matcher';
import { DEBUG } from '@glimmer/env';
import isThenable from './utils/is-thenable';

let HAS_REGISTERED = false;

interface AssertSomeResult {
result: boolean;
actual: string;
expected: string;
message: string;
}
interface AssertNoneResult {
result: boolean;
actual: string;
expected: '';
message: string;
}

function verifyAssertion(message: string, matcher: string | RegExp, label?: string): AssertSomeResult {
let passed = checkMatcher(message, matcher);

return {
result: passed,
actual: message,
expected: String(matcher),
message: label || `Expected an assertion during the test`,
};
}

function verifyNoAssertion(message: string | undefined, label?: string): AssertNoneResult {
let passed = !message;
return {
result: passed,
actual: message || '',
expected: '',
message: label || `Expected no assertions during test`,
};
}

export function configureAssertionHandler() {
if (HAS_REGISTERED === true) {
throw new Error(`Attempting to re-register the assert-assertion handler`);
}
HAS_REGISTERED = true;

QUnit.assert.expectAssertion = async function(
cb: () => unknown,
matcher: string | RegExp,
label?: string
): Promise<void> {
let outcome;
if (DEBUG) {
try {
let result = cb();
if (isThenable(result)) {
await result;
}
outcome = verifyAssertion('', matcher, label);
} catch (e) {
outcome = verifyAssertion(e.message, matcher, label);
}
} else {
outcome = {
result: true,
actual: '',
expected: '',
message: `Assertions do not run in production environments`,
};
}

this.pushResult(outcome);
};

QUnit.assert.expectNoAssertion = async function(cb: () => unknown, label?: string) {
let outcome;
try {
let result = cb();
if (isThenable(result)) {
await result;
}
outcome = verifyNoAssertion('', label);
} catch (e) {
outcome = verifyNoAssertion(e.message, label);
}

this.pushResult(outcome);
};
}
170 changes: 170 additions & 0 deletions packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import QUnit from 'qunit';
import { registerDeprecationHandler } from '@ember/debug';
import { checkMatcher } from './check-matcher';
import isThenable from './utils/is-thenable';

let HAS_REGISTERED = false;
let DEPRECATIONS_FOR_TEST: FoundDeprecation[];
let HANDLED_DEPRECATIONS_FOR_TEST: FoundDeprecation[];

interface DeprecationConfig {
id: string;
count?: number;
until: string;
message?: string | RegExp;
url?: string;
}
interface FoundDeprecation {
message: string;
options: {
id: string;
message?: string;
until: string;
url?: string;
};
}

interface AssertSomeResult {
result: boolean;
actual: { id: string; count: number };
expected: { id: string; count: number };
message: string;
}
interface AssertNoneResult {
result: boolean;
actual: FoundDeprecation[];
expected: FoundDeprecation[];
message: string;
}

/**
* Returns a qunit assert result object which passes if the given deprecation
* `id` was found *exactly* `count` times.
*
* Fails if not found or found more or less than `count`.
* Fails if `until` not specified
* Optionally fails if `until` has been passed.
*/
function verifyDeprecation(config: DeprecationConfig, label?: string): AssertSomeResult {
// TODO optionally throw if `until` is the current version or older than current version
let matchedDeprecations = DEPRECATIONS_FOR_TEST.filter(deprecation => {
let isMatched = deprecation.options.id === config.id;
if (!isMatched && config.message) {
// TODO when we hit this we should throw an error in the near future
isMatched = checkMatcher(deprecation.message, config.message);
}
return isMatched;
});
DEPRECATIONS_FOR_TEST = DEPRECATIONS_FOR_TEST.filter(deprecation => {
matchedDeprecations.indexOf(deprecation) === -1;
});
HANDLED_DEPRECATIONS_FOR_TEST.push(...matchedDeprecations);

let expectedCount = typeof config.count === 'number' ? config.count : 1;
let passed = matchedDeprecations.length === expectedCount;

return {
result: passed,
actual: { id: config.id, count: matchedDeprecations.length },
expected: { id: config.id, count: expectedCount },
message:
label ||
`Expected ${expectedCount} deprecation${expectedCount === 1 ? '' : 's'} for ${config.id} during test, ${
passed ? expectedCount : 'but ' + matchedDeprecations.length
} deprecations were found.`,
};
}

function verifyNoDeprecation(label?: string): AssertNoneResult {
const UNHANDLED_DEPRECATIONS = DEPRECATIONS_FOR_TEST;
DEPRECATIONS_FOR_TEST = [];

let deprecationStr = UNHANDLED_DEPRECATIONS.reduce((a, b) => {
return `${a}${b.message}\n`;
}, '');

let passed = UNHANDLED_DEPRECATIONS.length === 0;

return {
result: passed,
actual: UNHANDLED_DEPRECATIONS,
expected: [],
message:
label ||
`Expected 0 deprecations during test, ${
passed ? '0' : 'but ' + UNHANDLED_DEPRECATIONS.length
} deprecations were found.\n${deprecationStr}`,
};
}

export function configureDeprecationHandler() {
if (HAS_REGISTERED === true) {
throw new Error(`Attempting to re-register the assert-deprecation handler`);
}
HAS_REGISTERED = true;

QUnit.testStart(function() {
DEPRECATIONS_FOR_TEST = [];
HANDLED_DEPRECATIONS_FOR_TEST = [];
});

registerDeprecationHandler(function(message, options /*, next*/) {
if (DEPRECATIONS_FOR_TEST) {
DEPRECATIONS_FOR_TEST.push({ message, options });
}
// we do not call next to avoid spamming the console
});

QUnit.assert.expectDeprecation = async function(
cb: () => unknown,
config: string | RegExp | DeprecationConfig,
label?: string
): Promise<void> {
let origDeprecations = DEPRECATIONS_FOR_TEST;
let callback: (() => unknown) | null = null;

if (typeof cb !== 'function') {
config = cb;
callback = null;
} else {
callback = cb;
}

if (typeof config === 'string' || config instanceof RegExp) {
config = {
id: 'unknown-data-deprecation',
count: 1,
message: config,
until: '4.0',
};
}

if (callback) {
DEPRECATIONS_FOR_TEST = [];
let result = callback();
if (isThenable(result)) {
await result;
}
}

let result = verifyDeprecation(config, label);
this.pushResult(result);
DEPRECATIONS_FOR_TEST = origDeprecations.concat(DEPRECATIONS_FOR_TEST);
};

QUnit.assert.expectNoDeprecation = async function(cb, label?: string) {
let origDeprecations = DEPRECATIONS_FOR_TEST;

if (cb) {
DEPRECATIONS_FOR_TEST = [];
let result = cb();
if (isThenable(result)) {
await result;
}
}

let result = verifyNoDeprecation(label);
this.pushResult(result);
DEPRECATIONS_FOR_TEST = origDeprecations.concat(DEPRECATIONS_FOR_TEST);
};
}
Loading

0 comments on commit 55cec65

Please sign in to comment.