Protractor: المنقلة وحذاء التمهيد اليدوي الزاوي

تم إنشاؤها على ٣٠ أغسطس ٢٠١٣  ·  49تعليقات  ·  مصدر: angular/protractor

أواجه مشكلة عند تشغيل المنقلة 0.8 وأواجه مشكلات في تشغيل المنقلة على تطبيقنا الذي يتم تمهيده يدويًا.

فيما يلي بعض المقتطفات التي تكشف عن الأجزاء ذات الصلة من التطبيق والإعداد:
index.html:

 <script type="text/javascript" data-main="js/main" src="js/libraries/require.js"></script>

js / main.js:

require({
    shim: {
        .... snip ..
            }
           }, 
  ['require', ..... ], function(require) {
    return require(['bootstrap']);

bootstrap.js:

var appElm = $('html');
appElm.addClass('ng-app'); // this
angular.bootstrap(document, ['app']);

يعمل هذا عمليًا ويتم تشغيل Angular بطريقة صحيحة. عندما أعرض مصدر html ، لا يمكنني رؤية سمة ng-app تظهر على عنصر html. قد تكون المنقلة أيضا لا تفعل ذلك؟

أستخدم تكوين نموذج المنقلة وغيرت القيم ذات الصلة لتلائم تطبيقي:

specs: [
    '../src/test/javascript/protractorSpec/*_spec.js',
  ],
  baseUrl: 'http://localhost:8080/Viewer/',
  rootElement: 'html',

اختبار بسيط:

describe('List SMC Charts', function() {
        var ptor= protractor.getInstance();

        beforeEach(function() {
          ptor.get('#/smcChart');
        });

        it('list, no filter', function() {
          var selectOption = ptor.findElement(ptor.By.input("selectOption"));
        });
});

عند إجراء هذا الاختبار ، يظهر خطأان:

 1) List SMC Charts   list, no filter
   Message:
     Error: Angular could not be found on the page http://localhost:8080/Viewer/#/smcChart
   Stacktrace:
     Error: Angular could not be found on the page http://localhost:8080/Viewer/#/smcChart
    at /usr/local/lib/node_modules/protractor/lib/protractor.js:392:15

و

2) List SMC Charts list, no filter
   Message:
     TypeError: Cannot call method 'input' of undefined
   Stacktrace:
     TypeError: Cannot call method 'input' of undefined
    at null.<anonymous> (/Users/........//Viewer/src/test/javascript/protractorSpec/some_spec.js:9:55)

يبدو أن الخطأ الأول هو الأهم ، لكن الخطأ الأخير مثير للاهتمام أيضًا. يبدو لي أن السطر: ptor.By.input لا يعمل.

أيه أفكار؟

untriaged discussion

التعليق الأكثر فائدة

sjelin ما هي الطريقة الموثقة لدعم التمهيد اليدوي؟ لا يمكنني العثور على المعلومات ذات الصلة بالمنقلة 5.0.

ال 49 كومينتر

هل يتم تضمين الرمز الزاوي في الصفحة؟ يبدو أنك تطلب الرقائق والتمهيد وغير ذلك ولكن angular.min.js غير معروض.

'app': {
            deps: ['libraries/angular', 'libraries/angular-resource', 'libraries/angular-strap']
        },

يوجد المقتطف أعلاه داخل عنصر shim {} ، تركته خارج المقتطفات لأنه لا يبدو وثيق الصلة بي. ولكن هذه هي الطريقة التي يتم بها تحميل angular.js.

مرحبا،

نعم ، تتوقع Protractor حاليًا وجود تطبيق ng ، لذا ستواجه المواقع التي تم تمهيد تشغيلها يدويًا مشاكل. على أمل الحصول على حل بديل لهذا الموثق قريبًا.

طيب شكرا للتحديث. عندما توصلت إلى حل بديل ، هل يمكنك نشره في هذه المشكلة؟

نأسف لبطء الاستجابة - يجب أن تكون قادرًا على الإصلاح بالممارسة

describe('List SMC Charts', function() {
        var ptor= protractor.getInstance();

        beforeEach(function() {
          ptor.driver.get('#/smcChart'); // Just use the plain old webdriver here, it won't complain if Angular isn't loaded yet.
        });

        it('list, no filter', function() {
          var selectOption = ptor.findElement(ptor.By.input("selectOption"));
        });
});

هل قمت بإعداد متغير ptor في مكان ما؟ على سبيل المثال ، var ptor = protractor.getInstance() ؟

أي تحديث على هذا؟ الإصلاح الذي اقترحته لا يعمل معي ([email protected] ، [email protected])

لدي مجموعة محرجة من شاشة تسجيل الدخول غير الزاوي متبوعة بتطبيق متطلب تم تشغيله يدويًا:

describe('User levels', function() {
    var ptor, driver;

    var findByName = function (name) {
        return driver.findElement(protractor.By.name(name));
    };

    describe('Editors', function() {
        ptor = protractor.getInstance();
        driver = ptor.driver;
        it('Can log in', function() {
            driver.get('http://localhost:8000/');
            findByName('login').sendKeys('test_editor');
            findByName('pass').sendKeys('rubbish');
            driver.findElement(protractor.By.css('button[type="submit"]')).click();
        }, 20000);

        it('Shows the homepage', function() {
            var el = ptor.findElement(protractor.By.css('h1[field="pageTitle"]'));
            expect(el.getText()).toEqual('Welcome to Home');
        }, 30000);

    });
});

و main.js :

require([
    'angular',
    'app'
], function (angular, app) {
    'use strict';
    var body = document.body, name = app.name;
    body.setAttribute('ng-app', name);
    body.setAttribute('id', 'ng-app');
    angular.bootstrap(body, [name]);
});

يعمل جزء تسجيل الدخول ويمكنني رؤية وميض تحميل الصفحة المحمية قبل انتهاء أخطاء المنقلة باستخدام UnknownError: javascript error: angular is not defined . لقد حاولت إعادة تحميل الصفحة بـ driver.get('...') وحتى ptor.get('...') لكن لا شيء يعمل.

أي تلميحات / نصائح / إصلاحات وردت بامتنان.

magnetised ، ستحتاج إلى طريقة ما لإخبار اختبارك بالانتظار حتى يتم تسجيل الدخول قبل تجربة الاختبارات الأخرى. أعتقد أن ما يحدث هو أنك تحاول استخدام ptor.findElement قبل تحميل Angular على الصفحة.

يجب أن تنتهي مواصفات "يمكن تسجيل الدخول" ببيان انتظار يتحقق من بعض الشروط لتطبيقك. تحقق من المثال هنا - https://github.com/angular/protractor/blob/master/spec/login/viaConfigConf.js

juliemr الرائعة ، هذا يعمل بشكل مثالي.

لقد فهمت أن المنقلة ستقوم "بالانتظار حتى يتم تحميل الزاوية" ولكن أعتقد أنه لا يمكنك تغطية جميع الحالات.

شكرا لك مرة أخرى.

لدي نفس الإعداد بالضبط. juliemr هل تمانع في مشاركة الحل الخاص بك. ما هي حالة انتظارك؟ شكرا!

jorgenfb أتساءل عما إذا كنت تقصد توجيه هذا التعليق إلي؟

تضمن الحل الخاص بي فقط انتظار تشغيل جهاز التوجيه الزاوي وتغيير عنوان url من "/" العاري الذي يعيد توجيهك نظام تسجيل الدخول إليه ، إلى المسار الافتراضي - في حالتنا "/ # view".

لقد حولتها إلى وظيفة يمكنني إعادة استخدامها في جميع الاختبارات:

var waitUntilLoaded = function() {
    ptor.wait(function() {
      return ptor.driver.getCurrentUrl().then(function(url) {
        return /view/.test(url);
      });
    });
};

لا أعرف ما إذا كان هذا سيعمل من أجلك ، فهذا يعتمد على تكوين التوجيه الخاص بك.

juliemr شكرا لك ، يعمل مثل السحر :)

أواجه مشكلة مماثلة (وجدت في SO على: http://stackoverflow.com/questions/19391813/protractor-fails-to-find-angular) مع منقلة لا تعثر على Angular على الرغم من أن Angular يتم تحميلها وتشغيلها بشكل واضح. هل الحل السهل (الاختبار دون محاولة العثور على Angular) هو الطريقة التي يجب أن نسير بها؟ يبدو أنه يتعارض مع الغرض من بناء المنقلة خصيصًا لاختبار تطبيقات Angular.
تحرير: يجب أن أشير أيضًا إلى أن الحل المقترح في هذه المشكلة لا يناسبني.

+1 للحصول على وثائق تمهيدية يدوية زاويّة أفضل

هل هذا لا يزال ذا صلة؟

أنا بصراحة لا أعرف لأنني تخليت منذ ذلك الحين عن المحاولة وليس لدي الوقت حقًا للعودة ومعرفة ما إذا كان هناك شيء ما قد تغير. بالنظر إلى التغييرات التي طرأت على الإصدار منذ ذلك الحين ، إذا كنت تبحث عن إغلاق هذا ، فلن أجادل. يمكن دائمًا إعادة فتحه لاحقًا.

لقد بدأت للتو في استخدام منقلة اليوم واستخدامات تطبيقنا تتطلب.js ... إذا كان هناك أي تحديثات فيما يتعلق باختبار تطبيق تم تمهيده يدويًا ، فأنا شخصًا مهتم. :-)

نفس المشكلة هنا. حصلت على التطبيق مع صفحة تسجيل الدخول خارج التطبيق الزاوي. يبدو أن الحل البديل في التعليقات السابقة عفا عليه الزمن. أرغب بشدة في الحصول على مستند محدث حول كيفية التمكن من اختبار هذا النوع من السيناريوهات.

hankduan نعم ، أعتقد ذلك.

أنا أعاني من هذه المشكلة الآن. الخلفية مشابهة: لدي تطبيق أكبر تتم إدارته عبر RequireJS.


لقد قمت بالفعل بتحديث تطبيقي باستخدام window.name='NG_DEFER_BOOTSTRAP!'; & angular.resumeBootstrap() ، إلا أنه لا يزال لا يعمل.

قال هذا ، لا أعرف ماذا أفعل بعد ذلك. لمزيد من التحقيقات ، أعددت حالة اختبار على https://github.com/knalli/protractor-with-defirmed-bootstrap

  • git clone https://github.com/knalli/protractor-with-deferred-bootstrap.git
  • cd protractor-with-deferred-bootstrap
  • npm install
  • npm run-script webdriver (خادم السيلينيوم)
  • npm run-script server (خادم تطبيق تجريبي يخدم تطبيق AJS صغيرًا)
  • npm run-script e2e-test (يدير المنقلة ...)

النتيجه هي

Using the selenium server at http://localhost:4444/wd/hub
Login: Click
Login: Waiting...
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
The last active task was: 
unknown
F

Failures:

تليها

UnknownError: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element '

الخطأ الأخير غريب بعض الشيء وربما مضلل: تم إجراء الاختبار (كان ناجحًا بقدر ما كانت التوقعات جيدة وما يمكننا رؤيته في المتصفح).

Crosscheck: إذا قمت بتبديل التطبيق التجريبي إلى التمهيد غير المؤجل مع تضمين يدوي (هذا البديل متاح في الفرع no-deferred ) ، فسيعمل بنجاح.


لقد جربت بالفعل بعض ما يسمى "طرق العمل":

  1. http://www.sebdangerfield.me.uk/2014/01/angularjs-protractor-app-already-bootstrapped-error/
    غير ذي صلة أو مضلل -> لا فرق.
  2. https://github.com/angular/protractor/issues/325#issuecomment -36738048 باستخدام protractor.getInstance() و ignoreSynchronization -> لا فرق
  3. https://github.com/angular/protractor/issues/325#issuecomment -30701683 ترقيع clientSideScripts.js/waitForAngular -> لا فرق

لقد كتبت أول اختباراتي للمنقلة بالأمس وكانت لدي نفس المشكلة مثل كنالي.

شكرا لكتابة المثالknalli. سألقي نظرة في غضون أيام قليلة

لذلك تختبر المنقلة كل الأعمال (باستثناء فشل واحد ولكن هذا خطأي :-P).
اسمحوا لي أن أعرف إذا كان هذا لا يساعد / لا.
هذا هو الإعداد الخاص بي:

إصدار المنقلة:
الإصدار 1.0.0-rc4.0
مستقل السيلينيوم:
حتى الأن
chromedriver:
حتى الأن

الملفات ذات الصلة بالتأكيد:

التكوين

/*jshint expr: true*/
/*global browser: true*/
var TEST_DIR =  '../tests/';
exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub'
,  specs : [     '../tests/e2e/_protractor.js'       ]
,  capabilities: {'browserName': 'chrome'    }
,  chromeDriver: './chromedriver'  // <---- I remember not being able to get chromedriver working 
                                                    // for some reason, so I just downloaded the executable and put it
                                                    // in my config directory
,  onPrepare: function() {
    "use strict";
    browser.driver.get('http://localhost:5000/register');
    browser.driver.wait(function() {
      return browser.driver.getCurrentUrl().then(function(url) {
        return /\#\/registration/.test(url);
      });
    });
  }
    //  chromeOnly: true,
    //  baseUrl: 'http://localhost:5000/register'
,  jasmineNodeOpts: {
    showColors: true
  }
};

_protractor.js

/*jshint expr: true, undef: true */
/* global element: true, by: true, browser: true, model:true */
(function(){
  "use strict";

var RegistrationPage = function(){
  browser.driver.wait(function() {
    return browser.driver.getCurrentUrl().then(function(url) {
      return /\#\/registration/.test(url);
    });
  });
};
  var account = new RegistrationPage();

  account.elem = element.all(by.name('account_exists'));
  account.accountNumber = element(by.name('account_number'));
  account.submitAccountButton = element(by.css('#account_input button'));

  account.selectHasAccount = function(){
    account.elem.get(0).click();
    return browser.getCurrentUrl();
  };

  account.enterAccountNumber = function(keys){

    account.selectHasAccount().then(function(){
      account.accountNumber.sendKeys(keys);
      return account.submitAccountButton.click()
        .then(function(){
          return browser.getCurrentUrl();
      });
      //this wont log because already returned ^
//      console.log('need to return again');
    });
  };
  account.noAccount = function(){
    account.elem.get(1).click();
  };

describe('registration page', function() {
  it("will survive", function(){
    var registrationPage = new RegistrationPage()
    , title = browser.getTitle();
    expect(title).toBe('Web Shop | Homepage');
  });
  it('will change route on account_exists radiobox click', function(){
    var elem = element.all(by.name('account_exists'))
    , _url;
    elem.get(0).click()
    .then(function(){
      _url = browser.getCurrentUrl().then(function(_url){
        expect(_url).toBe('http://localhost:5000/register#/registration/has');
      });
    })
    .then(function(){
        elem.get(1).click().then(function(){
          _url = browser.getCurrentUrl();
          expect(_url).toBe('http://localhost:5000/register#/registration/no');
        });
      });
  });
  describe('navigate the hasAccount path:', function(){
    it('will click hasAccount which will cause a route change.', function () {
      expect(account.selectHasAccount()).toBe('http://localhost:5000/register#/registration/has');
    });
    it("will submit a valid account number", function(){
      expect(account.enterAccountNumber('1231231231')).toBe('http://localhost:5000/register#/user');
    });
  });
  it('will click noAccount which will cause a route change.', function () {
    var  _url;
    account.noAccount();
    _url = browser.getCurrentUrl();
    expect(_url).toBe('http://localhost:5000/register#/registration/no');
  });
});
})();

مطلوب / main.js:

var pathToJQuery
if('querySelector' in document
  && 'localStorage' in window
  && 'addEventListener' in window) {
  //ie9+ and all browsers
  pathToJQuery = 'lib/jquery/dist/jquery'
} else {
  //ie8 and ie7
  pathToJQuery = 'lib/jquery-1.7.2.min'
}
requirejs.config({

      paths : {

//        Paths

          "reg": 'js/registration'
        , "com": 'js/common'
        , "init": 'js/init'
        , "regD": 'js/registration/directives'
        , "regC": 'js/registration/controllers'
        , "regS": 'js/registration/services'
        , "regM": 'js/registration/modules'
//
//        Frameworks
        ,  "angular": "lib/angular/angular"
        ,  "angular.animate" : "lib/angular-animate/angular-animate"
        ,  "jquery": pathToJQuery   //< = == v    long story; don't judge me.
        ,  "jqueryMigrate" : "lib/jquery-migrate/jquery-migrate"
        ,  "mocks": "lib/angular-mocks/angular-mocks"
        ,  "ui_router": "lib/angular-ui-router/release/angular-ui-router"
        ,  "Q": "lib/q/q"

//        Init
        ,  "apps_init" : 'js/init/apps_init'
        ,  "apps_bootstrap" : 'js/init/apps_bootstrap'
//        ,  "jquery_bootstrap" : 'js/init/jquery_bootstrap'
        ,  "registration": "js/init/registration"

//       Common

//         Registration
        ,  "registration": "js/registration/registration"
//         Controllers
        ,  "account.controller" : 'js/registration/controllers/account.controller'
        ,  "user.controller" : 'js/registration/controllers/user.controller'
//         Directives
        ,  "account.directive" : 'js/registration/directives/account.directive'
//    Services
        , "user.service" : "js/registration/services/user.service"
    }
,     shim: {
        'angular': {
            exports : 'angular'
        }
    ,   'angular.animate' : {deps: ['angular']}
    ,   'jqueryMigrate' : {deps: ['jquery']}
    ,   'ui_router' : ['angular']
    ,   'mocks': { deps: ['angular'], 'exports': 'angular.mock' }
}
});

if( pathToJQuery ===  'lib/jquery/dist/jquery' ){
  requirejs([
        'angular' , 'jquery' , 'jqueryMigrate', 'init/jquery_bootstrap', 'init/apps_bootstrap' ]
      , function(angular, jquery, jquery_bootstrap, apps_bootstrap) {
      }
  );
} else {
  requirejs([
      'angular' , 'jquery' , 'jqueryMigrate', 'init/jquery_bootstrap', 'init/apps_bootstrap' ]
    , function(angular, jquery, jqueryMigrate, jquery_bootstrap, apps_bootstrap) {
    }
  );
}
console.log("working");

ملفات يحتمل أن تكون مفيدة:

العرض الافتراضي (المقاود)

<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org"
            xmlns:fab="http://angularjs.org"
            xmlns:ui ="http://angularjs.org"
            lang = "en" class = "no-js" >
<head >
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/x-icon" media="all" href="/images/favicon.ico" />
<script type="text/javascript" src="lib/modernizr.js"></script>

<!-- Default ie theme files:-->
<!--[if lte IE 9]><script type="text/javascript">console = {}; console.log = function(){};</script><![endif]-->
<!--[if IE 8]><link type="text/css" rel="stylesheet" href="build/css/ie8/theme.css" /><![endif]-->

<!--[if IE 7]><link type="text/css" rel="stylesheet" href="build/css/ie7/theme.css" /><![endif]-->

<!-- Normal styles -->
<link type="text/css" href="css/style.css" rel="stylesheet">


<!--[if IE 8]> <link type="text/css" rel="stylesheet" href="build/css/ie8/ie_8.css"  /> <![endif]-->
<!--[if IE 7]> <link type="text/css" rel="stylesheet" href="build/css/ie7/lte_ie7.css"/> <link type="text/css" rel="stylesheet" href="build/css/ie7/ie_7.css" /><![endif]-->


<script data-main="main" src="lib/requirejs/require.js"></script>
</head >

<body class = "page-homepage language-en" >
<div id = "wrapper" >
    <div id = "page" data-currency-iso-code = "USD" >
        {{> _header}}
        <a href = "#skip-to-content" class = "skiptocontent" >Skip to content</a >
        <a href = "#skiptonavigation" class = "skiptonavigation" >Skip to navigation menu</a >
    <!--[if lte IE 10]> <p class="browsehappy" style="margin-top: 10px; ">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p><![endif]-->
    <main ng-cloak id = "content" role = "main" class = "page_main <!--[if IE7]>ng-cloak<![endif]-->" >

        </main>
    </div >
</div >
</body >

</html >

controller.js (تكوين الخادم)

(function(){
    "use strict";

    //  node requires
    //==============================
    // express-hbs
    // express
    //
    const express = require('express')
        , portN = 5000
        , hbs = require('express-hbs')
        , app = express()
        , path = require('path')
        , Server = require('./server')
        , bodyParser = require('body-parser')
        , serveStatic = require('serve-static')
        , session = require('express-session')

    , router = express.Router()
    , logger  = require('morgan')
        , methodOverride = require('method-override')
        , errorhandler = require('errorhandler')


    //  view paths
    //==============================
    //
    //
    //
        , viewsD = __dirname + '/views/'
        , partialsD = viewsD + 'partials/'
        , layoutsD = viewsD + 'layouts/'
        , testsD =  __dirname + '/tests/'
    , publicD = __dirname + '/public/'
    , styleguideD = publicD+ '/styleguide/'
        , defaultF = layoutsD + 'default.hbs';
    //  Express setup.
    //==============================
    //
    //
    //
    app.use(express.static(publicD))
            .use(bodyParser())
            .use(logger('dev'))
            .use(methodOverride())
            .use(serveStatic(path.join(__dirname, 'public')))
            .use(errorhandler());

    app.set('view engine', 'hbs')
            .set('port', process.env.PORT || portN)
            .set('cache', false)
            .set('views', viewsD);

    app.engine('hbs', hbs.express3({
        partialsDir: partialsD,
        defaultLayout: defaultF,
        layoutsDir: layoutsD
    }));

    var indx = {};

    app.get( '/' ,function (req, res) {
        res.render(partialsD + '_home.hbs', indx);
    });

    app.get( '/register' ,function (req, res) {
        res.render(partialsD + '_register.hbs', indx);
    });

    new Server(app);

})();

server.js

module.exports = function(app){
  "use strict";
    var http = require('http');
    http.createServer(app).listen(app.get('port'), function(){
        console.log('Express server listening on port ' + app.get('port'));
    });
};


module.exports = function (app) {
    "use strict";
    var http = require ('http');
    http.createServer (app).listen (app.get ('port'),function () {
        console.log ('Express server listening on port ' + app.get ('port'));
    }).on ('error', function (e) {
        console.log ("got error: " + e.message);
    });
};

package.json (مقتطفات ذات صلة)

"dependencies": {
    "body-parser": "^1.2.1",
    "bower": "^1.3.2",
    "errorhandler": "^1.0.1",
    "express": "^4.3.1",
    "express-hbs": "^0.7.9",
    "express-session": "^1.2.0",
    "node-dev": "^2.3.0"
  },

  "scripts": {
    "start": "node --harmony $* ./node_modules/.bin/node-dev controller.js",
  },
"devDependencies": {
  "browserstack-webdriver": "^2.41.1",
  "grunt-protractor-runner": "^1.0.0",
  "method-override": "^1.0.2",
    "morgan": "^1.1.1",
    "protractor": "^0.23.1",
    "requirejs": "^2.1.11",
    "serve-static": "^1.1.0",
},
  "author": "Andrew Luhring"

هيكل الملف:

config/
   protractor.config.js
    chromedriver

server.js
controller.js

public/
   main.js
   js/
   lib/

tests/
   e2e/
      _protractor.js    <=== test file.

views/
  layouts/
      default.hbs

  partials/
      _head.hbs
      _register.hbs   <=== file being tested.

متأكد من أن هذا هو الإعداد الكامل الخاص بي. أحسب أنني سأذهب إلى الإسهاب. امل ان يساعد.

ما كان علي فعله هو:

  1. إضافة جزء خاص بالاختبار إلى عنوان URL ، بحيث يعرف رمز التمهيد الخاص بي ما إذا كان يعمل "بشكل طبيعي" أو كاختبار منقلة ، ثم للاختبارات فقط
  2. استدعاء angular.bootstrap من document.ready
  3. ضع اسم النافذة ليبدأ بـ "NG_DEFER_BOOTSTRAP!" قبل استدعاء angular.bootstrap
  4. اضبط السمة "ng-app" على عنصر المستوى الأعلى الخاص بي
  5. اضبط النافذة المستطيلة للإشارة إلى الزاوي

راجع https://github.com/mikaraento/protractor-reuse/blob/master/index.js

هل لي أن أعرف لماذا لا تستطيع البرامج النصية الخاصة بالمنقلة التي تعمل بشكل جيد في متصفحات Chrome و Firefox أن تنفذ دائمًا في Internet Explorer؟

على الرغم من أن نفس البرامج النصية يتم تنفيذها بشكل مثالي في المتصفحات الأخرى ، إلا أنه لا يمكن تنفيذها دائمًا في Internet Explorer. أحصل على أخطاء متكررة مثل استثناء المهلة
message: "timeout: انتهت المهلة بعد 30000 مللي ثانية في انتظار اكتمال المواصفات" ،
التتبع: {stack: undefined}}]
وكذلك في بعض الأحيان لا يتم اكتشاف العناصر في Internet Explorer.

على الرغم من أنني استخدمت الفاصل الزمني الافتراضي باعتباره افتراضيًا ، فالتوقيت الزمني: 1000000 ، في البرامج النصية الخاصة بي ، أحصل على الأخطاء المذكورة أعلاه أثناء التنفيذ في Internet Explorer ...

يمكن لأي شخص أن يساعدني على ذلك؟

يعتبر،
سانثوش تشونتشو

لا أرى أن هذه مشكلة في التمهيد اليدوي فقط؟ أم أنك قادر على تشغيل تطبيقات تمهيد التشغيل اليدوية الموجودة بالفعل في Chrome و Firefox؟

hankduan هل سبق لك إلقاء نظرة على حالة الاختبار؟ ربما أي شيء يمكننا مساعدته؟

لدي CL خارجًا يغير طريقة عمل التمهيد للمنقلة (https://github.com/angular/protractor/pull/1155). الغرض الرئيسي منه هو إصلاح عدد من المشكلات الأخرى ، لكنني أعتقد أنه يجب إصلاحها (أو على الأقل المساعدة) باستخدام التمهيد اليدوي اعتمادًا على كيفية قيامك بالتشغيل. ومع ذلك ، لم أقم مطلقًا بإعداد bootstrap يدويًا للاختبار ، لذلك هذا مجرد نظري.

تتطلب هذه العلاقات العامة تغييرًا في المنقلة وتغييرًا في Angular ، لذلك قد لا يتم تحريرها في فترة زمنية قصيرة.

يبدو أن هذه المشكلة هي أفضل نتيجة بحث عند البحث عن طرق لإقلاع Angular يدويًا للاستخدام مع منقلة ، لذلك اعتقدت أن هذا جيد مثل أي مكان لاقتراح حل آخر. يعمل هذا في الحالة التي تكون فيها الواجهة بالكامل عبارة عن تطبيق Angular (بدلاً من القيام بشيء مثل bootstrapping على div بعد تسجيل الدخول ، مثل الأمثلة المذكورة أعلاه).

في حين أنه قد يكون من الممكن تأخير اختبارات منقلة إلى ما بعد تحميل Angular ، فإن مستندات Angular الرسمية تنص على أنه لا يمكنك القيام بعملية تمهيد يدوية باستخدام منقلة. أميل إلى الابتعاد عن الحلول البديلة التي يبدو أن الوثائق الرسمية تمنعها.

بلدي الحل

أنا أستخدم Grunt إلى Concat / Uglify الشفرة الخاصة بي وصولاً إلى ملف JS واحد ، وهو البرنامج النصي الوحيد المشار إليه في index.html ، مع علامة البرنامج النصي. دعنا نسميها script.js. في التطوير ، أقوم بتشغيل مهمة Grunt مختلفة ، والتي تجمع معًا الملفات التي أحتاجها فقط لتحميل باقي ملفات JS ، بشكل منفصل وغير متزامن ومع طوابع زمنية لمنع التخزين المؤقت. تحل هذه المجموعة المسلسلة من البرامج النصية محل script.js أثناء التطوير. في أي من السيناريوهين ، أقوم فقط بتحميل script.js من index.html ، وباستخدام علامة البرنامج النصي.

تطوير

لذلك ، في التطوير ، يجب أن أقوم بتمهيد يدوي. هذا أمر سهل لأنني أستطيع تضمين ملف واحد لا أدخله في Production JS ، وأتأكد من تحميل هذا البرنامج النصي بعد تحميل جميع JS الأخرى.

bootstrap_dev.js

        .element(document.body)
        .ready(function() {
            angular.bootstrap(document.body, ['App']);
        });

الإنتاج / المنقلة

في الإنتاج ، لا يمكنني التمهيد يدويًا لأن المنقلة لا تحبها. وأنا أقوم بتشغيل منقلة مقابل كود الإنتاج الخاص بي. لقد قمت أيضًا بإزالة سمة "ng-app" من HTML الخاص بي ، لذلك لا يتم تمهيد التطبيق قبل الأوان في التطوير ، لذلك لا يحدث التمهيد التلقائي العادي. أعوض عن هذا في الإنتاج عن طريق وضع نص قبل كل JS الأخرى في script.js.

bootstrap_prod.js

    window.document.body.setAttribute("ng-app", "myApp");

فقط استبدل "myApp" باسم الوحدة الرئيسية الخاصة بك.

استنتاج

في التطوير ، إذا قمت بما سبق ، يمكنك تحميل البرنامج النصي الخاص بك بشكل غير متزامن والقيام بتمهيد يدوي. ولكن إذا كنت موافقًا فقط على تشغيل اختبارات Protractor الخاصة بك مقابل كود الإنتاج (والذي يمكن تحميله من ملف واحد عبر علامة البرنامج النصي ، فما عليك سوى إضافة التوجيه ng-app قبل تحميل Angular حتى يقوم بعملية التمهيد التلقائي. لديك الآن تحميل برنامج نصي غير متزامن لنصوصك المختلفة في التطوير ، وتشغيل اختبارات منقلة لرمز الإنتاج الخاص بك.

ما انتهى به الأمر بالنسبة لي هو إضافة الوظيفة التالية في منقلة .conf.js:

onPrepare: function() 
    {
        // implicit and page load timeouts
        browser.manage().timeouts().pageLoadTimeout(40000);
        browser.manage().timeouts().implicitlyWait(25000);

        // for non-angular page
        browser.ignoreSynchronization = true;

        // sign in before all tests
     }

إذا كانت هناك طريقة أفضل للقيام بذلك ، فيرجى إبلاغي بذلك =]

كان لديه مشكلة مماثلة. وجدت هذه المعلومات المفيدة:

عملية التمهيد

لا يوجد فرق ، كيف يتم تعزيز التطبيق في الإنتاج ، ولكن في الاختبارات تقوم المنقلة بذلك:

  1. يغير window.name بحيث يتم إيقاف الزاوي مؤقتًا قبل البدء: NG_DEFER_BOOTSTRAP! (هذه ميزة زاوية!)
  2. يقوم بأشياء وهمية ، ثم يستدعي angular.resumeBoostrap () ويبدأ التطبيق بالفعل.

لذا تأكد من أن كود الإنتاج الخاص بك لا يتعارض مع هذه العملية ، لأنه يمكن تعزيز الزاوية مرة واحدة فقط ، وستؤدي المكالمة الثانية إلى angular.boostrap () أو angular.resumeBoostrap () إلى كسر المنقلة أو التطبيق. لذلك ، لا حاجة إلى تطبيق ng في الجسم على الإطلاق ، ويمكنك استدعاء angular.boostrap () بنفسك وسيتم التعامل معه بواسطة منقلة باستخدام NG_DEFER_BOOTSTRAP! بصورة صحيحة.

window.name

تأكد من عدم تغيير window.name بواسطة أي رمز تطبيق أثناء التحميل والتمهيد. في حالتي كان jquery يفعل ذلك ، لا يمكنني معرفة السبب. تمت إزالة الاستفسار بالكامل من مشروعي ونجحت الاختبارات. هذا هو جذر المشكلة!

في الوقت الحالي ، أقوم بالبحث عن كيفية إعادة jquery دون كسر الاختبارات ، لأن مشروعي يحتاجها!

أخيرا،

كانت مشكلتنا في نسختين من jQuery على صفحة واحدة (تم تحميل الإصدار الثاني بواسطة مكتبة خارجية). تمت إزالته وتركت فقط jQuery على الصفحة ويعمل كل شيء.

قد تكون بعض التعليمات البرمجية مفيدة:

index.html

<body>
...
<script data-main="require.conf" type="text/javascript" src="bower_components/requirejs/require.js"></script>
</body>

يتطلب تكوين

...
 deps: ["proto/main"],
...

proto.js

// We just load deps and register the module:
 define(["deps"],function(){
   angular.module('proto'...
 }

بروتو / main.js

define(["require", "exports", "proto", "angular"], 
    function (require, exports) {

    angular.bootstrap(document, ['proto']);
});

وفي الواقع ، مواصفات الاختبار

var protractor = require('protractor');
var ptor;
function prepareBrowser() {

    ptor = protractor.getInstance();

    return ptor.get(ptor["baseUrl"] + '/login').then(function () {
        console.log("got");       
        return ptor.waitForAngular().then(function () {
            console.log("ngwaited");
        });
    });
}
describe('container', function () {
    beforeEach(function () {
        return prepareBrowser();
    });
    describe('form tests', function () {
        it('form is shown', function () {
            expect($('[ng-controller=LoginContr]').isDisplayed()).toBeTruthy();
        });

    });
});

انتاج |

Using the selenium server at http://localhost:4444/wd/hub
got
ngwaited
container
  form tests
    form is shown - pass


Finished in 3.112 seconds
1 test, 1 assertion, 0 failures

هوراي!

عندما قمنا بالتبديل من استخدام ng-app إلى angular.bootstrap() ، كانت إضافة rootElement: 'div' إلى projotractor.conf التغيير الوحيد الذي نحتاجه لإعادة عمل المنقلة. نحن نستخدم الزاوي 1.3.0 والمنقلة 1.3.1.

jongunnip نعم هذا عمل لي أيضًا ، شكرًا!

mikaraento لقد نجحت معي ، شكرًا ~

مرحبًا يا شباب ، شيء غريب يتعلق بهذا الموضوع.

لدي تطبيق زاوي عادي - لا يتطلب الأمر أو أي شيء ، فأنا أستخدم منقلة 2.0.0.

عندما أقوم بإجراء اختبارات النظام على بيئة التدريج ، فإنه يعمل.
عندما أقوم بتشغيله محليًا ، فإنه يعطيني:
رسالة org.openqa.selenium.WebDriverException: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element ...

عندما أقوم بتكوين خادم Nginx لخدمة المورد الثابت بدلاً من grunt:server كل شيء يعمل.

هل يهم حقًا إذا قمت بتشغيله مع وجود الكبد قيد التطوير؟

يبدو أن الخوادم الثابتة تتصرف بشكل مختلف ، ويقدم grunt بعض عمليات إعادة التوجيه 404 أو عمليات إعادة التوجيه ، لذلك يصبح webdriver مجنونًا.

أهلا بكم،

بعد الكثير من الوقت في القراءة والقراءة ، وجدت حلاً واحدًا يعمل جيدًا لمشروعي ( إصلاح تدفق تنفيذ المنقلة )

  1. عند فتح التطبيق لمنقلة ، أضف ?protractor-test إلى URL ( رمز المشروع )
  2. تغيير كود bootstrap الزاوي ليكون مثل أدناه ( رمز المشروع )
if(location.href.indexOf("protractor-test") < 0){
  // start angular app
  angular.bootstrap(document, [module.name]);
} else {
  // start angular app to protractor tests
  window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
  angular.bootstrap(document, [module.name]);
}

وأخيرًا عاد الكل للعمل مرة أخرى \ o /

مع نسخة juliemr

لقد بدأت مؤخرًا (أسبوع إلى أسبوعين فقط) في استخدام المنقلة لاختبار تطبيق Angular الخاص بي. يحتوي تطبيقي على تطبيق ng محدد في علامة النص في صفحة تسجيل الدخول. يستمر اختباري في الشكوى قائلاً "لا يمكن العثور على Angular في الصفحة HTP: // (عنوان موقع الويب): الزاوي لم يتم تقديم استئناف Bootstrap مطلقًا" ولكن تنفيذ الاختبار جيد. لست متأكدًا من المشكلة (إذا قمت بتشغيل متغير تجاهل المتصفح ، فهذا يعني أنه يعمل بشكل جيد ، ولكن هذه ليست الطريقة الصحيحة) ، يمكنني تجربة ما يقترحه جوليمر (استخدم برنامج التشغيل القديم للتنقل) ، ولكن فقط أحاول فهم سبب شكوى تطبيقي على الرغم من أنه يحتوي على تطبيق ng في علامة النص الأساسي. يشبه السلوك الوظيفي للتطبيق .. صفحة تسجيل الدخول .. بمجرد تسجيل الدخول ، انقر فوق رابط ما في الصفحة الرئيسية ويفتح نافذة / علامة تبويب أخرى. هل يمكن لأي شخص مساعدتي في العثور على الخطوات التي يحتاجها الجميع للتحقق للتأكد من أن التمهيد يتم بطريقة تلقائية (أحدهما هو معلمة ng-app في علامة الجسم)؟ هل أحتاج إلى التحقق من شيء ما في ملف bootstrap.js (لا أرى أي معلمة ng-app في ملف bootstrap ومن ثم التحقق منه. شكرًا لك

هل هناك أي تحديثات بشأن هذه المسألة؟ ما هي أفضل الممارسات أو الطرق لتكوين المنقلة للعمل عليها باستخدام تطبيق زاوية لا يحتوي على تطبيق ng؟ erkobridee هل يمكن أن تشرح مثالك أكثر؟ وهل يمكن لأي شخص أن يشرح كيفية التعامل مع window.name بشكل صحيح فيما يتعلق بالكيفية التي يجب أن تنتظر بها المنقلة عندما تنتهي الزاوية من التحميل؟

juliemr مع Angular 1.5 ، يعد التمهيد اليدوي هو الطريقة المفضلة للتمهيد. هل يوجد دعم مبارك للمنقلة على الطريق؟

+1 أعتقد أن هذه المشكلة يجب أن تكون ذات أولوية أعلى. إذا لم تعمل المنقلة مع التمهيد اليدوي ، فلا فائدة من استخدام المنقلة. بيت القصيد من استخدام منقلة عبر Webdriver هو أن المنقلة تتعامل مع كل المزامنة الزاوية نيابة عنك.

لدي نفس المشكلة. أي تحديث؟

مرحباً ، هل هناك أي خطة أو عملية لتحسين ذلك؟

غريب ليس هناك ردود فعل. لدي تطبيقات تفتقد إلى تطبيق ng ولا يمكنني اختبارها
لهم مع منقلة

في 16 تموز (يوليو) 2016 الساعة 5:01 صباحًا ، كتب "millerwx" [email protected] :

مرحباً ، هل هناك أي خطة أو عملية لتحسين ذلك؟

-
أنت تتلقى هذا لأنك علقت.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/angular/protractor/issues/66#issuecomment -233104701 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AOghFs2ff0e-88DLafNGD3iCH8uCOgVaks5qWEmIgaJpZM4A82d7
.

حتى هذا التاريخ في عام 2016 ، كان هذا لا يزال يمثل مشكلة بالنسبة لي. لقد اتبعت الإجابة الممغنطة لحل المشكلة. لقد أجريت بعض التغييرات. ما هو لطيف وخارج نطاق المحادثة هو تتبع عمليات إعادة التوجيه والعودة داخل تطبيقك. * لقد فعلت ذلك مع Babel ، لكن يمكنك كتابتها في ES5 بدلاً من ذلك.

"وصف ('شاشة تسجيل الدخول'، () => {

var urlTimeout = 9000;

const waitForUrlRegex = (regex, urlMatcher )=>{

    return driver.wait(()=>{
        return driver.getCurrentUrl().then( (url)=>{
            return regex.test(url);
        });
    }, urlTimeout, "Expectation error: Timeout for url not matching " + urlMatcher );
};

const waitForRoute = (route)=>{
    return waitForUrlRegex( new RegExp( route + "$" ), route  );
}

const waitForUrl = (url)=>{
    return waitForUrlRegex( new RegExp( "^https?:\/\/" + url ), url );
}

it('should go to homepage and click login button', ()=>{

    driver.get( app_url, urlTimeout);

    //there is a redirect to welcome route
    expect( waitForRoute("welcome") ).toBe(true);

    const loginButton = element.all(by.className("login_button")).get(0);
    loginButton.click();
});

it( 'should enter credentials', ()=>{
    expect( waitForUrl( non_angular_login_url ) ).toBe(true);
    driver.findElement( by.name("user")).sendKeys( "username");
    driver.findElement( by.name("password")).sendKeys( "userpassword");
    driver.findElement( by.tagName("button")).click();
});

it( 'should go back to app, and continue testing', ()=>{
    expect( waitForRoute( "user-screen") ).toBe(true);
});

}) ؛ `

config.on التحضير

onPrepare: ()=>{ require("babel-register"); global.driver = browser.driver; }

في حالة عدم رغبتك في النظر في عمليات إعادة التوجيه ، ببساطة اجعل السائق ينام ثم ابدأ العمل مع المنقلة.

`driver.get (app_url +" / # / welcome "، urlTimeout) ؛

    driver.sleep( 1000 );
    const loginButton = element.all(by.className("login_button")).get(0);
    loginButton.click();`

نحن بالفعل ندعم التمهيد اليدوي ، هذه المعلومات قديمة. سيصبح Bootstrapping أكثر موثوقية بمجرد تعاملنا مع https://github.com/angular/protractor/issues/3857 أيضًا.

sjelin ما هي الطريقة الموثقة لدعم التمهيد اليدوي؟ لا يمكنني العثور على المعلومات ذات الصلة بالمنقلة 5.0.

كنت أواجه نفس المشكلة أثناء التمهيد اليدوي. ووجدت الحل للركض بالنخر.
تستخدم منقلة الإصدار 2.5.1.

  1. أذكر هذا في ملف النخر الخاص بك.

grunt.initConfig({ protractor: { options: { configFile: "protractor.conf.js", // Default protractor config file keepAlive: true, // If false, the grunt process stops when the test fails. noColor: false, // If true, protractor will not use colors in its output. args: { // Arguments passed to the command } }, e2e: { options: { // Stops Grunt process if a test fails keepAlive: true } } } })

  1. قم بتثبيت npm install grunt-protractor-runner --save-dev وأضف لمهمة التحميل grunt.loadNpmTasks('grunt-protractor-runner')

  2. قم بتشغيل المنقلة بالأمر التالي:
    grunt protractor
    أو باسم الجناح
    grunt protractor --suite suite_name

واسمحوا لي أن أعرف إذا كان يعمل من أجلك.

هذا عمل لي.
browser.ignoreSynchronization = صحيح ؛
browser.get (url) ؛
browser.ignoreSynchronization = خطأ ؛

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات