Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

167
Visualizações
Mocha finds global variable is undefined when extended by class

I have the following ES6 module from a Chromecast receiver that I would like to test using Mocha...

// SUT - app.js
import { Queue } from 'queue.js'
export const app = async () => {
  const context = cast.framework.CastReceiverContext.getInstance();
  const options = {};
  options.queue = new Queue();
  context.start(options);
}

This code runs inside a Chromecast user agent which provides access to the global cast object. This cast object exposes an api which in turn enables the JS thread to interact directly with the Chromecast CAF SDK. This cast variable is always available at run time.

The Queue class is slightly unusual because in order for it to work according to the CAF framework documentation, is must extend an abstract class from the framework cast.framework.QueueBase...

// queue.js
class Queue extends cast.framework.QueueBase {
  initialize(){
    // build queue here
  }
}

Now I would like to write some unit tests to check my app function is correct. For example:

// app.test.js
import { app } from 'app.js';
it('should do some stuff', async function () {
  // inject a mock cast object
  global.cast = {
    framework: {
      QueueBase: class {},
      CastReceiverContext: {
        getInstance: () => {},
      },
    },
  };
  await app();
  // Make some assertions
});

However, even though I am injecting a mock using global.cast, which is sufficient for all regular references to the cast object, in the case where a class is extending the injected cast object, apparently it is not yet available and I receive the following error:

ReferenceError: cast is not defined

I found an ugly hack to make this error disappear. If I place the following snippet above the class declaration then I can inject the mock at runtime and it not only works for Mocha but also for execution on the Chromecast device....

try {
  // The following line throws in Mocha's node environment
  // but executes fine on the Chromecast device
  if (cast) {
  }
} catch {
  global.cast = {
    framework: {
      QueueBase: class {},
    },
  };
}

export class Queue extends cast.framework.QueueBase {
...

However, I would like to find a better solution so that I don't have to pollute my production code with this hack which is only there to allow me to run tests.

My .mocharc.yml file looks like this:

require:
  - '@babel/register'
  - 'ignore-styles'
  - 'jsdom-global/register'
  - 'babel-polyfill'

... and my command to run tests is:

mocha --recursive --use_strict

finally, my .babelrc file looks like this:

{
    "presets": [
        [
            "@babel/preset-env"
        ]
    ],
    "plugins": [
        "inline-svg",
        "import-graphql"
    ]
}
about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Static imports are always evaluated first, so the order of operations is roughly:

import { Queue } from 'queue.js'
class Queue extends cast.framework.QueueBase { // ReferenceError outside Chromecast!
  initialize(){
    // build queue here
  }
}
global.cast = {
    framework: {
      QueueBase: class {},
      CastReceiverContext: {
        getInstance: () => {},
      },
    },
  };

You can see that the mock is created after the reference to cast in app.js.

The only reliable way to run the mock creation before importing the app module is using a dynamic import:

// app.test.js
it('should do some stuff', async function () {
  // inject a mock cast object
  global.cast = {
    framework: {
      QueueBase: class {},
      CastReceiverContext: {
        getInstance: () => {},
      },
    },
  };
  const { app } = await import('app.js');
  await app();
  // Make some assertions
  delete global.cast;
});

If you prefer not to repeat the mock creation and the import in every test, you can move both out of the test definition:

// app.test.js
// inject a mock cast object
global.cast = {
  framework: {
    QueueBase: class {},
    CastReceiverContext: {
      getInstance: () => {},
    },
  },
};
const { app } = await import('app.js');
it('should do some stuff', async function () {
  await app();
  // Make some assertions
});
// Optionally clean up the mock after all tests
after(() => delete global.cast);
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda