segment-boneyard / nightmare

A high-level browser automation library.
https://open.segment.com
19.55k stars 1.08k forks source link

Nightmare with login, then loop and then run(). #90

Closed Cramertech closed 10 years ago

Cramertech commented 10 years ago

This issue has to do with the previous one that I made last night, but this problem I'm having is different.

I'm really not sure if this is due to my not understanding loops or some other logic in node/javascript, or maybe from a possible bug.

What I'm trying to do is start a nightmare up, and immediately login. After the login I need it to iterate through the same code using different values, then finally at the end run the nightmare in that manner.

What happens is it works perfectly until about the 4th, 5th or 6th iteration and just quits unexpectedly with no error or feedback as to why.

Here's my code, which I think is fairly simple considering, but has a lot of lines to it already.

// Apple store gift card checking.
// Provide a text file with card PINs listed on every new line.

var fs = require('fs');
var Nightmare = require('nightmare');

// Get the cards file contents. 
var fileContent = fs.readFileSync('./cards.txt').toString();
// Now split it line by line into an array.
var cardsList = fileContent.split("\n");
console.log("Found "+(cardsList.length)+" cards.");

// Go get the balances of the cards we've found.
getCardBalances(cardsList, fs);

function getCardBalances(cards, fs) {
    console.log("Now retrieving balances of " + cards.length + " cards.");
    var goCards = new Nightmare()
            .viewport(800, 1600)
            //Go to the Apple store gift card checking login page; login.
            .goto('https://secure.store.apple.com/us/giftcard/balance')
                .type('#login-appleId', "somebody@www.net")
                .type('#login-password', "P@ssw0rd")
                .click('#sign-in');
    //Iterate through every card, enter its PIN, check the value, write it to disk.
    for (i = 0; i < cards.length; i++) {
        console.log(i + ": " + cards.length);
        // Continue where nightmare left off..
        goCards.wait()
        // Enter the PIN (screenshot here) & click the button, then wait for a response.
        .type('#gift-card-balance-content-pin', cards[i]).screenshot('./screens/aftertypePIN'+i+'.jpg')
        .wait()
        .click('button#gift-card-balance-content-checkBalance-button')
        .wait()
        // Take another screenshot to be sure of what we're seeing.
        .screenshot('./screens/postBtnClick'+i+'.jpg')
        .wait('#gift-card-submited')
        .evaluate(function(cards, cardNum) {
            // Hold up; wait a minute; put a little value in it. (Check for a balance value)
            if (!document.querySelector('#gift-card-submited div span.col2 strong')) {
                return {err:"Not a valid card, or there was a problem.", cards: cards, cardNum: cardNum};
            }
            // If we're here, then there's a balance value.  Store it and move on to the callback.
            var cardValue = document.querySelector('#gift-card-submited div span.col2 strong').textContent;
            return {value: cardValue, cards: cards, cardNum: cardNum};
        }, function(res) {
            var cards = res.cards;
            var cardValue = res.value;
            var i = res.cardNum;
            var err = res.err;
            console.dir(cards);
            console.log("Card number is: " + i);
            // Check if there was an error, and if so, console.log it, skip appending the file, and continue looping.
            if (err) {
                console.log(err);
                return;
            }
            // No error; then we write the value of the card's balance to the file along with the card's PIN.
            console.log("Card " + i + ": " + cards[i] + ", " + cardValue);
            fs.appendFile('cardValues.txt', cards[i] + '\t' + cardValue + '\n', function (err) {
                if(err) console.log(err);
                console.log("Appended card balance to file.");
                return;
            });
            console.log((cards.length - i - 1) + " cards left.")
        }, cards, i)
        //Now one final thing... refresh the page so we can check more cards.
        .refresh();
    }
    goCards.run();
}
t3hmrman commented 10 years ago

Could you factor your code out into plugins (examples on http://www.nightmarejs.org/) ?

I think the organization will help with debug, and you can think about smaller chunks of this logic at a time. Specifically, having a single plugin handle one card, and then building on that abstraction with a plugin that handles multiple cards (simply by attaching multiple uses of the first plugin, if preferable).

Also, to speak a little more to the actual problem -- could you reproduce the verbose log (just the part close to where it fails)?

Also, I would recommend using sync node functions, just to eliminate that as a point of complexity (I don't think there's anything wrong with the calls you have right now, but just in case...)

Cramertech commented 10 years ago

Actually when I went to refactor my code into plugins, I somehow magically solved the problem. I already had thought this could help before, but was being lazy. Good enough for me! Thank you.

t3hmrman commented 10 years ago

Awesome, glad it was fixed! yeah the plugins are an awesome feature