3

I'm new to SpookyJS/CasperJS and I'm trying to figure out the execution flow.

This is what I'm trying to achieve:

  • load a page

  • store an image of the page

  • pass this image to a function and execute it (this process is quite long: ~15 seconds)

  • wait for the function to return the result

  • use the returned value to fill a field in the form in the loaded page

  • submit the form

this is a code snippet which tries to explain the solution I came up with:

var globProcessedImage;

try {
    var Spooky = require('spooky');
} catch (e) {
    var Spooky = require('../lib/spooky');
}

var spooky = new Spooky({
    child: {
        transport: 'http'
    },
    casper: {
        logLevel: 'debug',
        verbose: true
    }
}, function (err) {
    if (err) {
        e = new Error('Failed to initialize SpookyJS');
        e.details = err;
        throw e;
    }

    spooky.start('http://example.com/');

    spooky.then(function() {
        this.captureSelector('./image.png', '#img-node');
    });

    spooky.waitFor(function() {
        this.emit('image.processed');
        return globProcessedImage !== undefined;
    }, function then() {
        processedImage = globProcessedImage;
        this.sendKeys('#imagePassword', processedImage);
    });

    spooky.then(function() {
        this.capture('./page.png');
    });

    spooky.run();

    spooky.on('image.processed', function() {
        setTimeout(function() {
            globProcessedImage = 'my_result_string';
        }, 15000);
    });
});

spooky.on('error', function (e, stack) {
    console.error(e);

    if (stack) {
        console.log(stack);
    }
});

spooky.on('log', function (log) {
    if (log.space === 'remote') {
        console.log(log.message.replace(/ \- .*/, ''));
    }
});

When I run the application I receive the following error:

ReferenceError: Can't find variable: globProcessedImage

How do I make globProcessedImage visible in SpookyJS? Is this the correct approach to deal with external functions during Web automation?

Thanks in advance.

Rippo
  • 22,117
  • 14
  • 78
  • 117
lerio
  • 33
  • 4
  • This is *very* similar to your previous question, ok spookyjs versus casperjs... BTW why is this question tagged casperJS? I will remove it – Rippo May 15 '14 at 17:12
  • Yes, sorry. I needed to understand global variables in CasperJS first and so the differences in SpookyJs. I just wanted to avoid confusion. – lerio May 15 '14 at 22:22

1 Answers1

0

Edit: At the time of writing this SpookyJS didn't support the additional syntax of passing objects by value into waitFor callbacks. So this code doesn't work.

In contrast to casperjs, spookyjs has three possible contexts: spooky context, casper context and page context.

What you try is accessing a variable that is defined in the spooky context from the casper context. You can pass variables between the contexts as described in this issue: How to make global variables available to functions inside casper?

So adapting this to your code, you should have:

var globProcessedImage;

try {
    var Spooky = require('spooky');
} catch (e) {
    var Spooky = require('../lib/spooky');
}

var spooky = new Spooky({
    child: {
        transport: 'http'
    },
    casper: {
        logLevel: 'debug',
        verbose: true
    }
}, function (err) {
    if (err) {
        e = new Error('Failed to initialize SpookyJS');
        e.details = err;
        throw e;
    }

    spooky.start('http://example.com/');

    spooky.then(function() {
        this.captureSelector('./image.png', '#img-node');
        // start longRunning here
    });

    spooky.waitFor([{spookyGlobProcessedImage: globProcessedImage}, function() {
        return spookyGlobProcessedImage !== undefined;
    }], [{spookyGlobProcessedImage: globProcessedImage}, function then() {
        this.emit('image.processed', spookyGlobProcessedImage);
        processedImage = spookyGlobProcessedImage;
        this.sendKeys('#imagePassword', processedImage);
    }]);

    spooky.then(function() {
        this.capture('./page.png');
    });

    spooky.run();

    spooky.on('image.processed', function(spookyGlobProcessedImage) {
        this.echo("spookyGlobProcessedImage is " + spookyGlobProcessedImage);
    });
});

spooky.on('error', function (e, stack) {
    console.error(e);

    if (stack) {
        console.log(stack);
    }
});

spooky.on('log', function (log) {
    if (log.space === 'remote') {
        console.log(log.message.replace(/ \- .*/, ''));
    }
});

I don't know for sure if spooky.waitFor supports this syntax.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Looks like `spooky.waitFor` is still not able to find `spookyGlobProcessedImage` : `ReferenceError: Can't find variable: spookyGlobProcessedImage` – lerio May 15 '14 at 22:11
  • @lerio Then I guess waitFor doesn't work like `spooky.then` does. You could open an issue in the github project describing your feature request/bug. – Artjom B. May 15 '14 at 22:17