!function(){ "use strict"; variables().ADDON_TEST_CONFIG_MGR_STATE = 'ready'; variables().ADDON_TEST_CONFIG_MGR_ERRORS = []; Macro.add('touch', { handler: function() { "use strict"; if (!Config.debug) { return this.error("Shouldn't reach me outside of debug mode."); } let errs = variables().ADDON_TEST_CONFIG_MGR_ERRORS; if (!variables().ADDON_TEST_CONFIG_MGR_STATE === 'loading') { errs.push("Tried to {{{touch " + this.args.raw + "}}} while not loading a test config."); return this.error("Only use me during test configuration."); } const realpassage = this.contextSelect((ctx) => ctx.name === 'include')?.name ?? passage(); for(const item of this.args) { if (Story.has(item)) { State.create(item); } else { errs.push("Can't find passage {{{" + item + "}}} when {{{" + realpassage + "}}} tried to touch it."); } } } }); $(document).on(':passagestart', function(ev) { "use strict"; if (!Config.debug) { return; } switch(variables().ADDON_TEST_CONFIG_MGR_STATE) { case 'ready': // 1. load candidate config passages // 2. present UI // a. "no configs" message // b. "choose a config" selector and activation button // notes on activation button: // 1. silently executes chosen passage // 2. if the tour stack is empty, done // 3. if the tour stack is not empty: // a. push current location // b. reverse it // c. set state to "touring" // 4. reload current page without history entry let config_passages = Story.lookup('tags', 'test-config'); if (config_passages.length) { let dropdown = document.createElement("select"); dropdown.id = "addon_test_config_mgr_config_picker"; for (const p of config_passages) { let op = document.createElement("option"); op.value = p.title; op.text = p.title; dropdown.appendChild(op); } let load_button = document.createElement("button"); load_button.innerText = "Load"; load_button.onclick = function() { if (!Config.debug) { // debugging got disabled, ignore it return; } const orig_passage = passage(); variables().ADDON_TEST_CONFIG_MGR_STATE="loading"; const target = document.getElementById("addon_test_config_mgr_config_picker")?.value; if (!target) { return; } $.wiki("<>"); variables().ADDON_TEST_CONFIG_MGR_STATE = 'done'; Engine.play(orig_passage, passage() == orig_passage); }; $(ev.content).wiki("^^Test Config Manager^^\n" + "!!!Would you like to load a test config?\n"); $(ev.content).append(dropdown).append(load_button); $(ev.content).wiki("\n----\n"); } else { $(ev.content).wiki("^^Test Config Manager^^\n" + "!!!No test configs found.\n" + "To create a test configuration, create a passage " + "tagged with {{{test-config}}}, containing test setup " + "code for a test scenario. You can use the " + "{{{touch}}} macro inside a test configuration to " + "add passages to the history during setup.\n" + "----\n"); } variables().ADDON_TEST_CONFIG_MGR_STATE = 'done'; return; case 'loading': // do nothing, we are in the middle of processing a configuration return; } // state should be "done"; if not, that's an error. if (variables().ADDON_TEST_CONFIG_MGR_STATE !== 'done') { variables().ADDON_TEST_CONFIG_MGR_ERRORS.push( "Invalid state: \"$ADDON_TEST_CONFIG_MGR_STATE\""); } let errs = variables().ADDON_TEST_CONFIG_MGR_ERRORS; if (errs.length) { $(ev.content).wiki("^^Test Config Manager^^\n\n" + "!!Errors during test configuration.\n\n"); for (const err of errs) { $(ev.content).wiki("* " + err + "\n") } $(ev.content).wiki("\n----\n"); variables().ADDON_TEST_CONFIG_MGR_ERRORS = []; } }); }();