O maior obstáculo em testar ExtJS com Selenium é que ExtJS não renderiza elementos HTML padrão e o Selenium IDE irá ingenuamente (e corretamente) gerar comandos direcionados a elementos que atuam apenas como decoração - elementos supérfluos que ajudam ExtJS com toda a área de trabalho- aparência e sensação. Aqui estão algumas dicas e truques que reuni enquanto escrevia um teste Selenium automatizado em um aplicativo ExtJS.
Dicas Gerais
Localizando Elementos
Ao gerar casos de teste Selenium gravando as ações do usuário com Selenium IDE no Firefox, o Selenium baseará as ações registradas nos ids dos elementos HTML. No entanto, para a maioria dos elementos clicáveis, ExtJS usa ids gerados como "ext-gen-345" que provavelmente mudarão em uma visita subsequente à mesma página, mesmo se nenhuma alteração de código tiver sido feita. Depois de registrar as ações do usuário para um teste, é necessário um esforço manual para passar por todas as ações que dependem dos IDs gerados e substituí-los. Existem dois tipos de substituições que podem ser feitas:
Substituindo um Localizador de Id por um Localizador CSS ou XPath
Os localizadores CSS começam com "css =" e os localizadores XPath começam com "//" (o prefixo "xpath =" é opcional). Os localizadores CSS são menos detalhados e mais fáceis de ler e devem ser preferidos aos localizadores XPath. No entanto, pode haver casos em que os localizadores XPath precisam ser usados porque um localizador CSS simplesmente não pode cortá-lo.
Executando JavaScript
Alguns elementos requerem mais do que simples interações mouse / teclado devido à complexa renderização realizada pelo ExtJS. Por exemplo, um Ext.form.CombBox não é realmente um <select>
elemento, mas uma entrada de texto com uma lista suspensa separada que está em algum lugar na parte inferior da árvore do documento. Para simular adequadamente uma seleção de ComboBox, é possível primeiro simular um clique na seta suspensa e depois clicar na lista que aparece. No entanto, localizar esses elementos por meio de localizadores CSS ou XPath pode ser complicado. Uma alternativa é localizar o próprio componente ComoBox e chamar métodos nele para simular a seleção:
var combo = Ext.getCmp('genderComboBox'); // returns the ComboBox components
combo.setValue('female'); // set the value
combo.fireEvent('select'); // because setValue() doesn't trigger the event
No Selenium, o runScript
comando pode ser usado para realizar a operação acima de uma forma mais concisa:
with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
Lidando com AJAX e renderização lenta
Selenium tem sabores "* AndWait" para todos os comandos para aguardar o carregamento da página quando uma ação do usuário resulta em transições de página ou recarregamentos. No entanto, como as buscas AJAX não envolvem carregamentos de página reais, esses comandos não podem ser usados para sincronização. A solução é fazer uso de dicas visuais como a presença / ausência de um indicador de progresso AJAX ou a aparência de linhas em uma grade, componentes adicionais, links etc. Por exemplo:
Command: waitForElementNotPresent
Target: css=div:contains('Loading...')
Às vezes, um elemento aparecerá somente após um determinado período de tempo, dependendo da rapidez com que ExtJS renderiza os componentes após uma ação do usuário resultar em uma mudança de visualização. Em vez de usar atrasos arbitrários com o pause
comando, o método ideal é esperar até que o elemento de interesse esteja ao nosso alcance. Por exemplo, para clicar em um item depois de esperar que ele apareça:
Command: waitForElementPresent
Target: css=span:contains('Do the funky thing')
Command: click
Target: css=span:contains('Do the funky thing')
Depender de pausas arbitrárias não é uma boa ideia, pois as diferenças de tempo que resultam da execução dos testes em navegadores diferentes ou em máquinas diferentes tornarão os casos de teste instáveis.
Itens não clicáveis
Alguns elementos não podem ser acionados pelo click
comando. É porque o ouvinte de evento está realmente no contêiner, observando os eventos do mouse em seus elementos filho, que eventualmente borbulham para o pai. O controle da guia é um exemplo. Para clicar em uma guia, você deve simular um mouseDown
evento no rótulo da guia:
Command: mouseDownAt
Target: css=.x-tab-strip-text:contains('Options')
Value: 0,0
Validação de Campo
Os campos do formulário (componentes Ext.form. *) Que possuem expressões regulares ou vtypes associados para validação irão acionar a validação com um certo atraso (veja a validationDelay
propriedade que é definida como 250ms por padrão), após o usuário inserir o texto ou imediatamente quando o campo perder foco - ou desfoca (veja a validateOnDelay
propriedade). Para acionar a validação de campo após emitir o comando type Selenium para inserir algum texto dentro de um campo, você deve fazer o seguinte:
Validação com atraso de disparo
ExtJS dispara o cronômetro de atraso de validação quando o campo recebe eventos de ativação. Para acionar esse temporizador, simplesmente emita um evento de keyup fictício (não importa qual tecla você usa, pois ExtJS o ignora), seguido por uma pequena pausa que é mais longa do que o validationDelay:
Command: keyUp
Target: someTextArea
Value: x
Command: pause
Target: 500
Validação Imediata de Gatilho
Você pode injetar um evento de desfoque no campo para acionar a validação imediata:
Command: runScript
Target: someComponent.nameTextField.fireEvent("blur")
Verificando os resultados da validação
Após a validação, você pode verificar a presença ou ausência de um campo de erro:
Command: verifyElementNotPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
Command: verifyElementPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
Observe que a verificação "display: none" é necessária porque uma vez que um campo de erro é mostrado e precisa ser escondido, ExtJS irá simplesmente ocultar o campo de erro em vez de removê-lo totalmente da árvore DOM.
Dicas para elementos específicos
Clicar em um Ext.form.Button
Opção 1
Comando: clique em Destino: css = botão: contém ('Salvar')
Seleciona o botão pela legenda
opção 2
Comando: clique em Destino: css = # botão salvar-opções
Seleciona o botão por seu id
Selecionando um valor de um Ext.form.ComboBox
Command: runScript
Target: with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
Primeiro define o valor e, em seguida, dispara explicitamente o evento select caso haja observadores.