From 41cd335cf40558e56d2850ecef7dee2ecec80de1 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 26 Feb 2025 17:20:03 +0000 Subject: [PATCH] Add test for dynamically loading a language plugin --- core/modules/pluginswitcher.js | 31 ++++++++++-- core/modules/widgets/testcase.js | 24 +++++++++- core/ui/TestCases/DefaultTemplate.tid | 3 +- .../data/plugins/DynamicLoadLanguage.tid | 47 +++++++++++++++++++ .../jasmine/run-wiki-based-tests.js | 18 +++---- 5 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/plugins/DynamicLoadLanguage.tid diff --git a/core/modules/pluginswitcher.js b/core/modules/pluginswitcher.js index 71d9f3b03..9a7a7a351 100644 --- a/core/modules/pluginswitcher.js +++ b/core/modules/pluginswitcher.js @@ -38,6 +38,7 @@ function PluginSwitcher(options) { } PluginSwitcher.prototype.switchPlugins = function() { + var self = this; // Get the name of the current theme var selectedPluginTitle = this.wiki.getTiddlerText(this.controllerTitle); // If it doesn't exist, then fallback to one of the default themes @@ -61,13 +62,37 @@ PluginSwitcher.prototype.switchPlugins = function() { }; accumulatePlugin(selectedPluginTitle); // Read the plugin info for the incoming plugins - var changes = this.wiki.readPluginInfo(plugins); + var changedPluginInfo = this.wiki.readPluginInfo(plugins); + // Collect the shadow tiddlers of any deleted plugins + var changedShadowTiddlers = {}; + $tw.utils.each(changedPluginInfo.deletedPlugins,function(pluginTitle) { + var contents = changedPluginInfo.deletedPluginContents[pluginTitle]; + if(contents && contents.tiddlers) { + $tw.utils.each(Object.keys(contents.tiddlers),function(title) { + changedShadowTiddlers[title] = true; + }); + } + }); + // Collect the shadow tiddlers of any modified plugins + $tw.utils.each(changedPluginInfo.modifiedPlugins,function(pluginTitle) { + var pluginInfo = self.wiki.getPluginInfo(pluginTitle); + if(pluginInfo && pluginInfo.tiddlers) { + $tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) { + changedShadowTiddlers[title] = false; + }); + } + }); // Unregister any existing theme tiddlers var unregisteredTiddlers = this.wiki.unregisterPluginTiddlers(this.pluginType); // Register any new theme tiddlers - var registeredTiddlers = this.wiki.registerPluginTiddlers(this.pluginType,plugins,plugins[0] === "$:/languages/fr-FR"); + var registeredTiddlers = this.wiki.registerPluginTiddlers(this.pluginType,plugins); // Unpack the current theme tiddlers - this.wiki.unpackPluginTiddlers(); + this.wiki.unpackPluginTiddlers(this.doDebug); + // Queue change events for the changed shadow tiddlers + $tw.utils.each(changedShadowTiddlers,function(status,title) { + self.wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title], true); + }); + // Call the switch handler if(this.onSwitch) { this.onSwitch(plugins); diff --git a/core/modules/widgets/testcase.js b/core/modules/widgets/testcase.js index ad1905279..f04a7f75d 100644 --- a/core/modules/widgets/testcase.js +++ b/core/modules/widgets/testcase.js @@ -69,11 +69,24 @@ TestCaseWidget.prototype.render = function(parent,nextSibling) { }); var jsonPayload = JSON.stringify(tiddlers); this.testcaseWiki.addTiddlers(tiddlers); + // Suppress next tick dispatch for wiki change events + this.testcaseWiki.setDispatchMode(true); // Unpack plugin tiddlers this.testcaseWiki.readPluginInfo(); this.testcaseWiki.registerPluginTiddlers("plugin"); this.testcaseWiki.unpackPluginTiddlers(); this.testcaseWiki.addIndexersToWiki(); + // Install the plugin change event handler + $tw.utils.installPluginChangeHandler(this.testcaseWiki); + // Install the language switcher + var languageSwitcher = new $tw.PluginSwitcher({ + wiki: this.testcaseWiki, + pluginType: "language", + controllerTitle: "$:/language", + defaultPlugins: [ + "$:/languages/en-GB" + ] + }); // Generate a `transclusion` variable that depends on the values of the payload tiddlers so that the template can easily make unique state tiddlers this.setVariable("transclusion",$tw.utils.hashString(jsonPayload)); // Generate a `payloadTiddlers` variable that contains the payload in JSON format @@ -95,13 +108,20 @@ TestCaseWidget.prototype.render = function(parent,nextSibling) { } }); testcaseOutputWidget.render(testcaseOutputContainer); + // Install the wiki change event handler + this.testcaseWiki.addEventListener("change",function(changes) { + testcaseOutputWidget.refresh(changes,testcaseOutputContainer); + }); } // Clear changes queue this.testcaseWiki.clearTiddlerEventQueue(); // Run the actions if provided if(this.testcaseWiki.tiddlerExists(this.testcaseTestActions)) { testcaseOutputWidget.invokeActionString(this.testcaseWiki.getTiddlerText(this.testcaseTestActions)); - testcaseOutputWidget.refresh(this.testcaseWiki.changedTiddlers,testcaseOutputContainer); + // Make sure all wiki events have been cleared + while(this.testcaseWiki.eventsTriggered) { + this.testcaseWiki.processOutstandingTiddlerEvents(); + } } // Set up the test result variables var testResult = "", @@ -131,6 +151,8 @@ TestCaseWidget.prototype.render = function(parent,nextSibling) { parentWidget: this }); rootWidget.render(domNode); + // Re-enable next tick dispatch for wiki change events + this.testcaseWiki.setDispatchMode(false); // Trap changes in the wiki and refresh the rendering this.testcaseWiki.addEventListener("change",function(changes) { rootWidget.refresh(changes,domNode); diff --git a/core/ui/TestCases/DefaultTemplate.tid b/core/ui/TestCases/DefaultTemplate.tid index 2967a5157..db5aa0472 100644 --- a/core/ui/TestCases/DefaultTemplate.tid +++ b/core/ui/TestCases/DefaultTemplate.tid @@ -103,7 +103,8 @@ code-body: yes -Description -Narrative -[[$:/temp/testcase/draft-title]] --[has[plugin-type]] +-[[$:/status/RequireReloadDueToPluginChange]] +-[[$:/core]] -[prefix] -[prefix[$:/state/popup/export]] -[prefix[$:/HistoryList]] diff --git a/editions/test/tiddlers/tests/data/plugins/DynamicLoadLanguage.tid b/editions/test/tiddlers/tests/data/plugins/DynamicLoadLanguage.tid new file mode 100644 index 000000000..742f6aa17 --- /dev/null +++ b/editions/test/tiddlers/tests/data/plugins/DynamicLoadLanguage.tid @@ -0,0 +1,47 @@ +title: Plugins/DynamicLoadLanguage +description: Dynamically loading of language plugin +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +{{First}} ++ +title: Actions + +<$action-createtiddler $basetitle="$:/languages/fr-FR" $template="$:/languages/fr-FR/raw" type="application/json"/> +<$action-setfield $tiddler="$:/languages/fr-FR" plugin-type="language"/> +<$action-setfield $tiddler="$:/language" text="$:/languages/fr-FR"/> ++ +title: $:/languages/en-GB +list: readme +name: en-GB +plugin-type: language +type: application/json + +{ + "tiddlers": { + "First": { + "title": "First", + "text": "This is English" + } + } +} ++ +title: $:/languages/fr-FR/raw +list: readme +name: fr-FR +type: plain/text + +{ + "tiddlers": { + "First": { + "title": "First", + "text": "This is French" + } + } +} ++ +title: ExpectedResult + +

This is French

\ No newline at end of file diff --git a/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js b/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js index 536c51966..a14707045 100644 --- a/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js +++ b/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js @@ -39,10 +39,8 @@ describe("Wiki-based tests", function() { wiki.registerPluginTiddlers("plugin"); wiki.unpackPluginTiddlers(); wiki.addIndexersToWiki(); - // Install the plugin change event handler - $tw.utils.installPluginChangeHandler(wiki); // Install the language switcher - $tw.languageSwitcher = new $tw.PluginSwitcher({ + var languageSwitcher = new $tw.PluginSwitcher({ wiki: wiki, pluginType: "language", controllerTitle: "$:/language", @@ -50,6 +48,8 @@ describe("Wiki-based tests", function() { "$:/languages/en-GB" ] }); + // Install the plugin change event handler + $tw.utils.installPluginChangeHandler(wiki,doDebug); // Clear changes queue wiki.clearTiddlerEventQueue(); // Complain if we don't have the ouput and expected results @@ -62,18 +62,19 @@ describe("Wiki-based tests", function() { var widgetNode = createWidgetNode(parseText(text,wiki),wiki); // Render the widget node to the DOM var wrapper = renderWidgetNode(widgetNode); + // Install the wiki change event handler + wiki.addEventListener("change",function(changes) { + widgetNode.refresh(changes,wrapper); + }); // Run the actions if provided if(wiki.tiddlerExists("Actions")) { widgetNode.invokeActionString(wiki.getTiddlerText("Actions")); - refreshWidgetNode(widgetNode,wrapper); } // Make sure all wiki events have been cleared while(wiki.eventsTriggered) { wiki.processOutstandingTiddlerEvents(); - refreshWidgetNode(widgetNode,wrapper); } // Test the rendering - refreshWidgetNode(widgetNode,wrapper); expect(wrapper.innerHTML).toBe(wiki.getTiddlerText("ExpectedResult")); } }); @@ -112,11 +113,6 @@ describe("Wiki-based tests", function() { return wrapper; } - function refreshWidgetNode(widgetNode,wrapper) { - widgetNode.refresh(widgetNode.wiki.changedTiddlers,wrapper); -// console.log(require("util").inspect(wrapper,{depth: 8})); - } - }); })();