Skip to content

Document how to test hybrid apps that include angular.js components #24369

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

Closed
jpzwarte opened this issue Jun 8, 2018 · 29 comments
Closed

Document how to test hybrid apps that include angular.js components #24369

jpzwarte opened this issue Jun 8, 2018 · 29 comments
Labels
area: docs Related to the documentation area: upgrade Issues related to AngularJS → Angular upgrade APIs feature: under consideration Feature request for which voting has completed and the request is now under consideration feature: votes required Feature request which is currently still in the voting phase feature Issue that requests a new feature freq3: high P4 A relatively minor issue that is not relevant to core functions state: needs eng input
Milestone

Comments

@jpzwarte
Copy link

jpzwarte commented Jun 8, 2018

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

After upgrading an angular.js component and then making it available using downgradeComponent from @angular/upgrade/static, my angular.js karma test fails with:

Error: [$injector:unpr] Unknown provider: $$angularLazyModuleRefProvider <- $$angularLazyModuleRef

I'm not using a custom karma config. I'm just using the one generated by the angular-cli.

The upgrade guide at https://angular.io/guide/upgrade does not go into what you need to do to get tests running again when you have a hybrid application. It only covers upgrading the tests to angular. SO and Google are no help in this case.

Expected behavior

It should not fail and the docs should cover this scenario.

Minimal reproduction of the problem with instructions

This is my compatibility module for angular.js which is a dependency for the module i'm loading in my jasmine test (ng.mock.module):

export const compatModule = ng
  .module('compat', [])
  .directive('voPageFooter', downgradeComponent({ component: PageFooterComponent }) as ng.IDirectiveFactory)
  .directive('voPageHeader', downgradeComponent({ component: PageHeaderComponent }) as ng.IDirectiveFactory)
  .factory('ngZone', downgradeInjectable(NgZone));

What is the motivation / use case for changing the behavior?

Environment


Angular version: 6.0.2
Angular.js version: 1.6.9
@gkalpak
Copy link
Member

gkalpak commented Jun 8, 2018

Unfortunately, testing with interdependencies is generally a complex thing in ngUpgrade. You should either completely mock out the parts that come from the other framework (e.g. upgraded/downgraded components) or create "mini-apps" that contain all dependencies from both frameworks.

By "mini apps" I mean creating two modules (one for AngularJS and one for Angular) that contain all the necessary components for the test and then bootstrap that module (as you would bootstrap an actual app).

Most of our own ngUpgrade tests use this approach. See for example this test (but really most ngUpgrade tests use the same approach - feel free to look around).

We are also working on some test helpers for ngUpgrade (e.g. #16848), which should make such things easier in the future.

👍 on documenting this better. I think the main reason we haven't done so already is that we are not happy with the current state either (but some docs are better than no docs 😁).

@ngbot ngbot bot added this to the needsTriage milestone Jun 8, 2018
@jpzwarte
Copy link
Author

jpzwarte commented Jun 8, 2018

@gkalpak Thanks for the explanation.

@jenniferfell jenniferfell added feature Issue that requests a new feature freq3: high labels Jun 11, 2018
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Jun 11, 2018
@jenniferfell jenniferfell changed the title Error: [$injector:unpr] Unknown provider: $$angularLazyModuleRefProvider <- $$angularLazyModuleRef Document how to test hybrid apps that include angular.js components Jun 11, 2018
@AlexSwensen
Copy link

AlexSwensen commented Aug 3, 2018

@gkalpak This explanation is exactly what I have been searching for for a while. Thanks for taking the time to write this out.

I would agree with your statement that this should be documented in some form, even though testing in a hybrid app is not in an ideal state, there are many teams (including my own) that are having to follow the migration path instead of just rewriting from the ground up.
My own experience has been a process of discovery/the-blind-leading-the-blind. I would have loved some documentation for testing. :-)

As-is, i'll be using the text examples you referenced going forward.


This is the issue that i ended up on most of the time with my errors. Would be great to have a reference to this issue.
angular/angular-cli#5432

@edarioq
Copy link

edarioq commented Sep 20, 2018

We have a Hybrid app but without AngularCLI. What do you recommend for implementing testing? I can't find anything in the docs for this.

@aryaroudi
Copy link

aryaroudi commented Feb 20, 2019

Hey @gkalpak The problem I have is, it just doesn't render the angular 2 components while running the AngularJS unit test. There is no error. Do we have any resolution on this? is it bad news or good news that there is no error?

@gkalpak
Copy link
Member

gkalpak commented Feb 20, 2019

@aryaroudi, hard to tell with so little info. Make sure you have checked out #24369 (comment) (and the links provided there) 😉

@aryaroudi
Copy link

aryaroudi commented Feb 20, 2019

@aryaroudi, hard to tell with so little info. Make sure you have checked out #24369 (comment) (and the links provided there) 😉

isn't that comment referred to an angular2 unit test that loads the angular 1 component? In other words, is it possible to do the same in a [ajs-component].spec.js?

well let me add some info: we are building the whole app by Webpack using the @ngtools and the final bundle contains both applications then in Karma we added the Karma Webpack and it builds a bundle then it loads the tests

@AlexSwensen
Copy link

AlexSwensen commented Feb 20, 2019

@aryaroudi @gkalpak This is something that desperately needs to be documented. Thankfully it is a problem that we have solved. If the angular component is not being rendered, you probably are not bootstrapping the angular portion of your app correctly, or you aren't downgrading the component/service you are testing. Given components are simply declared with custom HTML tags, you probably will not get an error.

My team is successfully testing and slowly migrating an AngularJS application into Angular, and the hybrid is stable in production. I plan to write some posts on my personal blog soon detailing how to migrate from AngularJS to Angular.

Also, I figure I should ask if you are using ui-router or the stock AngularJS router for your app, as that is an important distinction.

@AlexSwensen
Copy link

@aryaroudi It's also worth pointing out that when I bootstrapped our tests in karma, I found we would hit a race-condition while angular was bootstrapping.

Here is a snippet from our test.ts file.

// test/test.ts
import * as jquery from 'jquery';
declare const window: any;
window.$ = jquery;
window.jQuery = jquery;

import 'zone.js'
import 'zone.js/dist/zone-testing';
import 'zone.js/dist/long-stack-trace-zone'
// import 'zone.js/dist/proxy.js'
import 'zone.js/dist/sync-test'
// import 'zone.js/dist/jasmine-patch'
// import 'zone.js/dist/async-test'
// import 'zone.js/dist/fake-async-test'

declare const __karma__: any;
declare const require: any;

__karma__.loaded = function () {};

import '../src/app/main';

// give the app a second to start...
// This timeout is needed because the process of bootstrapping Angular and AngularJS together
// is asynchronous, so the simplest way to solve the problem is with a short delay.
setTimeout(() => {

  // Then we find all the tests in the test/js directory.
  const context = require.context('./js', true, /_?\.?(s|S)pec$/);
  // and all the tests in the app directory
  const appContext = require.context('./../src', true, /_?\.?(s|S)pec$/)

  // load the modules.
  context.keys().map(context);
  appContext.keys().map(appContext);

  // and run the tests.
  __karma__.start();
}, 1000);

Since the bootstrap is asynchronous, we threw in a 1-second timeout before the tests start to be sure it is finished. Ever since then we did not encounter that race condition.

@aryaroudi
Copy link

aryaroudi commented Feb 21, 2019

@aryaroudi @gkalpak This is something that desperately needs to be documented. Thankfully it is a problem that we have solved. If the angular component is not being rendered, you probably are not bootstrapping the angular portion of your app correctly, or you aren't downgrading the component/service you are testing. Given components are simply declared with custom HTML tags, you probably will not get an error.

My team is successfully testing and slowly migrating an AngularJS application into Angular, and the hybrid is stable in production. I plan to write some posts on my personal blog soon detailing how to migrate from AngularJS to Angular.

Also, I figure I should ask if you are using ui-router or the stock AngularJS router for your app, as that is an important distinction.

Awesome @AlexSwensen, Thanks for the info. My question is the bootstrapping of the application is happening in the bundlethat is generating by Webpack and before the test gets start, Karma compiles the project and makes a bundle by webpackMiddleware and the downgrade, upgrade, etc already have been provided inside the bundle. From this point, is it necessary again you have it done separately in your tests? if yes then I guess we need to change the test unit files to TypeScript in order to be able to use angular decorators, etc for the test and do the operations there. make sense?

As I am seeing also in your test.ts it seems that you are running the test on Angular karma, not the Angularjs Karma

@AlexSwensen
Copy link

AlexSwensen commented Feb 21, 2019

@aryaroudi You shouldn't need to bootstrap the application twice. Once is enough.

We had an issue where we didn't want to re-create all of our tests. Turns out we didn't have to due to how you test AngularJS and Angular are different enough and (for the most part) do not interfere with each other.

if yes then I guess we need to change the test unit files to TypeScript in order to be able to use angular decorators, etc for the test and do the operations there. make sense?

Any tests that touch Angular components/services will need to be in TypeScript, but that is fairly easy to do.

As I am seeing also in your test.sh it seems that you are running the test on Angular karma, not the Angularjs Karma

I'm a little confused by what you mean here... Karma is a test runner and Jasmine is the default testing framework used by AngularJS and Angular. We are using Karma webpack to bundle our app for running tests, but eventually, we will be running all our tests through the Angular CLI (once we prioritize that part of the process)

@aryaroudi
Copy link

aryaroudi commented Feb 25, 2019

@aryaroudi You shouldn't need to bootstrap the application twice. Once is enough.

We had an issue where we didn't want to re-create all of our tests. Turns out we didn't have to due to how you test AngularJS and Angular are different enough and (for the most part) do not interfere with each other.

if yes then I guess we need to change the test unit files to TypeScript in order to be able to use angular decorators, etc for the test and do the operations there. make sense?

Any tests that touch Angular components/services will need to be in TypeScript, but that is fairly easy to do.

As I am seeing also in your test.sh it seems that you are running the test on Angular karma, not the Angularjs Karma

I'm a little confused by what you mean here... Karma is a test runner and Jasmine is the default testing framework used by AngularJS and Angular. We are using Karma webpack to bundle our app for running tests, but eventually, we will be running all our tests through the Angular CLI (once we prioritize that part of the process)

Thank you so much @AlexSwensen! I got it more or less to work just fixing some errors. I have two questions what is this for?

import '../src/app/main';

are you importing your main.ts of your app which has the bootstrapping function inside it? That would be great if you share an example of a test unit so everyone who is struggling with this problem can have a good picture of it.

currently, I am stuck with this:

'DynamicTestModule'. Please add a @Pipe/@Directive/@component annotation.

@AlexSwensen
Copy link

@aryaroudi main.ts is the main entry point for most stock angular applications. Yes, it also has a fair amount of bootstrapping code. If you are using UIRouter I suggest you look at the docs for ui-router/angular-hybrid

If you are using the stock router I'm really not sure what is involved there beyond what the official docs recommend. Sorry!

My unit tests import the real component code. Sadly I am not in a position where I can share an example for my main application. If I find some time I can try and create a stand-alone example. That might take some time as I have a lot going on at work and in my personal life for the next few weeks.

@gkalpak gkalpak added area: upgrade Issues related to AngularJS → Angular upgrade APIs and removed area: upgrade Issues related to AngularJS → Angular upgrade APIs comp: upgrade/static labels Mar 13, 2019
@fzxt
Copy link

fzxt commented Apr 13, 2019

@gkalpak, correct me if I am wrong but those test helpers introduced in #16848 seem to be targetted towards services (not components). Any thoughts on introducing some helpers for bootstrapping "mini hybrid apps"?

@gkalpak
Copy link
Member

gkalpak commented Apr 14, 2019

Right, @fzxt. There are no immediate plans, but #16848 are paving the way 😃 Hopefully, in the future we could have helpers for components as well (and ideally not even need the mini-apps (wishful thinking ❓)).

@kriscoleman
Copy link

@aryaroudi It's also worth pointing out that when I bootstrapped our tests in karma, I found we would hit a race-condition while angular was bootstrapping.

Here is a snippet from our test.ts file.

// test/test.ts
import * as jquery from 'jquery';
declare const window: any;
window.$ = jquery;
window.jQuery = jquery;

import 'zone.js'
import 'zone.js/dist/zone-testing';
import 'zone.js/dist/long-stack-trace-zone'
// import 'zone.js/dist/proxy.js'
import 'zone.js/dist/sync-test'
// import 'zone.js/dist/jasmine-patch'
// import 'zone.js/dist/async-test'
// import 'zone.js/dist/fake-async-test'

declare const __karma__: any;
declare const require: any;

__karma__.loaded = function () {};

import '../src/app/main';

// give the app a second to start...
// This timeout is needed because the process of bootstrapping Angular and AngularJS together
// is asynchronous, so the simplest way to solve the problem is with a short delay.
setTimeout(() => {

  // Then we find all the tests in the test/js directory.
  const context = require.context('./js', true, /_?\.?(s|S)pec$/);
  // and all the tests in the app directory
  const appContext = require.context('./../src', true, /_?\.?(s|S)pec$/)

  // load the modules.
  context.keys().map(context);
  appContext.keys().map(appContext);

  // and run the tests.
  __karma__.start();
}, 1000);

Since the bootstrap is asynchronous, we threw in a 1-second timeout before the tests start to be sure it is finished. Ever since then we did not encounter that race condition.

I'm not here to contribute to the conversation, but I just wanted to thank @AlexSwensen for this. I've been working on upgrading a angular 1.6 app to a hybrid w/ angular 8, and I've had a hell of a time bootstrapping the angularjs tests back in. After a day or two of searching around and playing with things, Alex's suggestion here finally got me somewhere. Thanks so much for sharing!!

Also ++ to suggesting this gets documented in the Upgrade documentation. That documentation is done well, but this is a gap that would certainly be helpful.

@aryaroudi
Copy link

@aryaroudi It's also worth pointing out that when I bootstrapped our tests in karma, I found we would hit a race-condition while angular was bootstrapping.
Here is a snippet from our test.ts file.

// test/test.ts
import * as jquery from 'jquery';
declare const window: any;
window.$ = jquery;
window.jQuery = jquery;

import 'zone.js'
import 'zone.js/dist/zone-testing';
import 'zone.js/dist/long-stack-trace-zone'
// import 'zone.js/dist/proxy.js'
import 'zone.js/dist/sync-test'
// import 'zone.js/dist/jasmine-patch'
// import 'zone.js/dist/async-test'
// import 'zone.js/dist/fake-async-test'

declare const __karma__: any;
declare const require: any;

__karma__.loaded = function () {};

import '../src/app/main';

// give the app a second to start...
// This timeout is needed because the process of bootstrapping Angular and AngularJS together
// is asynchronous, so the simplest way to solve the problem is with a short delay.
setTimeout(() => {

  // Then we find all the tests in the test/js directory.
  const context = require.context('./js', true, /_?\.?(s|S)pec$/);
  // and all the tests in the app directory
  const appContext = require.context('./../src', true, /_?\.?(s|S)pec$/)

  // load the modules.
  context.keys().map(context);
  appContext.keys().map(appContext);

  // and run the tests.
  __karma__.start();
}, 1000);

Since the bootstrap is asynchronous, we threw in a 1-second timeout before the tests start to be sure it is finished. Ever since then we did not encounter that race condition.

I'm not here to contribute to the conversation, but I just wanted to thank @AlexSwensen for this. I've been working on upgrading a angular 1.6 app to a hybrid w/ angular 8, and I've had a hell of a time bootstrapping the angularjs tests back in. After a day or two of searching around and playing with things, Alex's suggestion here finally got me somewhere. Thanks so much for sharing!!

Also ++ to suggesting this gets documented in the Upgrade documentation. That documentation is done well, but this is a gap that would certainly be helpful.

Well, What @AlexSwensen mentioned was very helpful for me and I could test it with success BUT remember that there is one issue. You have to modify all your tests after the migration again and if you have like 400-500 tests it's a hell of the work!

@AlexSwensen
Copy link

AlexSwensen commented Oct 16, 2019

@aryaroudi In our current use case, we are in the middle of a large rebrand & rebuild of many features in our application, so for us it makes sense to leave legacy code as-is and rebuild as much as we can in Angular, this includes new tests as well. At that point, it becomes more of a product and process issue than a technical one. The best way to get the work done is to make it a priority for the product/management team. :-)

EDIT: I also should point out that we finally upgraded to Angular 8 and implemented the CLI in our hybrid application. I would suggest teams take the time needed to do this, as in the end, it reduces complexity a lot.

@aryaroudi
Copy link

@aryaroudi In our current use case, we are in the middle of a large rebrand & rebuild of many features in our application, so for us it makes sense to leave legacy code as-is and rebuild as much as we can in Angular, this includes new tests as well. At that point, it becomes more of a product and process issue than a technical one. The best way to get the work done is to make it a priority for the product/management team. :-)

EDIT: I also should point out that we finally upgraded to Angular 8 and implemented the CLI in our hybrid application. I would suggest teams take the time needed to do this, as in the end, it reduces complexity a lot.

Very valuable point. I realized that we should do the same and move to CLI. Any important point to highlight while migrating from webpack to CLI? If you could share a demo of your config it would be very helpful. Thanks

@AlexSwensen
Copy link

AlexSwensen commented Oct 22, 2019

@aryaroudi I'll put together a demo hopefully soon.
There are a few important points, one is to use strictDi for AngularJS dependencies.
The other is for AngularJS templates you need to use raw-loader as part of the require statement if you are trying to load a .html in AngularJS. In Angular the templateUrl property works perfectly fine as-is.

Those two things required me to modify every single AngularJS component we had, along with several state definitions, but once i had that fixed things went very well.

@ghous92
Copy link

ghous92 commented Nov 22, 2019

@AlexSwensen _ Thanks for your input, I was able to bootstrap the Hybrid App. To Add on I have changed my .js spec files into .ts in order to utilize ES6

@Camo30
Copy link

Camo30 commented Jan 22, 2020

I'll put together a demo hopefully soon.

@AlexSwensen Any news about this? I am very interested in a runnable demo as I'm stuck with it

@AlexSwensen
Copy link

@Camo30 Very sorry I haven't checked back in. My project ran into some difficulty and (to put a long story short) my team and I are all looking for new work. 😅
If I ever get back into this space I am happy to build up a demo. In the meantime, I took most of my tips from this repo. https://github.com/ui-router/sample-app-angular-hybrid

In addition, if anyone wants some assistance I also take offers for consulting. 😉

@angular-robot angular-robot bot added the feature: votes required Feature request which is currently still in the voting phase label Jun 4, 2021
@angular-robot
Copy link
Contributor

angular-robot bot commented Jun 4, 2021

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

@angular-robot angular-robot bot added the feature: under consideration Feature request for which voting has completed and the request is now under consideration label Jun 5, 2021
@ryanki1
Copy link

ryanki1 commented Aug 26, 2021

@AlexSwensen Sorry to hear your project got into difficulties Alex.. hope you and your team were able to bounce back after getting over the shock 👍

@AlexSwensen
Copy link

@ryanki1 yes, we are fine. We have moved on to other projects. As for this, I do not anticipate ever getting back to this. Also, Angular has moved on quite a bit since my last experience with it. Given that, this issue is probably best to be closed.

@ryanki1
Copy link

ryanki1 commented Aug 26, 2021 via email

@josmar-crwdstffng josmar-crwdstffng added state: needs eng input doc-topic: dev-guides P4 A relatively minor issue that is not relevant to core functions labels Jun 28, 2022
@JeanMeche JeanMeche added area: docs Related to the documentation and removed area: aio labels Feb 1, 2024
@JeanMeche
Copy link
Member

We'll let the community provide info around this topic since angular.dev doesn't cover angularjs anymore.

@JeanMeche JeanMeche closed this as not planned Won't fix, can't repro, duplicate, stale Mar 23, 2024
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Apr 23, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: docs Related to the documentation area: upgrade Issues related to AngularJS → Angular upgrade APIs feature: under consideration Feature request for which voting has completed and the request is now under consideration feature: votes required Feature request which is currently still in the voting phase feature Issue that requests a new feature freq3: high P4 A relatively minor issue that is not relevant to core functions state: needs eng input
Projects
None yet
Development

No branches or pull requests