Differences Between Local Testing and Chrome Deployment

| Nov 15, 2020 min read

While implementing testing coverage across a chrome extension to parse recipes from webpages, a number of errors came up as I tested the code automatically using Jest on my local computer and when manually testing on real webpages. The issues all boil down to how code is packaged and made available when deployed as a chrome extension.

All scripts that are used in a chrome extension must be declared in the manifest.json file. This includes scripts that directly interact with the Chrome API and any dependencies that those scripts use. In my case, I had split out my functions across mutliple files to make it easier to test and debug specific features. After creating multiple files, I had forgotten to declare each of these files in the manifest file. After deploying, I received errors stating getPrintUrl is not a function.

When importing from a relative path in javascript, you can use const { importedThing } = require('path/to/importedThing'). However, when your extension is bundled and deployed to the browser, the file system is not the same; your files are re-packaged under a file system that uses the chrome extension ID. Additionally, because you have declared your scripts in the manifest file, you do not need to use require() in your code, and doing so actually triggers errors stating cannot access `X` before initialization

These differences between your file organization and declaration present an issue for testing. To develop well-tested code, we want to be able to test every function and and every pathway that data can move through your functions. But, we need to be able to know when the code is running in an environment run by Jest and when the code is being run in deployment in Chrome. To do so, we can detect the presence of the JEST_WORKER_ID environmental variable which is set to 1 when Jest is running the environment. When this environmental variable is present, we should import the required functions from relative path, and when it is not, we should not import anything because Chrome manages the code organization and deployment.

To implement this, we simply wrap our require() statements in an if statement and change the const to var:

if ( process.env.JEST_WORKER_ID !== undefined ) {
  var { importedThing } = require('path/to/importedThing')
}

By making this adjustment in every script that imports from a relative path, we are prepared for both local testing and deployment.