nx icon indicating copy to clipboard operation
nx copied to clipboard

Cannot run cypress e2e tests for a node app

Open aleesaan opened this issue 3 years ago โ€ข 15 comments

Current Behavior

The @nrwl/cypress:cypress builder doesn't seem to work when I pass a node app (which is using the @nrwl/node:node builder) as the devServerTarget. The node app gets compiled and served correctly, but cypress just never starts.

Expected Behavior

After compiling and serving the app, cypress should start testing.

Steps to Reproduce

Create a new node app, create a new e2e app targeting it, and try running it.

Environment

nx report

 >  NX   Report complete - copy this into the issue template

   Node : 14.18.1
   OS   : darwin arm64
   npm  : 6.14.16
   
   nx : 14.2.4
   @nrwl/angular : 14.2.4
   @nrwl/cypress : 14.2.4
   @nrwl/detox : Not Found
   @nrwl/devkit : 14.2.4
   @nrwl/eslint-plugin-nx : 14.2.4
   @nrwl/express : 14.2.4
   @nrwl/jest : 14.2.4
   @nrwl/js : 14.2.4
   @nrwl/linter : 14.2.4
   @nrwl/nest : Not Found
   @nrwl/next : Not Found
   @nrwl/node : 14.2.4
   @nrwl/nx-cloud : Not Found
   @nrwl/nx-plugin : Not Found
   @nrwl/react : Not Found
   @nrwl/react-native : Not Found
   @nrwl/schematics : Not Found
   @nrwl/storybook : 14.2.4
   @nrwl/web : Not Found
   @nrwl/workspace : 14.2.4
   typescript : 4.5.5
   ---------------------------------------
   Community plugins:
   	 @ng-bootstrap/ng-bootstrap: 12.1.2
   	 @ngrx/component-store: 13.2.0
   	 @ngrx/effects: 13.2.0
   	 @ngrx/router-store: 13.2.0
   	 @ngrx/store: 13.2.0
   	 @ngrx/store-devtools: 13.2.0
   	 @nguniversal/common: 13.1.1
   	 @nguniversal/express-engine: 13.1.1
   	 @nguniversal/builders: 13.1.1

aleesaan avatar Jun 20 '22 14:06 aleesaan

having the same problems, glad someone's opened an issue :)

paul-leathwood avatar Jul 29 '22 15:07 paul-leathwood

Hi @aleesaan and @ple16 , thank you for reporting. A node:app does not really open any network port. What are you trying to e2e a node:app or did you mean express:app?

nartc avatar Aug 04 '22 08:08 nartc

Hi @nartc,

I have setup an example repo with the issue https://github.com/ple16/nx-node-app-e2e

So it contains a node app (@nrwl/node:node) with a Koa server. nx serve node-web-app and you can browse to http://localhost:3000 and see the message "Hello World"

The cypress app(@nrwl/cypress:cypress) is configured with "devServerTarget": "node-web-app:serve" nx e2e node-web-app-e2e does start the node app but doesn't continue with the cypress tests

paul-leathwood avatar Aug 04 '22 13:08 paul-leathwood

@ple16 Thanks for the repro. I'm taking a look now

nartc avatar Aug 04 '22 13:08 nartc

@ple16 Gotcha. Let me explain

A node:app from Nx perspective can be a CLI application or a Web Server like you just shared. Hence, node:node executor (aka serve) doesn't have options for host and port like the other web-based executors (eg: nrwl/web:file-server). The host/port combination of a node:app as a web server is constructed by the consumers via the server's entry point rather than the executor's options.

The nrwl/cypress:cypress executor expects the devServerTarget to output a baseUrl to use but node:node doesn't return any baseUrl, cypress:cypress failed. And this is the intended behavior as explained above.

What you can do is to explicitly add baseUrl to nrwl/cypress:cypress executor image

Extra info: You're probably aware but by default Cypress expects text/html with cy.visit(). In the case of a web server, you'd probably need cy.request() instead. Unless your web server returns some kind of views

nartc avatar Aug 04 '22 13:08 nartc

Thanks @nartc that makes sense however the suggestion of just adding the baseUrl doesn't appear to have any affect

> nx run node-web-app-e2e:e2e

chunk (runtime: main) main.js (main) 1.17 KiB [entry] [rendered]
webpack compiled successfully (6f11dc4313e30e09)
Debugger listening on ws://localhost:9229/2f4cdf2d-6b5c-4be0-a7f5-ee4243a0b4a4
Debugger listening on ws://localhost:9229/2f4cdf2d-6b5c-4be0-a7f5-ee4243a0b4a4
For help, see: https://nodejs.org/en/docs/inspector
Server listening on http://localhost:3000

I might have to switch to express (or take a look at the express generator and write a Koa version)

I understand the need to use cy.request() we've already done that to validate a graphql api

paul-leathwood avatar Aug 04 '22 15:08 paul-leathwood

Actually @nartc I've just noticed @nwrl/express:app also sets up a serve executor using node "executor": "@nrwl/node:node", so it looks like cypress wouldn't be compatible with the express generator?

paul-leathwood avatar Aug 04 '22 15:08 paul-leathwood

@ple16 hm...what if you:

  • Remove devServerTarget from nrwl/cypress:cypress (keeps the baseUrl there)
  • Run serve in a terminal
  • Run e2e in a separate terminal

Just want to see if it works that way. If yes, there might be a better option.

nartc avatar Aug 04 '22 15:08 nartc

Hi @nartc,

Yes it does work that way.

I've also just seen this pr https://github.com/nrwl/nx/pull/11325 and given that's it's switched to using the node executor for a custom server I think that's possibly going to introduce the issue with cypress being able to serve.

I think I'm going to have a crack at writing a little executor as per https://nx.dev/executors/creating-custom-builders that just calls the node executor but takes an additional prop when I can set the baseUrl and return just see if I can't trick cypress into running

paul-leathwood avatar Aug 04 '22 15:08 paul-leathwood

Hi @nartc,

A node:app does not really open any network port. What are you trying to e2e a node:app or did you mean express:app?

I indeed meant an express:app which uses the @nrwl/node:node builder, sorry about that! I'm not sure how to test that with cypress without needing to run two terminals (e.g. on CI).

aleesaan avatar Aug 07 '22 17:08 aleesaan

@ple16 and @aleesaan, thank you for the info. Sorry for the delayed response. I'm still looking for a solution for this to work in CI. Will report back as soon as I make some progress.

nartc avatar Aug 16 '22 04:08 nartc

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Aug 31 '22 00:08 github-actions[bot]

Not stale

nartc avatar Aug 31 '22 13:08 nartc

@nartc thank you, I did succeed by using spawn and hooking into the output of the command... can't say I'm truly happy with it but I'll paste it in as an example if anyone else runs into this thread.

It's a bit wild but basically we use it to spin up multiple apps to e2e the system as a whole when really I should be mocking our GraphQL layer. While I'm fairly experienced, mocking subscriptions is something I've never really tried before (I only started using cypress in anger 3 days ago)

import { ChildProcessWithoutNullStreams, spawn } from 'child_process';

import { ExecutorContext, logger } from '@nrwl/devkit';

type ReadyCheck = {
  check: RegExp;
  ready: boolean;
};

function checkReadiness(readyChecks: ReadyCheck[], text: string): boolean {
  for (const readyCheck of readyChecks) {
    if (readyCheck.check.test(text)) {
      logger.info(text);
      readyCheck.ready = true;
    }
  }

  return readyChecks.every(({ ready }) => ready);
}

export async function startAppUnderTest(
  devServerTarget: string,
  healthchecks: string | string[],
  prod: boolean,
  context: ExecutorContext
): Promise<ChildProcessWithoutNullStreams> {
  const readyChecks: ReadyCheck[] = Array.isArray(healthchecks)
    ? healthchecks.map((healthcheck) => ({ check: new RegExp(`\\b${healthcheck}\\b`, 'gi'), ready: false }))
    : [{ check: new RegExp(`\\b${healthchecks}\\b`, 'gi'), ready: false }];

  return new Promise<ChildProcessWithoutNullStreams>((resolve, reject) => {
    const prodArg = prod ? '--prod' : '';
    const testTarget = spawn(
      `nx run-many --target=serve --projects=${devServerTarget} ${prodArg} --parallel=100 --output-style=stream`,
      {
        cwd: context.cwd,
        shell: true,
        stdio: 'pipe',
      }
    );
    testTarget.stdout.on('data', async (data) => {
      const text = data.toString().trim();
      logger.log(text);
      if (checkReadiness(readyChecks, text)) {
        resolve(testTarget);
      }
    });
    testTarget.stderr.on('data', async (data) => {
      // TODO: dependsOn of devServerTarget is outputting in stdout, but devServerTarget is coming out in stderr???
      const text = data.toString().trim();
      logger.log(text);
      if (checkReadiness(readyChecks, text)) {
        resolve(testTarget);
      }
    });
    testTarget.on('error', (e) => {
      logger.error(`Failed to start subprocess: ${e.message}`);
      reject(e);
    });
    testTarget.on('exit', (code, signal) => {
      logger.error(`subprocess exited: ${code}:${signal}`);
      reject(new Error('subprocess exited'));
    });
    testTarget.on('close', (code, signal) => {
      logger.error(`subprocess closed: ${code}:${signal}`);
      reject(new Error('subprocess closed'));
    });
  });
}

paul-leathwood avatar Sep 06 '22 17:09 paul-leathwood

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Sep 21 '22 00:09 github-actions[bot]

Not stale. @ple16 thank you for the example.

We're still looking for an optimal way to do this.

nartc avatar Sep 23 '22 09:09 nartc

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Oct 09 '22 00:10 github-actions[bot]

Still not stale ๐Ÿ˜…

aleesaan avatar Oct 10 '22 09:10 aleesaan

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Oct 25 '22 00:10 github-actions[bot]

still no stale

nartc avatar Oct 25 '22 00:10 nartc

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Nov 09 '22 00:11 github-actions[bot]

Not stale ๐Ÿ™ˆ

aleesaan avatar Nov 09 '22 08:11 aleesaan

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Nov 25 '22 00:11 github-actions[bot]

Still not stale ๐Ÿ˜‡

aleesaan avatar Nov 28 '22 08:11 aleesaan

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Dec 13 '22 00:12 github-actions[bot]

Hey @nartc, any update? I keep bumping the issue every two weeks ๐Ÿ˜‚

aleesaan avatar Dec 13 '22 09:12 aleesaan

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Dec 29 '22 00:12 github-actions[bot]

Hi all, Thanks for opening this issue, I'm having it as well for a project I'm working on. Has there been any progress? Is the spawn solution suggested by @ple16 the best one yet? :)

matslexell avatar Jan 03 '23 11:01 matslexell

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐Ÿ™

github-actions[bot] avatar Jan 18 '23 00:01 github-actions[bot]

Not stale

matslexell avatar Jan 18 '23 11:01 matslexell