4

What I'm trying to do is have some testing assertions based on the data in the Angular service, i.e. we're trying to create E2E tests and the tool we're using allows us to execute arbitrary JavaScript code for assertions, so for that I need to know if it's possible to get access to the Angular service instance.

How can I get access to an Angular service instance from plain JS code?

That is, if my Angular app is deployed, and I open the app in the browser, then open Chrome DevTools, can I get access to the service instance of the my Angular service that was provided to all components?

I know it's possible to get access to your component by through ng.probe($0) etc. but not sure about services.

From what I have searched so far, it seems like we have to do use the Injector class and then use it's .get() method to get access to one of the Angular service instances but I'm not sure how would I get access to the Injector class/instance itself?

Here's what I tried: ng.probe($0) ($0 being the <app-root> of my app) and then I see that the return value has an .injector property, I tried to call ng.probe($0).injector.get('MyServiceName') and got an error for: Uncaught Error: No provider for MyServiceName!.

(Even though I'm trying ng.probe above, I would love to know how to get access to the injector without ng.probe because during execution of the automated testing i.e. prod mode, I don't think I'll be able to do ng.probe($0))

So I'm not sure if I'm trying to access it the right way? Any ideas?

I'm using Angular 4.

Shikasta_Kashti
  • 701
  • 2
  • 13
  • 28
  • Possible duplicate of https://stackoverflow.com/a/48687412/3731501 – Estus Flask Mar 28 '18 at 18:10
  • doing `ng.probe($0)` for `` and looking into its `providerToken` I see that it only has one element and the service I want to get access to isn't one of them. – Shikasta_Kashti Mar 28 '18 at 18:27
  • also is there any other way without `ng.probe()` because `ng.probe()` will not work in production. – Shikasta_Kashti Mar 28 '18 at 18:34
  • Yes, there's no ng.probe in production. This means you can't do that in production environment. And e2e cannot be considered production environment, so you can switch to dev there. You can expose root injector to `window` but it will be useless without provider tokens (and root injector isn't the only one in Angular app, so it's a half-measure). What's available in providerToken depends on your app. Consider providing http://stackoverflow.com/help/mcve that shows the problem - a plunk or stackblitz. – Estus Flask Mar 28 '18 at 19:02

1 Answers1

8

This works for me in Angular 7 using ng.probe():

window.ng.probe(window.getAllAngularRootElements()[0]) .injector.view.root.ngModule._providers .find(p => p && p.constructor && p.constructor.name === 'MyServiceName');

And I guess it is not possible to do it another way without ng.probe()

Luděk
  • 101
  • 1
  • 3