From 34072d2f531185c35f1c1c201788045e148262ae Mon Sep 17 00:00:00 2001 From: adroitwhiz <adroitwhiz@protonmail.com> Date: Sun, 8 Mar 2020 08:12:40 -0400 Subject: [PATCH] Fix file input in tests --- test/helper/page-util.js | 53 +++++++++++++++++++++++++++++++ test/integration/cpu-render.html | 43 +++++++------------------ test/integration/index.html | 31 ++---------------- test/integration/pick-tests.js | 9 ++++-- test/integration/scratch-tests.js | 8 +++-- 5 files changed, 79 insertions(+), 65 deletions(-) create mode 100644 test/helper/page-util.js diff --git a/test/helper/page-util.js b/test/helper/page-util.js new file mode 100644 index 00000000..0648e1bf --- /dev/null +++ b/test/helper/page-util.js @@ -0,0 +1,53 @@ +/* global window, VirtualMachine, ScratchStorage, ScratchSVGRenderer */ +/* eslint-env browser */ + +// Wait for all SVG skins to be loaded. +// TODO: this is extremely janky and should be removed once vm.loadProject waits for SVG skins to load +window.waitForSVGSkinLoad = renderer => new Promise(resolve => { + // eslint-disable-next-line prefer-const + let interval; + + const waitInner = () => { + let numSVGSkins = 0; + let numLoadedSVGSkins = 0; + for (const skin of renderer._allSkins) { + if (skin.constructor.name !== 'SVGSkin') continue; + numSVGSkins++; + if (skin._svgRenderer.loaded) numLoadedSVGSkins++; + } + + if (numSVGSkins === numLoadedSVGSkins) { + clearInterval(interval); + resolve(); + } + }; + + interval = setInterval(waitInner, 1); +}); + +window.loadFileInputIntoVM = (fileInput, vm, render) => { + const reader = new FileReader(); + return new Promise(resolve => { + reader.onload = () => { + vm.start(); + vm.loadProject(reader.result) + .then(() => window.waitForSVGSkinLoad(render)) + .then(() => { + resolve(); + }); + }; + reader.readAsArrayBuffer(fileInput.files[0]); + }); +}; + +window.initVM = render => { + const vm = new VirtualMachine(); + const storage = new ScratchStorage(); + + vm.attachStorage(storage); + vm.attachRenderer(render); + vm.attachV2SVGAdapter(new ScratchSVGRenderer.SVGRenderer()); + vm.attachV2BitmapAdapter(new ScratchSVGRenderer.BitmapAdapter()); + + return vm; +}; diff --git a/test/integration/cpu-render.html b/test/integration/cpu-render.html index d6d36308..26a79c3f 100644 --- a/test/integration/cpu-render.html +++ b/test/integration/cpu-render.html @@ -2,6 +2,7 @@ <script src="../../node_modules/scratch-vm/dist/web/scratch-vm.js"></script> <script src="../../node_modules/scratch-storage/dist/web/scratch-storage.js"></script> <script src="../../node_modules/scratch-svg-renderer/dist/web/scratch-svg-renderer.js"></script> + <script src="../helper/page-util.js"></script> <!-- note: this uses the BUILT version of scratch-render! make sure to npm run build --> <script src="../../dist/web/scratch-render.js"></script> @@ -17,38 +18,18 @@ window.devicePixelRatio = 1; const gpuCanvas = document.getElementById('test'); var render = new ScratchRender(gpuCanvas); - var vm = new VirtualMachine(); - var storage = new ScratchStorage(); + var vm = initVM(render); - vm.attachStorage(storage); - vm.attachRenderer(render); - vm.attachV2SVGAdapter(new ScratchSVGRenderer.SVGRenderer()); - vm.attachV2BitmapAdapter(new ScratchSVGRenderer.BitmapAdapter()); - - document.getElementById('file').addEventListener('click', e => { - document.body.removeChild(document.getElementById('loaded')); - }); - - document.getElementById('file').addEventListener('change', e => { - const reader = new FileReader(); - const thisFileInput = e.target; - reader.onload = () => { - vm.start(); - vm.loadProject(reader.result) - .then(() => { - // we add a `#loaded` div to our document, the integration suite - // waits for that element to show up to assume the vm is ready - // to play! - const div = document.createElement('div'); - div.id='loaded'; - document.body.appendChild(div); - vm.greenFlag(); - setTimeout(() => { - renderCpu(); - }, 1000); - }); - }; - reader.readAsArrayBuffer(thisFileInput.files[0]); + const fileInput = document.getElementById('file'); + const loadFile = loadFileInputIntoVM.bind(null, fileInput, vm, render); + fileInput.addEventListener('change', e => { + loadFile() + .then(() => { + vm.greenFlag(); + setTimeout(() => { + renderCpu(); + }, 1000); + }); }); const cpuCanvas = document.getElementById('cpu'); diff --git a/test/integration/index.html b/test/integration/index.html index e3d8dd83..114fa5b9 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -2,6 +2,7 @@ <script src="../../node_modules/scratch-vm/dist/web/scratch-vm.js"></script> <script src="../../node_modules/scratch-storage/dist/web/scratch-storage.js"></script> <script src="../../node_modules/scratch-svg-renderer/dist/web/scratch-svg-renderer.js"></script> + <script src="../helper/page-util.js"></script> <!-- note: this uses the BUILT version of scratch-render! make sure to npm run build --> <script src="../../dist/web/scratch-render.js"></script> @@ -15,39 +16,13 @@ var canvas = document.getElementById('test'); var render = new ScratchRender(canvas); - var vm = new VirtualMachine(); - var storage = new ScratchStorage(); + var vm = initVM(render); var mockMouse = data => vm.runtime.postIOData('mouse', { canvasWidth: canvas.width, canvasHeight: canvas.height, ...data, }); - vm.attachStorage(storage); - vm.attachRenderer(render); - vm.attachV2SVGAdapter(new ScratchSVGRenderer.SVGRenderer()); - vm.attachV2BitmapAdapter(new ScratchSVGRenderer.BitmapAdapter()); - - document.getElementById('file').addEventListener('click', e => { - document.body.removeChild(document.getElementById('loaded')); - }); - - document.getElementById('file').addEventListener('change', e => { - const reader = new FileReader(); - const thisFileInput = e.target; - reader.onload = () => { - vm.start(); - vm.loadProject(reader.result) - .then(() => { - // we add a `#loaded` div to our document, the integration suite - // waits for that element to show up to assume the vm is ready - // to play! - const div = document.createElement('div'); - div.id='loaded'; - document.body.appendChild(div); - }); - }; - reader.readAsArrayBuffer(thisFileInput.files[0]); - }); + const loadFile = loadFileInputIntoVM.bind(null, document.getElementById('file'), vm, render); </script> </body> diff --git a/test/integration/pick-tests.js b/test/integration/pick-tests.js index a767ec40..a36ee150 100644 --- a/test/integration/pick-tests.js +++ b/test/integration/pick-tests.js @@ -13,9 +13,12 @@ const runFile = async (file, action, page, script) => { await page.goto(`file://${indexHTML}`); const fileInput = await page.$('#file'); await fileInput.uploadFile(testDir(file)); - // the index.html handler for file input will add a #loaded element when it - // finishes. - await page.waitForSelector('#loaded'); + + await page.evaluate(() => + // `loadFile` is defined on the page itself. + // eslint-disable-next-line no-undef + loadFile() + ); return page.evaluate(`(function () {return (${script})(${action});})()`); }; diff --git a/test/integration/scratch-tests.js b/test/integration/scratch-tests.js index d6cfebfd..9d3188a3 100644 --- a/test/integration/scratch-tests.js +++ b/test/integration/scratch-tests.js @@ -14,9 +14,11 @@ const testFile = (file, page) => test(file, async t => { await page.goto(`file://${indexHTML}`); const fileInput = await page.$('#file'); await fileInput.uploadFile(testDir(file)); - // the index.html handler for file input will add a #loaded element when it - // finishes. - await page.waitForSelector('#loaded'); + await page.evaluate(() => + // `loadFile` is defined on the page itself. + // eslint-disable-next-line no-undef + loadFile() + ); const says = await page.evaluate(() => { // This function is run INSIDE the integration chrome browser via some // injection and .toString() magic. We can return some "simple data"