node.jsmocha.jsnightmare

Testing NightmareJS code with Mocha fails


Recently I've started learning NodeJS and I have wrote a simple Youtube scraper, that uses NightmareJS and returns the number of likes, views, author and title names per video URL.

Now I'm trying to unit test my code with Mocha(to practice some unit-testing) and for some reason it fails with the following error:

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

I've tried to increase the timeout(up to 15 sec) but it didn't help, I guess it's hanging somewhere. What am I missing? I'll be also glad to hear some constructive criticism about the code structure and implementation.

Here is my code:

var Nightmare = require('nightmare');
var expect = require('chai').expect;
var assert = require('chai').assert;
youtube_url = 'https://www.youtube.com/watch?v=0_oPsFTyhjY';

describe('test youtube video url results', function() {
    it('should return the actual video url/title/author name/num of likes and views', function(done) {
        var nightmare = Nightmare({ show: false, gotoTimeout: 3000 })
        nightmare
            .goto(youtube_url)
            .scrollTo(10000,0)
            .wait('#comment-section-renderer-items')
            .evaluate(function (youtube_url) {
                var authorSelector = '#watch7-user-header > div > a';
                var titleSelector  = '#eow-title';
                var vcountSelector = '#watch7-views-info > div.watch-view-count';
                var lcountSelector = '#watch8-sentiment-actions > span > span:nth-child(1) > button > span';
                
                var authorElement = document.querySelector(authorSelector);
                var titleElement  = document.querySelector(titleSelector);
                var vcountElement = document.querySelector(vcountSelector);
                var lcountElement = document.querySelector(lcountSelector);

                var JSONres = {'VIDEO URL':url, 'VIDEO TITLE': titleElement.innerText,'AUTHOR NAME': authorElement.innerText,  
                'NUMBER OF VIEWS': vcountElement.innerText, 'NUMBER OF LIKES': lcountElement.innerText};

                return (JSONres)
            },youtube_url)
            .end()
            .then(function (result) {
                try{
                    expect(result['VIDEO URL']).to.equal(youtube_url);
                    expect(result['VIDEO TITLE']).to.equal('The Best Mouse in the World?');
                    expect(result['AUTHOR NAME']).to.equal('Unbox Therapy');
                    assert.isAtLeast(result['NUMBER OF VIEWS'], 1816808, 'The number of views is at least the number of views that has been already seen');
                    // It's possible to remove your like from the video so hypothetically many users may remove their likes thus there is no upper/lower
                    // bound on the like amount a video can have at any time except that it must be non-negative.
                    assert.isAtLeast(result['NUMBER OF LIKES'], 0, 'The number of likes is at least a non-negative number');
                    done();
                }
                catch(error){
                    done(error);
                }
            })

    });
});

Solution

  • Unexpectedly raising the timeout to 20 seconds [with this.timeout(20000);] just solved the problem (for some reason) though the test actually never took more than 6 seconds.