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

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

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

HTML:  HTML-код

Обратите внимание: я пытаюсь удалить пользователя Мэнди Смит, и хотя я могу просто использовать следующий код для ее выбора, в зависимости от того, насколько быстро тест дойдет до этого момента, он может фактически удалить первого пользователя.

Текущий код, удаляющий Мэнди Смит:

         // 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});
                }
            });

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

Флажок является динамическим, поэтому он будет повторяться в зависимости от того, что было щелкнуто, поэтому я не хочу выбирать точный флажок с его меткой # mat-checkbox-11, поскольку это то, что происходит, когда я смотрю на код, но он был 5 раньше.

Я думал, что это позволит мне найти индекс и применить его к флажку:

// 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});
                    }
                });
            }
        });
    });

На самом деле вместо этого просто удаляется автоматический пользователь.

Я провел несколько тестов и обнаружил, что строка, которую он возвращает, - это автоматизированный пользователь Мэнди Смит. Итак, хотя я просматриваю таблицу, кажется, что она извлекает оба текстовых поля. Мне что-то не хватает о том, как получить один набор текста, когда все имена классов одинаковы?

Это означает, что он удаляет первого пользователя, поскольку оператор if показывает Мэнди Смит, а затем выбирает первого пользователя, который является автоматическим пользователем, вместо второго пользователя, Мэнди Смит. Может быть, мне нужно знать, как брать текст из каждого класса с тем же именем.

Я не знаю, сейчас я немного не понимаю, как это сделать.

РЕДАКТИРОВАТЬ: Я обнаружил, что могу вызывать текст внутри оператора if, но он никогда не попадает в оператор if. Я проверил, что получилось, и вставил это в свое if, но это все равно не сработало. Вот код, который захватывает элементы innerText и предназначен для сравнения со словом. Есть ли причина, по которой он не оценил бы как истину?

    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');
            }
        });
    });

введите описание изображения здесь

РЕДАКТИРОВАТЬ 15.07.2020: вот изображение всей таблицы. Желтая стрелка - это ее строка, прямо над ней - строка пользователя 1. Зеленая стрелка - это ее флажок, красная стрелка - ее имя из столбца имени

HTML-изображение

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

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

Ответ

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

person SaintAvalon    schedule 13.07.2020    source источник
comment
Не могли бы вы показать, где находятся флажки в вашем html? Потому что флажок ввода не виден на скриншоте   -  person P D    schedule 14.07.2020
comment
Возможно, я могу предложить другой подход, например, с использованием cypress xpath. Сначала установите это: npmjs.com/package/cypress-xpath Затем вы можете выбрать checkbox с помощью xpath, я полагаю, будет проще, если мы сможем увидеть код с флажком и использовать xpath, содержащий текст.   -  person Sanja Paskova    schedule 14.07.2020
comment
@PD Я пошел дальше и добавил полный HTML-код начала и конца таблицы и отметил каждую интересующую точку стрелками с цветовой кодировкой. Надеюсь, это поможет, извините за это и спасибо за запрос.   -  person SaintAvalon    schedule 15.07.2020
comment
Вы должны предпочесть .siblings('td').find('input') .siblings().eq(0).children().eq(0), поскольку он менее подвержен поломке при изменении столбцов.   -  person Ackroydd    schedule 18.07.2020
comment
Также обратите внимание, что Cypress имеет .check() и .uncheck() для флажков, что может быть предпочтительнее .click() .   -  person Ackroydd    schedule 18.07.2020


Ответы (3)


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


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

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

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

Если оба элемента (столбец имени и поле ввода флажка) находятся в одной строке, нет необходимости циклически перебирать каждый элемент, возвращаемый 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()

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

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

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

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

Дальнейшее чтение:

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

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

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

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

person Old Schooled    schedule 14.07.2020
comment
Это не сработает, поскольку элементы будут давать оба имени из таблицы. Ваш точный текст даст мне ошибку, вы искали "Мэнди Смит", мы нашли "Автоматизированный пользователь Мэнди Смит". Он захватит каждое имя в столбце, поэтому я использую if и итерацию, чтобы разделить имена. Может, если я могу связать, должен отключиться от invoke? Я устрою это хороший тест, я также поставлю здесь свои флажки. - person SaintAvalon; 14.07.2020
comment
Я должен отметить, что причина, по которой я выполнял итерацию для столбца имени Мэнди Смит, заключалась в том, чтобы найти ее индекс, поэтому я мог использовать индекс при щелчке флажка. Как только я узнаю, где она находится в индексе, я могу просто использовать ее индекс для селектора флажка. Ваш текущий метод может дать мне ее имя в столбце, но тогда я понятия не имею, как это помогает мне установить ее флажок, поскольку он находится слева в другом столбце. Я не получу ее индекс по вашему маршруту, только, может быть, подтвердю, что она существует. `` cy.get ('. mat-cell.cdk-cell.text-capitalize.cdk-column-name.mat-column-name'). invoke ('text'). contains ('Mandy Smith'); `` '' - person SaintAvalon; 14.07.2020
comment
Ошибка, так как это не позволяет мне публиковать так много в комментарии: cy.contains () не удалось, потому что он требует, чтобы субъект был глобальным объектом окна. Полученная тема была следующей: ›Автоматизированный пользователь Мэнди Смит. Предыдущая выполнявшаяся команда была:› cy.invoke () Все 3 проверки субъектов по этой теме не прошли. - person SaintAvalon; 14.07.2020
comment
get().contains() работает - не используйте cy.invoke('text'), поэтому вы получаете каждое имя в столбце. - person eric99; 15.07.2020
comment
I have no clue how that helps me grab her checkbox since it's to the left in a different column. - ›Вам не нужен индекс. Столбец с именем находится в той же строке, что и флажок, поэтому они связаны siblings, и как только вы извлечете столбец имени с помощью get(), вы можете перейти к флажку с помощью .siblings. В моем ответе для вас есть пример и документация. - person Old Schooled; 15.07.2020
comment
Повторим некоторые моменты из ответа: если Mandy Smith уникален только для этой ячейки и не отображается в других ячейках, get().contains() вернет эту ячейку. Затем, используя .siblings, вы можете перейти к ячейке, содержащей флажок (см. Ссылки на документы, связанные с использованием братьев и сестер). Не используйте invoke. Я согласен с @ eric99, что это должно сработать, а если нет, мы сможем помочь вам заставить это работать. - person Old Schooled; 15.07.2020
comment
Думаю, мне что-то не хватает, я посмотрел на флажок, который стоит перед столбцом имени, я обновил свой исходный пост, добавив весь блок кода для всей Мэнди Смит, чтобы показать отношения. Я надеялся, что это будет полезно, чтобы указать, где находится флажок, или как назвать его родным братом. Я немного новичок, извините за невежество. Я попытаюсь выяснить, как они связаны, но мой разработчик сказал, что это не так, и это будет похоже на дедушку. На последнем изображении, которое я опубликовал, показан столбец с именем Мэнди Смит, а над ним - флажок. Я ценю вашу постоянную помощь. - person SaintAvalon; 15.07.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.

Душа

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();

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


Я изменил приведенный выше код Soultion после тестирования его на Angular Страница примера сетки материалов, используя пример «Таблица с выделением» (поиск «Гелий» во 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 определенного селектора

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


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


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


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

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

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

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

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

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

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

person eric99    schedule 15.07.2020
comment
Это хорошо объясняет и в лучшем формате, чем это возможно в комментариях. Спасибо. - person Old Schooled; 15.07.2020
comment
Отличный комментарий, это действительно помогло мне понять, что содержит, а не следует и вызывать. Спасибо! Можете ли вы взглянуть на последнее изображение в моем сообщении и увидеть связь между флажком и именем столбца? Он появляется перед Мэнди Смит, и td закрывается после установки флажка, затем создается новый td для имени столбца. Если вы или @OldSchooled хотите проверить последнее изображение и, возможно, дайте мне пример связывания Мэнди Смит установите ее флажок, что действительно поможет моему невежеству в этом вопросе и даст мне лучшее представление о том, как использовать братьев и сестер / родителей. Спасибо вам обоим за постоянные усилия. - person SaintAvalon; 15.07.2020

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

Затем вы можете установить флажок, используя xpath, если он содержит текст Мэнди Смит и т. Д.

person Sanja Paskova    schedule 14.07.2020
comment
Пожалуйста, не публикуйте ответы только по ссылке на другие вопросы по Stack Exchange. Вместо этого включите сюда основные части ответа и адаптируйте ответ к этому конкретному вопросу. - person Tschallacka; 14.07.2020
comment
@Tschalacka ссылка не на другой вопрос Stack Exchange, это на дополнительный пакет Cypress. - person Ackroydd; 18.07.2020