0

Use case:

I'm writing system tests using Geb/Selenium (so outside of angular). I want to decorate $http to log all requests/responses at run time.

and here's the catch: without touching the source code.

Before you rush to answer "use $provide#decorator", for example,

http://blog.xebia.com/2014/08/08/extending-angularjs-services-with-the-decorate-method/

That solution for this use case means adding a test hook into production code... that's normally a bad thing I want to avoid if possible.

Update: Geb allows you to run Javascript in the browser window. So just for the heck of it I ran the tutorial code to decorate $http. Unfortunately, it didn't work because apparently you can't re-config the app after it's been loaded. But even if it did work, this brings up another interesting point---I need to override $http before any modules have had a chance to use it.

U Avalos
  • 6,538
  • 7
  • 48
  • 81
  • I'd rather use interceptors for that, but they, too, have to be configured before runtime. You could abuse transformers though, as they can be added at runtime. – a better oliver Jan 19 '15 at 20:53
  • re:decorating before any modules had a chance to use it, thats the idea of config blocks, they will get executed during app bootstrap before your app code executes – Vlad Gurovich Jan 20 '15 at 23:22

1 Answers1

0

Since decorating $http service would be the cleanest way of doing this, you can avoid polluting production code by using something like ng-constants and gulp/grunt to only add decoration code for a 'test' environment.

See related Q/A here: How do I configure different environments in Angular.js?

If you are inclined on changing this at runtime(where runtime takes place in a test environment), you may need to go 'closer to the metal' and deal with XMLHttpRequests: Add a "hook" to all AJAX requests on a page

Community
  • 1
  • 1
Vlad Gurovich
  • 8,463
  • 2
  • 27
  • 28
  • Yes, we use grunt. No, I may not use ng-constants. But the main idea works for us: create a new grunt task that overrides the app config file (app.js in our app) with a test version. The only drawback is that you now have two versions of app.js to maintain so we may yet still need to touch prod code. But w/ this technique, test hooks in prod are minimal. – U Avalos Jan 20 '15 at 15:28
  • Out of curiousity, why cant you use ng-constants? All it does is generate a set of values/constants (at build time) that can be injected in your application? – Vlad Gurovich Jan 20 '15 at 23:21
  • Because of the requirement of not touching the production code. But after realizing that we would have to maintain two versions of app.js, adding simple test hooks doesn't look that bad – U Avalos Jan 24 '15 at 01:43
  • @UAvalos You dont need to "touch" production code. Using gulp/grunt you can instrument an angular service/constants/etc that will do something(decorate $log) when built for the test environment OR do a no-op when built for the production environment -- thats the beauty of the strategy that I linked to – Vlad Gurovich Jan 26 '15 at 17:51