Как проверить, что я выбрал правильного пользователя из таблицы в Cypress (html -table / angular -material) - PullRequest
4 голосов
/ 14 июля 2020

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

Проблема, я не могу Кажется, я нашел способ проверить, стоит ли флажок рядом с нужным мне пользователем. Я использовал гнездо .each (), чтобы сначала найти пользователя Мэнди Смит, а затем установить флажок с тем же индексом.

HTML: the HTML code

Note, I'm trying to delete the user "Mandy Smith" and while I can just use the following code to select her, depending on how quick the test gets to this point it might actually delete the first user.

Current code that deletes Mandy Smith:

         // looks for the checkbox related to Mandy Smith User
          cy.get('input[type="checkbox"]')
            .each(($elem, index) => {
                if(index === 2) {
                  cy.wrap($elem).click({force:true});
                }
            });

While this will generally grab her, depending how quickly filters are being cleared it can actually choose the Automated User for deletion. I of course don't want this, I'm trying to find a good way to verify the index Mandy Smith is at and apply that to her checkbox.

The checkbox is dynamic, so it will iterate up based on what is clicked, so i don't want to choose the exact checkbox with it's label "#mat-checkbox-11" as that's what it happens to be at while i'm looking at the code, but it was 5 earlier.

I thought this would let me find the index and apply it to the checkbox:

// looks for the checkbox related to Mandy Smith User
    it(`should select Mandy, through verification that it's her index`, () => {
        cy.get('.mat-column-name.ng-star-inserted')
          .each(($name, i) => {
            if($name === 'Mandy Smith') {
                let dex = i;
                cy.get('input[type="checkbox"]')
                  .each(($elem, index) => {
                    if(index === dex) {
                        cy.wrap($elem).click({force:true});
                    }
                });
            }
        });
    });

This actually just ends up deleting the Automated User instead.

I did run some tests and found the string it's returning is this, " Automated User Mandy Smith ". So, even though I'm iterating through the table, it seems to pull both text fields. Am I missing something on how to grab a single set of text, when all the class names are the same?

This means it deletes the first user as the if statement will show Mandy Smith, and then choose the first user which is Automated User instead of the second user, Mandy Smith. Maybe I need to know how to grab text from each class with the same name.

I don't know, I'm a little lost now on how to potentially do this.

EDIT: I found I can invoke text within the if statement, but it never gets within the if statement. I checked what it yielded and pasted that into my if and it still didn't work. Here is the code that is grabbing the elements innerText, and it's meant to compare to the word. Is there a reason it wouldn't evaluate true?

    it(`should select Mandy, through verification that it's her`, () => {
        cy.get('.mat-cell.cdk-cell.text-capitalize.cdk-column-name.mat-column-name')
          .each(($name, i) => {
            //let columnText = ($name).invoke('text');
            if(cy.get($name).invoke('text') === ' Mandy Smith ') {
                cy.log('it made it inside the if');
            }
        });
    });

enter image description here

EDIT 7/15/2020: Here is an image of the entire table. Yellow arrow is her row, right above that is user 1's row. Green arrow is her checkbox, red arrow is her name from the name column

html изображение

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

Решено Спасибо всем, вот ответ, я поговорил по телефону со старшим разработчиком и, увидев, что я делал он меня через несколько вещей. Спасибо @oldschooled за его потрясающий ответ и последующему @ eric99 за то, что он предложил немного подробнее для меня. Вы двое - рок-звезды.

Ответ

    it(`should select Mandy Smith with contains only`, () => {
        cy.contains('td', 'Mandy Smith').siblings().eq(0).children().eq(0).click();
    });

Ответы [ 3 ]

3 голосов
/ 15 июля 2020

Объяснение @ OldSchool правильное, но вы не следовали ему правильно.

В комментариях вы показываете

cy.get('.mat-cell.cdk-cell.text-capitalize.cdk-column-name.mat-column-name')
  .invoke('text')                // REMOVE THIS COMMAND
  .contains('Mandy Smith');

Проблема в invoke('text') после get(), который выбирает несколько элементов объединит весь текст всех этих элементов (т.е. все ячейки в столбце имени).

Напротив, .get().contains('Mandy') выбирает единственную ячейку, содержащую 'Мэнди ', затем использование sibling() ограничивает следующую часть (нахождение флажка) до только этой строки таблицы .

Если у вас есть одна и только одна таблица на страницу, я бы использовал следующую, поскольку она самая короткая и для максимального эффекта использует селектор Cypress.

Soultion

cy.contains('td', 'Mandy Smith')
  .siblings('td')   // get all sibling cells in the 'Mandy Smith' row
  .find('input')    // find the input within these cells
  .click();

Note , если данные таблицы извлекаются асинхронно, cy.contains(selector, content) предпочтительнее cy.get(selector).contains(content), так как первый будет повторять попытки до тех пор, пока не будет доставлено содержимое.

Я изменил приведенный выше код Soultion после тестирования на странице примера Angular Material Grid , используя пример «Таблица с выделением» (поиск «Гелий», который находится во 2-й строке).

Оказывается, селектор, используемый в .siblings(selector), не может обрабатывать ту же сложность, что и .get(selector), например,

.get('td input')      // succeeds and finds all input cells

.siblings('td input') // fails to find the input, although it does exist

Таким образом, использование .siblings('td').find('input') получает в нужное место.

Из документов .find ()

Получить дочерние элементы DOM спецификаций c селектор

т.е. .find() ограничивает поиск предыдущим предметом (ами), которые являются родственными ячейками.

Это работает на странице примера Angular Сетка материалов. Если вам все еще не повезло, опубликуйте свои фактические html из первых двух строк в виде текста, а не изображения, и я займусь исследованием.

Если у вас более одной сетки на странице, вам нужно будет улучшить селектор, чтобы изначально сузить его до требуемой сетки.

Исследовательское тестирование

Cypress имеет удобную функцию, которая позволяет вам экспериментировать с различными командами на фрагменте DOM.

  • Копировать фрагмент HTML, над которым вы работаете, в новый файл .html, поместив этот файл в папку /cypress, например, /cypress/myFragment.html.

  • Содержимое фрагмент html файл не обязательно должен быть полным HTML до c, теги заголовка и тела можно опустить. В этом случае вам понадобится тег <table>, тег <tbody> и вставьте их между первыми двумя строками, чего достаточно для этого эксперимента. (Не забудьте закрыть </table> и </tbody>).

  • Напишите экспериментальный spe c, который посещает фрагмент HTML, например cy.visit('cypress/myFragment.html'). Cypress загрузит это так же, как полную страницу HTML.

  • Следуйте cy.visit() с командами, с которыми вы хотите поэкспериментировать, например, код Solution выше.

  • Запустите только этот spe c и настройте команды, пока они не заработают.

2 голосов
/ 14 июля 2020

[ Изменить: проверьте дополнительный ответ @ eric99 ниже, чтобы получить подробное объяснение. ]

cy.get('.mat-column-name.ng-star-inserted').contains('mandy smith')

должен возвращать базовый элемент, который вы ищете, если имя является уникальным идентификатором в этих .mat-column-name элементах, который соответствует только одному элементу.

Оттуда, вы должны иметь возможность делать все, что хотите, с уверенностью, что у вас есть Мэнди Смит, например, переход к дочерним / родственным / родительским элементам и поиск элемента, который можно щелкнуть (например, флажка), выполнение других утверждений и т. д. c. Предполагается, что поле ввода имеет какое-то отношение к столбцу имени, то есть оба элемента существуют в одной строке или родительском элементе.

Если оба элемента (ввод столбца имени и флажка) находятся в одной строке, нет необходимости циклически перебирать каждый элемент, возвращаемый get(), просто перейдите прямо к тому, который содержит то, что вы хотите, а затем перейдите к элементу-брату input, расположенному внутри того же элемента строки.

например, если ваш html имеет такую ​​же структуру:

<tr tid='the-rowest-of-rows'>
  <td tid='the-checkist-of-checkboxes'><input tid='bam' ...></td>
  <td tid='name-column'>The mandiest Mandy Smith</td>
</tr>   

, тогда ваш селектор будет выглядеть примерно так.

cy.get('[tid=name-column]').contains('Mandy Smith')
  .siblings('[tid=the-checkist-of-checkboxes]')
  .find('[tid=bam]')
  .click()

(Примечание: я использую tid s вместо селекторов классов в get())

Потому что я не совсем уверен, как настроены ваши компоненты (нам понадобится необработанный html, окружающий этот пример, включая input для того, что отсутствует в вашем примере), я предполагаю, что это будет выглядеть примерно так.

В зависимости от того, как выложен ваш html, отношения могут варьироваться, и вам может понадобиться брат или сестра, номинал ent или их вариант / смесь. Однако смысл всего этого:

tl; dr: использовать get().contains() для получения элемента Мэнди Смит. При необходимости перейдите оттуда к дочерним / близким / родительским элементам.

Дополнительная литература:

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

обращая особое внимание на использование tid s для выбора элементов. Выбор по классу, как правило, плохая идея. Что еще более важно, здесь вам может помочь tid. В зависимости от вашего внешнего интерфейса вы можете динамически добавлять tid непосредственно к элементу, который вы хотите щелкнуть, который будет коррелировать с именем, которое вы ищете (например, <input tid='input-${name.last}'>), что может привести вас непосредственно к щелчку денег.

Кроме того, если вас интересует дополнительная информация о том, почему ваши операторы if не работают должным образом, можно прочитать следующее:

Надеюсь, это имеет для вас смысл. Извините за то, что написал книгу. Если это не имеет смысла или у вас есть вопросы, я с радостью постараюсь на них ответить.

1 голос
/ 14 июля 2020

Может быть, я могу предложить другой подход, например, с использованием cypress xpath. Сначала установите это: https://www.npmjs.com/package/cypress-xpath

Затем вы можете установить флажок, используя xpath, если он содержит текст Mandy Smith et c.

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