// Runs a very simple crawl on an HTTP server
// This is more of an integration test than a unit test.

/* eslint-env mocha */

var chai = require("chai"),
    uri = require("urijs");

var Server = require("./lib/testserver.js"),
    Crawler = require("../");

chai.should();

var makeCrawler = function (host, path, port) {
    var crawler = new Crawler(host, path, port);
    crawler.interval = 1;
    return crawler;
};

describe("Test Crawl", function() {

    // Create a new crawler to crawl this server
    var localCrawler = makeCrawler("127.0.0.1", "/", 3000),
        linksDiscovered = 0;

    it("should be able to be started", function(done) {

        localCrawler.on("crawlstart", function() {
            localCrawler.running.should.equal(true);
            done();
        });
        localCrawler.on("discoverycomplete", function() {
            linksDiscovered++;
        });

        localCrawler.start();
    });

    it("should emit an error when it gets a faulty cookie", function(done) {

        localCrawler.on("cookieerror", function(queueItem) {
            queueItem.url.should.equal("http://127.0.0.1:3000/stage2");
            done();
        });
    });

    it("should have a queue with at least the initial crawl path", function() {

        localCrawler.queue.length.should.be.greaterThan(0);
    });

    it("should discover all linked resources in the queue", function(done) {

        localCrawler.on("complete", function() {
            linksDiscovered.should.equal(5);
            done();
        });
    });

    it("should obey rules in robots.txt", function(done) {

        var crawler = new Crawler("127.0.0.1", "/", 3000);
        crawler.start();

        crawler.on("fetchdisallowed", function(parsedURL) {
            parsedURL.path.should.equal("/forbidden");
            done();
        });
    });

    it("should be able to disregard rules in robots.txt", function(done) {

        var crawler = new Crawler("127.0.0.1", "/", 3000);
        crawler.respectRobotsTxt = false;
        crawler.start();

        crawler.on("fetchcomplete", function(queueItem) {
            if (queueItem.url === "http://127.0.0.1:3000/forbidden") {
                crawler.stop();
                done();
            }
        });
        crawler.on("complete", function() {
            done(new Error("Didn't visit forbidden URL (even though it should have)"));
        });
    });

    it("should obey robots.txt on different hosts", function(done) {

        var server = new Server({
            "/robots.txt": function(write) {
                write(200, "User-agent: *\nDisallow: /disallowed\n");
            },

            "/disallowed": function(write) {
                write(200, "This is forbidden crawler fruit");
            }
        });
        server.listen(3001);

        var crawler = new Crawler("127.0.0.1", "/to/other/port", 3000);
        crawler.start();

        crawler.on("fetchdisallowed", function(parsedURL) {
            uri({
                protocol: parsedURL.protocol,
                hostname: parsedURL.host,
                port: parsedURL.port,
                path: parsedURL.path
            }).href().should.equal("http://127.0.0.1:3001/disallowed");

            done();
        });
    });

    it("should support async event listeners for manual discovery", function(done) {

        var crawler = makeCrawler("127.0.0.1", "/", 3000);

        // Use a different crawler this time
        crawler.discoverResources = false;
        crawler.queueURL("http://127.0.0.1:3000/async-stage1");
        crawler.start();

        crawler.on("fetchcomplete", function(queueItem, data) {
            var evtDone = this.wait();

            setTimeout(function() {
                linksDiscovered++;

                if (String(data).match(/complete/i)) {
                    return evtDone();
                }

                // Taking advantage of the fact that for these,
                // the sum total of the body data is a URL.
                crawler.queueURL(String(data)).should.equal(true);

                evtDone();
            }, 10);
        });

        crawler.on("complete", function() {
            linksDiscovered.should.equal(8);
            done();
        });
    });

    it("should not throw an error if header Referer is undefined", function(done) {

        var crawler = makeCrawler("127.0.0.1", "/depth/1", 3000);
        crawler.maxDepth = 1;

        crawler.start();

        crawler.on("complete", function() {
            done();
        });
    });

    it("it should remove script tags if parseScriptTags is disabled", function(done) {

        var crawler = makeCrawler("127.0.0.1", "/script", 3000);
        crawler.maxDepth = 1;
        crawler.parseScriptTags = false;

        crawler.start();

        crawler.on("complete", function() {
            crawler.queue.length.should.equal(2);
            done();
        });
    });

    it("it should emit an error when resource is too big", function(done) {

        var crawler = makeCrawler("127.0.0.1", "/big", 3000);
        var visitedUrl = false;

        crawler.start();

        crawler.on("fetchdataerror", function(queueItem) {
            visitedUrl = visitedUrl || queueItem.url === "http://127.0.0.1:3000/big";
        });

        crawler.on("complete", function() {
            done();
        });
    });

    // TODO

    // Test how simple error conditions are handled

});

@@ -1616,36 +1616,36 @@
   var crawler = 
-new 
+make
 Crawler(%22127.0.0
@@ -1933,36 +1933,36 @@
   var crawler = 
-new 
+make
 Crawler(%22127.0.0
@@ -2823,36 +2823,36 @@
   var crawler = 
-new 
+make
 Crawler(%22127.0.0

Call makeCrawler in testcrawl.js for new tests