wake-up-neo.com

Wie teste ich Dateieingaben mit Cypress?

Wie kann ich einen e2e-Flusstest schreiben, der eine Interaktion mit dem Dateieingabe-DOM-Element erfordert?

Wenn es sich um eine Texteingabe handelt, kann ich mit ihr interagieren (Wert prüfen, Wert einstellen) usw. als DOM-Komponente. Wenn ich jedoch ein Dateieingabeelement habe, schätze ich, dass die Interaktion begrenzt ist, bis ich den Dialog zur Auswahl einer Datei öffnen kann. Ich kann nicht vorwärts gehen und die Datei auswählen, die ich hochladen möchte, da der Dialog nativ und kein Browserelement wäre.

Wie würde ich testen, ob ein Benutzer eine Datei von meiner Website korrekt hochladen kann? Ich benutze Cypress , um meine e2e-Tests zu schreiben.

15
sidoshi

Das Testen von Dateieingabeelementen wird in Cypress noch nicht unterstützt. Die einzige Möglichkeit, Dateieingaben zu testen, besteht darin:

  1. Geben Sie native Ereignisse aus (die Cypress auf ihrer Roadmap hat).
  2. Verstehen Sie, wie Ihre Anwendung Datei-Uploads mit der Datei-API verarbeitet, und beenden Sie sie dann. Es ist möglich, aber nicht allgemein genug, um spezifische Ratschläge zu geben.

Weitere Informationen finden Sie in dieser offenen Ausgabe .

8

Mit diesem Ansatz/Hack können Sie es tatsächlich schaffen: https://github.com/javieraviles/cypress-upload-file-post-form

Es basiert auf unterschiedlichen Antworten aus dem oben genannten Thread https://github.com/cypress-io/cypress/issues/17

Erstes Szenario (upload_file_to_form_spec.js):

Ich möchte eine Benutzeroberfläche testen, in der eine Datei ausgewählt/hochgeladen werden muss, bevor das Formular gesendet wird. Fügen Sie den folgenden Code in Ihre Datei "command.js" im Cypress-Support-Ordner ein, damit der Befehl cy.upload_file () für jeden Test verwendet werden kann:
Cypress.Commands.add('upload_file', (fileName, fileType, selector) => {
    cy.get(selector).then(subject => {
        cy.fixture(fileName, 'hex').then((fileHex) => {

            const fileBytes = hexStringToByte(fileHex);
            const testFile = new File([fileBytes], fileName, {
                type: fileType
            });
            const dataTransfer = new DataTransfer()
            const el = subject[0]

            dataTransfer.items.add(testFile)
            el.files = dataTransfer.files
        })
    })
})

// UTILS
function hexStringToByte(str) {
    if (!str) {
        return new Uint8Array();
    }

    var a = [];
    for (var i = 0, len = str.length; i < len; i += 2) {
        a.Push(parseInt(str.substr(i, 2), 16));
    }

    return new Uint8Array(a);
}

Wenn Sie dann eine Excel-Datei hochladen, andere Eingaben eingeben und das Formular senden möchten, sieht der Test folgendermaßen aus:

describe('Testing the Excel form', function () {
    it ('Uploading the right file imports data from the Excel successfully', function() {

    const testUrl = 'http://localhost:3000/Excel_form';
    const fileName = 'your_file_name.xlsx';
    const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    const fileInput = 'input[type=file]';

    cy.visit(testUrl);
    cy.upload_file(fileName, fileType, fileInput);
    cy.get('#other_form_input2').type('input_content2');
    .
    .
    .
    cy.get('button').contains('Submit').click();

    cy.get('.result-dialog').should('contain', 'X elements from the Excel where successfully imported');
})

})

13
Javier Aviles

Auch basierend auf zuvor erwähntem Github-Problem , also ein großes Dankeschön an die Leute dort.

Die optimierte Antwort funktionierte anfangs für mich, aber ich hatte Probleme beim Dekodieren von Zeichenfolgen beim Versuch, mit JSON-Dateien umzugehen. Es fühlte sich auch nach zusätzlicher Arbeit an, sich mit Hex befassen zu müssen.

Der folgende Code behandelt JSON-Dateien etwas anders, um Probleme beim Codieren/Decodieren zu vermeiden, und verwendet das in Cypress integrierte Cypress.Blob.base64StringToBlob:

/**
 * Converts Cypress fixtures, including JSON, to a Blob. All file types are
 * converted to base64 then converted to a Blob using Cypress
 * expect application/json. Json files are just stringified then converted to
 * a blob (prevents issues with invalid string decoding).
 * @param {String} fileUrl - The file url to upload
 * @param {String} type - content type of the uploaded file
 * @return {Promise} Resolves with blob containing fixture contents
 */
function getFixtureBlob(fileUrl, type) {
  return type === 'application/json'
    ? cy
        .fixture(fileUrl)
        .then(JSON.stringify)
        .then(jsonStr => new Blob([jsonStr], { type: 'application/json' }))
    : cy.fixture(fileUrl, 'base64').then(Cypress.Blob.base64StringToBlob)
}

/**
 * Uploads a file to an input
 * @memberOf Cypress.Chainable#
 * @name uploadFile
 * @function
 * @param {String} selector - element to target
 * @param {String} fileUrl - The file url to upload
 * @param {String} type - content type of the uploaded file
 */
Cypress.Commands.add('uploadFile', (selector, fileUrl, type = '') => {
  return cy.get(selector).then(subject => {
    return getFixtureBlob(fileUrl, type).then(blob => {
      return cy.window().then(win => {
        const el = subject[0]
        const nameSegments = fileUrl.split('/')
        const name = nameSegments[nameSegments.length - 1]
        const testFile = new win.File([blob], name, { type })
        const dataTransfer = new win.DataTransfer()
        dataTransfer.items.add(testFile)
        el.files = dataTransfer.files
        return subject
      })
    })
  })
})
3
Scott

Die folgende Funktion funktioniert bei mir:

cy.getTestElement('testUploadFront').should('exist');

const fixturePath = 'test.png';
const mimeType = 'application/png';
const filename = 'test.png';

cy.getTestElement('testUploadFrontID')
  .get('input[type=file')
  .eq(0)
  .then(subject => {
    cy.fixture(fixturePath, 'base64').then(front => {
      Cypress.Blob.base64StringToBlob(front, mimeType).then(function(blob) {
        var testfile = new File([blob], filename, { type: mimeType });
        var dataTransfer = new DataTransfer();
        var fileInput = subject[0];

        dataTransfer.items.add(testfile);
        fileInput.files = dataTransfer.files;
        cy.wrap(subject).trigger('change', { force: true });
      });
    });
  });

// Cypress.Commands.add(`getTestElement`, selector =>
//   cy.get(`[data-testid="${selector}"]`)
// );
1
Vicky