3

I have a component which takes an argument as a sort of directive to set the size of the <div> within its template, the only problem now is that I am unsure how to test it?

I called my component like this, where small can be replaced with other pre-defined sizes such as medium/large etc:

<spinner small></spinner>

Then I take this as an @Input(<size>) and perform a set to change a size variable that is then passed into an [ngStyle] to change the CSS of the displayed component size.

component.ts

size: number;

@Input('small') set small(value) {
  this.size = !value ? 25 : this.size;
}

get getSize() {
  const myStyle = {
    width: this.size + 'px',
    height: this.size + 'px'
  };
  return myStyle;
}

component.html

<div [ngStyle]="getSize"></div>

I have successfully tested the get getSize() function, but I have become a bit stuck around the @Input(<val>) set functions :-/

2 Answers 2

5

To know what test to make, ask yourself this question :

What does my [feature/component/service/function/variable/...] do ?

In this case, your setters can answer with

As a setter with an Input decorator, I should set the value of the size variable if my own value is undefined. If my own value is defined, I should fall back to the default value.

This means that your setter tests will look like this :

it('should set size variable with value undefined', () => {
  component.size = 10;
  component.small = '';
  epxect(component.size).toEqual(25);
});

it('should not change size variable with value defined', () => {
  component.size = 10;
  component.small = 'ff';
  epxect(component.size).toEqual(10);
});
Sign up to request clarification or add additional context in comments.

Comments

1

Stackblitz demo

In order to spyOn getter/setter properties, you can use jasmine spyOnProperty:

enter image description here

So in your example we have: obj -> component, propertyName -> 'small', accessType -> 'set' :

  it('call small setter method', () => {
    const small = spyOnProperty(component, 'small', 'set'); // just spyOn setter method of small
    component.size = 10; // set initial value of size to 10

    component.small = 'large'; // set small property which as expected - should call setted method

    // we expect that `small` setter method will be called 
    //  with 'large' argument, since we setted it before 
    expect(small).toHaveBeenCalledWith('large'); 

    // we also expect, that the logic of your setter method works correctly: `this.size = !value ? 25 : this.size;`
    // since we pass value, your `this.size` will not change
    expect(component.size).toBe(10); 
  });

Edit

This is another test in case when we pass to setter argument an empty string:

it('call small setter method 2', () => {
    const small = spyOnProperty(component, 'small', 'set').and.callThrough();

    component.small = '';

    expect(small).toHaveBeenCalledWith('');
    expect(component.size).toBe(25);
  });

As expected - the small setter will be called with '' empty string and the size property will be 25 because of this: this.size = !value ? 25 : this.size;

11 Comments

I'm not sure about this... I mean, it passes; but the test sets the size and then calls the size? like component.size = 10 and then expect(component.size).toEqual(10)... Of course it will be 10. Or is this just the way that it should be done, because that's all the @Input() is doing? I may just be dense :P - Also, I had no idea you could test on stackblitz! That's awesome!
"but the test sets the size and then calls the size" - what do you mean by calls size? there is no any calls. I've edited the answer and added explanation, check it out.
Ah I understand more from what your comments on the code now say! That makes more sense.
I'd say your test is "too specific" : it is indeed the "right way" to write a test, but you're relying on the implementation of getters and setters by Typescript. The purpose of a unit testing is to test a single unit and make abstraction of other code, and in this case, you're testing if Typescript does its job (which isn't your job)
@sherlock.92 that's why I didn't downvote : your answer is technically valid, I'm just giving my opinion on it from what I have learnt myself !
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.