Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bare import not working #3018

Closed
FlippieCoetser opened this issue Jun 22, 2022 · 7 comments
Closed

bare import not working #3018

FlippieCoetser opened this issue Jun 22, 2022 · 7 comments

Comments

@FlippieCoetser
Copy link

Issue description or question

Typescript path mapping workaround as described here, does not work.
Use-case seems to be different:

Rather than import { Dictionary } from '/dictionary.js' I would like to do import { Dictionary } from 'dictionary': a bare import

Although the testing does not work,
I am able to build the module and use it chrome browser.

To build the module with bare imports requires two pieces:

  1. Typescript Compiler Paths
{
"paths": {
            "dictionary": ["../node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js"]
        }
}
  1. Importmap in index.html
<script type="importmap">
    {
        "imports": {
            "dictionary": "../node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js",
            "events": "../lib/events.js"
        }
    }
</script>

To make the testing work I have to provide a relative path:

import { Dictionary } from "../node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js" in events.ts file.

A small demonstratable project can be downloaded from GitHub here

The HTML script type importmap works great with the chrome browser, is there a way to insert the importmap into the HTML file used by wallaby? or is there a different approach?

@smcenlly
Copy link
Member

Thanks for the sample repo. It looks like it's missing your tsconfig.json settings. Could you please update the repo to do the following:

  1. Include your tsconfig.json
  2. Update to use import { Dictionary } from 'dictionary' where your tests are working using Karma (npm run test) but with Wallaby failing.

@FlippieCoetser
Copy link
Author

FlippieCoetser commented Jun 23, 2022

@smcenlly quick response time, much appreciated!

My communication can improve. Let me provide a bit more clarification:

Building and Testing the module are done with two different typescript compiler configurations.
There is no specific tsconfig.json. The /tasks folder contains the two configs:

  • Build: /tasks/build.lib.json
  • Test: /tasks/build.test.json

To execute a Build or Test use:

  • npm run build.lib
  • npm test

What works? Publishing or using the module.

The module and its dependencies are resolved in es6 compatible browsers.
Dependency modules are imported using bare import:

import { Dictionary } from "dictionary"

This works because the demo/index.html contains an importmap

<script type="importmap">
    {
        "imports": {
            "dictionary": "../node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js",
            "events": "../lib/events.js"
        }
    }
</script>

The dictionary entry is a dependency module reference. The reference can also point to an https:/**/*.js.
In this case it is a locally installed npm module.
The events entry is the current module in development. The reference points to the lib/ folder: the output folder of the build task

During development, adding and/or updating the source code: src/events.ts, the typescript compiler is happy with the bare dependency import,

import { Dictionary } from "dictionary"

Because of the compiler configuration:

{
"paths": {
            "dictionary": ["../node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js"]
        }
}

What does not work? Testing

Both automated wallaby and manual karma: executed by npm script: npm test fails when using the bare dependency import.

Current way of testing

Import dependency modules via a complete path

import { Dictionary } from "../node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js"

This makes both automated wallaby and manual karma happy.

Potential Solution

For karma runner, it is possible to use a custom context.html file. I was thinking of using a custom html file that includes the same importmap used in /demo/index.html. However, before I explore than I thought to first found a solution for wallaby. Hope you can help me get the automated testing working as expected. Is importmaps potentially something we can add to the html file used by wallaby for testing?

@smcenlly
Copy link
Member

I think ideally your Wallaby and Karma solution should be the same. You need something to process the module imports and re-write your aliases for you so they can resolved by the browser.

For what you're looking to do, I myself would be setting up webpack for Karma with resolve aliases. Wallaby also supports webpack and the same webpack configuration that works with Karma should work with webpack.

@FlippieCoetser
Copy link
Author

@smcenlly, I got my unit tests working via Karma without rewriting any alias. But not yet Wallaby.

What I did was configure Karma to use a custom HTML context.
To do so, I added the below configuration option in my karma.conf.js:

customContextFile: "custom.context.html"

my custom HTML file is a copy of what Karma uses by default.
The only change I made was to add the importmap:

<script type="importmap">
    {
        "imports": {
            "dictionary": "/base/node_modules/@browser-modules/typescript.dictionary/lib/dictionary.js"
        }
    }
</script>

Help me out with Wallaby, please! I would really like to avoid implementing any bundler.

Question:
Is there a way to tell Wallaby to also use the same custom HTML context as Karma?

I pushed the changes I made to the git repo, so you can just do a pull and execute npm test to see successful unit testing via Karma

@FlippieCoetser
Copy link
Author

@smcenlly I updated the path to the test repo

@NikGovorov
Copy link
Member

@FlippieCoetser, To make Wallaby working in your repo you need to create the following file aliases.js:

const importMap = {
    imports: {
      "@browser-modules/dictionary":
        "/node_modules/@browser-modules/dictionary/lib/dictionary.js",
    },
  };

  const element = document.createElement("script");
  element.type = "importmap";
  element.textContent = JSON.stringify(importMap);
  document.currentScript.after(element);

https://github.com/WICG/import-maps#dynamic-import-map-example

and add the file path as the first entry to files collection in wallaby.js:

// typescript paths is an example of how to map an npm module name directly to a file path.

module.exports = function (wallaby) {
  return {
    files: [
+++   "aliases.js",
      "src/**/*.ts",
      "node_modules/@browser-modules/dictionary/lib/dictionary.js",
    ],
    tests: ["test/*.ts"],
    trace: true,
    compilers: {
      "**/*.ts": wallaby.compilers.typeScript({
        module: "es2020",
        target: "es2020",
        sourceMap: true,
        inlineSources: true,
      }),
    }
  };
};

You may consider using the same file for Karma to have only one source of truth for path aliases in your project.

@FlippieCoetser
Copy link
Author

@NikGovorov works like a charm! as per your suggestion I also simplified Karma using aliases.js. Can't believe the solution is so simple. In the end pure Typescript, Wallaby, and Typedoc, that is It. I can publish and consume ES6 Modules via NPM, using NO BUNDLER! Absolutely Perfect! Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants