diff --git a/.eslintignore b/.eslintignore index 68b8560b4a8..3956d17380d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -12,7 +12,7 @@ lib/highlight_js/ plugins/**/lib/javascripts/locale public/ vendor/ -app/assets/javascripts/discourse/tests/test_helper.js +app/assets/javascripts/discourse/tests/test-boot-rails.js app/assets/javascripts/discourse/tests/fixtures node_modules/ dist/ diff --git a/.prettierignore b/.prettierignore index 3884169675c..217c164e17c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -20,7 +20,7 @@ lib/highlight_js/ plugins/**/lib/javascripts/locale public/ vendor/ -app/assets/javascripts/discourse/tests/test_helper.js +app/assets/javascripts/discourse/tests/test-boot-rails.js app/assets/javascripts/discourse/tests/fixtures node_modules/ dist/ diff --git a/app/assets/javascripts/discourse-common/addon/lib/debounce.js b/app/assets/javascripts/discourse-common/addon/lib/debounce.js index 5e30864574f..dcd2693b78c 100644 --- a/app/assets/javascripts/discourse-common/addon/lib/debounce.js +++ b/app/assets/javascripts/discourse-common/addon/lib/debounce.js @@ -11,7 +11,9 @@ let testingFunc = isLegacyEmber() ? run : next; export default function () { if (isTesting()) { - return testingFunc(...arguments); + // Don't include the time argument (in ms) + let args = [].slice.call(arguments, 0, -1); + return testingFunc.apply(void 0, args); } else { return debounce(...arguments); } diff --git a/app/assets/javascripts/discourse/ember-cli-build.js b/app/assets/javascripts/discourse/ember-cli-build.js index 5125e7e08e5..602f51f189b 100644 --- a/app/assets/javascripts/discourse/ember-cli-build.js +++ b/app/assets/javascripts/discourse/ember-cli-build.js @@ -37,8 +37,66 @@ module.exports = function (defaults) { // We don't use SRI in Rails. Disable here to match: enabled: false, }, + + "ember-cli-terser": { + enabled: true, + exclude: [ + "**/test-*.js", + "**/core-tests*.js", + "**/highlightjs/*", + "**/javascripts/*", + ], + }, + + // We need to build tests in prod for theme tests + tests: true, }); + // Patching a private method is not great, but there's no other way for us to tell + // Ember CLI that we want the tests alone in a package without helpers/fixtures, since + // we re-use those in the theme tests. + app._defaultPackager.packageApplicationTests = function (tree) { + let appTestTrees = [] + .concat( + this.packageEmberCliInternalFiles(), + this.packageTestApplicationConfig(), + tree + ) + .filter(Boolean); + + appTestTrees = mergeTrees(appTestTrees, { + overwrite: true, + annotation: "TreeMerger (appTestTrees)", + }); + + let tests = concat(appTestTrees, { + inputFiles: [ + "**/tests/acceptance/*.js", + "**/tests/integration/*.js", + "**tests/unit/*.js", + ], + headerFiles: ["vendor/ember-cli/tests-prefix.js"], + footerFiles: ["vendor/ember-cli/app-config.js"], + outputFile: "/assets/core-tests.js", + annotation: "Concat: Core Tests", + sourceMapConfig: false, + }); + + let testHelpers = concat(appTestTrees, { + inputFiles: [ + "**/tests/test-boot-ember-cli.js", + "**/tests/helpers/**/*.js", + "**/tests/fixtures/**/*.js", + "**/tests/setup-tests.js", + ], + outputFile: "/assets/test-helpers.js", + annotation: "Concat: Test Helpers", + sourceMapConfig: false, + }); + + return mergeTrees([tests, testHelpers]); + }; + // WARNING: We should only import scripts here if they are not in NPM. // For example: our very specific version of bootstrap-modal. app.import(vendorJs + "bootbox.js"); diff --git a/app/assets/javascripts/discourse/package.json b/app/assets/javascripts/discourse/package.json index 32b109253a9..056a33e0880 100644 --- a/app/assets/javascripts/discourse/package.json +++ b/app/assets/javascripts/discourse/package.json @@ -34,7 +34,7 @@ "discourse-common": "^1.0.0", "discourse-hbr": "^1.0.0", "discourse-widget-hbs": "^1.0.0", - "ember-auto-import": "^1.10.1", + "ember-auto-import": "^1.12.0", "ember-buffered-proxy": "^2.0.0-beta.0", "ember-cli": "~3.25.3", "ember-cli-app-version": "^4.0.0", diff --git a/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js new file mode 100644 index 00000000000..8f46890eb42 --- /dev/null +++ b/app/assets/javascripts/discourse/public/assets/scripts/discourse-test-listen-boot.js @@ -0,0 +1,4 @@ +document.write( + "" +); +require('discourse/tests/test-boot-ember-cli'); diff --git a/app/assets/javascripts/discourse/tests/plugin_tests.js.erb b/app/assets/javascripts/discourse/tests/active-plugins.js.erb similarity index 53% rename from app/assets/javascripts/discourse/tests/plugin_tests.js.erb rename to app/assets/javascripts/discourse/tests/active-plugins.js.erb index 0bb267961df..6b2958541e9 100644 --- a/app/assets/javascripts/discourse/tests/plugin_tests.js.erb +++ b/app/assets/javascripts/discourse/tests/active-plugins.js.erb @@ -8,13 +8,4 @@ require_asset(f) end end - - Discourse.plugins.each do |p| - root_path = "#{File.dirname(p.path)}/test/javascripts" - - to_glob = [root_path + '/**/**.es6'] - to_glob << (root_path + '/**/**.js') if p.transpile_js - - Dir.glob(to_glob) { |f| require_asset(f) } - end %> diff --git a/app/assets/javascripts/discourse/tests/core_plugins_tests.js b/app/assets/javascripts/discourse/tests/core-tests.js similarity index 75% rename from app/assets/javascripts/discourse/tests/core_plugins_tests.js rename to app/assets/javascripts/discourse/tests/core-tests.js index f9c99ce034e..1890b65888e 100644 --- a/app/assets/javascripts/discourse/tests/core_plugins_tests.js +++ b/app/assets/javascripts/discourse/tests/core-tests.js @@ -1,4 +1,3 @@ //= require_tree ./acceptance //= require_tree ./integration //= require_tree ./unit -//= require ./plugin_tests diff --git a/app/assets/javascripts/discourse/tests/index.html b/app/assets/javascripts/discourse/tests/index.html index 34c33c48e40..1c9ac2bb559 100644 --- a/app/assets/javascripts/discourse/tests/index.html +++ b/app/assets/javascripts/discourse/tests/index.html @@ -50,9 +50,14 @@ - + - + + + + {{content-for "body-footer"}} diff --git a/app/assets/javascripts/discourse/tests/plugin-tests.js.erb b/app/assets/javascripts/discourse/tests/plugin-tests.js.erb new file mode 100644 index 00000000000..f2b38319a4a --- /dev/null +++ b/app/assets/javascripts/discourse/tests/plugin-tests.js.erb @@ -0,0 +1,10 @@ +<% + Discourse.plugins.each do |p| + root_path = "#{File.dirname(p.path)}/test/javascripts" + + to_glob = [root_path + '/**/**.es6'] + to_glob << (root_path + '/**/**.js') if p.transpile_js + + Dir.glob(to_glob) { |f| require_asset(f) } + end +%> diff --git a/app/assets/javascripts/discourse/tests/test-helper.js b/app/assets/javascripts/discourse/tests/test-boot-ember-cli.js similarity index 96% rename from app/assets/javascripts/discourse/tests/test-helper.js rename to app/assets/javascripts/discourse/tests/test-boot-ember-cli.js index ffb266b9724..cfbc0b9ff8c 100644 --- a/app/assets/javascripts/discourse/tests/test-helper.js +++ b/app/assets/javascripts/discourse/tests/test-boot-ember-cli.js @@ -34,3 +34,4 @@ document.addEventListener("discourse-booted", () => { setupEmberOnerrorValidation: !skippingCore, }); }); +window.EmberENV.TESTS_FILE_LOADED = true; diff --git a/app/assets/javascripts/discourse/tests/theme_qunit_helper.js b/app/assets/javascripts/discourse/tests/test-helpers-rails.js similarity index 82% rename from app/assets/javascripts/discourse/tests/theme_qunit_helper.js rename to app/assets/javascripts/discourse/tests/test-helpers-rails.js index a9c60c90f9e..71bb2c44530 100644 --- a/app/assets/javascripts/discourse/tests/theme_qunit_helper.js +++ b/app/assets/javascripts/discourse/tests/test-helpers-rails.js @@ -3,4 +3,3 @@ //= require_tree ./helpers //= require_tree ./fixtures //= require ./setup-tests -//= require test-shims diff --git a/app/assets/javascripts/discourse/tests/theme_qunit_tests_vendor.js b/app/assets/javascripts/discourse/tests/test-support-rails.js similarity index 69% rename from app/assets/javascripts/discourse/tests/theme_qunit_tests_vendor.js rename to app/assets/javascripts/discourse/tests/test-support-rails.js index 3c6865b1e04..4f916572efc 100644 --- a/app/assets/javascripts/discourse/tests/theme_qunit_tests_vendor.js +++ b/app/assets/javascripts/discourse/tests/test-support-rails.js @@ -5,11 +5,10 @@ //= require fake_xml_http_request //= require route-recognizer //= require pretender - -// These are not loaded in prod or development -// But we need them for testing handlebars templates in qunit -//= require handlebars -//= require ember-template-compiler - //= require sinon //= require break_string +//= require test-shims +//= require jquery.magnific-popup.min.js +//= require handlebars +//= require ember-template-compiler +//= require markdown-it-bundle diff --git a/app/assets/javascripts/discourse/tests/test_helper.js b/app/assets/javascripts/discourse/tests/test_helper.js deleted file mode 100644 index 028f3a5167f..00000000000 --- a/app/assets/javascripts/discourse/tests/test_helper.js +++ /dev/null @@ -1,38 +0,0 @@ -// discourse-skip-module - -//= require env -//= require jquery.debug -//= require jquery.ui.widget -//= require ember.debug -//= require message-bus -//= require qunit -//= require ember-qunit -//= require fake_xml_http_request -//= require route-recognizer -//= require pretender -//= require locales/i18n -//= require locales/en -//= require discourse-loader - -// Our base application -//= require vendor -//= require discourse-shims -//= require markdown-it-bundle -//= require application -//= require admin - -// These are not loaded in prod or development -// But we need them for testing handlebars templates in qunit -//= require handlebars -//= require ember-template-compiler - -// Test helpers -//= require sinon -//= require_tree ./helpers -//= require break_string - -//= require_tree ./fixtures - -//= require ./setup-tests -//= require test-shims -//= require jquery.magnific-popup.min.js diff --git a/app/assets/javascripts/discourse/tests/theme_qunit_vendor.js b/app/assets/javascripts/discourse/tests/theme_qunit_vendor.js deleted file mode 100644 index 9eb492b917d..00000000000 --- a/app/assets/javascripts/discourse/tests/theme_qunit_vendor.js +++ /dev/null @@ -1,30 +0,0 @@ -// This bundle contains the same dependencies as app/assets/javascripts/vendor.js -// minus ember_jquery. -// ember_jquery doesn't work with theme tests in production because it -// contains production builds of Ember and jQuery, so we have a separate bundle -// caled theme_qunit_ember_jquery which contains a debug build for Ember and jQuery. -// We don't put theme_qunit_ember_jquery in this bundle because it would make the -// bundle too big and cause OOM exceptions during rebuilds for self-hosters on -// low-end machines. - -//= require logster - -//= require template_include.js - -//= require message-bus -//= require jquery.ui.widget.js -//= require Markdown.Converter.js -//= require bootbox.js -//= require popper.js -//= require bootstrap-modal.js -//= require caret_position -//= require jquery.sortable.js -//= require lodash.js -//= require itsatrap.js -//= require rsvp.js -//= require uppy.js -//= require buffered-proxy -//= require virtual-dom -//= require virtual-dom-amd -//= require discourse-shims -//= require pretty-text-bundle diff --git a/app/assets/javascripts/yarn.lock b/app/assets/javascripts/yarn.lock index 691b5eea85e..80a80588c24 100644 --- a/app/assets/javascripts/yarn.lock +++ b/app/assets/javascripts/yarn.lock @@ -4810,6 +4810,41 @@ ember-auto-import@^1.10.1, ember-auto-import@^1.5.3: walk-sync "^0.3.3" webpack "^4.43.0" +ember-auto-import@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.12.0.tgz#52246b04891090e2608244e65c4c6af7710df12b" + integrity sha512-fzMGnyHGfUNFHchpLbJ98Vs/c5H2wZBMR9r/XwW+WOWPisZDGLUPPyhJQsSREPoUQ+o8GvyLaD/rkrKqW8bmgw== + dependencies: + "@babel/core" "^7.1.6" + "@babel/preset-env" "^7.10.2" + "@babel/traverse" "^7.1.6" + "@babel/types" "^7.1.6" + "@embroider/core" "^0.33.0" + babel-core "^6.26.3" + babel-loader "^8.0.6" + babel-plugin-syntax-dynamic-import "^6.18.0" + babylon "^6.18.0" + broccoli-debug "^0.6.4" + broccoli-node-api "^1.7.0" + broccoli-plugin "^4.0.0" + broccoli-source "^3.0.0" + debug "^3.1.0" + ember-cli-babel "^7.0.0" + enhanced-resolve "^4.0.0" + fs-extra "^6.0.1" + fs-tree-diff "^2.0.0" + handlebars "^4.3.1" + js-string-escape "^1.0.1" + lodash "^4.17.19" + mkdirp "^0.5.1" + resolve-package-path "^3.1.0" + rimraf "^2.6.2" + semver "^7.3.4" + symlink-or-copy "^1.2.0" + typescript-memoize "^1.0.0-alpha.3" + walk-sync "^0.3.3" + webpack "^4.43.0" + ember-buffered-proxy@^2.0.0-beta.0: version "2.0.0-beta.0" resolved "https://registry.yarnpkg.com/ember-buffered-proxy/-/ember-buffered-proxy-2.0.0-beta.0.tgz#65be4e2d0dcf40a5a2dab548c84a21aa332555a2" diff --git a/app/controllers/bootstrap_controller.rb b/app/controllers/bootstrap_controller.rb index 811058d7526..af3919e8285 100644 --- a/app/controllers/bootstrap_controller.rb +++ b/app/controllers/bootstrap_controller.rb @@ -69,7 +69,7 @@ class BootstrapController < ApplicationController locale_script: locale, stylesheets: @stylesheets, plugin_js: plugin_js, - plugin_test_js: [script_asset_path("plugin_tests")], + plugin_test_js: [script_asset_path("plugin-tests")], setup_data: client_side_setup_data, preloaded: @preloaded, html: create_html, diff --git a/app/controllers/qunit_controller.rb b/app/controllers/qunit_controller.rb index 309d2af8b20..7e196d72369 100644 --- a/app/controllers/qunit_controller.rb +++ b/app/controllers/qunit_controller.rb @@ -8,15 +8,28 @@ class QunitController < ApplicationController } layout false + def is_ember_cli_proxy? + request.headers["HTTP_X_DISCOURSE_EMBER_CLI"] == "true" + end + # only used in test / dev def index - raise Discourse::NotFound.new if request.headers["HTTP_X_DISCOURSE_EMBER_CLI"] == "true" + raise Discourse::NotFound.new if is_ember_cli_proxy? raise Discourse::InvalidAccess.new if Rails.env.production? end def theme raise Discourse::NotFound.new if !can_see_theme_qunit? + @is_proxied = is_ember_cli_proxy? + @legacy_ember = Rails.env.development? && !@is_proxied + + # In production mode all bundles use `application` + @app_bundle = "application" + if Rails.env.development? && @is_proxied + @app_bundle = "discourse" + end + param_key = nil @suggested_themes = nil if (id = get_param(:id)).present? diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c5a96271231..f232bd5b7e5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -13,9 +13,11 @@ module ApplicationHelper @extra_body_classes ||= Set.new end - def discourse_config_environment + def discourse_config_environment(testing: false) + # TODO: Can this come from Ember CLI somehow? - { modulePrefix: "discourse", + config = { + modulePrefix: "discourse", environment: Rails.env, rootURL: Discourse.base_path, locationType: "auto", @@ -32,7 +34,16 @@ module ApplicationHelper version: "#{Discourse::VERSION::STRING} #{Discourse.git_version}", exportApplicationGlobal: true } - }.to_json + } + + if testing + config[:environment] = "test" + config[:locationType] = "none" + config[:APP][:autoboot] = false + config[:APP][:rootElement] = '#ember-testing' + end + + config.to_json end def google_universal_analytics_json(ua_domain_name = nil) diff --git a/app/helpers/qunit_helper.rb b/app/helpers/qunit_helper.rb index e0376a1ad26..029c4d04c97 100644 --- a/app/helpers/qunit_helper.rb +++ b/app/helpers/qunit_helper.rb @@ -1,6 +1,33 @@ # frozen_string_literal: true module QunitHelper + + def support_bundles + result = [] + if Rails.env.production? || @legacy_ember + result << preload_script("discourse/tests/test-support-rails") + result << preload_script("discourse/tests/test-helpers-rails") + else + result << preload_script("test-support") + result << preload_script("test-helpers") + end + result.join("\n").html_safe + end + + def boot_bundles + result = [] + if @legacy_ember + result << preload_script("discourse/tests/test_starter") + elsif @is_proxied + result << preload_script("scripts/discourse-test-listen-boot") + result << preload_script("scripts/discourse-boot") + else + result << preload_script("discourse-test-listen-boot") + result << preload_script("discourse-boot") + end + result.join("\n").html_safe + end + def theme_tests theme = Theme.find_by(id: request.env[:resolved_theme_id]) return "" if theme.blank? diff --git a/app/views/qunit/index.html.erb b/app/views/qunit/index.html.erb index 830e3d8bb50..9912387a2d7 100644 --- a/app/views/qunit/index.html.erb +++ b/app/views/qunit/index.html.erb @@ -5,8 +5,15 @@ <%= discourse_color_scheme_stylesheets %> <%= discourse_stylesheet_link_tag(:desktop, theme_id: nil) %> <%= discourse_stylesheet_link_tag(:test_helper, theme_id: nil) %> - <%= preload_script "discourse/tests/test_helper" %> - <%= preload_script "discourse/tests/core_plugins_tests" %> + <%= preload_script "locales/#{I18n.locale}" %> + <%= preload_script "vendor" %> + <%= preload_script "application" %> + <%= preload_script "admin" %> + <%= preload_script "discourse/tests/test-support-rails" %> + <%= preload_script "discourse/tests/test-helpers-rails" %> + <%= preload_script "discourse/tests/active-plugins" %> + <%= preload_script "discourse/tests/core-tests" %> + <%= preload_script "discourse/tests/plugin-tests" %> <%= preload_script "discourse/tests/test_starter" %> <%= csrf_meta_tags %> diff --git a/app/views/qunit/theme.html.erb b/app/views/qunit/theme.html.erb index 53752cc9a29..23db6bf4513 100644 --- a/app/views/qunit/theme.html.erb +++ b/app/views/qunit/theme.html.erb @@ -6,17 +6,12 @@ <%- if !@suggested_themes %> <%= discourse_stylesheet_link_tag(:desktop, theme_id: nil) %> <%= discourse_stylesheet_link_tag(:test_helper, theme_id: nil) %> - <%= preload_script "locales/en" %> - <%= preload_script "discourse/tests/theme_qunit_ember_jquery" %> - <%= preload_script "discourse/tests/theme_qunit_vendor" %> - <%= preload_script "discourse/tests/theme_qunit_tests_vendor" %> - <%= preload_script "markdown-it-bundle" %> - <%= preload_script "application" %> - <%- Discourse.find_plugin_js_assets(include_official: allow_plugins?, include_unofficial: allow_third_party_plugins?, request: request).each do |file| %> - <%= preload_script file %> - <%- end %> + <%= preload_script "locales/#{I18n.locale}" %> + <%= preload_script "vendor" %> + <%= preload_script @app_bundle %> <%= preload_script "admin" %> - <%= preload_script "discourse/tests/theme_qunit_helper" %> + <%= preload_script "discourse/tests/active-plugins" %> + <%= support_bundles %> <%= theme_translations_lookup %> <%= theme_js_lookup %> <%= theme_lookup("head_tag") %> @@ -24,7 +19,7 @@ <%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %> - <%= preload_script "discourse/tests/test_starter" %> + <%- else %>