Um dia desses recebi um email com uma dúvida específica, sobre como selecionar (com o Protractor) uma data qualquer, quando a aplicação utiliza MaterializeCSS.

Até então eu nunca havia tido que interagir com tal elemento nos projetos em que utilizei Protractor, porém, visto que gosto de explorar novas tecnologias e também gosto de ajudar as pessoas, resolvi experimentar.

A ideia deste post é compartilhar este aprendizado, para o  caso em que alguém tenha que lidar com tal situação também.

Aos que preferem ver o código logo, o mesmo pode ser encontrado a partir do seguinte repositório no GitHub.

Aos que preferem acompanhar o processo, desde seu início até a resolução, aí vai:

Inicialmente comecei com alguns testes simples, para entender como o Materialize funciona. Neste momento criei os seguintes casos de teste:

  • Clica no campo de data (birthdate) e verifica que o date picker é aberto
  • Com o date picker aberto, clica no link Today e verifica que uma data foi selecionada, clica no link Close, e verifica que uma data continua selecionada e que o date picker não está mais aberto
  • Com o date picker aberto, clica no link Today, clica no link Clear, e verifica que não há uma data selecionada (uma nova verificação foi adicionada a este caso de teste depois, mais detalhes mais para o final do post)

Até aqui tudo tranquilo. Mas daí chegou a hora de testar a seleção de uma data qualquer no futuro ou no passado. Neste momento resolvi realizar a uma pesquisa no Google, a qual no primeiro resultado me levou ao stackoverflow.

E ali estava exatamente o que eu procurava. O post do stackoverflow comentava sobre a API do datepicker.js, a qual é utilizada pelo Materialize. Neste post foi possível descobrir como setar uma data em um campo date picker, através do seguinte código:

var $input = $('.datepicker').pickadate();
var picker = $input.pickadate('picker');

picker.set('select', [2015, 3, 20]);

Porém, como eu faria para utilizar tal código com o Protractor? Para isso o Protractor dispõe da seguinte função, que pode ser executada pelo navegador. A função executeScript.

A função executeScript funciona da seguinte forma:

// Isto é um exemplo de uso da função executeScript:
browser.executeScript("alert('Olá');");

Então eu poderia utilizar a função executeScript do Protractor para executar o código da API do datepicker.js para fazer a seleção de qualquer data. Bastou criar a função auxiliar setDate, a qual pude utilizar nos próximos dois casos de teste:

function setDate(date) {
    const setDatescript = "var $input = $('.datepicker').pickadate();" +
    "var picker = $input.pickadate('picker');" +
    "return picker.set('select', [" + date +"]);";
    return setDatescript;
}

Os casos de teste criados foram os seguintes:

it('select some date in the future', () => {
    // In the below date, consider that January is equal to 0, February is 1, ..., December is 11
    const futureDate = '2033, 11, 25';

    browser.executeScript(setDate(futureDate));
    sleepOneSecond();

    expect(pickerDaySelected.isPresent()).toBe(true);

    pickerCloseLink.click();
    sleepOneSecond();

    // Verificação aqui.
});

it('select some date in the past', () => {
    // In the below date, consider that January is equal to 0, February is 1, ..., December is 11
    const pastDate = '1982, 3, 15';

    browser.executeScript(setDate(pastDate));
    sleepOneSecond();

    expect(pickerDaySelected.isPresent()).toBe(true);

    pickerCloseLink.click();
    sleepOneSecond();

    // Verificação aqui.
});

Observação.: Os sleep times no testes foram adicionados para fins de demonstração quando os testes são executados, para tornar tal execução um pouco mais lenta, para simular a utilização por um humano.

Mas e como verificar que a data correta foi realmente setada? Para isso foi criada uma nova função auxiliar getDate, a qual pode ser consultada a seguir:

function getDate() {
    const getDatescript = "var $input = $('.datepicker').pickadate();" +
    "var picker = $input.pickadate('picker');" +
    "return picker.get();";
    return getDatescript;
}

Como a função setDate, a função getDate também pode ser executada pela função executeScript do Protractor, porém, de uma forma diferente, onde desta vez se verifica o retorno da promessa de tal função, para fazer a verificação.

it('select some date in the future', () => {
    // In the below date, consider that January is equal to 0, February is 1, ..., December is 11
    const futureDate = '2033, 11, 25';
    const year = futureDate.substr(0, 4);
    const monthAsNumber = futureDate.substr(6, 2);
    const monthAsString = months[monthAsNumber];
    const day = futureDate.substr(10, 2);
    const dateNewFormat = day + ' ' + monthAsString + ', ' + year;

    browser.executeScript(setDate(futureDate));
    sleepOneSecond();

    expect(pickerDaySelected.isPresent()).toBe(true);

    pickerCloseLink.click();
    sleepOneSecond();

    browser.executeScript(getDate()).then((date) => {
       expect(date).toEqual(dateNewFormat);
    });
 });

it('select some date in the past', () => {
    // In the below date, consider that January is equal to 0, February is 1, ..., December is 11
    const pastDate = '1982, 3, 15';
    const year = pastDate.substr(0, 4);
    const monthAsNumber = pastDate.substr(6, 1);
    const monthAsString = months[monthAsNumber];
    const day = pastDate.substr(9, 2);
    const dateNewFormat = day + ' ' + monthAsString + ', ' + year;

    browser.executeScript(setDate(pastDate));
    sleepOneSecond();

    expect(pickerDaySelected.isPresent()).toBe(true);

    pickerCloseLink.click();
    sleepOneSecond();

    browser.executeScript(getDate()).then((date) => {
        expect(date).toEqual(dateNewFormat);
    });
 });

Veja que neste momento, além da verificação adicionada, também foram adicionadas algumas outras variáveis, necessárias para gerar a data em um novo formato, o qual é o retorno da função getDate.

Além disso, para geração da data neste novo formato, o seguinte array de meses foi criado:

const months = [
    'January', 'February', 'March',
    'April', 'May', 'June',
    'July', 'August', 'September',
    'October', 'November', 'December'
];

E também aproveitei a nova função getDate para adicionar uma nova verificação  ao caso de teste que selecionava a data de hoje e logo após a limpava, conforme comentado mais acima. A nova verificação foi a seguinte:

browser.executeScript(getDate()).then((date) => {
    expect(date).toEqual('');
});

Executando o testes, obtive o seguinte resultado:

> materialize-protractor@0.0.1 test /Users/user/www/materialize-protractor
> protractor

[23:18:13] I/direct - Using ChromeDriver directly...
[23:18:13] I/launcher - Running 1 instances of WebDriver
Spec started
Started

1 Materialize - Forms
 ✓ open date picker (5 secs)
. ✓ pick today's date and close date picker (5 secs)
. ✓ clear birthdate field right after picking today's date (7 secs)
. ✓ select some date in the future (5 secs)
. ✓ select some date in the past (5 secs)
.
Executed 5 of 5 specs SUCCESS in 26 secs.

5 specs, 0 failures
Finished in 26.226 seconds
[23:18:40] I/launcher - 0 instance(s) of WebDriver still running
[23:18:40] I/launcher - chrome #01 passed

Uhuu! Tudos os testes passaram.

Ainda há espaço para melhorias, mas por enquanto foi aqui que cheguei, e creio já valer o post para compartilhar com a comunidade.

Uma versão refatorada dos testes está disponível através do seguinte link.

Gostou do post? Gostaria de saber mais o que é possível fazer com o framework Protractor? Veja o livro que publiquei pela editora Casa do Código sobre testes end-to-end automatizados com Protractor.

Bons testes!

=)

 

2 comentários em “Dicas de Protractor – Selecionando datas em sites que utilizam Materialize

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s