From 3114ac4e2b6dd60abc34cd5435319558d41f4870 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 10 Mar 2023 17:27:54 -0600 Subject: [PATCH] mpy/sagas: fix tests attempting to load .wasm via http Since we are using jsdom, the emscripten generated code doesn't use the node filesystem lookup for .wasm files. But then it falls back to node for file:// urls, but this doesn't work because node treats file: as a drive letter. We can work around this by modifying the node path.normalize() function to return the correct path. Fixes: https://github.com/pybricks/pybricks-code/issues/1584 --- src/mpy/sagas.test.ts | 36 +++++++++++++++++++++++++++++++++++- src/mpy/sagas.ts | 32 +++++++++++++------------------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/mpy/sagas.test.ts b/src/mpy/sagas.test.ts index 06260a39..78093b29 100644 --- a/src/mpy/sagas.test.ts +++ b/src/mpy/sagas.test.ts @@ -1,10 +1,44 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020-2022 The Pybricks Authors +// Copyright (c) 2020-2023 The Pybricks Authors +import path from 'path'; import { AsyncSaga } from '../../test'; import { compile, didCompile, didFailToCompile } from './actions'; import mpy from './sagas'; +const mpyCrossV5Wasm = require.resolve('@pybricks/mpy-cross-v5/build/mpy-cross.wasm'); +const mpyCrossV6Wasm = require.resolve( + '@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm', +); + +beforeEach(() => { + // HACK: work around Emscripten + Webpack bugs + // Since we are using jsdom, emscripten thinks we are in a browser and + // sees that the path starts with file:// but just passes this to + // path.normalize() which treats file: as a windows-style drive prefix. + // Also, the webpack import.meta.url doesn't work correctly in the test + // environment either and returns a path relative to the directory where + // it was called rather than the node_modules/ directory. So we have to + // fake the normalization to get the correct path. + jest.spyOn(path, 'normalize').mockImplementation((p) => { + // NB: we can't call require.resolve() here because it would recursively + // call this function via path.normalize()! + if (p.endsWith('@pybricks/mpy-cross-v5/build/mpy-cross.wasm')) { + return mpyCrossV5Wasm; + } + + if (p.endsWith('@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm')) { + return mpyCrossV6Wasm; + } + + return p; + }); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + test('compiler works', async () => { const saga = new AsyncSaga(mpy); diff --git a/src/mpy/sagas.ts b/src/mpy/sagas.ts index 7a83b932..b7b29598 100644 --- a/src/mpy/sagas.ts +++ b/src/mpy/sagas.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020-2022 The Pybricks Authors +// Copyright (c) 2020-2023 The Pybricks Authors import { compile as mpyCrossCompileV5 } from '@pybricks/mpy-cross-v5'; import { compile as mpyCrossCompileV6 } from '@pybricks/mpy-cross-v6'; @@ -54,12 +54,10 @@ function* handleCompile(action: ReturnType): Generator { 'main.py', action.script, action.options, - process.env.NODE_ENV === 'test' - ? undefined - : new URL( - '@pybricks/mpy-cross-v5/build/mpy-cross.wasm', - import.meta.url, - ).toString(), + new URL( + '@pybricks/mpy-cross-v5/build/mpy-cross.wasm', + import.meta.url, + ).toString(), ), ); if (result.status === 0 && result.mpy) { @@ -77,12 +75,10 @@ function* handleCompile(action: ReturnType): Generator { 'main.py', action.script, action.options, - process.env.NODE_ENV === 'test' - ? undefined - : new URL( - '@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm', - import.meta.url, - ).toString(), + new URL( + '@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm', + import.meta.url, + ).toString(), ), ); if (result.status === 0 && result.mpy) { @@ -188,12 +184,10 @@ function* handleCompileMulti6(): Generator { py.path, py.contents, undefined, - process.env.NODE_ENV === 'test' - ? undefined - : new URL( - '@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm', - import.meta.url, - ).toString(), + new URL( + '@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm', + import.meta.url, + ).toString(), ), );