5
votes

La fonction de route Cypress ne détecte pas la demande réseau

J'essaye d'attendre une demande faite par mon application mais Cypress ne la détecte pas sur cy.wait

    cy.server();
    cy.getAuthenticatedUrl();
    cy.route('POST', '/showroom/validate').as('uploadShowroom');

    cy.get('[data-testid=Next]').click();

    cy.uploadFile('[id=uploadArea]', 'testfile-valid.xlsx', 'application/vnd.ms-excel');

    cy.wait('@uploadShowroom');

    cy.contains('FILE UPLOAD DONE');

Si je vérifie ma console pendant les tests, je peux voir que la demande a été faite à mon serveur

screenshot-console

Mon client et mon serveur fonctionnent en local mais de manière différente les ports.

L'erreur est la suivante: CypressError: expiration du délai de réessai: cy.wait () a expiré en attendant 5000ms pour la 1ère requête à l'itinéraire: 'uploadShowroom'. Aucune demande n'a jamais eu lieu.


3 commentaires

L'itinéraire apparaît-il de la même manière dans le journal des commandes de cyprès? Et cela apparaît-il avant que l'erreur de temporisation ne soit générée?


@Brendan oui, la deuxième capture d'écran provient du journal de cyprès (journalisé quelques secondes avant l'expiration du délai)


Cela ne ressemble pas au journal des commandes. Je parle du journal des commandes dans le testeur: docs.cypress .io / guides / core-concepts / test-runner.html . Je suppose que la demande n'est pas une XHR comme le mentionne Richard Matsen dans sa réponse. S'il s'agit d'un XHR, il apparaîtra dans le journal des commandes, sinon, ce ne sera pas le cas.


3 Réponses :


-3
votes

Essayez de remplacer le délai d'attente par défaut:

cy.wait ('@ uploadShowroom', {timeout: 10000);


0 commentaires

4
votes

Je pense que c'est parce que votre formulaire utilise la soumission de formulaire natif, mais cy.route () de Cypress ne répond qu'aux appels XHR (pour le moment).

Il y a une grande discussion dans le numéro 170 . p >

Gleb Bahmutov a une idée intéressante dans ce commentaire a >, codez dans ce référentiel . Essentiellement, il se moque de la soumission native avec une soumission XHR, à la volée.

J'ai essayé une variante qui se rapproche de votre scénario. Suivez le référentiel READ.ME pour configurer le test, mais mettez d'abord à jour la version Cypress dans package.json . Ajoutez le fichier à télécharger dans /cypress/fixtures.

Ensuite, essayez la spécification suivante.

Le troisième test est une alternative qui utilise cy.url () au lieu de cy.route () .

Commande uploadFile (ou variante similaire)

const fs = require('fs')

module.exports = (on, config) => {
  on('task', {
    deleteFile: (path) => {
      if (fs.existsSync(path)) {
        fs.unlinkSync(path)
      }
      return null
    }
  })
}

Fonction pour «simuler» l'envoi natif avec XHR ( place en haut de Spec)

describe('waiting for form-data post', () => {

  beforeEach(() => {
    cy.task('deleteFile', '../../uploads/Sample_data.xlsx')
    cy.visit('localhost:3000')
    cy.get('input[name="userid"]').type('foo@bar.com')
  })

  it('upload with native form submit (fails because of native event)', () => {
    cy.server()
    cy.route('POST', '/upload').as('upload');

    cy.uploadFile('Sample_data.xlsx', '[id=fileToUpload]')
    cy.get('input[type="submit"]').click()

    cy.wait('@upload');
    cy.readFile('uploads/Sample_data.xlsx') // check saved file
  })

  it('upload with form submit mocked to XHR send (succeeds)', () => {
    cy.server()
    cy.route('POST', '/upload').as('upload');

    cy.uploadFile('Sample_data.xlsx', '[id=fileToUpload]')
    cy.get('form').then(form => mockNativeSubmitWithXhr(form))
    cy.get('input[type="submit"]').click()

    cy.wait('@upload');
    cy.readFile('uploads/Sample_data.xlsx')
  })

  it('upload with native form submit (testing url has changed)', () => {
    cy.uploadFile('Sample_data.xlsx', '[id=fileToUpload]')
    cy.get('input[type="submit"]').click()

    cy.url().should('eq', 'http://localhost:3000/upload')
    cy.readFile('uploads/Sample_data.xlsx')
  })
})

Spec

const mockNativeSubmitWithXhr = (form$) => {
  let win
  cy.window().then(w => {
    win = w
  })
  form$.on('submit', e => {
    e.preventDefault()
    const form = new FormData(e.target)
    const XHR = new win.XMLHttpRequest()
    XHR.onload = response => {
      win.document.write(XHR.responseText)
      win.history.pushState({}, '', XHR.url)
    }
    XHR.open(e.target.method, e.target.action)
    XHR.send(form)
    return true
  })
}

Tâche de suppression du fichier téléchargé entre les tests (modifier '/cypress/plugins/index.js')

Cypress.Commands.add('uploadFile', (fileName, selector) =>
  cy.get(selector).then(subject => {
    return cy
      .fixture(fileName, 'base64')
      .then(Cypress.Blob.base64StringToBlob)
      .then(blob => {
        const el = subject[0];
        const testFile = new File([blob], fileName, {
          type: 'application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet',
        });
        const dataTransfer = new DataTransfer();
        dataTransfer.items.add(testFile);
        el.files = dataTransfer.files;
        return subject;
      });
  })
);


2 commentaires

La note «utilise cy.url () au lieu de cy.route ()» est déroutante. cy.route est utilisé pour stub ou alias l'appel réseau, pas pour affirmer l'url


@MichaelFreidgeim - si vous regardez les deux premiers tests, ils utilisent un alias pour attendre (sur la route). Comme alternative, le troisième test utilise le mécanisme de relance de Cypress (via .should () ) pour attendre que l'URL change.



1
votes

J'ai lancé quelque chose de similaire. L'astuce n'était pas de vérifier l'itinéraire par rapport à une chaîne mais par rapport à une expression régulière. Essayez ceci pour correspondre à votre route POST:

cy.route('POST', /showroom\/validate/).as('uploadShowroom');
// [...]
cy.wait('@uploadShowroom');

Si vous voyez que la route correspond dans le journal des commandes de cyprès (badge jaune à côté de la route), cela devrait faire ce que vous voulez. p>


0 commentaires