Обработка нескольких обещаний в команде Cypress - PullRequest
1 голос
/ 27 февраля 2020

Что у меня есть

У меня есть команда, которая может запросить токен, и он разрешает обещание при ответе. Как только обещание разрешается, я помещаю токен в sessionStorage в SomeTest. js. Это работает. Но я должен поставить точно такой же cy.window()... в каждом тесте.

SomeTest. js:

before(()=>{
  cy.login().then(res=>
    cy.window().then((window) => {
       window.sessionStorage.setItem('token', JJSON.stringify(res))
    })
  );
});

команда в командах. js

Cypress.Commands.add('login', function () { 
    fetcher.emit('tokenRequest',{email:'dummy@mail.com', password:'dummy'});
    return new Cypress.Promise((resolve, reject) => {
        fetcher.on('onTokenResponse',function(response) {
            resolve(response);
        });
    });
});

Что я хочу

Я бы хотел установить sessionStorage в команде login().

SomeTest. js:

before(()=>{
  cy.login();
});

команда в командах. js

Cypress.Commands.add('login', function () { 
    fetcher.emit('tokenRequest',{email:'dummy@mail.com', password:'dummy'});
    return new Cypress.Promise((resolve, reject) => {
        fetcher.on('onTokenResponse',function(response) {
            cy.window().then((window) => {
                window.sessionStorage.setItem('token', JSON.stringify(response));
                resolve(response);
            })
        });
    });
});

Но выдает ошибку : Uncaught CypressError: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise., The cy command you invoked inside the promise was:> cy.window().


Я понимаю, что проблема в том, что я пытаюсь вызвать другое обещание, которое не возвращается. Но как мне добиться чего-то подобного?

Мне нужно

  1. emit tokenRequest
  2. ждать получения tokenResponse
  3. cy.window() и установите элемент sessionStorage

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

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

Cypress.Commands.add('loginFull', function () {
    return cy.login().then((response)=>{
        cy.window().then((window) => {
            window.sessionStorage.setItem('token', JSON.stringify(response));
        });
    });
});

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Один из способов, который работает, - переместить команду cy.window() на самый внешний уровень пользовательской команды, поэтому вы не пытаетесь использовать ее в Обещании.

Тест

describe('web socket event handler', () => {

  let fetcher;
  before(() => {
    const io = require('socket.io-client'); 
    fetcher = io.connect('http://127.0.0.1:5000');
    cy.window().then(win => {
      win.sessionStorage.clear();  // ensure clean before test
    })
  })

  Cypress.Commands.add('login', function () { 
    cy.window().then(win => {
      fetcher.emit('tokenRequest',{email:'dummy@mail.com', password:'dummy'});
      return new Cypress.Promise((resolve, reject) => {
        fetcher.on('onTokenResponse',function(response) {
          win.sessionStorage.setItem('token', JSON.stringify(response));
          return resolve(response);
        });
      });
    });
  });

  it('waits for token', () => {
    cy.login().then(_ => {
      cy.window().then(win => {
        console.log(win.sessionStorage.getItem('token'))
        // logs "Response: dummy@mail.com"
      })
    })
  })
})

Сервер

io.on('connection', function(socket){
  socket.on('tokenRequest', function(msg){
    setTimeout(() => {
      io.emit('onTokenResponse', `Response: ${msg.email}`);
    }, 2000)
  });
});

В идеале хотелось бы, чтобы команда входа в систему ожидала события получения (с тайм-аутом?).

Я попробовал этот подход Следите за DOM API , но пока безуспешно.


Другой способ - установить флаг в приемнике событий и добавить команду в очередь, которая его ожидает.

Cypress.Commands.add('login', function () { 
  cy.window().then(win => {
    fetcher.emit('tokenRequest',{email:'dummy@mail.com', password:'dummy'});
    let flag = { done: false };
    fetcher.on('onTokenResponse',function(response) {
      win.sessionStorage.setItem('token', JSON.stringify(response));
      flag.done = true;
    })
    cy.wrap(flag).its('done').should('equal', true); // wait here until done
  });
});

Теперь вы можете синхронно вызывать логин

it('waits for token', () => {
  cy.login();
  cy.window().then(win => {
    console.log(win.sessionStorage.getItem('token'))
    // logs "Response: dummy@mail.com"
  })
})
1 голос
/ 27 февраля 2020
Cypress.Commands.add('login', function () { 
    function waitForSocket(callback) {
        fetcher.emit('tokenRequest',{email:'dummy@mail.com', password:'dummy'});
        fetcher.on('onTokenResponse',function(response) {
            callback(response);
        });
    }

    waitForSocket((res) => {
        cy.window().then((window) => {
           window.sessionStorage.setItem('token', JJSON.stringify(res))
        })
    })
});

Ошибка указывает на это: Команды Cypress уже являются обещаниями, и они сами будут ждать / разрешать . Так что я думаю, что не должно быть оберточного обещания для сборщика. Изменить: Я думаю, вы можете обернуть задачи сокета в функцию обратного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...