samedi 23 décembre 2017

nock handles fetch req but does not prevent http call

I am using nock to intercept a fetch call to https://www.youtube.com/oembed?url=https://youtu.be/m4hklkGvTGQ . Like so:

it(`properly responds to YouTube URL ${url}`, async () => {
    nock('https://www.youtube.com')
        .get('/oembed')
        .query(true)
        .reply(200, remoteResponse);
    const youTube = new YouTube(url);
    const response = await youTube.getResponse(); // this contains the fetch call
    expect(response).toEqual(expectedResponse);
    nock.restore();
});

I see that nock properly intercepts my fetch because

  • If I change the remoteResponse (see line 5, .reply(200, remoteResponse) my tests behave / fail as expected
  • If I change the intercepting url from https://www.youtube.com to http://ift.tt/2l0LBUX, nock tells me it did not catch a fetch request.

However, if I switch off my WiFi and run my tests I can see that my application warns me about a failed HTTP request:

request to https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=m4hklkGvTGQ failed, reason: getaddrinfo ENOTFOUND www.youtube.com www.youtube.com:443

Also, when I run my tests, they take about 1 second (which already seems long), when I turn of my WiFi, they are done immediately.

I wonder why there are still http requests

vendredi 22 décembre 2017

Jest test case failing for React conditional

I am testing for the third conditional state error of the amount to equal a specific string, but when I run it I get an empty string.

Conditional:

if (!this.state.amount) {
    this.setState(() => ({ error: 'Please provide amount.' }));
}

Jest Test Case:

test('should render error for lack of amount', () => {
    const onSubmitSpy = jest.fn();
    const wrapper = shallow(<ExpenseForm expense={errors[1]} onSubmit={onSubmitSpy} />);
    expect(wrapper).toMatchSnapshot();
    wrapper.find('form').simulate('submit', {
        preventDefault: () => { },
    });
    expect(wrapper).toMatchSnapshot();
    console.log(wrapper.state('error'));
    expect(wrapper.state('error')).toBe('Please provide amount.');
}); 

Error array index:

id: '5',
description: 'Gas',
note: '',
amount: '',
createdAt: moment(0).add(4, 'days').valueOf()

Ideally, this condition should test for the amount state to equal '' and give the error message of 'Please provide amount.'

Run tests with Spring reading data from a csv file

I'm trying to run a test multiple times, reading the input data needed from a csv file. I want to run the test for each line of the file.

I was going to do it manually, but I discovered Spring Batch. I'm new to spring batch, but I thought the following:

  • Create a spring boot application implementing command line runner.
  • In the run method, launch a spring batch job
  • This job would read the data from the csv file line by line, and for each line would run the @Test method for the data of the current line.

Is this approach ok? Is there a better way to do it? Can you provide any example code about how could it be done?

Thank you.

test mapDispatchToProps async actions

I am trying to test my mapDispatchToProps function when an asyncronous function is dispatched. I have read Dan Abramov's suggestions on how to test mapDispatchToProps and I am trying to test my code as such.

I am getting the error...

 TypeError: Cannot read property 'then' of undefined

Here is my test...

describe("mapDispatchToProps", () => {

    const dispatchSpy = jest.fn();
    const {signupUser} = mapDispatchToProps(dispatchSpy);

    it("should dispatch signupActions.signupUser()", () => {
        // mockAxios.onPost(endpoints.SIGNUP,{})
        //         .reply(200,'test_success');
        // tried with and without mockAxios

        signupUser({})
        const spyLastCall = dispatchSpy.mock.calls[0][0];
        expect(spyLastCall)
            .toEqual(signupActions.signupUser({}));
    })

})

The function that I want to test...

export const mapDispatchToProps = dispatch => {
    return { signupUser: (user) => {
        dispatch(signupActions.signupUser(user))
            .then((response) => {
                // do something on success
            }, (error) => {
                // do something on failure
            })
    }
}

I have already tested signupActions.signupUser and I know that it returns a promise. Here is the code...

export function signupUser(user) {
    return (dispatch) => {
        return dispatch(rest.post(SIGNUP,user))
            .then((response) => {
                return Promise.resolve(response);
            },(error) => {
                return Promise.reject(error)
            }
        )
}}

What am I doing wrong?

Ps: I also tried:

 const dispatchSpy = jest.fn().mockImplementation( () => {
    return p = new Promise((reject,resolve) => {
        resolve({})
    }) 
 }

with the same result

Ionic 3 testing cannot find button with by.css('button')

I am trying to get my button, which I have given the classname loginButton. My test constantly fails and the error says: "Expected the method spy push to have been called but it was never called". I am testing with karma and jasmine. Maybe it is because it cannot find the button ?

test class:

import { TestBed, ComponentFixture, async } from '@angular/core/testing';
import {IonicModule, NavController} from 'ionic-angular';
import {StatusBar} from "@ionic-native/status-bar";
import {SplashScreen} from "@ionic-native/splash-screen";
import {NavMock} from "../../mocks";
import {By} from "@angular/platform-browser";
import {DebugElement} from "@angular/core";
import {LoginPage} from "./login";
import {MyApp} from "../../app/app.component";
import {HomePage} from "../home/home";

let comp: LoginPage;
let fixture: ComponentFixture<LoginPage>;
let de: DebugElement;

describe('Component: Login forward', () => {

  beforeEach(async(() => {

    TestBed.configureTestingModule({

      declarations: [MyApp, LoginPage],

      providers: [
        {
          provide: NavController,
          useClass: NavMock
        },
        [StatusBar],
        [SplashScreen]
      ],

      imports: [
        IonicModule.forRoot(MyApp)
      ]

    }).compileComponents();

  }));

  beforeEach(() => {

    fixture = TestBed.createComponent(LoginPage);
    comp    = fixture.componentInstance;

  });

  afterEach(() => {
    fixture.destroy();
    comp = null;
    de = null;
  });

  it('should be able to navigate to home page', () => {

    let navCtrl = fixture.debugElement.injector.get(NavController);
    spyOn(navCtrl, 'push');

    de = fixture.debugElement.query((By.css('button')));
    de.triggerEventHandler('click', null);

    expect(navCtrl.push).toHaveBeenCalled();
  });
});

html page:

<ion-header>

  <ion-navbar>
    <ion-title>Login</ion-title>
  </ion-navbar>

</ion-header>


<ion-content class="master">
    <div class="loginWindow">
      <ion-item>
        <ion-label fixed>Sign in</ion-label>
      </ion-item>
      <ion-item>
        <ion-label fixed>Email</ion-label>
        <ion-input type="email" name="email"></ion-input>
      </ion-item>

      <ion-item>
        <ion-label fixed>Password</ion-label>
        <ion-input type="password" name="password"></ion-input>
      </ion-item>
      <ion-item>
        <div padding>
          <button ion-button (click)="doLogin()" class="loginButton" color="avioBlue" block>Sign in</button>
        </div>
      </ion-item>
    </div>
</ion-content>

Using nock to test POST request in async action creator

I am using nock to mock my asynchronous thunk action creators. Everything works as expected for GET requests, but I haven't been able to make a POST request work. I have read everything I can find online but nothing fixed my problem. I can see the response body in the failed test run. The issue is that there is no nock match for the url. Can anyone spot the problem?

Test file:

describe('#saveReminder', () => {
    it(`creates ${constants.actions.REQUEST_SAVE_REMINDER}
      and ${constants.actions.RECEIVE_SAVE_REMINDER}`, () => {

      data = { payload: 'payload' };

      nock(constants.paths.API_AUTHORITY)
        .post('api/prospect/add-reminder', {
          prospect: 1,
          reminder_datetime: '2017-12-22T18:42:00.000Z',
          description: 'description',
        })
        .reply(200, { data } )

      const expectedActions = [
        { type: constants.actions.REQUEST_SAVE_REMINDER },
        { type: constants.actions.RECEIVE_SAVE_REMINDER, data }
      ]

      return store.dispatch(actions.saveReminder({
        id: 1,
        description: 'description',
        date: moment(),
        time: moment(),
      })).then(() => {
        expect(store.getActions()).toEqual(expectedActions)
      })
    })
  })

Async action:

export function saveReminder({ id, description, date, time }) {
  return (dispatch) => {
    requestSaveReminder();
    return fetch(`${constants.paths.API_AUTHORITY}api/prospect/add-reminder`, {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'X-Csrf-Token': Cookie.get('X-Csrf-Token'),
      },
      credentials: 'same-origin',
      method: 'POST',
      body: JSON.stringify(
        {
          prospect: id,
          reminder_datetime: moment(`${date.format('MM/DD/YYYY')} ${time.format('HH:mm')}`, 'MM/DD/YYYY HH:mm'),
          description,
        }
      ),
    }).then(response => {
      response.json();
    })
      .then(json => dispatch(receiveSaveReminder(json.data)))
      .catch(ex => dispatch(requestSaveReminderFailure(ex)));
  };
}

Test Failure:

Object {
    -     "type": "REQUEST_SAVE_REMINDER",
    +     "data": [FetchError: request to http://localhost:8080/api/prospect/add-reminder failed, reason: Nock: No match for request {
    +   "method": "POST",
    +   "url": "http://localhost:8080/api/prospect/add-reminder",
    +   "headers": {
    +     "accept": [
    +       "application/json"
    +     ],
    +     "content-type": [
    +       "application/json"
    +     ],
    +     "accept-encoding": [
    +       "gzip,deflate"
    +     ],
    +     "user-agent": [
    +       "node-fetch/1.0 (+http://ift.tt/18q0Hew)"
    +     ],
    +     "connection": [
    +       "close"
    +     ],
    +     "content-length": [
    +       89
    +     ]
    +   },
    +   "body": "{\"prospect\":1,\"reminder_datetime\":\"2017-12-22T18:56:00.000Z\",\"description\":\"description\"}"
    + }],
    +     "type": "REQUEST_SAVE_REMINDER_FAILURE",
        },
    -   Object {
    -     "data": Object {
    -       "payload": "payload",
    -     },
    -     "type": "RECEIVE_SAVE_REMINDER",
    -   },

The urls appear to match. Why does it say Nock: No match for request? Thanks!

scalamock and Skinny - overriding method addAttributeForCreation

I'm developing over Play 2.6.7, Skinny framework 2.5.0, Scalike 3.1.0 and scalamock 4.0.0.

My problem: I have a support class that extends of SkinnyCRUDMapper.

trait PersonSupport extends SkinnyCRUDMapper[Person]

The test has this declaration:

val personSupportMock = stub[PersonSupport]

When I wanna to run the test, it returns the following error:

Error:(16, 32) overriding method addAttributeForCreation in trait NoIdCUDFeature of type (namedValue: => (scalikejdbc.SQLSyntax, Any))services.PersonServiceTest.$anon.type;
 method addAttributeForCreation has incompatible type
  val personSupportMock = stub[PersonSupport]

Any idea of can I solve this problem?

Thanks!!

Lucas.