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

feature request: Component testing for StencilJS #24054

Open
Samuel-Schober-USU opened this issue Sep 30, 2022 · 19 comments
Open

feature request: Component testing for StencilJS #24054

Samuel-Schober-USU opened this issue Sep 30, 2022 · 19 comments
Labels
CT Issue related to component testing type: feature New feature that does not currently exist

Comments

@Samuel-Schober-USU
Copy link

What would you like?

Since more and more companies are using web components and StencilJS is often used for building them, it would be awesome if Cypress could support also StencilJS components in their component testing.

Why is this needed?

Our company is currently using the Puppeteer based approach for testing our web components, but since we are already testing our applications with Cypress, we would love to have it harmonized and use Cypress everywhere.

Maybe you can also have some future cooperation with the Stencil developers so they support Cypress testing as a default instead of Puppeteer.

Other

No response

@astone123 astone123 added type: feature New feature that does not currently exist CT Issue related to component testing labels Oct 3, 2022
@chris-kt
Copy link

VERY interested in this, as well. Seem like the lift may not be massive but the value would be tremendous for those invested in web component architecture.

@lmiller1990
Copy link
Contributor

Here's a simple example showing how to make a mount function for Web Components: https://github.com/lmiller1990/cypress-web-components-example

We can no doubt do something similar for Stencil!

@pedroresende
Copy link

Any news about this ?

@lmiller1990
Copy link
Contributor

@pedroresende Sure is, I'm working on a better way to add support for third party libraries to our onboarding workflow. You can follow that here: #25637

The code is almost done, I expect we can ship this before the end of Feb 2023. Then we can work on some Stencil integrations, without needing to make a PR against Cypress. There will be better documentation on how to integrate with Cypress (basically like https://github.com/lmiller1990/cypress-web-components-example, but once someone does it, everyone can re-use the integration).

I haven't used Stencil before, but it should be easy enough to integrate.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Feb 17, 2023

Hi @pedroresende @chris-kt @Samuel-Schober-USU, we have a public API for this feature coming in the next release.

If either of you is interested, you could either make your own one for Stencil now. If you want to work on it together or have any questions, please let me know.

@dpunna-ut
Copy link

Hi @pedroresende @chris-kt @Samuel-Schober-USU, we have a public API for this feature coming in the next release.

If either of you is interested, you could either make your own one for Stencil now. If you want to work on it together or have any questions, please let me know.

Hi @lmiller1990 - I'm looking into implement this for stencil js, it is currently not mounting the component using cypress. It would be good if you have any experience here

@lmiller1990
Copy link
Contributor

lmiller1990 commented Aug 2, 2023

Sure, got a repository I can contribute to or take a look at? Happy to help out, I know this still really well, would love to try writing some Stencil components and tests.

@dpunna-ut
Copy link

Sure, got a repository I can contribute to or take a look at? Happy to help out, I know this still really well, would love to try writing some Stencil components and tests.

Thats great! I have already started implementing, however for some reason i can't see the mounting component in the html. As shown in the screenshots

(1) `test-file.tsx'
Screenshot 2023-08-03 at 10 27 06

(2) 'test-file.cy.tsx`

Screenshot 2023-08-03 at 10 27 12

(3) Actual test in cypress
Screenshot 2023-08-03 at 10 27 22

@lmiller1990
Copy link
Contributor

Hi! Can you please post a minimal repository I can clone and run? Screenshots aren't something I'm able to debug.

@dpunna-ut
Copy link

dpunna-ut commented Aug 7, 2023

Hi! Can you please post a minimal repository I can clone and run? Screenshots aren't something I'm able to debug.

I managed to mount it by using your example function for mount

import { getContainerEl, setupHooks } from "@cypress/mount-utils";

function cleanup() {
  const root = getContainerEl();
  root.innerHTML = '';
}

export function mount(template) {
  const root = getContainerEl();
  root.innerHTML = template;

  // adds output to the command log
  return cy.wait(0, { log: false }).then(() => {
    Cypress.log({
      name: "mount",
      message: "Mounted component",
    });
  });
}

setupHooks(cleanup); 

It works if I do cy.mount(click me, however i'm not sure if I can pass the whole .ts` object to the mount? It looks the mount function for stencilJs cannot import the who file for the sourceCode, is that correct? If yes is there anyway we can do that?

Something like this cy.mount('<Button { ...defaultStatProps } />')

This is the code I used


import {
  defineCustomElements,
} from '../../../../dist/js/tk-components/loader';

import '../../../scss/ut_asset_toolkit.scss';

import { Button} from './button';

const defaultProps: Partial<Button> = {
  variant: 'destructive',
};

defineCustomElements(window);

describe('Mount button component', () => {
  beforeEach(() => {
      cy.mount(<Button { ...defaultProps } />)
    });
});

This is the ERROR:

The following error originated from your test code, not from Cypress.



  > Module parse failed: Unexpected token (10:18)

File was processed with these loaders:

 * ./node_modules/source-map-loader/dist/cjs.js

You may need an additional loader to handle the result of these loaders.

| import { Button} from './button';

|

> const defaultProps: Partial<Button> = {

|   variant: 'destructive',

| };

@lmiller1990
Copy link
Contributor

lmiller1990 commented Aug 7, 2023

^ problem is it does not know how to pass TS, normally we will grab your config (webpack/vite/whatever) but I'm not sure what the most common/default is for Stencil JS development.

Please post a minimal reproduction I can run, I'll help out. How do your normally make a Stencil JS app? Anything is possible and I will do my best to get a production ready Stencil JS adapter working but I can't piece together something based on snippets, I need a repo I can clone and tinker with.

@lmiller1990
Copy link
Contributor

Taking a look... I'm trying to build something but getting

import { Component, Prop, h } from '@stencil/core';

Gives

 The requested module '/__cypress/src/node_modules/.vite/deps/@stencil_core.js?v=15a1a7dc' does not provide an export named 'Component'

Same issue in Node.js:

> const s =require('@stencil/core')
undefined
> s
{ h: [Function (anonymous)] }

I do not know much about how Stencil works, it looks like they don't use a standard dev-server, so we will need to make it work with Vite / webpack or write an integration for their own thing.

@lmiller1990
Copy link
Contributor

Same issue if you log Component in the Stencil starter. How does this work? Is there some kind of internal preprocessing? The docs suggest Stencil is a compiler - I guess this export is a compile time thing?

image

@lmiller1990
Copy link
Contributor

Maybe we can use their dev server: https://stenciljs.com/docs/dev-server-api

@lmiller1990
Copy link
Contributor

lmiller1990 commented Aug 18, 2023

I tried but no luck yet

const { defineConfig } = require('cypress');
const devServer = require('@stencil/core/dev-server');
const compiler = require('@stencil/core/compiler');


module.exports = defineConfig({
  component: {
    devServer: async args => {
      const port = 5553;
      /** @type {import("@stencil/core/internal").StencilDevServerConfig} */
      const config = {
        port,
        root: '__cypress/src',
        logRequests: false
      };

      const logger = console;
      logger.createTimeSpan = () => {
        return {
          duration: 10000,
          finish: () => {
            return 2000
          },
        };
      };

      logger.getLevel = () => 4;
      devServer.start(config);

      return {
        port,
      };
    },
  },
});

How are you supposed to use the Stencil dev server?


Another alternative is to just build the prod bundle and test those. It's not really the fast feedback loop you'd want, but until we figure out how to integrate it, it's the best I can come up with. I got this working:
image

import { MyComponent } from '../../dist/components/my-component'

import { getContainerEl, setupHooks } from "@cypress/mount-utils";

function cleanup() {
  // runs after each test
}

function mount(template, options = {}) {
  for (const [tag, comp] of Object.entries(options.components ?? {})) {
    customElements.define(tag, comp);
  }

  // get the root element to mount the component
  const root = getContainerEl();
  root.innerHTML = template;

  // adds output to the command log
  return cy.wait(0, { log: false }).then(() => {
    Cypress.log({
      name: "mount",
      message: "Mounted component",
    });
  });
}

setupHooks(cleanup);

describe('ComponentName.cy.jsx', () => {
  it('playground', () => {
    mount(`<my-component first="Stencil" last="'Don't call me a framework' JS"></my-component>`, {
      components: {
        'my-component': MyComponent
      }
    })
  })
})

To do this I had to do npm run build and import the dist'd output. It's just a web component, so I followed my own guide: https://github.com/lmiller1990/cypress-web-components-example/tree/main

Who is the best person to talk to on the Stencil team about how to use their dev server? Maybe @JessicaSachs can point me in the right direction.

@lmiller1990 lmiller1990 reopened this Aug 18, 2023
@lmiller1990 lmiller1990 changed the title Component testing for StencilJS feature request: Component testing for StencilJS Aug 18, 2023
@junelau
Copy link

junelau commented Oct 19, 2023

hi @lmiller1990 - working off your example, I can get stencil's dev server started, but it closes within the stencil dev server startup process...

My devServer function in cypress.config.js is

devServer: async () => {
      const port = 3333;
      const config = {
        port,
        root: './'
      };

      const logger = stencilNode.createNodeLogger({process});

      const stencilServer = devServer.start(config, logger);

      return {
        port: port,
        close: {
          done: (await stencilServer).close(),
        },
      };
    },

Cypress' UI flickers to the "select browser" screen for a split second, and then I get a rather cryptic stack trace:

Error at S. (:4410:60024) at Object.onceWrapper (node:events:628:26) at S.emit (node:events:513:28) at S.emit (:4410:49620) at ChildProcess. (:4410:49047) at ChildProcess.emit (node:events:513:28) at emit (node:internal/child_process:937:14) at process.processTicksAndRejections (node:internal/process/task_queues:83:21)

While debugging, it seems to me that the stencil dev-server is shutting down due to the output "Debugger attached" being sent to stderr.
image

In console, I get:

dev server closed: 

@lmiller1990
Copy link
Contributor

I wonder why the Stencil dev server is dying. It's a bit of a black box - we'll need to find out how/why that isn't working. Do you have much knowledge of it? I had a quick look, but it looks like it isn't webpack or Vite based.

@CoderIllusionist
Copy link

CoderIllusionist commented Feb 17, 2024

@lmiller1990 I've created a package that integrates Stencil with Cypress' Component Testing :)
link

@lmiller1990
Copy link
Contributor

Neat, I will try it out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CT Issue related to component testing type: feature New feature that does not currently exist
Projects
None yet
Development

No branches or pull requests

10 participants