#How to run a command to start server in different folder

43 messages · Page 1 of 1 (latest)

knotty fable
#

I have a microservice A that Im currnetly testing and in this microservice, it sends api requests to another microservice B that I have. My question is: how can I run that other microservce B in my global-setup.js in order for it to start running before I run my jest tests for microservice A

ionic quail
#

what is global-setup.js?

#

setup file for testing?

knotty fable
#

yes

ionic quail
#

Is it an async capable file?

knotty fable
#
/* eslint-disable */
var __TEARDOWN_MESSAGE__: string;

module.exports = async function () {
  // Start services that that the app needs to run (e.g. database, docker-compose, etc.).
  console.log('\nSetting up...\n');

  // Hint: Use `globalThis` to pass variables to global teardown.
  globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
};

#

i am working in an nx workspace

ionic quail
#

oh its CJS

#

nx?

#

CJS modules have to resolve immediately, so you can't wait thre

#

you might have to wait in a test instead

knotty fable
#

thats just the file that was auto generated when i created the nx workspace. So I'm guessig they want me to start services inside this file

ionic quail
#

Yeah but you cannot wait inside a CJS module, they are syncronous

#

So you either need a testing framework that uses ESM or has an async compatible startup, like it imports a function and waits for it. Or you need to wait for A to be ready in your async tests.

#

Maybe Jest has async setup

#

Oh!

#

yeah it's exporting a function, so you're good.

#

So in that case I would just return a Promise that pings server A until it's ready

knotty fable
#

I see

#

how would I run that other microservice programmaticaly?

ionic quail
#

What do you mean?

knotty fable
#

npx nx run treasury-microservice:serve

This is the command i use to start that microservice

ionic quail
#

You probably want to use spawn to run a command

knotty fable
#

I've tried but it keeps throwing errors

ionic quail
#
import { spawn, SpawnOptionsWithoutStdio } from 'child_process'
import { ArrayMinLength } from '../types/helpers.js'

export function spawnShellCommand(command: string, extras: SpawnOptionsWithoutStdio) {
    const parts = command.split(' ') as ArrayMinLength<string, 1> // eslint-disable-line no-type-assertion/no-type-assertion -- split returns an array of length at least 1
    // if (process.platform === 'win32') {
    //     parts[0] += '.cmd'
    // }
    const options = {
        shell: true,
        ...extras
    }
    return spawn(parts[0], parts.slice(1), options)
}
#
export type TupleOfLength<T, N extends number, Acc extends T[] = []> = Acc['length'] extends N ? Acc : TupleOfLength<T, N, [...Acc, T]>;
export type ArrayMinLength<T, N extends number> = [...TupleOfLength<T, N>, ...T[]];
#
const command = 'my command'
const service = spawnShellCommand(command, {
  //cwd: theDir 
})
knotty fable
#

ok ill give it a go

ionic quail
#

You can write it differently, but that's the function and helper types I use to make it nice.

#
    // if (process.platform === 'win32') {
    //     parts[0] += '.cmd'
    // }

This used to be needed on windows, but seems not now. Probably its only needed on older version of node.

knotty fable
#

Great it works

ionic quail
#

Cool

knotty fable
#

thanks so much. been stuck on that for ages

ionic quail
#

Are you able to wait for it to start OK?

#

You can either ping it in a promise, or just for the spawn to give you a certain output that indicates it's ready.

knotty fable
#

I mean a work around could be to just set a delay of 10s and then proceed right?

ionic quail
#

In your setup function

return new Promise<boolean>( (resolve, reject) => {
  const service = spawnShellCommand(command, { cwd: foo })
  service.on('data', (data: string) => {
    if (data.includes('Service Ready') resolve(true)
  })
}
#

You could add a timer to resolves with false, or rejects, after a period of time. But something like that should be good enough.

#

I didn't test that, data might be a buffer or something, but I think you can work it out

#

If it's a Buffer, you can probably just to data.toString()

knotty fable
#

Perfect thank you