From 82ee0bb8bef07f11098de467465dde5562c40b17 Mon Sep 17 00:00:00 2001 From: Gaurav Munjal Date: Wed, 4 Dec 2019 23:39:22 -0500 Subject: [PATCH] [CHORE] Cron job to check for external deprecations (#6844) * [CHORE] Move assert-all-deprecations to test-infra and apply to encapsulation apps * enable environment variable * find a way to generate a list of the encountered deprecations * add cron job * fix encapsulation tests * fix cron job? * Get cron job working Co-Authored-By: Chris Thoburn * address feedback --- .github/workflows/nightly.yml | 54 +++++++++++++++ packages/-ember-data/testem.js | 4 +- packages/-ember-data/tests/test-helper.js | 65 +++---------------- .../tests/test-helper.js | 3 + .../tests/test-helper.js | 6 ++ .../tests/test-helper.js | 6 ++ .../tests/test-helper.js | 6 ++ .../tests/test-helper.js | 6 ++ .../assert-all-deprecations.js | 62 ++++++++++++++++++ .../addon-test-support/async.js | 1 + .../addon-test-support/legacy.js | 27 ++++++++ .../testem/custom-qunit-adapter.js | 10 +++ packages/unpublished-test-infra/package.json | 4 +- .../src/testem/custom-dot-reporter.js | 21 ++++++ yarn.lock | 10 ++- 15 files changed, 226 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/nightly.yml create mode 100644 packages/unpublished-test-infra/addon-test-support/assert-all-deprecations.js create mode 100644 packages/unpublished-test-infra/addon-test-support/legacy.js create mode 100644 packages/unpublished-test-infra/addon-test-support/testem/custom-qunit-adapter.js create mode 100644 packages/unpublished-test-infra/src/testem/custom-dot-reporter.js diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 00000000000..4a3c6e484ae --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,54 @@ +name: 'Nightly' + +on: + schedule: + - cron: '* 14 * * *' # 14:00 in UTC is 6am PST + branches: + - master + +jobs: + test-all-deprecations: + strategy: + fail-fast: false + matrix: + scenario: [ember-beta, ember-canary] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install dependencies for master + run: yarn install + - name: Basic Tests + env: + CI: true + ASSERT_ALL_DEPRECATIONS: true + run: yarn test + - name: Encapsulation tests + env: + CI: true + ASSERT_ALL_DEPRECATIONS: true + run: yarn test:encapsulation + + test-all-deprecations-releases: + strategy: + fail-fast: false + matrix: + scenario: [ember-beta, ember-canary] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install dependencies for master + run: yarn install + - name: Basic Tests + env: + CI: true + ASSERT_ALL_DEPRECATIONS: true + run: yarn test:try-one ${{ matrix.scenario }} + diff --git a/packages/-ember-data/testem.js b/packages/-ember-data/testem.js index 40945172507..3fb0affae16 100644 --- a/packages/-ember-data/testem.js +++ b/packages/-ember-data/testem.js @@ -1,3 +1,5 @@ +const customDotReporter = require('@ember-data/unpublished-test-infra/src/testem/custom-dot-reporter'); + const TestIE = process.env.TEST_IE11; if (TestIE) { @@ -7,7 +9,7 @@ if (TestIE) { module.exports = { test_page: 'tests/index.html?hidepassed', disable_watching: true, - reporter: 'dot', + reporter: customDotReporter, launch_in_ci: TestIE ? ['IE'] : ['Chrome'], launch_in_dev: ['Chrome'], browser_start_timeout: 120, diff --git a/packages/-ember-data/tests/test-helper.js b/packages/-ember-data/tests/test-helper.js index d35ecd9d26a..031f6976e45 100644 --- a/packages/-ember-data/tests/test-helper.js +++ b/packages/-ember-data/tests/test-helper.js @@ -3,56 +3,29 @@ import config from '../config/environment'; import RSVP from 'rsvp'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; -import { DEBUG } from '@glimmer/env'; import QUnit from 'qunit'; -import { wait, asyncEqual, invokeAsync } from '@ember-data/unpublished-test-infra/test-support/async'; import configureAsserts from '@ember-data/unpublished-test-infra/test-support/qunit-asserts'; +import additionalLegacyAsserts from '@ember-data/unpublished-test-infra/test-support/legacy'; +import assertAllDeprecations from '@ember-data/unpublished-test-infra/test-support/assert-all-deprecations'; +import customQUnitAdapter from '@ember-data/unpublished-test-infra/test-support/testem/custom-qunit-adapter'; if (window.Promise === undefined) { window.Promise = RSVP.Promise; } configureAsserts(); +additionalLegacyAsserts(); setApplication(Application.create(config.APP)); -const { assert } = QUnit; +assertAllDeprecations(); -QUnit.begin(() => { - function assertAllDeprecations(assert) { - if (typeof assert.test.expected === 'number') { - assert.test.expected += 1; - } - assert.expectNoDeprecation(undefined, undefined, deprecation => { - // only assert EmberData deprecations - const id = deprecation.options.id.toLowerCase(); - const isEmberDataDeprecation = - id.includes('ds.') || - id.includes('emberdata') || - id.includes('ember-data') || - id.includes('mismatched-inverse-relationship-data-from-payload'); - - if (!isEmberDataDeprecation) { - // eslint-disable-next-line no-console - console.warn('Detected Non-Ember-Data Deprecation:', deprecation.message, deprecation.options.stacktrace); - } - - return isEmberDataDeprecation; - }); - } - // ensure we don't regress quietly - // this plays nicely with `expectDeprecation` - if (DEBUG) { - QUnit.config.modules.forEach(mod => { - const hooks = (mod.hooks.afterEach = mod.hooks.afterEach || []); - - if (mod.tests.length !== 0) { - hooks.unshift(assertAllDeprecations); - } - }); - } +if (window.Testem) { + window.Testem.useCustomAdapter(customQUnitAdapter); +} +QUnit.begin(function() { RSVP.configure('onerror', reason => { // only print error messages if they're exceptions; // otherwise, let a future turn of the event loop @@ -64,26 +37,6 @@ QUnit.begin(() => { }); }); -assert.wait = wait; -assert.asyncEqual = asyncEqual; -assert.invokeAsync = invokeAsync; -assert.assertClean = function(promise) { - return promise.then( - this.wait(record => { - this.equal(record.get('hasDirtyAttributes'), false, 'The record is now clean'); - return record; - }) - ); -}; - -assert.contains = function(array, item) { - this.ok(array.indexOf(item) !== -1, `array contains ${item}`); -}; - -assert.without = function(array, item) { - this.ok(array.indexOf(item) === -1, `array doesn't contain ${item}`); -}; - QUnit.config.testTimeout = 2000; QUnit.config.urlConfig.push({ id: 'enableoptionalfeatures', diff --git a/packages/unpublished-adapter-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-adapter-encapsulation-test-app/tests/test-helper.js index 00c05dc1857..06522723487 100644 --- a/packages/unpublished-adapter-encapsulation-test-app/tests/test-helper.js +++ b/packages/unpublished-adapter-encapsulation-test-app/tests/test-helper.js @@ -3,9 +3,12 @@ import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; import configureAsserts from '@ember-data/unpublished-test-infra/test-support/qunit-asserts'; +import assertAllDeprecations from '@ember-data/unpublished-test-infra/test-support/assert-all-deprecations'; configureAsserts(); setApplication(Application.create(config.APP)); +assertAllDeprecations(); + start(); diff --git a/packages/unpublished-debug-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-debug-encapsulation-test-app/tests/test-helper.js index 0382a848dd0..06522723487 100644 --- a/packages/unpublished-debug-encapsulation-test-app/tests/test-helper.js +++ b/packages/unpublished-debug-encapsulation-test-app/tests/test-helper.js @@ -2,7 +2,13 @@ import Application from '../app'; import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; +import configureAsserts from '@ember-data/unpublished-test-infra/test-support/qunit-asserts'; +import assertAllDeprecations from '@ember-data/unpublished-test-infra/test-support/assert-all-deprecations'; + +configureAsserts(); setApplication(Application.create(config.APP)); +assertAllDeprecations(); + start(); diff --git a/packages/unpublished-model-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-model-encapsulation-test-app/tests/test-helper.js index 0382a848dd0..06522723487 100644 --- a/packages/unpublished-model-encapsulation-test-app/tests/test-helper.js +++ b/packages/unpublished-model-encapsulation-test-app/tests/test-helper.js @@ -2,7 +2,13 @@ import Application from '../app'; import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; +import configureAsserts from '@ember-data/unpublished-test-infra/test-support/qunit-asserts'; +import assertAllDeprecations from '@ember-data/unpublished-test-infra/test-support/assert-all-deprecations'; + +configureAsserts(); setApplication(Application.create(config.APP)); +assertAllDeprecations(); + start(); diff --git a/packages/unpublished-record-data-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-record-data-encapsulation-test-app/tests/test-helper.js index 0382a848dd0..06522723487 100644 --- a/packages/unpublished-record-data-encapsulation-test-app/tests/test-helper.js +++ b/packages/unpublished-record-data-encapsulation-test-app/tests/test-helper.js @@ -2,7 +2,13 @@ import Application from '../app'; import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; +import configureAsserts from '@ember-data/unpublished-test-infra/test-support/qunit-asserts'; +import assertAllDeprecations from '@ember-data/unpublished-test-infra/test-support/assert-all-deprecations'; + +configureAsserts(); setApplication(Application.create(config.APP)); +assertAllDeprecations(); + start(); diff --git a/packages/unpublished-serializer-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-serializer-encapsulation-test-app/tests/test-helper.js index 0382a848dd0..06522723487 100644 --- a/packages/unpublished-serializer-encapsulation-test-app/tests/test-helper.js +++ b/packages/unpublished-serializer-encapsulation-test-app/tests/test-helper.js @@ -2,7 +2,13 @@ import Application from '../app'; import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; +import configureAsserts from '@ember-data/unpublished-test-infra/test-support/qunit-asserts'; +import assertAllDeprecations from '@ember-data/unpublished-test-infra/test-support/assert-all-deprecations'; + +configureAsserts(); setApplication(Application.create(config.APP)); +assertAllDeprecations(); + start(); diff --git a/packages/unpublished-test-infra/addon-test-support/assert-all-deprecations.js b/packages/unpublished-test-infra/addon-test-support/assert-all-deprecations.js new file mode 100644 index 00000000000..a1adf3d7177 --- /dev/null +++ b/packages/unpublished-test-infra/addon-test-support/assert-all-deprecations.js @@ -0,0 +1,62 @@ +/* eslint-disable no-console */ +import { DEBUG } from '@glimmer/env'; +import QUnit from 'qunit'; +import config from 'ember-get-config'; + +const { ASSERT_ALL_DEPRECATIONS } = config; + +const ALL_ASSERTED_DEPRECATIONS = {}; + +function pushDeprecation(deprecation) { + if (deprecation in ALL_ASSERTED_DEPRECATIONS) { + ALL_ASSERTED_DEPRECATIONS[deprecation]++; + } else { + ALL_ASSERTED_DEPRECATIONS[deprecation] = 1; + } +} + +export default function configureAssertAllDeprecations() { + QUnit.begin(() => { + function assertAllDeprecations(assert) { + if (typeof assert.test.expected === 'number') { + assert.test.expected += 1; + } + assert.expectNoDeprecation(undefined, undefined, deprecation => { + // only assert EmberData deprecations + const id = deprecation.options.id.toLowerCase(); + const isEmberDataDeprecation = + id.includes('ds.') || + id.includes('emberdata') || + id.includes('ember-data') || + id.includes('mismatched-inverse-relationship-data-from-payload'); + + if (!isEmberDataDeprecation) { + if (ASSERT_ALL_DEPRECATIONS) { + pushDeprecation((deprecation.options && deprecation.options.id) || deprecation); + } else { + console.warn('Detected Non-Ember-Data Deprecation:', deprecation.message, deprecation.options.stacktrace); + } + } + + return ASSERT_ALL_DEPRECATIONS ? true : isEmberDataDeprecation; + }); + } + // ensure we don't regress quietly + // this plays nicely with `expectDeprecation` + if (DEBUG) { + QUnit.config.modules.forEach(mod => { + const hooks = (mod.hooks.afterEach = mod.hooks.afterEach || []); + + if (mod.tests.length !== 0) { + hooks.unshift(assertAllDeprecations); + } + }); + } + }); + + QUnit.done(function() { + if (ASSERT_ALL_DEPRECATIONS) { + QUnit.config.deprecations = ALL_ASSERTED_DEPRECATIONS; + } + }); +} diff --git a/packages/unpublished-test-infra/addon-test-support/async.js b/packages/unpublished-test-infra/addon-test-support/async.js index ef6ead01d80..7f335d821db 100644 --- a/packages/unpublished-test-infra/addon-test-support/async.js +++ b/packages/unpublished-test-infra/addon-test-support/async.js @@ -1,6 +1,7 @@ import { all, resolve } from 'rsvp'; import { run } from '@ember/runloop'; +// Should not use these going forward, use async/await instead. export function wait(callback, timeout) { let done = this.async(); diff --git a/packages/unpublished-test-infra/addon-test-support/legacy.js b/packages/unpublished-test-infra/addon-test-support/legacy.js new file mode 100644 index 00000000000..1939956d9a5 --- /dev/null +++ b/packages/unpublished-test-infra/addon-test-support/legacy.js @@ -0,0 +1,27 @@ +import { wait, asyncEqual, invokeAsync } from './async'; +import QUnit from 'qunit'; + +const { assert } = QUnit; + +export default function additionalLegacyAsserts() { + assert.wait = wait; + assert.asyncEqual = asyncEqual; + assert.invokeAsync = invokeAsync; + + assert.assertClean = function(promise) { + return promise.then( + this.wait(record => { + this.equal(record.get('hasDirtyAttributes'), false, 'The record is now clean'); + return record; + }) + ); + }; + + assert.contains = function(array, item) { + this.ok(array.indexOf(item) !== -1, `array contains ${item}`); + }; + + assert.without = function(array, item) { + this.ok(array.indexOf(item) === -1, `array doesn't contain ${item}`); + }; +} diff --git a/packages/unpublished-test-infra/addon-test-support/testem/custom-qunit-adapter.js b/packages/unpublished-test-infra/addon-test-support/testem/custom-qunit-adapter.js new file mode 100644 index 00000000000..7aceee7c474 --- /dev/null +++ b/packages/unpublished-test-infra/addon-test-support/testem/custom-qunit-adapter.js @@ -0,0 +1,10 @@ +import QUnit from 'qunit'; + +export default function customQUnitAdapter(socket) { + QUnit.done(function() { + let deprecations = QUnit.config.deprecations; + console.log(deprecations); // eslint-disable-line no-console + + socket.emit('test-metadata', 'deprecations', deprecations); + }); +} diff --git a/packages/unpublished-test-infra/package.json b/packages/unpublished-test-infra/package.json index 594d8eea6fa..1a24db000d9 100644 --- a/packages/unpublished-test-infra/package.json +++ b/packages/unpublished-test-infra/package.json @@ -20,9 +20,11 @@ "ember-cli-babel": "^7.12.0", "ember-cli-blueprint-test-helpers": "^0.19.1", "ember-cli-typescript": "^3.1.1", + "ember-get-config": "^0.2.4", "ember-qunit": "^4.6.0", "qunit": "^2.9.3", - "rsvp": "^4.8.5" + "rsvp": "^4.8.5", + "testem": "^2.17.0" }, "engines": { "node": ">= 8.0.0" diff --git a/packages/unpublished-test-infra/src/testem/custom-dot-reporter.js b/packages/unpublished-test-infra/src/testem/custom-dot-reporter.js new file mode 100644 index 00000000000..6b0920ed241 --- /dev/null +++ b/packages/unpublished-test-infra/src/testem/custom-dot-reporter.js @@ -0,0 +1,21 @@ +let DotReporter = require('testem/lib/reporters/dot_reporter'); + +class CustomDotReporter extends DotReporter { + finish() { + super.finish(); + + if (process.env.ASSERT_ALL_DEPRECATIONS === 'true') { + this.out.write('\n============ Deprecations ============\n'); + this.out.write(JSON.stringify(this.deprecations, null, 2) + '\n'); + this.out.write('======================================\n'); + } + } + + reportMetadata(tag, metadata) { + if (tag === 'deprecations') { + this.deprecations = metadata; + } + } +} + +module.exports = CustomDotReporter; diff --git a/yarn.lock b/yarn.lock index 08d03b62fa0..f32e6e21225 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6158,7 +6158,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.12.0, ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1: +ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.12.0, ember-cli-babel@^6.16.0, ember-cli-babel@^6.3.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1: version "6.18.0" resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz#3f6435fd275172edeff2b634ee7b29ce74318957" integrity sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA== @@ -6686,6 +6686,14 @@ ember-export-application-global@^2.0.1: resolved "https://registry.npmjs.org/ember-export-application-global/-/ember-export-application-global-2.0.1.tgz#b120a70e322ab208defc9e2daebe8d0dfc2dcd46" integrity sha512-B7wiurPgsxsSGzJuPFkpBWnaeuCu2PGpG2BjyrfA1VcL7//o+5RSnZqiCEY326y7qmxb2GoCgo0ft03KBU0rRw== +ember-get-config@^0.2.4: + version "0.2.4" + resolved "https://registry.npmjs.org/ember-get-config/-/ember-get-config-0.2.4.tgz#118492a2a03d73e46004ed777928942021fe1ecd" + integrity sha1-EYSSoqA9c+RgBO13eSiUICH+Hs0= + dependencies: + broccoli-file-creator "^1.1.1" + ember-cli-babel "^6.3.0" + ember-inflector@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/ember-inflector/-/ember-inflector-3.0.1.tgz#04be6df4d7e4000f6d6bd70787cdc995f77be4ab"