From db51ea55fc9d3d00dc43dfcc97f17e7da2f9f123 Mon Sep 17 00:00:00 2001 From: Dannii Willis Date: Thu, 3 Oct 2024 13:21:24 +1000 Subject: [PATCH] Support Async Dialogs --- .eslintrc.cjs | 29 ------------ bin/regtest.js | 2 +- eslint.config.js | 31 +++++++++++++ package.json | 6 +-- src/observer.js | 73 ++++++++++++++++++++++++++----- src/runner.js | 2 +- tests/parchment-async-dialog.html | 65 +++++++++++++++++++++++++++ tests/runtests.sh | 4 +- 8 files changed, 167 insertions(+), 45 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100644 eslint.config.js create mode 100644 tests/parchment-async-dialog.html diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index a1155e5..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - env: { - browser: true, - es2020: true, - jquery: true, - node: true, - }, - extends: 'eslint:recommended', - globals: { - regtest_data: 'readonly', - regtest_event: 'readonly', - regtest_log: 'readonly', - }, - parserOptions: { - ecmaVersion: 12, - sourceType: 'module', - }, - root: true, - rules: { - eqeqeq: ['error', 'always', {'null': 'ignore'}], - indent: ['error', 4], - 'linebreak-style': ['error', 'unix'], - 'no-empty': ['off'], - 'no-var': ['error'], - 'prefer-const': ['error', {"destructuring": "all"}], - quotes: ['error', 'single'], - semi: ['error', 'never'], - }, -} \ No newline at end of file diff --git a/bin/regtest.js b/bin/regtest.js index f6ec65f..2b00532 100755 --- a/bin/regtest.js +++ b/bin/regtest.js @@ -32,7 +32,7 @@ const options = { interpreter_path: argv.i || argv.interpreter, //list: argv.l || argv.list, pdf: argv.pdf, - port: 8080, + port: 8090, tests: argv._.slice(1), testfile_path, timeout: parseInt(argv.t || argv.timeout || '1', 10), diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..b567152 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,31 @@ +import js from '@eslint/js' +import globals from 'globals' + +export default [ + js.configs.recommended, + { + languageOptions: { + ecmaVersion: 12, + globals: { + ...globals.browser, + ...globals.es2020, + ...globals.jquery, + ...globals.node, + regtest_data: 'readonly', + regtest_event: 'readonly', + regtest_log: 'readonly', + }, + sourceType: 'module', + }, + rules: { + eqeqeq: ['error', 'always', {'null': 'ignore'}], + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + 'no-empty': ['off'], + 'no-var': ['error'], + 'prefer-const': ['error', {'destructuring': 'all'}], + quotes: ['error', 'single'], + semi: ['error', 'never'], + }, + }, +] \ No newline at end of file diff --git a/package.json b/package.json index 93e7622..79d2078 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "regtest-html", - "version": "0.1.3", + "version": "0.1.4", "description": "RegTest compatible test framework for HTML interpreters", "repository": "curiousdannii/regtest-html", "keywords": [ @@ -22,11 +22,11 @@ }, "dependencies": { "http-server": "^14.1.1", - "minimist": "^1.2.7", + "minimist": "^1.2.8", "puppeteer": "^23.0.0" }, "devDependencies": { - "eslint": "^8.28.0" + "eslint": "^9.0.0" }, "scripts": { "lint": "eslint .", diff --git a/src/observer.js b/src/observer.js index 42cc33a..aef2dac 100644 --- a/src/observer.js +++ b/src/observer.js @@ -119,6 +119,41 @@ document.addEventListener('DOMContentLoaded', () => { glkote_window_obsever.observe(document.getElementById('windowport'), {childList: true}) + // Observe the opening of the async dialog + const glkote_async_dialog_observer = new MutationObserver(records => { + for (const record of records) { + if (record.type === 'attributes') { + const dialog = $(record.target) + if (dialog.prop('open')) { + regtest_data({ + type: 'input_requested', + data: { + type: 'fileref_prompt', + }, + }) + } + } + } + }) + + // Observe the body for the insertion of the async dialog + let async_dialog + const body_observer = new MutationObserver(records => { + for (const record of records) { + if (record.type === 'childList') { + for (const node of record.addedNodes) { + const $node = $(node) + if ($node.hasClass('asyncglk_file_dialog')) { + async_dialog = $node + glkote_async_dialog_observer.observe($node[0], {attributeFilter: ['open']}) + body_observer.disconnect() + } + } + } + } + }) + body_observer.observe(document.body, {childList: true}) + // Submit a Glk event window.regtest_event = data => { if (data.type === 'line') { @@ -132,21 +167,39 @@ document.addEventListener('DOMContentLoaded', () => { } if (data.type === 'fileref_prompt') { // Now to fill in the dialog form... - const accept = $('#dialog_accept') - if (accept.text() === 'Save') { - $('#dialog_infield').val(data.value) + if (async_dialog) { + const form_button = async_dialog.find('> .inner > .foot button.submit') + if (form_button.text() === 'Save') { + $('#filename_input').val(data.value) + } + else { + const options = async_dialog.find('> .inner > div[role=listbox] button') + for (const option of options) { + const $option = $(option) + if ($option.find('.name').text().startsWith(data.value + '.')) { + $option.click() + } + } + } + form_button.click() } else { - const test = new RegExp(`^${data.value}\\s`) - const options = $('#dialog_select option') - for (const option of options) { - const $option = $(option) - if (test.test($option.text())) { - $option.prop('selected', true) + const accept = $('#dialog_accept') + if (accept.text() === 'Save') { + $('#dialog_infield').val(data.value) + } + else { + const test = new RegExp(`^${data.value}\\s`) + const options = $('#dialog_select option') + for (const option of options) { + const $option = $(option) + if (test.test($option.text())) { + $option.prop('selected', true) + } } } + accept.click() } - accept.click() } } diff --git a/src/runner.js b/src/runner.js index 9e6d98f..6d91055 100644 --- a/src/runner.js +++ b/src/runner.js @@ -49,7 +49,7 @@ export class Runner { new URL(options.interpreter_path) options.interpreter_url = options.interpreter_path } - catch (_) { + catch { options.interpreter_url = `http://localhost:${options.port}/${path.relative(cwd, options.interpreter_path)}` } options.gamefile_url = options.gamefile_path ? `http://localhost:${options.port}/${path.relative(cwd, options.gamefile_path)}` : '' diff --git a/tests/parchment-async-dialog.html b/tests/parchment-async-dialog.html new file mode 100644 index 0000000..c3bbf85 --- /dev/null +++ b/tests/parchment-async-dialog.html @@ -0,0 +1,65 @@ + + + + + Parchment 2024.10.3 + + + + + + + + + + + + +
+
+

Parchment

+

is an interpreter for Interactive Fiction. Find out more.

+

Find stories to play at the Interactive Fiction Database.

+

+ + +

+

+ + + + +
+
+ + +
+ + \ No newline at end of file diff --git a/tests/runtests.sh b/tests/runtests.sh index c162a8b..63f7aa3 100755 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -7,4 +7,6 @@ echo Praxix echo Advent ./bin/regtest.js -i tests/parchment.html tests/advent.z5.regtest echo Inputeventtest -./bin/regtest.js -i tests/parchment.html -t 3 tests/inputeventtest.ulx.regtest \ No newline at end of file +./bin/regtest.js -i tests/parchment.html -t 3 tests/inputeventtest.ulx.regtest +echo "Async Dialog (Advent)" +./bin/regtest.js -i tests/parchment-async-dialog.html tests/advent.z5.regtest \ No newline at end of file