mirror of
https://github.com/discourse/discourse.git
synced 2025-04-29 07:04:37 +08:00
FIX: In test mode, initializers were modifying classes over and over
This adds a new property, `pluginId` which you can pass to `modifyClass` which prevent the class from being modified over and over again. This also includes a fix for polls which was leaking state between tests which this new functionality exposed.
This commit is contained in:
parent
fa66d1fa82
commit
09764291b1
@ -86,6 +86,25 @@ import { addSearchSuggestion } from "discourse/widgets/search-menu-results";
|
|||||||
// If you add any methods to the API ensure you bump up this number
|
// If you add any methods to the API ensure you bump up this number
|
||||||
const PLUGIN_API_VERSION = "0.12.2";
|
const PLUGIN_API_VERSION = "0.12.2";
|
||||||
|
|
||||||
|
// This helper prevents us from applying the same `modifyClass` over and over in test mode.
|
||||||
|
function canModify(klass, type, resolverName, changes) {
|
||||||
|
if (!changes.pluginId) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
"To prevent errors, add a `pluginId` key to your changes when calling `modifyClass`"
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = "_" + type + "/" + changes.pluginId + "/" + resolverName;
|
||||||
|
if (klass.class[key]) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
klass.class[key] = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PluginApi {
|
class PluginApi {
|
||||||
constructor(version, container) {
|
constructor(version, container) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
@ -138,10 +157,14 @@ class PluginApi {
|
|||||||
/**
|
/**
|
||||||
* Allows you to overwrite or extend methods in a class.
|
* Allows you to overwrite or extend methods in a class.
|
||||||
*
|
*
|
||||||
|
* You should add a `pluginId` property to identify your plugin
|
||||||
|
* to help Discourse reload classes properly.
|
||||||
|
*
|
||||||
* For example:
|
* For example:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* api.modifyClass('controller:composer', {
|
* api.modifyClass('controller:composer', {
|
||||||
|
* pluginId: 'my-plugin',
|
||||||
* actions: {
|
* actions: {
|
||||||
* newActionHere() { }
|
* newActionHere() { }
|
||||||
* }
|
* }
|
||||||
@ -150,9 +173,15 @@ class PluginApi {
|
|||||||
**/
|
**/
|
||||||
modifyClass(resolverName, changes, opts) {
|
modifyClass(resolverName, changes, opts) {
|
||||||
const klass = this._resolveClass(resolverName, opts);
|
const klass = this._resolveClass(resolverName, opts);
|
||||||
if (klass) {
|
if (!klass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canModify(klass, "member", resolverName, changes)) {
|
||||||
|
delete changes.pluginId;
|
||||||
klass.class.reopen(changes);
|
klass.class.reopen(changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,9 +198,15 @@ class PluginApi {
|
|||||||
**/
|
**/
|
||||||
modifyClassStatic(resolverName, changes, opts) {
|
modifyClassStatic(resolverName, changes, opts) {
|
||||||
const klass = this._resolveClass(resolverName, opts);
|
const klass = this._resolveClass(resolverName, opts);
|
||||||
if (klass) {
|
if (!klass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canModify(klass, "static", resolverName, changes)) {
|
||||||
|
delete changes.pluginId;
|
||||||
klass.class.reopenClass(changes);
|
klass.class.reopenClass(changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ function initializeDetails(api) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
api.modifyClass("controller:composer", {
|
api.modifyClass("controller:composer", {
|
||||||
|
pluginId: "discourse-details",
|
||||||
actions: {
|
actions: {
|
||||||
insertDetails() {
|
insertDetails() {
|
||||||
this.toolbarEvent.applySurround(
|
this.toolbarEvent.applySurround(
|
||||||
|
@ -82,6 +82,7 @@ function initializeDiscourseLocalDates(api) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
api.modifyClass("component:d-editor", {
|
api.modifyClass("component:d-editor", {
|
||||||
|
pluginId: "discourse-local-dates",
|
||||||
actions: {
|
actions: {
|
||||||
insertDiscourseLocalDate(toolbarEvent) {
|
insertDiscourseLocalDate(toolbarEvent) {
|
||||||
showModal("discourse-local-dates-create-modal").setProperties({
|
showModal("discourse-local-dates-create-modal").setProperties({
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
|
|
||||||
|
const PLUGIN_ID = "new-user-narrative";
|
||||||
|
|
||||||
function initialize(api) {
|
function initialize(api) {
|
||||||
const messageBus = api.container.lookup("message-bus:main");
|
const messageBus = api.container.lookup("message-bus:main");
|
||||||
const currentUser = api.getCurrentUser();
|
const currentUser = api.getCurrentUser();
|
||||||
const appEvents = api.container.lookup("service:app-events");
|
const appEvents = api.container.lookup("service:app-events");
|
||||||
|
|
||||||
api.modifyClass("component:site-header", {
|
api.modifyClass("component:site-header", {
|
||||||
|
pluginId: PLUGIN_ID,
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this.dispatch("header:search-context-trigger", "header");
|
this.dispatch("header:search-context-trigger", "header");
|
||||||
@ -14,6 +17,8 @@ function initialize(api) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
api.modifyClass("controller:topic", {
|
api.modifyClass("controller:topic", {
|
||||||
|
pluginId: PLUGIN_ID,
|
||||||
|
|
||||||
_togglePostBookmark(post) {
|
_togglePostBookmark(post) {
|
||||||
// if we are talking to discobot then any bookmarks should just
|
// if we are talking to discobot then any bookmarks should just
|
||||||
// be created without reminder options, to streamline the new user
|
// be created without reminder options, to streamline the new user
|
||||||
|
@ -4,6 +4,7 @@ import { withPluginApi } from "discourse/lib/plugin-api";
|
|||||||
|
|
||||||
function initializePollUIBuilder(api) {
|
function initializePollUIBuilder(api) {
|
||||||
api.modifyClass("controller:composer", {
|
api.modifyClass("controller:composer", {
|
||||||
|
pluginId: "discourse-poll-ui-builder",
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
"siteSettings.poll_enabled",
|
"siteSettings.poll_enabled",
|
||||||
"siteSettings.poll_minimum_trust_level_to_create",
|
"siteSettings.poll_minimum_trust_level_to_create",
|
||||||
|
@ -4,10 +4,30 @@ import { getRegister } from "discourse-common/lib/get-owner";
|
|||||||
import { observes } from "discourse-common/utils/decorators";
|
import { observes } from "discourse-common/utils/decorators";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
|
|
||||||
|
const PLUGIN_ID = "discourse-poll";
|
||||||
|
let _glued = [];
|
||||||
|
let _interval = null;
|
||||||
|
|
||||||
|
function rerender() {
|
||||||
|
_glued.forEach((g) => g.queueRerender());
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanUpPolls() {
|
||||||
|
if (_interval) {
|
||||||
|
clearInterval(_interval);
|
||||||
|
_interval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glued.forEach((g) => g.cleanUp());
|
||||||
|
_glued = [];
|
||||||
|
}
|
||||||
|
|
||||||
function initializePolls(api) {
|
function initializePolls(api) {
|
||||||
const register = getRegister(api);
|
const register = getRegister(api);
|
||||||
|
cleanUpPolls();
|
||||||
|
|
||||||
api.modifyClass("controller:topic", {
|
api.modifyClass("controller:topic", {
|
||||||
|
pluginId: PLUGIN_ID,
|
||||||
subscribe() {
|
subscribe() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this.messageBus.subscribe("/polls/" + this.get("model.id"), (msg) => {
|
this.messageBus.subscribe("/polls/" + this.get("model.id"), (msg) => {
|
||||||
@ -23,14 +43,8 @@ function initializePolls(api) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let _glued = [];
|
|
||||||
let _interval = null;
|
|
||||||
|
|
||||||
function rerender() {
|
|
||||||
_glued.forEach((g) => g.queueRerender());
|
|
||||||
}
|
|
||||||
|
|
||||||
api.modifyClass("model:post", {
|
api.modifyClass("model:post", {
|
||||||
|
pluginId: PLUGIN_ID,
|
||||||
_polls: null,
|
_polls: null,
|
||||||
pollsObject: null,
|
pollsObject: null,
|
||||||
|
|
||||||
@ -110,16 +124,6 @@ function initializePolls(api) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanUpPolls() {
|
|
||||||
if (_interval) {
|
|
||||||
clearInterval(_interval);
|
|
||||||
_interval = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glued.forEach((g) => g.cleanUp());
|
|
||||||
_glued = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
api.includePostAttributes("polls", "polls_votes");
|
api.includePostAttributes("polls", "polls_votes");
|
||||||
api.decorateCooked(attachPolls, { onlyStream: true, id: "discourse-poll" });
|
api.decorateCooked(attachPolls, { onlyStream: true, id: "discourse-poll" });
|
||||||
api.cleanupStream(cleanUpPolls);
|
api.cleanupStream(cleanUpPolls);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user