2015-10-05 4 views
8

Я новичок в тесте, как в модульном тесте и тесте UIНе удается найти переменную: страницу в PhantomJS

Я пытаюсь создать тест пользовательского интерфейса для моей страницы входа, используя следующий код:

console.log("Teste de Login"); 

var page = require('webpage').create(); 
page.open('http://localhost/login', function(status) { 
    console.log("Page loadeed"); 

    if(status === "success") { 
     page.render('example1.png'); 
    } 

    page.evaluate(function() { 
     // $("#numeroUsuario").val("99734167"); 
     document.getElementById('numeroUsuario').value = "99734167"; 
     page.render('exampl2.png'); 

     // $("#formLogin").submit(); 
     page.render('example3.png'); 
    }); 

    phantom.exit(); 
}); 

Но этот код возвращает следующую ошибку:

> phantomjs.exe ./testLogin.js 
Teste de Login 
Page loadeed 
ReferenceError: Can't find variable: page 

    phantomjs://webpage.evaluate():4 
    phantomjs://webpage.evaluate():8 

Где элемент $("#numeroUsuario") существует. Что я сделал не так?

+0

Если вы показываете весь код, ошибка в строке 8, которая будет 'page.render («example1.png»); ', и указывает на то, что глобальная 'var page' не определена. Вы можете проверить это, изучив ответ на метод 'create()'. – Mogsdad

ответ

3

Удостоверьтесь, что в среде page.evaluate вы не можете ссылаться ни на что из сценария Phantom.

В вашем случае, вы могли бы на самом деле есть несколько оценки вызовов:

console.log("Teste de Login"); 

var page = require('webpage').create(); 
page.open('http://localhost/login', function(status) { 
    console.log("Page loadeed"); 

    if(status === "success") { 
     page.render('example1.png'); 
    } 

    page.evaluate(function() { 
     // $("#numeroUsuario").val("99734167"); 
     document.getElementById('numeroUsuario').value = "99734167"; 
    }); 

    page.render('exampl2.png'); 

    page.evaluate(function() { 
     // $("#formLogin").submit(); 
    }); 

    page.render('example3.png'); 

    phantom.exit(); 
}); 
10

documentation говорит следующее о контексте страницы (курсив мой):

The execution is sandboxed, the web page has no access to the phantom object and it can't probe its own setting.

Это означает, что переменные определены вне функции обратного вызова page.evaluate() недоступны внутри него. Это также означает, что this относится к объекту window.

Вы можете, конечно, разделить page.evaluate() вызов на несколько вызовов и переместить движение вызовов, которые используют внешние переменные между page.evaluate() вызовами как Platinum Azure showed, но это не работает, если вы хотите вызвать некоторую функцию PhantomJS изнутри обратный вызов внутри обратного вызова page.evaluate().

Решение будет заключаться в использовании window.callPhantom and page.onCallback pair. Это идеально подходит для асинхронных функций:

var renderId = 0; 
page.onCallback = function(data){ 
    console.log("Callback: " + data.type); 
    if (data.type === "exit") { 
     phantom.exit(); 
    } else if (data.type === "render") { 
     page.render(data.fname || ("screenshot_" + (renderId++) + ".png")); 
    } 
}; 

page.onConsoleMessage = function(msg){ 
    console.log("remote> " + msg); 
}; 

var getUrl = "http://example.com"; 
page.open(url, function(){ 
    page.evaluate(function(getUrl){ 
     $.get(getUrl, "", function(data){ 
      console.log(JSON.stringify(data)); 
      window.callPhantom({ type: "render" }); 
      window.callPhantom({ type: "exit" }); 
     }); 
    }, getUrl); 
}); 

Выход может помешать ранее выполненной операции рендеринга. Это, безусловно, можно задержать выход в этом случае с помощью некоторого фиксированного количества времени, таких как половина секунды:

if (data.type === "exit") { 
    setTimeout(function(){ 
     phantom.exit(); 
    }, 500); 
} 

Кроме того, невозможно передать page объект в контексте страницы, поскольку только сериализуемые объекты могут быть переданы в:

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!

+1

ЭТО ответ! Благодаря! –

+0

К моему знанию это больше не работает. Если у меня есть страница в методе onCallback, она не знает переменную –

+0

@ PoulK.Sørensen Не уверен, что вы имеете в виду. Возможно, это не сработает, если выход произойдет во время рендеринга. Было бы возможно добавить небольшую задержку во время выхода. –