From 55cec65de52f5c5c94be0340e3185dbbe3721e52 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Thu, 24 Oct 2019 20:39:26 +0200 Subject: [PATCH] [CHORE] adds infra for testing calls to Ember warn|deprecate|assert (#6626) * [CHORE] adds infra for testing calls to Ember warn|deprecate|assert * fix production tests * address feedback * feedback on labels * remove id checks --- package.json | 1 - packages/-ember-data/package.json | 1 - .../helpers/qunit-asserts/assert-assertion.ts | 90 ++++++++++ .../qunit-asserts/assert-deprecation.ts | 170 ++++++++++++++++++ .../helpers/qunit-asserts/assert-warning.ts | 170 ++++++++++++++++++ .../helpers/qunit-asserts/check-matcher.ts | 16 ++ .../tests/helpers/qunit-asserts/index.ts | 9 + .../qunit-asserts/utils/is-thenable.ts | 3 + .../inverse-relationship-load-test.js | 90 ++++++++-- packages/-ember-data/tests/test-helper.js | 3 + .../package.json | 1 - .../tests/integration/normalize-test.js | 2 +- .../tests/integration/push-payload-test.js | 2 +- packages/-test-infra/package.json | 1 + .../addon/-private/system/store/finders.js | 2 +- packages/store/types/qunit/index.d.ts | 20 ++- yarn.lock | 12 +- 17 files changed, 557 insertions(+), 36 deletions(-) create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/index.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts diff --git a/package.json b/package.json index 6a4e126d994..965c5dbc47d 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/-ember-data/package.json b/packages/-ember-data/package.json index c307a366002..381059842c0 100644 --- a/packages/-ember-data/package.json +++ b/packages/-ember-data/package.json @@ -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", diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts b/packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts new file mode 100644 index 00000000000..b65acedaf85 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts @@ -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 { + 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); + }; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts b/packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts new file mode 100644 index 00000000000..a695067a0bc --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts @@ -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 { + 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); + }; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts b/packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts new file mode 100644 index 00000000000..51f8022fa5d --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts @@ -0,0 +1,170 @@ +import QUnit from 'qunit'; +import { registerWarnHandler } from '@ember/debug'; +import { checkMatcher } from './check-matcher'; +import isThenable from './utils/is-thenable'; + +let HAS_REGISTERED = false; +let WARNINGS_FOR_TEST: FoundWarning[]; +let HANDLED_WARNINGS_FOR_TEST: FoundWarning[]; + +interface WarningConfig { + id: string; + count?: number; + until?: string; + message?: string | RegExp; + url?: string; +} +interface FoundWarning { + 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: FoundWarning[]; + expected: FoundWarning[]; + message: string; +} + +/** + * Returns a qunit assert result object which passes if the given warning + * `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 verifyWarning(config: WarningConfig, label?: string): AssertSomeResult { + // TODO optionally throw if `until` is the current version or older than current version + let matchedWarnings = WARNINGS_FOR_TEST.filter(warning => { + let isMatched = warning.options.id === config.id; + if (!isMatched && config.message) { + // TODO when we hit this we should throw an error in the near future + isMatched = checkMatcher(warning.message, config.message); + } + return isMatched; + }); + WARNINGS_FOR_TEST = WARNINGS_FOR_TEST.filter(warning => { + matchedWarnings.indexOf(warning) === -1; + }); + HANDLED_WARNINGS_FOR_TEST.push(...matchedWarnings); + + let expectedCount = typeof config.count === 'number' ? config.count : 1; + let passed = matchedWarnings.length === expectedCount; + + return { + result: passed, + actual: { id: config.id, count: matchedWarnings.length }, + expected: { id: config.id, count: expectedCount }, + message: + label || + `Expected ${expectedCount} warning${expectedCount === 1 ? '' : 's'} for ${config.id} during test, ${ + passed ? expectedCount : 'but ' + matchedWarnings.length + } warnings were found.`, + }; +} + +function verifyNoWarning(label?: string): AssertNoneResult { + const UNHANDLED_WARNINGS = WARNINGS_FOR_TEST; + WARNINGS_FOR_TEST = []; + + let warningStr = UNHANDLED_WARNINGS.reduce((a, b) => { + return `${a}${b.message}\n`; + }, ''); + + let passed = UNHANDLED_WARNINGS.length === 0; + + return { + result: passed, + actual: UNHANDLED_WARNINGS, + expected: [], + message: + label || + `Expected 0 warnings during test, ${ + passed ? '0' : 'but ' + UNHANDLED_WARNINGS.length + } warnings were found.\n${warningStr}`, + }; +} + +export function configureWarningHandler() { + if (HAS_REGISTERED === true) { + throw new Error(`Attempting to re-register the assert-warning handler`); + } + HAS_REGISTERED = true; + + QUnit.testStart(function() { + WARNINGS_FOR_TEST = []; + HANDLED_WARNINGS_FOR_TEST = []; + }); + + registerWarnHandler(function(message, options /*, next*/) { + if (WARNINGS_FOR_TEST) { + WARNINGS_FOR_TEST.push({ message, options }); + } + // we do not call next to avoid spamming the console + }); + + QUnit.assert.expectWarning = async function( + cb: () => unknown, + config: string | RegExp | WarningConfig, + label?: string + ): Promise { + let origWarnings = WARNINGS_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-warning', + count: 1, + message: config, + until: '4.0', + }; + } + + if (callback) { + WARNINGS_FOR_TEST = []; + let result = callback(); + if (isThenable(result)) { + await result; + } + } + + let result = verifyWarning(config, label); + this.pushResult(result); + WARNINGS_FOR_TEST = origWarnings.concat(WARNINGS_FOR_TEST); + }; + + QUnit.assert.expectNoWarning = async function(cb, label?: string) { + let origWarnings = WARNINGS_FOR_TEST; + + if (cb) { + WARNINGS_FOR_TEST = []; + let result = cb(); + if (isThenable(result)) { + await result; + } + } + + let result = verifyNoWarning(label); + this.pushResult(result); + WARNINGS_FOR_TEST = origWarnings.concat(WARNINGS_FOR_TEST); + }; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts b/packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts new file mode 100644 index 00000000000..0a32e455482 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts @@ -0,0 +1,16 @@ +function includes(message, search) { + return message.includes ? message.includes(search) : message.indexOf(search) !== -1; +} + +export function checkMatcher(message, matcher) { + if (typeof matcher === 'string') { + return includes(message, matcher); + } else if (matcher instanceof RegExp) { + return !!message.match(matcher); + } else if (matcher) { + throw new Error(`Assert helpers can only match Strings and RegExps. "${typeof matcher}" was provided.`); + } + + // No matcher always returns true. Makes the code easier elsewhere. + return true; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/index.ts b/packages/-ember-data/tests/helpers/qunit-asserts/index.ts new file mode 100644 index 00000000000..8993fa5e150 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/index.ts @@ -0,0 +1,9 @@ +import { configureAssertionHandler } from './assert-assertion'; +import { configureDeprecationHandler } from './assert-deprecation'; +import { configureWarningHandler } from './assert-warning'; + +export default function configureAsserts() { + configureAssertionHandler(); + configureDeprecationHandler(); + configureWarningHandler(); +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts b/packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts new file mode 100644 index 00000000000..da0404e8a70 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts @@ -0,0 +1,3 @@ +export default function isThenable(obj: unknown): boolean { + return typeof obj === 'object' && obj !== null && 'then' in obj; +} diff --git a/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js b/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js index 9c58a4d114e..615dd682871 100644 --- a/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js +++ b/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js @@ -1523,7 +1523,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1629,7 +1632,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1729,7 +1735,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1829,7 +1838,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1918,7 +1930,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); @@ -2010,7 +2025,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = store.peekRecord('dog', '1'); @@ -2100,7 +2118,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); @@ -2190,7 +2211,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); @@ -2285,7 +2309,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2370,7 +2397,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2450,7 +2480,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2530,7 +2563,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2644,7 +2680,10 @@ module('inverse relationship load test', function(hooks) { let person1Dogs = await person1.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person1.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -2817,7 +2856,10 @@ module('inverse relationship load test', function(hooks) { let person1Dogs = await person1.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person1.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -2971,7 +3013,10 @@ module('inverse relationship load test', function(hooks) { await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -3090,7 +3135,10 @@ module('inverse relationship load test', function(hooks) { await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -3209,7 +3257,10 @@ module('inverse relationship load test', function(hooks) { let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -3327,7 +3378,10 @@ module('inverse relationship load test', function(hooks) { let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); diff --git a/packages/-ember-data/tests/test-helper.js b/packages/-ember-data/tests/test-helper.js index 6bde911fcfa..b87f4f8f0df 100644 --- a/packages/-ember-data/tests/test-helper.js +++ b/packages/-ember-data/tests/test-helper.js @@ -7,6 +7,9 @@ import { start } from 'ember-qunit'; import QUnit from 'qunit'; import DS from 'ember-data'; import { wait, asyncEqual, invokeAsync } from 'dummy/tests/helpers/async'; +import configureAsserts from 'dummy/tests/helpers/qunit-asserts'; + +configureAsserts(); setApplication(Application.create(config.APP)); diff --git a/packages/-serializer-encapsulation-test-app/package.json b/packages/-serializer-encapsulation-test-app/package.json index c1363e9f245..3b65ef41b96 100644 --- a/packages/-serializer-encapsulation-test-app/package.json +++ b/packages/-serializer-encapsulation-test-app/package.json @@ -38,7 +38,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", "eslint": "^6.5.1", diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js b/packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js index 9de120f7c12..144e3d0a52c 100644 --- a/packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js +++ b/packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js @@ -83,7 +83,7 @@ module('integration/serializer - normalize method forwards to Serializer#normali const store = this.owner.lookup('service:store'); - assert.expectAssertion(() => { + assert.throws(() => { store.normalize('person', { id: '1', type: 'person', diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js b/packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js index 488f80ddc6b..cb397fa9ab0 100644 --- a/packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js +++ b/packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js @@ -90,7 +90,7 @@ module('integration/push-payload - pushPayload method forwards to Serializer#pus const store = this.owner.lookup('service:store'); - assert.expectAssertion(() => { + assert.throws(() => { store.pushPayload('person', { data: { id: '1', diff --git a/packages/-test-infra/package.json b/packages/-test-infra/package.json index 127b35733d0..67afb35ed32 100644 --- a/packages/-test-infra/package.json +++ b/packages/-test-infra/package.json @@ -1,6 +1,7 @@ { "name": "@ember-data/-test-infra", "version": "3.15.0-alpha.1", + "private": true, "description": "The default blueprint for ember-data private packages.", "keywords": [], "repository": "", diff --git a/packages/store/addon/-private/system/store/finders.js b/packages/store/addon/-private/system/store/finders.js index 5f91898f5cd..16194b02d2b 100644 --- a/packages/store/addon/-private/system/store/finders.js +++ b/packages/store/addon/-private/system/store/finders.js @@ -178,7 +178,7 @@ function ensureRelationshipIsSetToParent(payload, parentInternalModel, store, pa let expectedModel = Ember.inspect(parentInternalModel); let got = Ember.inspect(relationshipData); let prefix = typeof index === 'number' ? `data[${index}]` : `data`; - let path = `${prefix}.relationships.${inverse}.data`; + let path = `${prefix}.relationships.${inverseKey}.data`; let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null; let relationshipFetched = `${Ember.inspect(parentInternalModel)}.${parentRelationship.kind}("${ parentRelationship.name diff --git a/packages/store/types/qunit/index.d.ts b/packages/store/types/qunit/index.d.ts index 55a51047435..4e567630e29 100644 --- a/packages/store/types/qunit/index.d.ts +++ b/packages/store/types/qunit/index.d.ts @@ -3,17 +3,33 @@ interface DeprecationConfig { count?: number; until: string; message?: string; + url?: string; +} +interface WarningConfig { + id: string; + count?: number; + until?: string; + message?: string; + url?: string; } interface Assert { - expectDeprecation(callback: () => unknown, options: DeprecationConfig | string): Promise; + expectDeprecation(callback: () => unknown, options: DeprecationConfig | string | RegExp): Promise; expectNoDeprecation(callback: () => unknown): Promise; + expectWarning(callback: () => unknown, options: WarningConfig | string | RegExp): Promise; + expectNoWarning(callback: () => unknown): Promise; + expectAssertion(callback: () => unknown, matcher: string | RegExp): Promise; + expectNoAssertion(callback: () => unknown): Promise; } declare namespace QUnit { export interface Assert { - expectDeprecation(callback: () => unknown, options: DeprecationConfig | string): Promise; + expectDeprecation(callback: () => unknown, options: DeprecationConfig | string | RegExp): Promise; expectNoDeprecation(callback: () => unknown): Promise; + expectWarning(callback: () => unknown, options: WarningConfig | string | RegExp): Promise; + expectNoWarning(callback: () => unknown): Promise; + expectAssertion(callback: () => unknown, matcher: string | RegExp): Promise; + expectNoAssertion(callback: () => unknown): Promise; } } diff --git a/yarn.lock b/yarn.lock index 929f4de0c70..d30d1f9b583 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3688,7 +3688,7 @@ broccoli-file-creator@^2.1.1: broccoli-plugin "^1.1.0" mkdirp "^0.5.1" -broccoli-filter@^1.0.1, broccoli-filter@^1.2.2, broccoli-filter@^1.2.3: +broccoli-filter@^1.2.2, broccoli-filter@^1.2.3: version "1.3.0" resolved "https://registry.npmjs.org/broccoli-filter/-/broccoli-filter-1.3.0.tgz#71e3a8e32a17f309e12261919c5b1006d6766de6" integrity sha512-VXJXw7eBfG82CFxaBDjYmyN7V72D4In2zwLVQJd/h3mBfF3CMdRTsv2L20lmRTtCv1sAHcB+LgMso90e/KYiLw== @@ -5744,7 +5744,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0: resolved "https://registry.npmjs.org/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.0.tgz#de3baedd093163b6c2461f95964888c1676325ac" integrity sha512-Zr4my8Xn+CzO0gIuFNXji0eTRml5AxZUTDQz/wsNJ5AJAtyFWCY4QtKdoELNNbiCVGt1lq5yLiwTm4scGKu6xA== -ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.12.0, ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.8.2, ember-cli-babel@^6.9.0: +ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.12.0, ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.8.2: version "6.18.0" resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz#3f6435fd275172edeff2b634ee7b29ce74318957" integrity sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA== @@ -6307,14 +6307,6 @@ ember-maybe-import-regenerator@^0.1.6: ember-cli-babel "^6.0.0-beta.4" regenerator-runtime "^0.9.5" -ember-qunit-assert-helpers@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/ember-qunit-assert-helpers/-/ember-qunit-assert-helpers-0.2.2.tgz#6fec8a33fd0d2c3fb6202f849291a309581727a4" - integrity sha512-P5eAqD753+p/qEeBi6OGpl2EzRxx8O9dUnr6HgyxU9fqQsSNQkJNGZ+ajbtePI8oMDGm+X7uOnf1+BgQ7eJ7qg== - dependencies: - broccoli-filter "^1.0.1" - ember-cli-babel "^6.9.0" - ember-qunit@^4.5.1: version "4.5.1" resolved "https://registry.npmjs.org/ember-qunit/-/ember-qunit-4.5.1.tgz#dc4b0a794fbeb6702a02f28bf19091de0f90fd5a"