How to disable animations in protractor?

2019-06-25 09:50发布

问题:

I've found some answers on google, but they don't seem to be applicable to my project.

Some of the answers talked about adding some code to their conf.js file's onPrepare() function, but I don't have that file in my project. I have a file named protractor.config.js, which was in the angular quickstart project by default. Anyway, this config file also has an onPrepare() function, so I tried to add the code from answer #2 in this question: How to disable animations in protractor for angular js application, but then my tests failed with:

message: Failed: Trying to load mock modules on an Angular2 app is not yet supported.

回答1:

If you want to disable the Angular 2 animation go for the answer as commented by @NeilLunn. If you want to disable CSS-animations you can override it with a customer css Javascript injection. The script below can be taken as an example. Place it in the onPrepare in your protractor config file

return browser.driver.executeScript(disableCSSAnimation);

function disableCSSAnimation() {
  var css = '* {' +
    '-webkit-transition-duration: 0s !important;' +
    'transition-duration: 0s !important;' +
    '-webkit-animation-duration: 0s !important;' +
    'animation-duration: 0s !important;' +
    '}',
    head = document.head || document.getElementsByTagName('head')[0],
    style = document.createElement('style');

  style.type = 'text/css';
  style.appendChild(document.createTextNode(css));
  head.appendChild(style);
}

What it will do is it will add a piece of custom CSS to override some animations. This will for example prevent a color animation when you hover.

Hope it helps

Update:

The script needs to be injected after loading the url. If you place it in the onPrepare and you don't load the url before injecting the script the script will be injected on the data-url. Using it like this would do the trick

describe('Demo test', () => {
  beforeEach(() => {
    browser.get('http://www.protractortest.org/#/');
    browser.driver.executeScript(disableCSSAnimation);

    function disableCSSAnimation() {
      var css = '* {' +
        '-webkit-transition-duration: 0s !important;' +
        'transition-duration: 0s !important;' +
        '-webkit-animation-duration: 0s !important;' +
        'animation-duration: 0s !important;' +
        '}',
        head = document.head || document.getElementsByTagName('head')[0],
        style = document.createElement('style');

      style.type = 'text/css';
      style.appendChild(document.createTextNode(css));
      head.appendChild(style);
    }
  });

  it('Should go to Protractor test page', () => {
    expect(browser.getTitle()).toEqual('Protractor - end-to-end testing for AngularJS')
  });
});

Important:

Make a method of it so you can re-use it because each time the page reloads / goes to an other url, the script needs to be injected.

This should do the trick in the end. Good luck with it.



回答2:

I managed to accomplish this using a query parameter.

Building on Neils answer I was able to update my SharedModule to switch between BrowserAnimationModule and NoopAnimationModule.

I created a method that appends a query parameter that I will look for later. I use this method for all navigation in my tests so I can be sure the parameter is always present.

E2eCommon

public static navigateTo(path: string) {
  browser.get('/' + path + '?qa=true');
  browser.waitForAngular();
}

Then in my module where I declare the animation module I check for the query parameter and based on whether or not it's present I either load BrowserAnimationModule or NoopAnimationModule

shared.module.ts

@NgModule({
  declarations: [
    ...
  ],
  exports: [
    AnimationModule(),
    ...
  ],
  imports: [
    AnimationModule(),
    ...
  ]
})
export class SharedModule { }

export function AnimationModule(): any {
  return window.location.search.indexOf('qa=true') > -1 ? NoopAnimationsModule : BrowserAnimationsModule;
}