Webdriverio: Erro de cadeia de promessa

Criado em 30 jan. 2015  ·  44Comentários  ·  Fonte: webdriverio/webdriverio

Erro de cadeia de promessa:

client
            .url(sid.url)
            .then(client.waitFor('.result', 5000))
            .then(client.getValue('#SSID'))
            .then(function(sid){
                 console.log('resolved', sid);  // here gets resolved ass [].length =4
                 return sid;                          // should be a SINGLE element     
             })

Eu acho que nesta última promessa se seria
10 chamadas para webdriverio
a promessa resolvida teria uma matriz de 10 elementos.

agora estou contornando isso nivelando uma matriz.

respSid = _.isArray(respSid) ? _.first(respSid) : respSid;

Ajuda é muito bem vinda

Bug🐛 Project Related v6

Todos 44 comentários

É possível que esta lib passe a especificação Promise \ A + em um futuro previsível?
https://github.com/promises-aplus/promises-tests

Agora há muitos bugs, e o WebdriverIo não interopera bem com outras bibliotecas.
Mesmo assim, o WebdriverIo é uma das melhores implementações de selênio.

@syzer obrigado por apontar esse conjunto de testes de conformidade. Esta será uma boa adição aos testes existentes. Em geral, o WebdriverIO é mais uma biblioteca baseada em retorno de chamada em cadeia. Portanto, a ideia é que seus testes de selênio sejam assim:

it('test something', function(done) {
    client
        .command()
        .command()
        .getAttribute('selector', 'attribute', function(err, value) {
             assert(err, undefined);
             assert(value, 'something');
         })
         .call(done);
});

Como isso é um pouco prolixo, implementei um comportamento prometido apenas para usar as bibliotecas de asserções baseadas em promessas, para que possamos fazer:

it('test something', function(done) {
    client
        .command()
        .command()
        .getAttribute('selector', 'attribute').should.eventually.become('something')
        .call(done);
});

Estou ansioso para melhorar o gerenciador de promessas para que possamos fazer fluxos de trabalho de promessas mais sofisticados.

Sim, você também pode dizer isso como um novo recurso.

Como mencionei, o WebdriverIo poderia ser muito mais.
Comportamentos baseados em promessa / monádica são principalmente para capacidade de composição
O fato de o código parecer melhor é apenas um subproduto.

agora:

// only client/WebdriveIo
client
        .command()
        .command()
        .getAttribute('selector', 'attribute').should.eventually.become('something')
        .call(done);

nisso

client
        .url('127.0.0.1')
        .then(command())
        .then(command())
        .then(OtherLib.doPredictionAnalytics)
        .then(mathLib.calcBestUrl)  //=> url  / returns url
        // now back in webdriverio!!!!!
         .then(url=>{
               return client.url(url);
         })
        .then(client.getAttribute('selector', 'attribute'))
         .then(seletorValue=>{
              seletorValue.should.eventually.become('something') 
         })
         // this cathes from webdriverIo AND OtherLib AND mathLib
         .catch(function(err){
                fail(done);
          })
        //aka finally
        .call(done);

Você concorda que compor de 3 a 5 bibliotecas em um produto seria muito mais fácil?

Precisa de ajuda com este?
Eu meio que preciso disso para o meu trabalho diário :)

Tho q foi uma das primeiras alternativas de código aberto para async
q era / é? Promessa / A + / mônada inválida
Bluebird , ou when Acho que sim.

Estava tentando usar a função promisify bluebird, q (tem denodefy ou sth)
Para usar com WDIO
Mas

  1. u / temos Async? em nomes de funções exportadas,
  2. algumas das funções WDIO não resolvem
    cb (erro, valor)
  3. Eu olho para os internos do WDIO .. e async lib é meio antigo ... como 2010/2011?

como você abrevia Webdriver.io? WDIO?

como você abrevia Webdriver.io? WDIO?

wdio é uma abreviatura legal

Qualquer ajuda é sempre bem-vinda!

u / temos Async? em nomes de funções exportados

O que você quer dizer com isso?

algumas das funções WDIO não resolvem para cb (err, valor)

Atualmente todos os comandos de protocolo (ver lib/protocol ) retornam com cb (err, res). O WebdriverIO está usando esses comandos de protocolo para criar comandos de "ação" úteis. Por exemplo, click combina element + elementIdClick para clicar em algo. Todos esses comandos (consulte lib/commands ) retornam como cb (err, resultado, respostas) em que o resultado é o resultado final do comando higienizado e as respostas são todas as respostas que obtivemos do servidor de selênio para obter esse resultado.

Eu olho para o interior do WDIO ... e a biblioteca assíncrona é meio velha ... como 2010/2011?

Você pode estar certo, mas ele faz o que deve ser feito certo e isso é tudo o que importa. Qualquer outra lib em mente?

ad1.
TypeError: não é possível promisificar uma API que tem métodos normais com o sufixo 'Async'
ad2. o clique retorna cb (errar, resposta)?
ad.3 promessa / q dá a mesma coisa que async + mais.
na verdade, bluebird é muito bom, e seria o suficiente.

Estou sendo mordido por isso também. Eu gosto da API baseada em encadeamento desta biblioteca, mas há um bug _muito_ confuso no comportamento atual do método .then :

Código de exemplo:

// Suppose there are two windows.
client
  .windowHandles()
  .then(function(result) {
    return result.value;
  })
  .then(function(windowHandles) {
    console.log(windowHandles);
  });

Saída esperada: um Array contendo ambas as alças de janela:

["CDwindow-E7129659-BD49-4EE8-999B-3B7004C4CE78", "CDwindow-E7129659-BD49-4EE8-999B-3B7004C4CE79"]

Saída real: a String , o primeiro identificador de janela:

CDwindow-E7129659-BD49-4EE8-999B-3B7004C4CE78

Este é um bug muito fácil, basta fazer _.first (windowHandles)
Mas a questão permanece .. há ppl / força de vontade suficiente para reescrever algumas coisas para passar as promessas de A +?

Também lance Error ()
.catch () seria bom

@maxbrunsfeld Interessante .. não testei esse caso de uso. Funciona se você retornar uma promessa. Vou consertar isso.

@syzer, a ideia básica por trás das promessas do WebdriverIO é que algo assim é possível:

client.getTagName('#elem').should.become('div');

Como o WebdriverIO é baseado em ChainIt (encadeamento baseado em retorno de chamada), não é muito simples colocar promessas em cima disso e, às vezes, um pouco hacky. Definitivamente, há espaço para melhorias. Gostaria de manter o ChainIt e a forma como o WebdriverIO enfileira os comandos.

.catch () seria bom
Deve ser suportado, veja aqui

Este é um bug muito fácil, basta fazer _.first (windowHandles).

Isso não ajuda porque preciso de todos eles.

@ christian-bromann entendo: você gostaria de manter o máximo possível intacto :)

Tho usar callback para controlar 30 clientes é um pesadelo !.
Mudei para java para isso :(
Não estou feliz com isso ....

100% concordam que colocar promessas pode ser maluco.
Mas se todos os métodos exportados usarem o mesmo estilo de retorno de chamada semelhante a um nó, você pode promisificar todos os métodos.

Portanto, a questão é ... devemos gastar mão de obra para levar a um comportamento pleno / boa promessa / compostável?

@maxbrunsfeld você pode sobrescrever o método wd.io para retornar _.first ()
basta fazer um decorador em cima do wd.io e / ou enviar-nos o patch :-)

Eu não quero _.first . Eu quero a matriz.

return [ _.first(response) ] 

?

Quero todos os elementos de windowHandles (por exemplo, o segundo, o terceiro, o quarto) porque quero mudar para uma janela diferente. _.first não seria útil para mim de forma alguma.

Ok, eu entendi:
.windowHandles ()
retorna []
isso está correto?
os métodos de wd.io que eu uso, retorna o elemento SINGLE,
então eu posso q.Todos eles

Mas se todos os métodos exportados usarem o mesmo estilo de retorno de chamada semelhante a um nó, você pode promisificar todos os métodos.

Eles fazem: callback (erro, resultado) é o esquema para todos os comandos

Portanto, a questão é ... devemos gastar mão de obra para levar a um comportamento pleno / boa promessa / compostável?

Definitivamente sim!

Tho usar callback para controlar 30 clientes é um pesadelo !.

Infelizmente, o WebdriverIO não tem um bom suporte para executar testes em paralelo. O próximo passo em meu roteiro imaginário é uma ferramenta cli alá transferidor. Algum problema já está propondo funcionalidade. Sinta-se à vontade para lançar ideias

promessas são minhas primeiras 20 idéias ...
que permite a execução de código em paralelo e sequencialmente, ou qualquer outra forma humanamente capaz de visualizar

27 deste mês temos um hackaton ... poderíamos hackear através do wb.io
embora muitas mudanças seriam necessárias ....
ex: q => alguma lib que é especificação de promessa A + (como quando, ou bluebird)
você estaria interessado?

também precisaríamos de um conjunto de testes baseados em promessas com falha.

também adoro a sua página io!

PS. 21 idéia é fazer a aventura nodeshool com wb.io

também precisaríamos de um conjunto de testes baseados em promessas com falha.

Tentei incorporar https://github.com/promises-aplus/promises-tests para fins de teste de promessa. Fiz funcionar, embora tenha sido muito hacky.

poderíamos hackear através do wb.io

parece maravilhoso

q => alguma lib que é especificação de promessa A + (como quando, ou bluebird)

De acordo com https://promisesaplus.com/implementations Q é uma implementação A + de promessa em conformidade

ad.Q: ok, talvez seja agora .. não era o caso há um ou dois anos.
também Q estava tendo um desempenho muito ruim em termos de desempenho em MUITO ruim em termos de uso de RAM, é aceitável agora?
também o erro não foi passado para .catch ()
e também exigia uma ligação
.feito()
para se certificar de que catch foi invocado corretamente

ok, eu irei PM e tentarei obter seu skype e se encontrarmos 1 ou 2 mais caras, faremos promessas A +.

também Q estava tendo um desempenho muito ruim em termos de desempenho em MUITO ruim em termos de uso de RAM, é aceitável agora?

mhm .. não encontrei nenhuma estatística que compare Q> v1.0

tente pegar seu skype

Eu envio um pedido

se encontrarmos mais 1 ou 2 caras, passaremos pelas promessas A +

Parece maravilhoso!!

Mais problemas com promessas:

client
    .waitForExist('.certain-thing', 1000)
    .then(function(exists){
        if(exists){
            return driver
                .waitForExist('.certain-other-thing, 5000)
        }
    })
    .click('.another-thing')

Ele chama .click imediatamente em vez de esperar que a promessa interna termine. Nota: FUNCIONA quando você coloca outro .entre o clique e a chamada. Mesmo que esse outro .então contenha apenas um console.log.

EDIT: aparentemente, eu estava fazendo algo errado e funciona bem.

sim,
também a captura não é tratada corretamente
quem quer reescrever o PromiseHandler?

Já fiz alguns progressos e resolvi problemas como este. Atualmente, estou trabalhando em uma solução completamente diferente e compartilharei meu resultado em breve

+1 Christian :)
Lembre-se de que você sempre pode ir a Basel para o hackergarden e podemos refatorar juntos.

@maxbrunsfeld Eu encontrei o problema (já que estava tendo o mesmo problema em que apenas o primeiro elemento foi retornado). O problema está na linha 59 no PromiseHandler (https://github.com/webdriverio/webdriverio/blob/master/lib/utils/PromiseHandler.js#L59). Uma vez que não faz um array quando já é um array. Agora, isso é bom para o webdriverio, no entanto, isso quebra as promessas normais que retornam um array ..

!(result.value instanceof Array)

deve ser removido. No entanto, também temos que consertar o resto da biblioteca para funcionar com as promessas adequadas.

No entanto, o que você pode fazer no momento é, em vez de usar argumentos nomeados, simplesmente usar a palavra-chave arguments para recuperar todos os seus argumentos.

O encadeamento de promessas está me mordendo muito. Estou realmente pensando em mudar para o selênio-webdriver normal, uma vez que não há trabalho suficiente sendo feito para corrigir esses tipos de problemas críticos.

Não há como construir apropriadamente algo mais complexo do que um simples .click (). GetAttribute () e testar o atributo. Se eu quiser obter o atributo de algo e, em seguida, fazer uma ação dinâmica com base nisso, torna-se extremamente complexo, pois as promessas não funcionam corretamente.

@Robinfr

Você poderia me dar um exemplo de um de seus testes complexos?
Por favor, tenha paciência comigo, atualmente reescrevo todo o núcleo para tornar tudo monádico. Não quero perder tempo melhorando a solução atual porque isso nunca funcionaria no final.

@ christian-bromann Tudo bem, mas por favor, forneça mais atualizações sobre isso para que possamos acompanhar o progresso.

Quanto a um cenário mais complexo:

var specialModel = {
    1: 'foo',
    2: 'bar'
};

driver
    .getAttribute('.draggable-object', 'data-special')
    .then(function(specialId){
        return driver
                .dragAndDrop('.draggable-object[data-special="' + specialId + '"]', '.droppable-object[data-special2="' + specialModel[specialId] + "]');
    })
    .continueWithWhatever();

Este é um caso real que estou tendo no momento, eu recupero uma propriedade e a combino com um objeto para encontrar um elemento DOM diferente e arrasto um para o outro. No entanto, neste momento, ele não vai esperar até que o dragAndDrop termine, ele simplesmente continuaráWithWhatever () imediatamente. Normalmente, quando você retorna uma promessa de dentro de uma promessa, a próxima promessa não será executada até que a promessa devolvida seja concluída.

Eu sei que é feio, mas nesses casos, por favor, faça uso de callbacks:

driver
    .getAttribute('.draggable-object', 'data-special', function(err, specialId){
        driver.dragAndDrop('.draggable-object[data-special="' + specialId + '"]', '.droppable-object[data-special2="' + specialModel[specialId] + "]');
    })
    .continueWithWhatever();

@ christian-bromann sim, parece que funciona. Mas não está claro para mim por que isso funciona, uma vez que algumas funções parecem ser assíncronas e outras (suponho que aqui) dragAndDrop não são? Alguma ideia de quando essa nova versão será finalizada? Porque estou realmente ansioso por isso.

algumas funções parecem ser assíncronas e outras [...] não são

Todos os comandos são chamadas http assíncronas. O WebdriverIO é baseado no ChainIt que cuida do fluxo de execução. Se você executar um comando, ele colocará a solicitação em uma fila e a executará assim que todos os comandos anteriores forem concluídos. Também permite chamadas aninhadas como no exemplo acima. É quase como um código de execução sequencial como em Java ;-)

Alguma ideia de quando essa nova versão será finalizada?

Sinceramente não sei! Fiz algum progresso nos últimos dias. A nova estrutura monádica é incrível. Ele retorna um novo objeto webdriverio após cada chamada. Isso significa que você pode fazer algo assim no futuro:

function MyPageObject(path) {
    this.header = client.element('header')
    this.loginButton = client.element('#login');

    this.login = function() {
        client.click(this.loginButton).setInput(...)
    }

    // ...
}

O problema com a solução atual é que as promessas são sobrescritas cada vez que você chama um novo comando porque estamos trabalhando no mesmo objeto durante toda a sessão. Mesmo se eu consertasse os problemas no PromiseHandler, nunca poderíamos atribuir promessas a uma variável como no exemplo acima.

O WebdriverIO é baseado no ChainIt que cuida do fluxo de execução. Se você executar um comando, ele colocará a solicitação em uma fila e a executará assim que todos os comandos anteriores forem concluídos.

Veja que teria sido muito útil ter documentado e claramente visível, porque muda completamente a maneira como você constrói os testes. Desde que li isso, ficou muito mais fácil contornar os problemas que eu estava tendo.

Sinceramente não sei! Fiz algum progresso nos últimos dias. A nova estrutura monádica é incrível. Ele retorna um novo objeto webdriverio após cada chamada.

Isso parece incrível, mas se parece muito com a forma como o selênio-webdriver está fazendo isso. Quais são as vantagens na sua maneira de fazer as coisas?

O problema com a solução atual é que as promessas são sobrescritas cada vez que você chama um novo comando porque estamos trabalhando no mesmo objeto durante toda a sessão. Mesmo se eu consertasse os problemas no PromiseHandler, nunca poderíamos atribuir promessas a uma variável como no exemplo acima.

Honestamente, seu jeito monádico parece muito legal, mas as promessas também são incríveis (quando funcionam corretamente). Você geralmente não atribui promessas a uma variável como essa, então não tenho certeza se isso seria um problema. Com as promessas, você simplesmente encadeia todas as ações que deseja, usando etapas intermediárias quando necessário (usando uma instrução .then, por exemplo).

No geral, estou ansioso pelo seu progresso. Seria bom poder ajudá-lo nisso. Você tem planos de abrir o código durante o desenvolvimento? Ou você vai esperar até que termine?

Eu olhei para isso e estava corrigindo manualmente algumas partes do PromiseHandler .. mas o metaprograming que é usado é bem radical. Estou querendo ajudar. Alguém quer se unir e consertar para sempre?

@syzer @Robinfr verifique meu branch v3 . Substituí completamente o núcleo em favor de uma estrutura de objeto com base monádica . Eu me livrei do chainIt e do bom e velho PromiseHandler, bem como dos callbacks. v3 não suportará mais callbacks. Se você estiver interessado na resposta, ligue para then .

Minhas próximas etapas são reescrever todos os comandos para retornar uma promessa em vez de chamar a função de retorno de chamada. Posso precisar de tanta ajuda quanto possível. Vocês me ajudariam?

@ christian-bromann disse a você: venha para o hackergarden nós forneceremos pizza + telhado + ajuda :)
BTW também API pode suportar callbacks e promessas.
Vou olhar para v3

@ christian-bromann, você já tem algum comando reescrito para que eu tenha uma ideia do que você está procurando? Então talvez eu possa dar uma mão: smiley:

Esses problemas serão história em v3 ;-)

@syzer, obrigado por todas as suas contribuições! Sinta-se à vontade para ajudar @Robinfr e eu a mover o branch v3 adiante. A partir de hoje eu tenho um suporte de promessa bastante estável implementado usando uma abordagem monádica e Q promessas. Qualquer ajuda do seu site é muito apreciada! Fale conoscoGitter

+1

No sábado, 18 de abril de 2015 às 19h39, Christian Bromann < notificaçõ[email protected]

escreveu:

@syzer https://github.com/syzer obrigado por todos os seus comentários! Sinta-se livre para
ajude @Robinfr https://github.com/Robinfr e eu movendo o branch v3
frente. A partir de hoje, eu tenho um suporte de promessa bastante estável implementado
usando uma abordagem monádica e promessas Q. Qualquer ajuda de seu site é altamente
estimado! Fale conosco no [image: Gitter]
https://gitter.im/webdriverio/webdriverio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/webdriverio/webdriverio/issues/402#issuecomment -94186655
.

--Lukas 'SyZer' Gintowt

Você vai publicar uma versão npm de v3 breve?

Olá @maxbrunsfeld ,

Espero que sim. Embora leve algum tempo para reescrever todos os comandos, pois agora eles são baseados em promessas (retornos de chamada ainda serão suportados). Também precisamos atualizar alguns documentos, portanto, não até a próxima semana ou depois. Parei de fazer previsões sobre lançamentos. Qualquer ajuda nos ajudará a fazer esse lançamento acontecer mais cedo ;-)
Apenas me mande um pingGitter

@ christian-bromann parece ótimo! Obrigado pela atualização.

Esta página foi útil?
0 / 5 - 0 avaliações