Как войти в Auth0 в тест E2E с Cypress? - PullRequest
0 голосов
/ 06 июля 2018

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

Приветствуется страница приветствия с кнопкой для входа, которая перенаправит вас на услугу auth0. Пользователь входит в систему по электронной почте и паролю, затем перенаправляется обратно в веб-приложение с токеном.

Я пробовал много разных подходов, каждый из которых приводил к отдельной проблеме.

Примечание: я не хочу проверять Auth0, я просто хочу войти в свое веб-приложение.

Попытка 1. Нажатие на кнопку входа в систему

Пробовал: Cypress должен делать то же, что и пользователь, поэтому в тесте нажмите кнопку входа в систему и перейдите к Auth0 и введите учетные данные. Проблема: Cypress не позволяет вам перейти к другому домену во время теста.

Поскольку Cypress изменяет свой собственный URL-адрес хоста в соответствии с URL-адресом ваших приложений, он требует, чтобы ваше приложение оставалось на одном супердомене в течение всего одного теста.

Предполагается, что вы сможете отключить эту настройку "chromeWebSecurity": false в cypress.json, но она пока не будет работать, поскольку вы можете посетить только один домен с cy.visit()

Попытка 2. Войдите в систему программно из теста

Пробовал: войти в систему из кипарисного теста с библиотекой auth0-js, поэтому не нужно нажимать кнопку входа в систему и, следовательно, не происходит никаких изменений домена.

describe('Waiting to fetch', () => {
  beforeEach(() => {
    this.fetchAuthDeferred = getDeferred()
    cy.visit('http://localhost:3000', {
      onBeforeLoad(win) {
        cy.stub(win, 'fetch')
          .withArgs($url)
          .as('fetchAuth')
          .returns(this.fetchAuthDeferred.promise)
      }
    })
  })

  it('login', () => {
    cy.visit('http://localhost:3000')

    const auth = new auth0.WebAuth(authOptions)
    auth.login(loginOptions)

    cy.get('@fetchAuth', { timeout: 10000 }).should('haveOwnProperty', 'token')

    cy.visit('http://localhost:3000')
    cy.get('[class*="hamburger"]').click()
  })
})

Проблемы: cy.route() не ждет запроса на выборку , обходной путь должен использовать cy.stub(win, 'fetch'). Это не будет ждать:

enter image description here

Попытка 3. Войдите в систему программно из веб-приложения

Попробовал: я начал думать, что Cypress только шпионский запрос сделан из приложения, а не из самого теста (как я пытался в пункте выше).

Я добавил кнопку fake-login на странице приветствия, которая вызовет auth0-js (без изменения домена) с жестко закодированными учетными данными и щелкнет по ней из теста

cy.get('#fake-login').click()

Проблемы: эта стратегия сработала, но, конечно, я не хочу добавлять кнопку с учетными данными на странице приветствия. Поэтому я попытался добавить элемент кнопки в веб-приложение во время теста:

it('Login adding element', () => {
  cy.visit('http://localhost:3000')
  const = document.createElement('div')
  fakeLogin.innerHTML = 'Fake login'
  fakeLogin.onclick = function() {
    const auth = new auth0.WebAuth(authOptions)
    auth.login(loginOptions)
  }
  fakeLogin.style.position = 'absolute'
  fakeLogin.style.zIndex = 1000
  fakeLogin.id = 'fake-login'

  cy.get('#root').invoke('prepend', fakeLogin)
  cy.get('#fake-login').click()
  cy.get('[class*="hamburger"]').click() // Visible when logged in
})

И по какой-то причине это не работает, элемент добавляется, но yt не будет ждать, пока запрос не будет сделан.

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

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Вы можете следовать этой статье , хотя для меня это не сработало. Мне удалось это с помощью этой статьи :

пряжа добавить auth0-js --dev

Давайте создадим пользовательскую команду с именем loginAsAdmin:

Cypress.Commands.add('loginAsAdmin', (overrides = {}) => {
Cypress.log({
    name: 'loginAsAdminBySingleSignOn'
});

const webAuth = new auth0.WebAuth({
    domain: 'my-super-duper-domain.eu.auth0.com', // Get this from https://manage.auth0.com/#/applications and your application
    clientID: 'myclientid', // Get this from https://manage.auth0.com/#/applications and your application
    responseType: 'token id_token'
});

webAuth.client.login(
    {
        realm: 'Username-Password-Authentication',
        username: 'mytestemail@something.co.uk',
        password: 'SoVeryVeryVery$ecure',
        audience: 'myaudience', // Get this from https://manage.auth0.com/#/apis and your api, use the identifier property
        scope: 'openid email profile'
    },
    function(err, authResult) {
        // Auth tokens in the result or an error
        if (authResult && authResult.accessToken && authResult.idToken) {
            const token = {
                accessToken: authResult.accessToken,
                idToken: authResult.idToken,
                // Set the time that the access token will expire at
                expiresAt: authResult.expiresIn * 1000 + new Date().getTime()
            };

            window.sessionStorage.setItem('my-super-duper-app:storage_token', JSON.stringify(token));
        } else {
            console.error('Problem logging into Auth0', err);
throw err;
        }
    }
);
  });

Чтобы использовать это:

    describe('access secret admin functionality', () => {
    it('should be able to navigate to', () => {
        cy.visitHome()
            .loginAsAdmin()
            .get('[href="/secret-adminny-stuff"]') // This link should only be visible to admins
            .click()
            .url()
            .should('contain', 'secret-adminny-stuff/'); // non-admins should be redirected away from this url
    });
});

Весь кредит идет на Джонни Рейли

0 голосов
/ 11 сентября 2018

Это в настоящее время не поддерживается в Cypress. Я создал обходной путь, который может помочь, хотя.

Я установил простой сервер, который работает параллельно Cypress. Конечная точка открывает безголовый экземпляр Puppeteer и завершает процесс входа в систему, отвечая на вызов со всеми куки:

const micro = require("micro");
const puppeteer = require("puppeteer");
const url = require("url");

const login = async (email, password) => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto("https://my-login-page.com");
  // do whatever you have to do to get to your auth0 lock screen, then:
  await page.waitFor(".auth0-lock-input-email");
  await page.waitFor("span.auth0-label-submit");
  await page.type(".auth0-lock-input-email input", email);
  await page.type(".auth0-lock-input-password input", password);
  await page.click("span.auth0-label-submit");
  await page.waitFor("some-selector-on-your-post-auth-page");
  return page.cookies();
 };

const server = micro(async (req, res) => {
  // expect request Url of form `http://localhost:3005?email=blahblah&password=blahblah
  const data = url.parse(req.url, true);
  const { email, password} = data.query;
  console.log(`Logging ${email} in.`);
  return login(email, password);
});

server.listen(3005);

Затем я просто расширяю Cypress, чтобы добавить команду login:

Cypress.Commands.add("login", (email, password) => {
  const reqUrl = `http://localhost:3005?email=${encodeURIComponent(
    email
  )}&password=${encodeURIComponent(password)}`;
  console.log("Beginning login.", reqUrl);
  cy.request(reqUrl).then(res => {
    const cookies = res.body;
    cookies.forEach((c) => {
      cy.setCookie(c.name, c.value, c);
    });
  });
});

Каждый вызов занимает ~ 5-10 с, что отстой, но лучше, чем отсутствие аутентификации вообще: /

...