Code Monkey home page Code Monkey logo

cypress-angular-unit-test's Introduction

cypress-angular-unit-test

npm version renovate-app badge cypress version ci status cypress-angular-unit-test

Installation

npm install -D cypress cypress-angular-unit-test

Add to your support file

// cypress/support/index.js
// core-js 3.*
require('core-js/es/reflect');
// core-js 2.*
require('core-js/es7/reflect');
require('cypress-angular-unit-test/support');

Webpack config

Create a new file webpack.config.ts in cypress/plugins folder. You can find the file content here :

Cypress >= v7

npm install -D @cypress/webpack-dev-server html-webpack-plugin

Enable component testing in cypress.json.

{
  "component": {
    "componentFolder": "src/app",
    "testFiles": "**/*cy-spec.ts"
  }
}

Configure cypress/plugins/index.js to transpile Angular code.

const webpackConfig = require('./webpack.config');
const { startDevServer } = require('@cypress/webpack-dev-server');

module.exports = (on, config) => {
  on('dev-server:start', (options) =>
    startDevServer({
      options,
      webpackConfig,
    }),
  );
  return config;
};

Run npx cypress open-ct

Cypress < v7

npm install -D @cypress/webpack-preprocessor

Enable experimental component testing mode in cypress.json and point at the spec files. Usually they are alongside your application files in src folder.

{
  "experimentalComponentTesting": true,
  "componentFolder": "src",
  "testFiles": "**/*cy-spec.*"
}

Configure cypress/plugins/index.js to transpile Angular code.

const wp = require('@cypress/webpack-preprocessor');
const webpackConfig = require('./webpack.config');
module.exports = (on, config) => {
  const options = {
    webpackConfig,
  };
  on('file:preprocessor', wp(options));
  return config;
};

Run npx cypress open

Use

import { mount } from 'cypress-angular-unit-test';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  it('shows the input', () => {
    // Init Angular stuff
    initEnv(AppComponent);
    // You can also :
    // initEnv({declarations: [AppComponent]});
    // initEnv({imports: [MyModule]});

    // component + any inputs object
    mount(AppComponent, { title: 'World' });
    // use any Cypress command afterwards
    cy.contains('Welcome to World!');
  });
});

Demo

Examples

Use case Description
Input Test inject @Input() value
Output Test catching @Output()
Bootstrap Bootstrap integration with style : setConfig({ stylesheet: 'https://...});
Add style Add custom style for testing : setConfig({ style: 'p {background-color: blue;}' });
HTML mount Mount a component with html, don't forget to call detectChanges() after
Image Snapshot Mount a component and visual asserting
Material Material integration
Prime NG PrimeNG integration
OnPush strategy Component with changeDetection: ChangeDetectionStrategy.OnPush need call detectChanges()
Directive Test directive with mountHtml
Pipe Test pipe with mountHtml
Stub service Stub a service with Observable
Only service Test a service without a component
Web Component Test a custom element with shadow dom
Assets assets folder accessible by Cypress
Async Async test with cy.tick
Routing Test routing link
Network Test with http calls
NGRX NGRX store

Code coverage

Integration test

  • Install ngx-build-plus to extends the Angular CLI's build process and instrument the code

npm i -D ngx-build-plus

  • Add webpack coverage config file coverage.webpack.js to cypress folder
module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|ts)$/,
        loader: 'istanbul-instrumenter-loader',
        options: { esModules: true },
        enforce: 'post',
        include: require('path').join(__dirname, '..', 'src'),
        exclude: [
          /\.(e2e|spec)\.ts$/,
          /node_modules/,
          /(ngfactory|ngstyle)\.js/,
        ],
      },
    ],
  },
};
  • Update angular.json to use ngx-build with extra config
"serve": {
  "builder": "ngx-build-plus:dev-server",
  "options": {
    "browserTarget": "cypress-angular-coverage-example:build",
    "extraWebpackConfig": "./cypress/coverage.webpack.js"
  },
}
  • Instrument JS files with istanbul for code coverage reporting

npm i -D istanbul-instrumenter-loader

  • Add cypress code coverage plugin

npm install -D @cypress/code-coverage

  • Then add the code below to your supportFile and pluginsFile
// cypress/support/index.js
import '@cypress/code-coverage/support';
// cypress/plugins/index.js
module.exports = (on, config) => {
  require('@cypress/code-coverage/task')(on, config);
  return config;
};

source : https://github.com/skylock/cypress-angular-coverage-example

Unit test

  • Instrument JS files with istanbul for code coverage reporting

npm i -D istanbul-instrumenter-loader

  • In your cypress/plugins/cy-ts-preprocessor.ts add this rule
rules: [
  {
    test: /\.(js|ts)$/,
    loader: 'istanbul-instrumenter-loader',
    options: { esModules: true },
    enforce: 'post',
    include: path.join(__dirname, '../..', 'src'),
    exclude: [/\.(e2e|spec)\.ts$/, /node_modules/, /(ngfactory|ngstyle)\.js/],
  },
];

Report

You can find the HTML report at coverage/lcov-report/index.html

Working

I have successfully used this mounting approach to test components in other frameworks.

Debugging

You can turn on debugging log by setting environment variable :

// Unix
export DEBUG="cypress-angular-unit-test,cypress:webpack:stats"

// PowerShell
$env:DEBUG="cypress-angular-unit-test,cypress:webpack:stats"

Development

This project only transpiles the library, to see it in action:

  • Install dependencies npm i
  • Compile the library npm run build
  • Open Cypress with npx cypress open

Pick any component test spec file to run

cypress-angular-unit-test's People

Contributors

ahmedhalat avatar bahmutov avatar geocine avatar lejeanbono avatar medavid avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cypress-angular-unit-test's Issues

Components and Styles not rendering

from #277

Current behavior

I've created a repo that contains two components, and two tests. Both show different issues.

  1. The CardComponent Spec isn't getting rendered because it uses a third party libraries to render SVG (needed for our usecase) which throws an error in cypress:
Error: Can't resolve all parameters for InlineSVGComponent: (?, ?).
    at syntaxError (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:10366)
    at CompileMetadataResolver._getDependenciesMetadata (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:30280)
    at CompileMetadataResolver._getTypeMetadata (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:30175)
    at CompileMetadataResolver.getNonNormalizedDirectiveMetadata (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:29790)
    at CompileMetadataResolver._getEntryComponentMetadata (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:30375)
    at eval (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:30031)
    at Array.map (<anonymous>)
    at CompileMetadataResolver.getNgModuleMetadata (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:30031)
    at CompileMetadataResolver.getNgModuleSummary (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:29859)
    at eval (:55857/__cypress/tests?p=projects/cyng-oasis/src/lib/container/card/card.component.spec.ts:29941) 
  1. The CheckboxComponent Spec shows that styles aren't loaded into cypress. You can use Storybook to see how the component should look like. Further details in the Readme.

Desired behavior

  1. Components should be rendering even when not using the @Inject() (which shouldn't be needed since we are not using custom provider). Especially since I can't change how third party components inject their dependencies.

  2. The styles (CSS,SCSS,SASS) should be loading in cypress, since those are important for the UI and therefore testing.

Test code to reproduce

The repo I created is here.

Versions

    "@angular/core": "~10.2.1",
    "@angular/material": "^10.2.6",
    "cypress": "^6.1.0",
    "cypress-angular-unit-test": "^3.6.0",

Thanks :)

SyntaxError: 'import' and 'export' may appear only with 'sourceType: module

I've copied your cypress/integration/spec.ts file to my cypress/integration/ folder, but when I try to open (cypress open), I'm getting this error:

SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' (4:0) while parsing /code/pricing-proj/pricing-ui/dev/pricing-portal-ui/cypress/integration/test-ng.ts while parsing file: /code/pricing-proj/pricing-ui/dev/pricing-portal-ui/cypress/integration/test-ng.ts

I have my tsconfig.spec.json set to use module: "commonjs".

tsconfig.json
`{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"sourceMap": true,
"skipLibCheck": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",
"baseUrl": "./",
"module": "commonjs",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
],
"baseUrl": "./node_modules",
"paths": {
"core-js/es7/reflect": [
"../node_modules/core-js/proposals/reflect-metadata"
],
"core-js/es6/": ["../node_modules/core-js/es"],
"core-js/es7/
": ["../node_modules/core-js/es"]
}
},
"exclude": [
"**/.spec.ts",
"./node_modules/
"
]

}`

tsconfig.spec.json
{ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/spec", "module": "commonjs", "types": [ "jasmine", "node" ] }, "files": [ "test.ts", "polyfills.ts" ], "include": [ "**/*.spec.ts", "**/*.d.ts" ] }

Do you know what might be the issue?

Error importing typescript when located outside module under test in nx monorepo

I am trying to run unit test in an angular project using nx.

When importing ts files which located in a different folder I an error.

This is the import statement:

import { Option, parseInteger } from '../../../../libs/utils/src/index';

Error:

Module parse failed: Unexpected token (18:29)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|  * If an empty list of observables is provided, this will emit []
|  */
> export function flattenLatest<T>(observables: Observable<T[]>[]): Observable<T[]> {
|   const sources = observables.map(obs => obs.pipe(startWith<T[]>([])));
|   if (sources.length === 0) {

It appears to fail because it does not recognise it as typescript.

The following import does work:

import { test } from './myfunction'

The state of this repository?

I would really like to try unit testing with Cypress for our Angular application, but I can't get this to work:

  • According to the readme, the code in this repository still doesn't work. According to this pull request it should work.

  • When I try to clone the repository I get a lot of TypeScript errors, so I can't see if it works:

E:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts
๏ฟฝ[tsl] ๏ฟฝ๏ฟฝ๏ฟฝERROR๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ in ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝE:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts(138,47)๏ฟฝ๏ฟฝ
๏ฟฝ๏ฟฝ      TS1005: ';' expected.๏ฟฝ๏ฟฝ

E:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts
๏ฟฝ[tsl] ๏ฟฝ๏ฟฝ๏ฟฝERROR๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ in ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝE:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts(138,90)๏ฟฝ๏ฟฝ
๏ฟฝ๏ฟฝ      TS1005: '(' expected.๏ฟฝ๏ฟฝ

E:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts
๏ฟฝ[tsl] ๏ฟฝ๏ฟฝ๏ฟฝERROR๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ in ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝE:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts(138,104)๏ฟฝ๏ฟฝ
๏ฟฝ๏ฟฝ      TS1005: ']' expected.๏ฟฝ๏ฟฝ

E:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts
๏ฟฝ[tsl] ๏ฟฝ๏ฟฝ๏ฟฝERROR๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ in ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝE:\Projects\libraries\cypress-angular-unit-test\node_modules\@types\jasmine\index.d.ts(138,112)๏ฟฝ๏ฟฝ
๏ฟฝ๏ฟฝ      TS1005: ',' expected.๏ฟฝ๏ฟฝ
  • Unlike the other cypress-*-unit-test packages (like Vue), cypress-angular-unit-test does not have an NPM package.

  • The Angular version used here is 5. I don't know if this will create compatibility errors when using Angular 6 or 7.

  • If it does work, the readme is seriously outdated.

  • I don't know if this repo is still being maintained.

Does this actually work? What are all those TypeScript errors? I'd like to create a PR, but I don't know how to fix those errors.

Unit testing without UI

Hi,
Is there a way to perform unit testing in angular apps without UI, ie., test specific components / services / directives. I am new to unit testing on JS frameworks, so a bit confused whether the mentioned UI unit test is the usual approach or testing individual components (like they do in jasmine and karma) is the general one

Testing Angular Service

I have problems with creating unit tests for my AuthService properties and methods. I couldn`t find any example on the web. Please, can u provide an example?

Improve angular component mounting

Appreciate your work on Component Testing using Cypress across frameworks.

It would be great to be able to mount an Angular component like you can in React

describe('Display', () => {
  beforeEach(() => {
    mount(<Display value="100" />)
  })

  it('shows prop value', () => {
    cy.contains('.component-display', '100')
  })
})

This is possible in Angular Spectator (equivalent of React Enzyme)

it('should display the title', () => {
    host = createHost(`<zippy title="Zippy title"></zippy>`);

    expect(host.query('.zippy__title')).toHaveText(( text ) => 'Zippy title');
  });

Also possible in the cross-framework DOM Testing Library

test('should render counter', async () => {
    const { getByText } = await render(CounterComponent, {
      componentProperties: { counter: 5 },
    })

    expect(getByText('Current Count: 5'))
  })

Understand you still need to create an full HTML DOM angular app first, but as far as loading an angular component with props and provider injection maybe their source code is of use to improve things?

Release new component mounting method

Trying in https://github.com/bahmutov/cypress-angular-unit-test/tree/try-as-component-spec

  • clone the repository
  • git checkout try-as-component-spec
  • Install dependencies with npm i
  • npm run cy:open
  • click on the component spec filename

Screen Shot 2020-05-06 at 10 13 52 AM

but hitting an error

Screen Shot 2020-05-05 at 3 58 01 PM

The test tries to import and bootstrap a module

import 'core-js/es7/reflect';
import { ApplicationRef, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import 'zone.js';
import { AppComponent } from '../../src/app/app.component';

// dynamic loading based on blog post
// https://blog.angularindepth.com/how-to-manually-bootstrap-an-angular-application-9a36ccf86429

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  entryComponents: [AppComponent]
})
class AppModule {
  app: ApplicationRef;
  ngDoBootstrap(app: ApplicationRef) {
    debugger
    this.app = app;
  }
}

/* eslint-env mocha */
/* global cy */
describe('AppComponent', () => {
  beforeEach(() => {
    const html = `
      <head>
        <meta charset="UTF-8">
      </head>
      <body>
        <app-root></app-root>
      </body>
    `;
    const document = (cy as any).state('document');
    document.write(html);
    document.close();

    cy.get('app-root').then(el$ => {
      platformBrowserDynamic()
        .bootstrapModule(AppModule)
        .then(function (moduleRef) {
          moduleRef.instance.app.bootstrap(AppComponent, el$.get(0));
        });
    });
  });
})

Can't load MaterialUI styles

Hi man!
I am learning to write tests for my components using cypress, and I ran into such a problem - when using third-party libraries, the webpack config does not pull up the library styles of the imported module.

describe('Basics', () => {
  it('Shows navigation panel', () => {
    initEnv(AppComponent, {
      imports: [
        AppRoutingModule,
        MatTabsModule,
        HomeModule,
        LoginModule,
        BookModule,
        FavouritesModule,
        OptionsModule,
        AccountModule,
      ],
      providers: [AuthService, AuthGuard, { provide: APP_BASE_HREF, useValue: '/' }],
    });
    mount(AppComponent, {});
    cy.findByTestId(/navigation/).should('exist');
  });
});

Can you help meะฑ how to configure the webpack config so that it loads the styles of third-party modules.

Does not work with components which has changeDetection: ChangeDetectionStrategy.OnPush

Hi
Great and very interesting work, I have used it with angular 9 with only one problem.
There are problems with components that has ChangeDetectionStrategy.OnPush.
I have played around with your code and even returned a componentRef.instance, where I set input and an app where I call tick.
I have tried different things, like componentRef.changeDetectorRef.markForCheck(); but can still not get it to work.
It might be because there is no view?
Do you have any idea how to fix this?
Thanks

Loading assets like images using document.documentElement.style.setProperty

Trying to load an image onto a web page.

Using scss:

.logo {
    width: 200px;
    height: 64px;
    background-image: var(--image-logo);
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
}

HTML looks like:

<div class="logo"></div>

Code to set the --image-logo

document.documentElement.style.setProperty(
      `--image-logo`,
      `url('assets/images/logo')`
  );

Webpack looks like this:

const webpackOptions = {
  resolve: {
    extensions: ['.ts', '.js'],
    alias: {
        assets: path.resolve(__dirname, '../../src/assets'),
    }
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        // loaders: ['ts-loader', 'angular2-template-loader'],
        use: [{
          loader: 'ts-loader',
          options: {
            transpileOnly: true
          }
        }, {
          loader: 'angular2-template-loader'
        }],
        exclude: [/node_modules/],
      },
      {
        test: /\.(css)$/,
        loaders: ['to-string-loader', 'css-loader', 'sass-loader'],
        exclude: /\.async\.(css)$/
      },
      {
        test: /\.(scss)$/,
        loaders: ['to-string-loader', 'css-loader', 'sass-loader'],
        exclude: /\.async\.(css)$/
      },
      {
        test: /\.(html)$/,
        loader: 'html-loader',
        exclude: /\.async\.(css)$/
      },
      {
        test: /\.async\.(html|css)$/,
        loaders: ['file?name=[name].[hash].[ext]', 'extract']
      },
      {
          test: /\.(png|svg|jpg|gif)$/,
          loader: 'file-loader',
      },
    ]
  }
}

When mounting components with these settings and code execution. Cypress throws a 404 unable to find the resource even though explicitly indication in webpack that assets is in that specific location.

Screenshot from 2020-10-04 21-19-36

Am I doing something wrong here?
I noticed that the URL where it is searching for the asset is incorrect.

Loading styles (CSS/SCSS/SASS) stored under assets for all components

Hi @LeJeanbono this is a question in regards to the assets.
At the moment the project I am trying to get to load assets for all components with styles stored in subfolders under assets. Now I am not sure exactly what each component requires, but is it possible to load all those assets stored in subfolders of subfolders and bundle them up. Cos at the moment I need to do the following:

        "src/app/login/login.component.scss",
        // "src/assets/styles/main.scss",
        // "src/assets/styles/partials/_all.scss",
        // "src/assets/styles/base/_all.scss",
        "node_modules/primeng/resources/primeng.min.css",
        "node_modules/@fullcalendar/core/main.css",
        "node_modules/@fullcalendar/daygrid/main.css",
        "node_modules/quill/dist/quill.snow.css",
        "node_modules/primeicons/primeicons.css",
        "src/assets/styles/variables.css",
      ], stylesheets: [
        "/assets/monaco/vs/loader.js",
        "/assets/styles/partials/_common.scss",
        "/assets/styles/partials/_dashboard.scss",
        "/assets/styles/partials/_forms.scss",
        "/assets/styles/partials/_icons.scss",
        "/assets/styles/partials/_login.scss",
        "/assets/styles/partials/_main.scss",
        "/assets/styles/partials/_menu.scss",
        "/assets/styles/partials/_message.scss",
        "/assets/styles/partials/_misc.scss",
        "/assets/styles/partials/_overlay.scss",
        "/assets/styles/partials/_panel.scss",
        "/assets/styles/partials/_quick-actions.scss",
        "/assets/styles/partials/_splash.scss",
        "/assets/styles/partials/_utils.scss",
        "/assets/styles/partials/_data.scss",
        "/assets/styles/base/_common.scss",
        "/assets/styles/base/_defaults.scss",
        "/assets/styles/base/_fonts.scss",
        "/assets/styles/base/_layout.scss",
        "/styles.scss",
      ], detectChanges: true });```

initEnv's & initEnvHtml's component parameter should be removed

Current Behavior

initEnv's & initEnvHtml's first parameter is a component that should be added to TestBed's declarations.

In most cases, developers will import the module containing the component to avoid redeclaring all the imported dependencies like this:

initEnvHtml(undefined, {imports: [MyTestedModule]});
mount(MyTestedComponent);

instead of:

initEnv(MyTestedComponent, {imports: [AModule, BModule]});
mount(MyTestedComponent)

because in the latter case, developers will have to maintain the imports as the test is coupled to the implementation details.

In the rare cases where developers want to declare a component without importing modules, they can still use TestModuleMetadata.declarations like this:

initEnvHtml(undefined, {declarations: [MyTestedComponent]});

Using declarations is natural and least surprising for Angular developers.

Issues with current behavior

  1. Developers have to declare components|pipes|directives instead of importing the containing module.
  2. Declaring a component and importing the containing module will produce a duplicate declaration error.
  3. In order to just import the containing module, we have to call initEnvHtml(undefined, {imports: ...}) which is not very intuitive nor convenient.

Suggestions

Here are some suggestions that avoid introducing any breaking changes.

A. Deprecate initEnv and initEnvHtml and introduce a new function for initializing the environment that only takes moduleDef as a single parameter.

Ideas for naming the function are welcome! I am currently thinking of initTestBed or configure or setUpEnv.

initTestBed({declarations: [MyTestedComponent});
initTestBed({imports: [MyTestedModule]});

B. This one can be an addition to A.
In order to make things easier when developers only have one test in a test block, we can merge mount and init in one function by passing the moduleDef

B.1. ... as an additional parameter

mount(MyTestedComponent, {myInput: 'hello'}, {imports: [MyTestedModule]});

B.2. ... or a parameter also containing the inputs

mount(MyTestedComponent, {
  imports: [MyTestedModule]
  inputs: {myInput: 'hello'}
});

C. Keep things like they are and let Younes cry ๐Ÿ˜ญ

I'll be more than happy to contribute with a PR if we agree on the issue and a solution.

Uncaught Error: No component factory found for ClientDetailsComponent.

Uncaught Error: No component factory found for ClientDetailsComponent. Did you add it to @NgModule.entryComponents?

Hello.
Angular 10 App
ClientDetailsComponent is dynamically loaded at runtime and is present in the @NgModule.entryComponents
The app is working with ng serve but it shows that error when running cypress with your extension.
I also tried to this setup without success

    initEnv(AppComponent, {
      providers: [MyMqttService, CommandHandlerService, ClientDetailsComponentFactoryService, EnvService],
      declarations: [ClientDetailsComponent],
      imports: [FormsModule, HttpClientModule, MqttModule.forRoot(MQTT_SERVICE_OPTIONS)],
    });
    getCypressTestBed().configureTestingModule({declarations: [ClientDetailsComponent]})
    getCypressTestBed().overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [ClientDetailsComponent] } })

Could you help me?
Thanks in advance
Giancarlo

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm ng-inline-svg Unavailable
npm tslint Unavailable

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency @cypress/code-coverage to v3.12.44
  • chore(deps): update dependency @types/node to v16.18.105
  • chore(deps): update dependency ng-inline-svg to v13.1.2
  • chore(deps): update dependency tslib to v2.6.3
  • fix(deps): update dependency debug to v4.3.6
  • chore(deps): update dependency core-js to v3.38.0
  • chore(deps): update dependency @cypress/webpack-preprocessor to v6
  • chore(deps): update dependency @types/node to v20
  • chore(deps): update dependency cypress to v13
  • chore(deps): update dependency html-loader to v5
  • chore(deps): update dependency husky to v9
  • chore(deps): update dependency ngx-build-plus to v18
  • chore(deps): update dependency prettier to v3
  • chore(deps): update dependency pretty-quick to v4
  • chore(deps): update dependency primeng to v17
  • chore(deps): update dependency semantic-release to v24
  • chore(deps): update dependency tslint to v6
  • chore(deps): update dependency typescript to v5
  • chore(deps): update dependency webpack-dev-server to v5
  • fix(deps): update dependency @cypress/mount-utils to v4
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/badges.yml
  • actions/checkout v2
.github/workflows/ci.yml
  • actions/checkout v2
  • cypress-io/github-action v2
  • actions/upload-artifact v2
.github/workflows/release.yml
  • actions/checkout v2
  • cypress-io/github-action v2
  • cycjimmy/semantic-release-action v2
npm
package.json
  • @cypress/mount-utils 1.0.2
  • debug 4.3.4
  • @angular-devkit/build-angular 12.2.18
  • @angular/animations 12.2.17
  • @angular/cdk 12.2.13
  • @angular/cli 12.2.18
  • @angular/common 12.2.17
  • @angular/compiler 12.2.17
  • @angular/compiler-cli 12.2.17
  • @angular/core 12.2.17
  • @angular/forms 12.2.17
  • @angular/language-service 12.2.17
  • @angular/localize 12.2.17
  • @angular/material 12.2.13
  • @angular/platform-browser 12.2.17
  • @angular/platform-browser-dynamic 12.2.17
  • @angular/router 12.2.17
  • @cypress/code-coverage 3.12.23
  • @cypress/webpack-dev-server 1.8.4
  • @cypress/webpack-preprocessor 5.17.1
  • @ngrx/store 12.5.1
  • @types/cypress-image-snapshot 3.1.9
  • @types/node 16.18.82
  • angular-router-loader 0.8.5
  • angular2-template-loader 0.6.2
  • codelyzer 6.0.2
  • core-js 3.36.0
  • cypress 9.7.0
  • cypress-image-snapshot 4.0.1
  • html-loader 3.1.2
  • html-webpack-plugin 5.6.0
  • husky 7.0.4
  • istanbul-instrumenter-loader 3.0.1
  • ng-inline-svg 13.1.1
  • ngx-build-plus 12.2.0
  • prettier 2.8.8
  • pretty-quick 3.3.1
  • primeng 13.4.1
  • raw-loader 1.0.0
  • rxjs 7.8.1
  • semantic-release 19.0.5
  • to-string-loader 1.2.0
  • ts-loader 9.5.1
  • ts-node 10.9.2
  • tslib 2.6.2
  • tslint 5.20.1
  • typescript 4.6.2
  • webpack-dev-server 3.11.3
  • zone.js 0.13.1
  • @angular/common *
  • @angular/compiler *
  • @angular/core *
  • @angular/platform-browser *
  • @angular/platform-browser-dynamic *
  • html-webpack-plugin >=4
  • core-js *
  • zone.js *

  • Check this box to trigger a request for Renovate to run again on this repository

Issues when setting up (in an Angular CLI Library project)

There are a few things I stumbled over when trying to set up cypress-angular-unit-test for our Angular Component Library.
Currently it looks like the repo is setup in a way to test components of an application. But we want to test components of a library. Here they come:

  • First of all the guide tells you to modify the cypress config files. It could use a note that you need to run cypress once for the config files to be generated. Just a little thing but the guide should just give you a small heads up.

  • Next the guide tells you to import the typescript file "cy-ts-preprocessor.ts" in the javascript file "index.js". It doesn't work out. You actually need to make "cypress/plugin/index.js" a typescript file i.e. rename it to "cyrpress/plugin/index.ts" and tell the cypress json, what the index file is. ( "pluginsFile": "cypress/plugins/index.ts"). Also the helper.ts isn't mentioned.

  • Now cypress finally launches and you can start writing a test. But when running your first test you notice, that it can't resolve "angular2-template-loader". That also needs to be installed via NPM.

  • Then it says it can't resolve 'cypress-angular-unit-test/support'. I actually have to call require('cypress-angular-unit-test/dist/support');. Not sure why this is here. Last time i tried it, it wasn't an issue.

  • Next up I can't render the component because it says "Expected 'styles' to be an array of strings.". So something is off with the webpack config. I change cy-ts-preprocessor to not use raw-loader for css/scss files but to-string-loader in the following way:

{
    test: /\.(css|scss)$/,
    loaders: ['to-string-loader', 'css-loader', 'sass-loader']
}

(we are using .scss files for this library)

  • Then it says "The template specified for component CardComponent is not a string". I use html-loader instead of raw-loader and it seems to work.

  • After all that we come to the more curious stuff. I get some template parse errors. After updating the test, to include all needed modules, it says it can not resolve all parameters for a specific third-party-component that is used inside of a component that is used in the component that i test here. "Can't resolve all parameters for InlineSVGComponent: (?, ?)."

  • after removing every mention of the icon component that uses the third-party InlineSVGComponent i see that the test now finally runs and loads my component, but without any Styling whatsoever.

The Spec File for my test:

import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { initEnv, mount } from 'cypress-angular-unit-test';
import { ButtonModule } from '../../button/button.module';
import { LoadingModule } from '../../misc/loading/loading.module';
import { CardComponent } from './card.component';

describe('CardComponent', () => {
  it('shows the input', () => {
    // Init Angular stuff
    initEnv(CardComponent, {
      imports: [
        CommonModule,
        ButtonModule,
        TranslateModule,
        LoadingModule,
      ]
    });
    // component + any inputs object
    mount(CardComponent, { title: 'Hello World' });
    // use any Cypress command afterwards
    cy.contains('Hello World');
  });
});

So yeah this leaves me with a situation that doesn't allow me to use cypress to unit test my angular components, because the styles arent loading and i cant't even load all needed components.

Im pretty sure most of this has to do with the loader situation. Im not sure why the raw-loader throws these errors, and why the other loaders dont seem to include the css correctly.

If anyone has any clues please hit me up. If anyone needs more code ill talk with my boss about it.

EDIT:
I found out, after some testing that i get the same "Can't resolve all parameters for CheckboxComponent: (?)." error when trying to render components with paramters in their constuctors. Like the CheckboxComponent for example has the following constructor:

  constructor(injector: Injector) {
    super(injector);
  }

So the (?) is signifying the injector parameter. No clue how to resolve this tho.

Requires the ability to load the entire component module.

I tried writing a unit test for a simple component that uses Modules from Material Design and custom directives. As a result, I ran into the problem that I have to import the directive (otherwise, the component initialization fails with an error), but another error occurs.
It would be much easier if the documentation showed examples of testing complex components, or at least links to the main "possible" problems.

spec-without-declaration
spec-without-declaration-error

Fix support file import

Current behavior

From #277
Since support file have been converted in TS, the import path is cypress-angular-unit-test/dist/support.

Desired behavior

Should remove the dist folder from the path.

"Mocha" has already been patched with "Zone" Error occurs when Async test with waitForAsync()

Description

I have add asynchronous unit test cases (e.g REST API calls) using angular testBed and running the test suite with cypress test runner. It executes all test cases and passed for very first time without no Issues. On subsequent changes made to the spec file (or) Run all Tests again cause this issue

image

Import file

import 'zone.js/dist/zone-testing'; this dependency must be added to handle async methods via waitForAsync() before all imports in spec.js file / in the cypress->support.js file.

Support Needed

I know the message says it not related cypress but i don't know how to approach this problem in-terms of loading this dependency in test suite or the zone.js package itself have issues. Any Suggestions please from the community?

Need to package actual code

The code that is now in spec-private-api.ts beforeEach and make it into a reusable function other projects can use to run their Angular components

Expected 'styles' to be an array of strings.

I followed your example for the SCSS styles I indicated that I was to use the raw-loader & sass-loader in the webpack.config.

But I receive the following error:

Expected 'styles' to be an array of strings.
Because this error occurred during a before each hook we are skipping the remaining tests in the current suite: Login

issue

Cant execute HTTPClient request with TDD

I am struggling to get the HTTPClient requests from a service and even from a Component call.

Below is my Test file for a service call.

import {  HttpClientModule, HttpClient, HttpHandler  } from '@angular/common/http';
import { getTestBed  } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { SPOperationService } from './spoperation.service';

describe('SPOperationService', () => {

  let service: SPOperationService;
  before(() => {
    getTestBed().resetTestEnvironment();
    getTestBed().initTestEnvironment(
      BrowserDynamicTestingModule,
      platformBrowserDynamicTesting(),
    );
    getTestBed().configureTestingModule({
      providers: [SPOperationService, HttpClientModule, HttpClient, HttpHandler]
    });

    service = getTestBed().inject(SPOperationService);
  });

  it('Check service values', () => {
    const res = service.setBaseUrl("http://localhost:8080/sites/Medcomqa"); //// Sets the call to see if the 
    service.getUserInfo(103).then(res1 =>{ console.log(res1);});

    service.getUsers().then(res2=>{console.log(res2);});
    expect(1).equals(1);
  });

});

Definitions for the two function getUserInfo and getUsers. This is a partial definition of the whole TS

import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
export class SPOperationService {

constructor(private httpClient: HttpClient) { }

  async getUserInfo(id: number) {
    const url = this.getUserURL(id);
    console.log(url); //// http://localhost:8080/sites/Medcomqa/_api/web/getUserById(103)?$expand=Groups
    const res = await this.httpClient.get(url,).toPromise().catch((err: HttpErrorResponse) => {
      const error = err.error;
      return error;
    });
    console.log(res); //// Returns undefined. 
    return this.parseRetSingle(res); //// This can be excepted as the above result is undefined. 
  }

  async getUsers() {
    let result = await this.httpClient.get('https://jsonplaceholder.cypress.io/users?_limit=3',).toPromise().catch((err: HttpErrorResponse) => {
      const error = err.error;
      return error;
    });
    console.log("Await one" +  result); //// Returns undefined. 
    return result;
  }

}

I tried my own run and even the example code but both doesn't create any actual HTTP call. I don't receive any error in the catch but just an undefined value when I log after the call.

I updated the code of the sample to see if there is any issue with my code but the example code creates a HTTP call.

Network component.ts

import { Component, OnInit } from '@angular/core';
import { NetworkService } from '../network.service';

@Component({
  selector: 'app-network',
  templateUrl: './network.component.html',
  styleUrls: ['./network.component.css'],
})
export class NetworkComponent implements OnInit {
  users = [];

  constructor(private networkService: NetworkService) {}

  async ngOnInit(): Promise<void> {
    let res = await this.networkService.getUsers();
    console.log(res);
    this.users = res;
      //.subscribe((response) => (this.users = response));
  }
}

Network service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class NetworkService {
  constructor(private httpClient: HttpClient) {}

  async getUsers() {
    // return this.httpClient.get<any[]>(
    //   'https://jsonplaceholder.cypress.io/users?_limit=3',
    // );

    let result = await this.httpClient.get('http://localhost:8080/sites/Medcomqa/_api/web/getUserById(103)?$expand=Groups',)
    .toPromise().catch((err: HttpErrorResponse) => {
      const error = err.error;
      return error;
    });

    return result; //// Provides me with result on the sample solution but not in my solution. 
  }
}

I compared both the sample solution and my solution and could only find two difference

  1. The Angular version. I am using 11.0.0 while the sample solution is using 11.2.11 so in the sample .ToPromise() comes deprecated while it doesn't provides me with that issue.
  2. My Angular solution is configured to serve with a proxy settings to redirect calls to port 8080 on local environment. For this reason in my testbed I added a call to set the URL to 8080 for all my HTTPClient calls but it didn't worked.

node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --proxy-config proxy.conf.json

proxy.conf.json

{
  "/sites/*": {
      "target": "http://localhost:8080",
      "secure": false,
      "changeOrigin": true,
      "logLevel": "debug",
      "pathRewrite": {"^/sites" : "http://localhost:8080/sites"}
    }
}

I cant upgrade to 11.2.11 now as it started giving me some issues. Is there any other configurations I need to make for the HTTP calls to work from TestBed. I will be happy to provide the whole solution also if there is an need to the same.

Do you have any test example to work with *.d.ts file

amp-configuration-ui

Currently, I am getting an web compilation error if component uses declaration typescript file.

example: .d.ts file

export interface Schedulable {
calendar?: CalendarPattern;
startDate?: Date;
stopDate?: Date;
}

How to scaffold a component in the test iframe?

The mount function exposed by this package should mount the given component under test in the iframe's window. For example, here is the same code from https://github.com/bahmutov/cypress-angularjs-unit-test

export const mount = function (template, modules = []) {
  if (arguments.length === 1) {
    // test did not pass a template, just list of modules
    modules = template
    template = ''
  }

  // must inject into a "div" and not into "document" directly,
  // Angular.js goes up to "html" parent element
  // and stores its state there, affecting every test afterwards
  const html = `
    <head>
      <meta charset="UTF-8">
    </head>
    <body>
      <div id="app">
        ${template}
      </div>
    </body>
  `

  const document = cy.state('document')
  document.write(html)
  document.close()

  cy.window().then(w => {
    w.angular = angular
    cy.log('Angular.js', w.angular.version.full)
    const el = document.getElementById('app')
    w.angular.bootstrap(el, modules)
  })
}

In this repo, I could not find how to scaffold Angular component on demand. See cypress/integration/spec.ts currently. I am trying to put the component into the test iframe and start the app

  beforeEach(() => {
    const html = `
      <head>
        <meta charset="UTF-8">
      </head>
      <body>
        <app-root></app-root>
      </body>
    `
    const document = (cy as any).state('document')
    document.write(html)
    document.close()

    cy.get('app-root').then(el$ => {
      platformBrowserDynamic()
        .bootstrapModule(AppModule)
        .then(function (moduleRef) {
          moduleRef.instance.app.bootstrap(AppComponent, el$.get(0))
        })
    })
  })

  it('works', () => {})

But so far - no luck.

steps to reproduce

  • Clone this repo
  • npm install
  • npx cypress open starts Cypress GUI
  • click on spec.ts file and it will run the test

Attention @IgorMinar

Merge setConfig and init*

Issues with current behavior

setConfig is currently somewhat hidden.

Suggestion

Adding config options to the init* functions could be more intuitive ; in addition to keeping setConfig.

initEnv(AppComponent, {styles: '...', imports: [...]});

Is there a way to load both AngularJs component/services and Angular in Cypress

I am evaluating Cypress tool to use it for Angular Unit testing. Our application is hybrid of AngularJs and Angular currently and progressing towards transforming everything to Angular. But, it is mix of AngularJs and Angular rightnow.
I am trying to write cypress unit tests for components which imports services from AngularJS. I thought as testing component is Angular wouldn't cause any problem but when ran the test, it displays AngularJs is not loaded.
Attached screenshot for reference. Please direct me on this.
angularjsloadissue

Instrumenting Unit Testing Coverage for Angular

Instrumenting unit test coverage didn't work for me with babel-plugin-istanbul. Can you provide an example of how to instrument unit tests and at the same time to have coverage for both unit + e2e

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.