mirror of
https://github.com/discourse/discourse.git
synced 2025-05-28 01:56:58 +08:00
FEATURE: Introduce theme/component QUnit tests (#12517)
This commit allows themes and theme components to have QUnit tests. To add tests to your theme/component, create a top-level directory in your theme and name it `test`, and Discourse will save all the files in that directory (and its sub-directories) as "tests files" in the database. While tests files/directories are not required to be organized in a specific way, we recommend that you follow Discourse core's tests [structure](https://github.com/discourse/discourse/tree/master/app/assets/javascripts/discourse/tests). Writing theme tests should be identical to writing plugins or core tests; all the `import` statements and APIs that you see in core (or plugins) to define/setup tests should just work in themes. You do need a working Discourse install to run theme tests, and you have 2 ways to run theme tests: * In the browser at the `/qunit` route. `/qunit` will run tests of all active themes/components as well as core and plugins. The `/qunit` now accepts a `theme_name` or `theme_url` params that you can use to run tests of a specific theme/component like so: `/qunit?theme_name=<your_theme_name>`. * In the command line using the `themes:qunit` rake task. This take is meant to run tests of a single theme/component so you need to provide it with a theme name or URL like so: `bundle exec rake themes:qunit[name=<theme_name>]` or `bundle exec rake themes:qunit[url=<theme_url>]`. There are some refactors to internal code that's responsible for processing themes/components in Discourse, most notably: * `<script type="text/discourse-plugin">` tags are automatically converted to modules. * The `theme-settings` service is removed in favor of a simple `lib` file responsible for managing theme settings. This was done to allow us to register/lookup theme settings very early in our Ember app lifecycle and because there was no reason for it to be an Ember service. These refactors should 100% backward compatible and invisible to theme developers.
This commit is contained in:
@ -276,7 +276,7 @@ HTML
|
||||
def transpile(html)
|
||||
f = ThemeField.create!(target_id: Theme.targets[:mobile], theme_id: 1, name: "after_header", value: html)
|
||||
f.ensure_baked!
|
||||
[f.value_baked, f.javascript_cache]
|
||||
[f.value_baked, f.javascript_cache, f]
|
||||
end
|
||||
|
||||
it "transpiles ES6 code" do
|
||||
@ -286,10 +286,21 @@ HTML
|
||||
</script>
|
||||
HTML
|
||||
|
||||
baked, javascript_cache = transpile(html)
|
||||
baked, javascript_cache, field = transpile(html)
|
||||
expect(baked).to include(javascript_cache.url)
|
||||
expect(javascript_cache.content).to include('var x = 1;')
|
||||
expect(javascript_cache.content).to include("_registerPluginCode('0.1'")
|
||||
|
||||
expect(javascript_cache.content).to include("if ('define' in window) {")
|
||||
expect(javascript_cache.content).to include(
|
||||
"define(\"discourse/theme-#{field.theme_id}/initializers/theme-field-#{field.id}-mobile-html-script-1\""
|
||||
)
|
||||
expect(javascript_cache.content).to include(
|
||||
"settings = require(\"discourse/lib/theme-settings-store\").getObjectForTheme(#{field.theme_id});"
|
||||
)
|
||||
expect(javascript_cache.content).to include("name: \"theme-field-#{field.id}-mobile-html-script-1\",")
|
||||
expect(javascript_cache.content).to include("after: \"inject-objects\",")
|
||||
expect(javascript_cache.content).to include("(0, _pluginApi.withPluginApi)(\"0.1\", function (api) {")
|
||||
expect(javascript_cache.content).to include("var x = 1;")
|
||||
expect(javascript_cache.content).to include("(0, _utilities.rescueThemeError)(__theme_name__, err, api);")
|
||||
end
|
||||
|
||||
it "wraps constants calls in a readOnlyError function" do
|
||||
@ -369,83 +380,32 @@ HTML
|
||||
theme_field = theme.set_field(target: :common, name: :after_header, value: '<script type="text/discourse-plugin" version="1.0">alert(settings.name); let a = ()=>{};</script>')
|
||||
theme.save!
|
||||
|
||||
transpiled = <<~HTML
|
||||
(function() {
|
||||
if ('Discourse' in window && Discourse.__container__) {
|
||||
Discourse.__container__
|
||||
.lookup("service:theme-settings")
|
||||
.registerSettings(#{theme.id}, {"name":"bob"});
|
||||
}
|
||||
})();
|
||||
(function () {
|
||||
if ('Discourse' in window && typeof Discourse._registerPluginCode === 'function') {
|
||||
var __theme_name__ = "awesome theme\\\"";
|
||||
|
||||
var settings = Discourse.__container__.lookup("service:theme-settings").getObjectForTheme(#{theme.id});
|
||||
|
||||
var themePrefix = function themePrefix(key) {
|
||||
return "theme_translations.#{theme.id}.".concat(key);
|
||||
};
|
||||
|
||||
Discourse._registerPluginCode('1.0', function (api) {
|
||||
try {
|
||||
alert(settings.name);
|
||||
|
||||
var a = function a() {};
|
||||
} catch (err) {
|
||||
var rescue = require("discourse/lib/utilities").rescueThemeError;
|
||||
|
||||
rescue(__theme_name__, err, api);
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
HTML
|
||||
|
||||
theme_field.reload
|
||||
expect(Theme.lookup_field(theme.id, :desktop, :after_header)).to include(theme_field.javascript_cache.url)
|
||||
expect(theme_field.javascript_cache.content).to eq(transpiled.strip)
|
||||
expect(theme_field.javascript_cache.content).to include("if ('require' in window) {")
|
||||
expect(theme_field.javascript_cache.content).to include(
|
||||
"require(\"discourse/lib/theme-settings-store\").registerSettings(#{theme_field.theme.id}, {\"name\":\"bob\"});"
|
||||
)
|
||||
expect(theme_field.javascript_cache.content).to include("if ('define' in window) {")
|
||||
expect(theme_field.javascript_cache.content).to include(
|
||||
"define(\"discourse/theme-#{theme_field.theme.id}/initializers/theme-field-#{theme_field.id}-common-html-script-1\","
|
||||
)
|
||||
expect(theme_field.javascript_cache.content).to include("var __theme_name__ = \"awesome theme\\\"\";")
|
||||
expect(theme_field.javascript_cache.content).to include("name: \"theme-field-#{theme_field.id}-common-html-script-1\",")
|
||||
expect(theme_field.javascript_cache.content).to include("after: \"inject-objects\",")
|
||||
expect(theme_field.javascript_cache.content).to include("(0, _pluginApi.withPluginApi)(\"1.0\", function (api)")
|
||||
expect(theme_field.javascript_cache.content).to include("alert(settings.name)")
|
||||
expect(theme_field.javascript_cache.content).to include("var a = function a() {}")
|
||||
|
||||
setting = theme.settings.find { |s| s.name == :name }
|
||||
setting.value = 'bill'
|
||||
theme.save!
|
||||
|
||||
transpiled = <<~HTML
|
||||
(function() {
|
||||
if ('Discourse' in window && Discourse.__container__) {
|
||||
Discourse.__container__
|
||||
.lookup("service:theme-settings")
|
||||
.registerSettings(#{theme.id}, {"name":"bill"});
|
||||
}
|
||||
})();
|
||||
(function () {
|
||||
if ('Discourse' in window && typeof Discourse._registerPluginCode === 'function') {
|
||||
var __theme_name__ = "awesome theme\\\"";
|
||||
|
||||
var settings = Discourse.__container__.lookup("service:theme-settings").getObjectForTheme(#{theme.id});
|
||||
|
||||
var themePrefix = function themePrefix(key) {
|
||||
return "theme_translations.#{theme.id}.".concat(key);
|
||||
};
|
||||
|
||||
Discourse._registerPluginCode('1.0', function (api) {
|
||||
try {
|
||||
alert(settings.name);
|
||||
|
||||
var a = function a() {};
|
||||
} catch (err) {
|
||||
var rescue = require("discourse/lib/utilities").rescueThemeError;
|
||||
|
||||
rescue(__theme_name__, err, api);
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
HTML
|
||||
|
||||
theme_field.reload
|
||||
expect(theme_field.javascript_cache.content).to include(
|
||||
"require(\"discourse/lib/theme-settings-store\").registerSettings(#{theme_field.theme.id}, {\"name\":\"bill\"});"
|
||||
)
|
||||
expect(Theme.lookup_field(theme.id, :desktop, :after_header)).to include(theme_field.javascript_cache.url)
|
||||
expect(theme_field.javascript_cache.content).to eq(transpiled.strip)
|
||||
end
|
||||
|
||||
it 'is empty when the settings are invalid' do
|
||||
|
Reference in New Issue
Block a user