2016-12-10 1 views
2

Проблемы

У меня есть /login маршрута, который использует ember-simple-auth для осуществления аутентификации. Во время тестирования ember-cli-mirage используется для фальсификации бэкэнд. Пользователь регистрируется, указав свой адрес электронной почты и пароль.EmberJS тест не первый раз работаю в phantomjs

В общей сложности у меня есть 4 приемочные испытания для данного маршрута, аналогичные ниже теста:

test('should show error message for invalid email', function(assert) { 
    visit('/login'); 
    fillIn('input#email', 'invalid-email'); 
    fillIn('input#password', 'invalid-password'); 
    click('button.button'); 
    andThen(function() { 
    assert.equal(find('div.notification').text(), "Invalid email/password"); 
    }); 
}); 

Когда я запускаю тесты с использованием ember t только первый тест в файл не удается. Если я прокомментирую этот тест, следующий не удастся и т. Д. Если я запускаю тесты в режиме сервера с ember t -s, то те же тесты терпят неудачу; однако, когда я нажимаю , введите для повторного запуска тестов, все тесты пройдут.

сообщение о сбое всегда то же самое, как показано ниже:

not ok 7 PhantomJS 2.1 - Acceptance | login: should show error message for invalid email 
    --- 
     actual: > 

     expected: > 
      Invalid email/password 
     stack: > 
      http://localhost:7357/assets/tests.js:22:19 
      [email protected]://localhost:7357/assets/vendor.js:48231:41 
      http://localhost:7357/assets/vendor.js:48174:24 
      [email protected]://localhost:7357/assets/vendor.js:49302:30 
      http://localhost:7357/assets/vendor.js:49258:23 
      [email protected]://localhost:7357/assets/vendor.js:68726:20 
      [email protected]://localhost:7357/assets/vendor.js:68738:21 
      [email protected]://localhost:7357/assets/vendor.js:68709:21 
      http://localhost:7357/assets/vendor.js:48192:24 
      [email protected]://localhost:7357/assets/vendor.js:10892:18 
      [email protected]://localhost:7357/assets/vendor.js:10960:15 
      [email protected]://localhost:7357/assets/vendor.js:11084:20 
      [email protected]://localhost:7357/assets/vendor.js:11154:28 
      [email protected]://localhost:7357/assets/vendor.js:11277:19 
      [email protected]://localhost:7357/assets/vendor.js:32073:32 
      http://localhost:7357/assets/vendor.js:48783:24 
     Log: | 

После того, как все тесты закончились, тест выдает исключение:

# tests 60 
# pass 59 
# skip 0 
# fail 1 
Not all tests passed. 
Error: Not all tests passed. 
    at EventEmitter.getExitCode (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/lib/app.js:434:15) 
    at EventEmitter.exit (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/lib/app.js:189:23) 
    at /home/jon/projects/jonblack/wishlist-web/node_modules/testem/lib/app.js:103:14 
    at tryCatcher (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/util.js:16:23) 
    at Promise._settlePromiseFromHandler (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:510:31) 
    at Promise._settlePromise (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:567:18) 
    at Promise._settlePromise0 (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:612:10) 
    at Promise._settlePromises (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/promise.js:691:18) 
    at Async._drainQueue (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/async.js:138:16) 
    at Async._drainQueues (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/async.js:148:10) 
    at Immediate.Async.drainQueues (/home/jon/projects/jonblack/wishlist-web/node_modules/testem/node_modules/bluebird/js/release/async.js:17:14) 
    at runCallback (timers.js:637:20) 
    at tryOnImmediate (timers.js:610:5) 
    at processImmediate [as _immediateCallback] (timers.js:582:5) 

Кажется странным, что это испускается для испытаний а не просто сообщить об ошибке тестирования, поэтому, возможно, это связано.

Выполнение тестов в Firefox и Chromium, а также запуск приложения в режиме разработки и ведение журнала вручную. Проблема ограничена фантомами.

У меня есть другие приемочные испытания для другого маршрута, и все это проходит. Кажется, он ограничен маршрутом /login, что указывает на то, что он, возможно, связан с аутентификацией.

Debugging

Я пытался отладки путем добавления pauseTest() к тесту и "phantomjs_debug_port": 9000 к testem.js но и Firefox и Chromium ничего не делать, когда я использую консоль отладки. Возможно, это недостаток опыта отладки phantomjs, но я бы по крайней мере ожидал, что он даст мне ошибку - это буквально ничего не делает.

Похоже, что существует проблема синхронизации между фантомами и чем-то, возможным ember-simple-auth, в моем приложении Ember.

Я не испытываю проблем с отладочной ошибкой phantomjs и ошибок при приеме проб с использованием Ember, поэтому любая помощь оценивается.

Версия

ember-cli 2.10.0 
ember-simple-auth 1.1.0 
ember-cli-mirage 0.2.4 

Update 1

Кнопка находится внутри login-form компонента:

<form {{action 'login' on='submit'}}> 
    <p class="control has-icon"> 
    {{input value=email id='email' placeholder='email' class='input'}} 
    <i class="fa fa-envelope"></i> 
    </p> 
    <p class="control has-icon"> 
    {{input value=password id='password' placeholder='password' 
      type='password' class='input'}} 
    <i class="fa fa-lock"></i> 
    </p> 
    <p class="control"> 
    <button class="button is-success" disabled={{isDisabled}}>Log In</button> 
    </p> 
</form> 

Войти компонента действия только вызовы переданных в обработчик входа:

import Ember from 'ember'; 

export default Ember.Component.extend({ 
    email: "", 
    password: "", 

    isDisabled: Ember.computed('email', 'password', function() { 
    return this.get('email') === "" || this.get('password') === ""; 
    }), 

    actions: { 
    login() { 
     var email = this.get('email'); 
     var password = this.get('password'); 
     this.attrs.login(email, password); 
    } 
    } 
}); 

Какой authenticate метод в контроллере авторизации:

import Ember from 'ember'; 

export default Ember.Controller.extend({ 
    session: Ember.inject.service(), 

    actions: { 
    authenticate(email, password) { 
     this.get('session').authenticate('authenticator:oauth2', email, password).catch((data) => { 
     this.set('errors', data['errors']); 
     }); 
    } 
    } 
}); 

Update 2

Как предложил Даниилу я добавил задержку теста:

test('should show error message for invalid email', function(assert) { 
    visit('/login'); 
    fillIn('input#email', 'invalid-email'); 
    fillIn('input#password', 'invalid-password'); 
    click('button.button'); 
    andThen(function() { 
    Ember.run.later(this, function() { 
     assert.equal(find('div.notification').text(), "Invalid email/password"); 
    }, 0); 
    }); 
}); 

Использование только Ember.run.later тест еще провалился, но при этом он попал внутрь andThen. Вы заметили причудливую часть? Задержка составляет 0 миллисекунд.

Я все еще хочу найти объяснение этого, потому что я не верю, что это будет работать на той же машине, на которой запущены тесты.

Update 3

Сегодня у меня был сюрприз: вдруг тесты снова работает!

Я добавил новый маршрут с приемочными испытаниями. Сам маршрут является аутентифицированным маршрутом, поэтому в тестах используется тестовый помощник authenticateSession от ember-simple-auth для аутентификации.

При удалении тестов, которые используют этот помощник, возвращается ошибка!.

Я не уверен, что это значит. Похоже, проблема связана с ember-simple-auth, но также может быть гигантским совпадением, что помощник решает другую проблему с синхронизацией.

вниз кроличью нору мы идем ...

Update 4

Ниже конфигурация для AUTH конечных точек в Ember-CLI-мираж:

this.post('/token', function({db}, request) { 
    var data = parsePostData(request.requestBody); 

    if (data.grant_type === 'password') { 
    // Lookup user in the mirage db 
    var users = db.users.where({ email: data.username }); 
    if (users.length !== 1) { 
     return new Mirage.Response(400, {'Content-Type': 'application/json'}, { 
     errors: [{ 
      id: 'invalid_login', 
      status: '400', 
      title: 'Invalid email/password', 
     }] 
     }); 
    } 
    var user = users[0]; 

    // Check password 
    if (data.password === user.password) { 
     if (!user.active) { 
     return new Mirage.Response(400, {'Content-Type': 'application/json'}, { 
      errors: [{ 
      id: 'inactive_user', 
      status: '400', 
      title: 'Inactive user', 
      }] 
     }); 
     } else { 
     return new Mirage.Response(200, { 
      'Content-Type': 'application/json' 
     }, { 
      access_token: 'secret token!', 
      user_id: user.id 
     }); 
     } 
    } else { 
     return new Mirage.Response(400, {'Content-Type': 'application/json'}, { 
     errors: [{ 
      id: 'invalid_login', 
      status: '400', 
      title: 'Invalid email/password', 
     }] 
     }); 
    } 
    } else { 
    return new Mirage.Response(400, {'Content-Type': 'application/json'}, { 
     errors: [{ 
     id: 'invalid_grant_type', 
     status: '400', 
     title: 'Invalid grant type', 
     }] 
    }); 
    } 
}); 

this.post('/revoke', function(db, request) { 
    var data = parsePostData(request.requestBody); 

    if (data.token_type_hint === 'access_token' || 
     data.token_type_hint === 'refresh_token') { 
    return new Mirage.Response(200, {'Content-Type': 'application/json'}); 
    } else { 
    return new Mirage.Response(400, {'Content-Type': 'application/json'}, 
           {error: 'unsupported_token_type'}); 
    } 
}); 

Update 5

Вот мой config/environment.js файл:

/* jshint node: true */ 

module.exports = function(environment) { 
    var ENV = { 
    modulePrefix: 'wishlist-web', 
    environment: environment, 
    rootURL: '/', 
    locationType: 'auto', 
    EmberENV: { 
     FEATURES: { 
     }, 
     EXTEND_PROTOTYPES: { 
     // Prevent Ember Data from overriding Date.parse. 
     Date: false 
     } 
    }, 

    APP: { 
    } 
    }; 

    if (environment === 'development') { 
    } 

    if (environment === 'test') { 
    // Testem prefers this... 
    ENV.locationType = 'none'; 

    // keep test console output quieter 
    ENV.APP.LOG_ACTIVE_GENERATION = false; 
    ENV.APP.LOG_VIEW_LOOKUPS = false; 

    ENV.APP.rootElement = '#ember-testing'; 
    } 

    if (environment === 'production') { 
    ENV.ServerTokenEndpoint = 'http://localhost:9292/token'; 
    ENV.ServerTokenRevocationEndpoint = 'http://localhost:9292/revoke'; 
    ENV.ApiHost = 'http://localhost:9292'; 
    } 

    return ENV; 
}; 
+0

Когда вы нажали кнопку 'button.button', как вы создаете обещание? Можете ли вы предоставить код, который создает обещание? (Мое предположение заключается в том, что обещание не может быть разрешено в среде phantomjs.) – ykaragol

ответ

1

У вас есть несколько вещей, чтобы попробовать здесь, чтобы отладить эту проблему.

  1. Вы можете удалить {{isDisabled}} от кнопки, чтобы убедиться, что он не отключается, когда вы пытаетесь выбрать его.

  2. Используйте setTimeout вместо andThen и посмотрите, не проблема.

  3. Заменить подлинный код действия ничем, чтобы убедиться, что это не приводит к сбою теста.

Вы также можете переписать тест, чтобы поставить assert.ok после некоторого события в JavaScript. Например, вы можете высмеять свойство проверки подлинности или свойство ошибок наблюдателя. Вы можете сделать это, используя поисковые системы или регистры в среде принятия решений - тесты одного из моих админ-админ-админ-модулей помогут вам - ember-link-action/tests/acceptance/link-action-test.js.

Редактировать

Увидев, что работал для вас опыт подсказывает мне, что вы должны попробовать 2 вещи.

Для этого кода:

andThen(function() { 
    Ember.run.later(this, function() { 
     assert.equal(find('div.notification').text(), "Invalid email/password"); 
    }, 0); 
    }); 

Вы можете попробовать Ember.run.scheduleOnce('afterRender', this,() => { ... assert here } вместо использования Ember.run.later. Или вы можете попробовать использовать только Ember.run вместо Ember.run.later.

Заключение: Ключом к устранению этой проблемы может быть ваше утверждение в Ember Run Loop.

+0

Отличные предложения. У меня есть компонентный тест для '{{isDisabled}}', и это отлично работает; все равно удалил, и это не помогло. Используя второй вариант, мне удалось пройти тест (задерживая assert с помощью 'Ember.run.later', но мне все еще нужно использовать' andThen'. Я обновил свой вопрос, потому что это похоже на то, что он может легко (например, если сервер CI находится под нагрузкой, а задержка недостаточно высока). Я все еще хочу перейти к первопричине. – Jon

+0

Только что заметил что-то странное: с задержкой установлено 0 миллисекунд, это работает. – Jon

+0

Hey Jon , Я обновил ответ, потому что вы нашли что-то очень интересное.;) Мне любопытно, если это поможет ... –

1

Я бы предположил, что ошибка, которую вы видите (Invalid email/password), является ответом сервера (mock) и указывает, что что-то не так с макетом или учетными данными, которые вы используете в тесте.

Я также не использовал мираж для издевательств над запросом на аутентификацию. mirage (как и Jason API) основан на ресурсах, а не на том, что хорошо подходит для аутентификации.

+0

Да, сообщение «Недействительный адрес электронной почты/пароль» происходит от макета (ember-cli-mirage). Я обновил вопрос, включив в него конфигурацию. Я согласен, что ember-cli-mirage плохо подходит для издевательств, основанных на не-ресурсах, но я ничего не знаю о другом, и это было не так много. Считаете ли вы, что это может быть причиной? Может ли это объяснить, почему тест проходит, когда запускается другой тест с помощником ember-simple-auths 'authenticateSession'? – Jon

+0

Можете ли вы поделиться своим «config/environment.js»? – marcoow

+0

Добавлен мой 'config/environment.js'.Насколько я вижу, только производственные настройки новы, но они не должны использоваться во время тестирования. – Jon