How to mock Image object with Karma (Angular 7)?










2















I'm trying to mock the default DOM Image object for unit testing an Angular service.



The service is simple, it checks the "webP" format support :



import Injectable from '@angular/core';
import Promise from 'es6-promise';
import environment from '../../../../environments/environment';

@Injectable(
providedIn: 'root'
)
export class AppLoadService

constructor()


initializeApp(): Promise<any>
return new Promise((resolve) =>
console.log(`initializeApp:: inside promise`);
if (typeof Image === 'undefined')
console.log(`initializeApp:: Image undefined`);
resolve();
return;

const webP = new Image();
webP.onload = () =>
console.log(`initializeApp:: WebP support: true`);
environment.webP = true;
resolve();
;
webP.onerror = () =>
console.log(`initializeApp:: WebP support: false`);
resolve();
;
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
);




I found a way to check the webP support (default in chromium where Karma is running), and a way to check fallback on Image undefined.



But I cannot find a way to checks the onerror fallback...



Here is my spec file :



import TestBed from '@angular/core/testing';
import AppLoadService from './app-load.service';
import environment from '../../../../environments/environment';

describe('AppLoadService', () =>
let service: AppLoadService;
const originalImage = Image;

beforeEach(() => TestBed.configureTestingModule());

beforeEach(() =>
service = TestBed.get(AppLoadService);
);

it('should be created', () =>
expect(service).toBeTruthy();
);

it('should resolve with webP', (done) =>
const test = () =>
Image = originalImage;
service.initializeApp().then(() =>
expect(environment.webP).toBe(true);
done();
);
;
test();
);

it('should resolve without webP (A)', (done) =>
const test = () =>
Image = undefined;
service.initializeApp().then(() =>
expect(environment.webP).toBe(false);
done();
);
;
test();
);

it('should resolve without webP (B)', (done) =>
// How to force Image to throw "onerror" ?
const test = () =>
Image = originalImage;
service.initializeApp().then(() =>
expect(environment.webP).toBe(false);
done();
);
;
test();
);
);


The question is on should resolve without webP (B) test, at the end of the file..



Moreover, is there a better way to check undefined Image object or onload callback ?



Thanks !




EDIT



Can't get it works as it is, so I change the service constructor to provide "Image" dependency.



constructor(@Inject('Image') image: typeof Image) 
this.image = image;



Have to load the module like that :



providers: [
AppLoadService,
// [...]
provide: 'Image', useValue: Image,
]


And each resolve() now includes environment.webP result. Otherwise, individual test are a real pain, environment is randomly rewritten before being tested.



With a simple Mock it works like this :



import TestBed from '@angular/core/testing';
import AppLoadService from './app-load.service';

class MockImageFail
public onerror: Function;
private _src: string;

set src(src)
this._src = src;
if (this.onerror)
this.onerror();




describe('AppLoadService', () =>

beforeEach(() =>
TestBed.configureTestingModule(
providers: [provide: 'Image', useValue: Image]
);
);

it('should be created', () =>
const service = TestBed.get(AppLoadService);
expect(service).toBeTruthy();
);

it('should resolve with webP', (done) =>
const service = TestBed.get(AppLoadService);
service.initializeApp().then((supportWebP) =>
expect(supportWebP).toBe(true);
done();
);
);

it('should not resolve without webP (A)', (done) =>
TestBed.overrideProvider('Image', useValue: undefined);
const service = TestBed.get(AppLoadService);
service.initializeApp().then((supportWebP) =>
expect(supportWebP).toBe(false);
done();
);
);

it('should not resolve without webP (B)', (done) =>
TestBed.overrideProvider('Image', useValue: MockImageFail);
const service = TestBed.get(AppLoadService);
service.initializeApp().then((supportWebP) =>
expect(supportWebP).toBe(false);
done();
);
);
);


I'm not really happy with that and I'm sure there is another better way :/










share|improve this question




























    2















    I'm trying to mock the default DOM Image object for unit testing an Angular service.



    The service is simple, it checks the "webP" format support :



    import Injectable from '@angular/core';
    import Promise from 'es6-promise';
    import environment from '../../../../environments/environment';

    @Injectable(
    providedIn: 'root'
    )
    export class AppLoadService

    constructor()


    initializeApp(): Promise<any>
    return new Promise((resolve) =>
    console.log(`initializeApp:: inside promise`);
    if (typeof Image === 'undefined')
    console.log(`initializeApp:: Image undefined`);
    resolve();
    return;

    const webP = new Image();
    webP.onload = () =>
    console.log(`initializeApp:: WebP support: true`);
    environment.webP = true;
    resolve();
    ;
    webP.onerror = () =>
    console.log(`initializeApp:: WebP support: false`);
    resolve();
    ;
    webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
    );




    I found a way to check the webP support (default in chromium where Karma is running), and a way to check fallback on Image undefined.



    But I cannot find a way to checks the onerror fallback...



    Here is my spec file :



    import TestBed from '@angular/core/testing';
    import AppLoadService from './app-load.service';
    import environment from '../../../../environments/environment';

    describe('AppLoadService', () =>
    let service: AppLoadService;
    const originalImage = Image;

    beforeEach(() => TestBed.configureTestingModule());

    beforeEach(() =>
    service = TestBed.get(AppLoadService);
    );

    it('should be created', () =>
    expect(service).toBeTruthy();
    );

    it('should resolve with webP', (done) =>
    const test = () =>
    Image = originalImage;
    service.initializeApp().then(() =>
    expect(environment.webP).toBe(true);
    done();
    );
    ;
    test();
    );

    it('should resolve without webP (A)', (done) =>
    const test = () =>
    Image = undefined;
    service.initializeApp().then(() =>
    expect(environment.webP).toBe(false);
    done();
    );
    ;
    test();
    );

    it('should resolve without webP (B)', (done) =>
    // How to force Image to throw "onerror" ?
    const test = () =>
    Image = originalImage;
    service.initializeApp().then(() =>
    expect(environment.webP).toBe(false);
    done();
    );
    ;
    test();
    );
    );


    The question is on should resolve without webP (B) test, at the end of the file..



    Moreover, is there a better way to check undefined Image object or onload callback ?



    Thanks !




    EDIT



    Can't get it works as it is, so I change the service constructor to provide "Image" dependency.



    constructor(@Inject('Image') image: typeof Image) 
    this.image = image;



    Have to load the module like that :



    providers: [
    AppLoadService,
    // [...]
    provide: 'Image', useValue: Image,
    ]


    And each resolve() now includes environment.webP result. Otherwise, individual test are a real pain, environment is randomly rewritten before being tested.



    With a simple Mock it works like this :



    import TestBed from '@angular/core/testing';
    import AppLoadService from './app-load.service';

    class MockImageFail
    public onerror: Function;
    private _src: string;

    set src(src)
    this._src = src;
    if (this.onerror)
    this.onerror();




    describe('AppLoadService', () =>

    beforeEach(() =>
    TestBed.configureTestingModule(
    providers: [provide: 'Image', useValue: Image]
    );
    );

    it('should be created', () =>
    const service = TestBed.get(AppLoadService);
    expect(service).toBeTruthy();
    );

    it('should resolve with webP', (done) =>
    const service = TestBed.get(AppLoadService);
    service.initializeApp().then((supportWebP) =>
    expect(supportWebP).toBe(true);
    done();
    );
    );

    it('should not resolve without webP (A)', (done) =>
    TestBed.overrideProvider('Image', useValue: undefined);
    const service = TestBed.get(AppLoadService);
    service.initializeApp().then((supportWebP) =>
    expect(supportWebP).toBe(false);
    done();
    );
    );

    it('should not resolve without webP (B)', (done) =>
    TestBed.overrideProvider('Image', useValue: MockImageFail);
    const service = TestBed.get(AppLoadService);
    service.initializeApp().then((supportWebP) =>
    expect(supportWebP).toBe(false);
    done();
    );
    );
    );


    I'm not really happy with that and I'm sure there is another better way :/










    share|improve this question


























      2












      2








      2








      I'm trying to mock the default DOM Image object for unit testing an Angular service.



      The service is simple, it checks the "webP" format support :



      import Injectable from '@angular/core';
      import Promise from 'es6-promise';
      import environment from '../../../../environments/environment';

      @Injectable(
      providedIn: 'root'
      )
      export class AppLoadService

      constructor()


      initializeApp(): Promise<any>
      return new Promise((resolve) =>
      console.log(`initializeApp:: inside promise`);
      if (typeof Image === 'undefined')
      console.log(`initializeApp:: Image undefined`);
      resolve();
      return;

      const webP = new Image();
      webP.onload = () =>
      console.log(`initializeApp:: WebP support: true`);
      environment.webP = true;
      resolve();
      ;
      webP.onerror = () =>
      console.log(`initializeApp:: WebP support: false`);
      resolve();
      ;
      webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
      );




      I found a way to check the webP support (default in chromium where Karma is running), and a way to check fallback on Image undefined.



      But I cannot find a way to checks the onerror fallback...



      Here is my spec file :



      import TestBed from '@angular/core/testing';
      import AppLoadService from './app-load.service';
      import environment from '../../../../environments/environment';

      describe('AppLoadService', () =>
      let service: AppLoadService;
      const originalImage = Image;

      beforeEach(() => TestBed.configureTestingModule());

      beforeEach(() =>
      service = TestBed.get(AppLoadService);
      );

      it('should be created', () =>
      expect(service).toBeTruthy();
      );

      it('should resolve with webP', (done) =>
      const test = () =>
      Image = originalImage;
      service.initializeApp().then(() =>
      expect(environment.webP).toBe(true);
      done();
      );
      ;
      test();
      );

      it('should resolve without webP (A)', (done) =>
      const test = () =>
      Image = undefined;
      service.initializeApp().then(() =>
      expect(environment.webP).toBe(false);
      done();
      );
      ;
      test();
      );

      it('should resolve without webP (B)', (done) =>
      // How to force Image to throw "onerror" ?
      const test = () =>
      Image = originalImage;
      service.initializeApp().then(() =>
      expect(environment.webP).toBe(false);
      done();
      );
      ;
      test();
      );
      );


      The question is on should resolve without webP (B) test, at the end of the file..



      Moreover, is there a better way to check undefined Image object or onload callback ?



      Thanks !




      EDIT



      Can't get it works as it is, so I change the service constructor to provide "Image" dependency.



      constructor(@Inject('Image') image: typeof Image) 
      this.image = image;



      Have to load the module like that :



      providers: [
      AppLoadService,
      // [...]
      provide: 'Image', useValue: Image,
      ]


      And each resolve() now includes environment.webP result. Otherwise, individual test are a real pain, environment is randomly rewritten before being tested.



      With a simple Mock it works like this :



      import TestBed from '@angular/core/testing';
      import AppLoadService from './app-load.service';

      class MockImageFail
      public onerror: Function;
      private _src: string;

      set src(src)
      this._src = src;
      if (this.onerror)
      this.onerror();




      describe('AppLoadService', () =>

      beforeEach(() =>
      TestBed.configureTestingModule(
      providers: [provide: 'Image', useValue: Image]
      );
      );

      it('should be created', () =>
      const service = TestBed.get(AppLoadService);
      expect(service).toBeTruthy();
      );

      it('should resolve with webP', (done) =>
      const service = TestBed.get(AppLoadService);
      service.initializeApp().then((supportWebP) =>
      expect(supportWebP).toBe(true);
      done();
      );
      );

      it('should not resolve without webP (A)', (done) =>
      TestBed.overrideProvider('Image', useValue: undefined);
      const service = TestBed.get(AppLoadService);
      service.initializeApp().then((supportWebP) =>
      expect(supportWebP).toBe(false);
      done();
      );
      );

      it('should not resolve without webP (B)', (done) =>
      TestBed.overrideProvider('Image', useValue: MockImageFail);
      const service = TestBed.get(AppLoadService);
      service.initializeApp().then((supportWebP) =>
      expect(supportWebP).toBe(false);
      done();
      );
      );
      );


      I'm not really happy with that and I'm sure there is another better way :/










      share|improve this question
















      I'm trying to mock the default DOM Image object for unit testing an Angular service.



      The service is simple, it checks the "webP" format support :



      import Injectable from '@angular/core';
      import Promise from 'es6-promise';
      import environment from '../../../../environments/environment';

      @Injectable(
      providedIn: 'root'
      )
      export class AppLoadService

      constructor()


      initializeApp(): Promise<any>
      return new Promise((resolve) =>
      console.log(`initializeApp:: inside promise`);
      if (typeof Image === 'undefined')
      console.log(`initializeApp:: Image undefined`);
      resolve();
      return;

      const webP = new Image();
      webP.onload = () =>
      console.log(`initializeApp:: WebP support: true`);
      environment.webP = true;
      resolve();
      ;
      webP.onerror = () =>
      console.log(`initializeApp:: WebP support: false`);
      resolve();
      ;
      webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
      );




      I found a way to check the webP support (default in chromium where Karma is running), and a way to check fallback on Image undefined.



      But I cannot find a way to checks the onerror fallback...



      Here is my spec file :



      import TestBed from '@angular/core/testing';
      import AppLoadService from './app-load.service';
      import environment from '../../../../environments/environment';

      describe('AppLoadService', () =>
      let service: AppLoadService;
      const originalImage = Image;

      beforeEach(() => TestBed.configureTestingModule());

      beforeEach(() =>
      service = TestBed.get(AppLoadService);
      );

      it('should be created', () =>
      expect(service).toBeTruthy();
      );

      it('should resolve with webP', (done) =>
      const test = () =>
      Image = originalImage;
      service.initializeApp().then(() =>
      expect(environment.webP).toBe(true);
      done();
      );
      ;
      test();
      );

      it('should resolve without webP (A)', (done) =>
      const test = () =>
      Image = undefined;
      service.initializeApp().then(() =>
      expect(environment.webP).toBe(false);
      done();
      );
      ;
      test();
      );

      it('should resolve without webP (B)', (done) =>
      // How to force Image to throw "onerror" ?
      const test = () =>
      Image = originalImage;
      service.initializeApp().then(() =>
      expect(environment.webP).toBe(false);
      done();
      );
      ;
      test();
      );
      );


      The question is on should resolve without webP (B) test, at the end of the file..



      Moreover, is there a better way to check undefined Image object or onload callback ?



      Thanks !




      EDIT



      Can't get it works as it is, so I change the service constructor to provide "Image" dependency.



      constructor(@Inject('Image') image: typeof Image) 
      this.image = image;



      Have to load the module like that :



      providers: [
      AppLoadService,
      // [...]
      provide: 'Image', useValue: Image,
      ]


      And each resolve() now includes environment.webP result. Otherwise, individual test are a real pain, environment is randomly rewritten before being tested.



      With a simple Mock it works like this :



      import TestBed from '@angular/core/testing';
      import AppLoadService from './app-load.service';

      class MockImageFail
      public onerror: Function;
      private _src: string;

      set src(src)
      this._src = src;
      if (this.onerror)
      this.onerror();




      describe('AppLoadService', () =>

      beforeEach(() =>
      TestBed.configureTestingModule(
      providers: [provide: 'Image', useValue: Image]
      );
      );

      it('should be created', () =>
      const service = TestBed.get(AppLoadService);
      expect(service).toBeTruthy();
      );

      it('should resolve with webP', (done) =>
      const service = TestBed.get(AppLoadService);
      service.initializeApp().then((supportWebP) =>
      expect(supportWebP).toBe(true);
      done();
      );
      );

      it('should not resolve without webP (A)', (done) =>
      TestBed.overrideProvider('Image', useValue: undefined);
      const service = TestBed.get(AppLoadService);
      service.initializeApp().then((supportWebP) =>
      expect(supportWebP).toBe(false);
      done();
      );
      );

      it('should not resolve without webP (B)', (done) =>
      TestBed.overrideProvider('Image', useValue: MockImageFail);
      const service = TestBed.get(AppLoadService);
      service.initializeApp().then((supportWebP) =>
      expect(supportWebP).toBe(false);
      done();
      );
      );
      );


      I'm not really happy with that and I'm sure there is another better way :/







      angular image dom karma-jasmine angular7






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 15 '18 at 10:35









      Goncalo Peres

      1,4541519




      1,4541519










      asked Nov 13 '18 at 9:07









      DoubidouDoubidou

      458417




      458417






















          0






          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53277359%2fhow-to-mock-image-object-with-karma-angular-7%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53277359%2fhow-to-mock-image-object-with-karma-angular-7%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Use pre created SQLite database for Android project in kotlin

          Darth Vader #20

          Ondo