最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to return Map object from Cypress each? - Stack Overflow

programmeradmin4浏览0评论

So, I write TAF to automate user cases using Cypress. I'm a novice in it.

I need to return from Cypress each mand a Map with some values to use it in next mand as input value.

In DOM there are some amount of canvas tags like this:

<canvas class="leaflet-tile leaflet-tile-loaded" width="256" height="256" style="width: 256px; height: 256px; transform: translate3d(613px, 246px, 0px); opacity: 1;"></canvas>

From style attribute I need to extract two coordinates, so, just transform value:

width: 256px; height: 256px; transform: translate3d(613px, 246px, 0px); opacity: 1;

to

613 246

and set it like a key to Map object. And as value I need to set a buffer of encoded canvas data.

So, I add custom mand like this:

function convertCanvasMatrixToPictureCommand() {
  Cypress.Commands.add('renderCanvasMatrixToPng', { prevSubject: true }, (subject, savePath) => {
    const bufferMap = new Map();
    cy.wrap(subject)
      .each(canvas => {
        Cypress.Blob.canvasToBlob(canvas.get(0))
          .then(blob => Cypress.Blob.blobToArrayBuffer(blob))
          .then(buff => {
            const coordinates = extract(canvas.attr('style'));
            const buffer = Buffer.from(buff);
            bufferMap.set(coordinates, buffer);
          });
      // and here in some way I need to return bufferMap obj
      // to use it as input data in next cypress task:
      })
      .task('mergeImages', { buffers: bufferMap, savePath: 'cypress/snapshots' });
  });
}

mergeImages task will proceed the map and using specified sorting, merge all canvases to a single PNG image.

But is it possible in some way to return this map from each mand?

This bufferMap object valid only inside each mand. But out of each it still empty

cy.wprap() also not resolve this issue. Or I use it incorrect...

Thanks!

So, I write TAF to automate user cases using Cypress. I'm a novice in it.

I need to return from Cypress each mand a Map with some values to use it in next mand as input value.

In DOM there are some amount of canvas tags like this:

<canvas class="leaflet-tile leaflet-tile-loaded" width="256" height="256" style="width: 256px; height: 256px; transform: translate3d(613px, 246px, 0px); opacity: 1;"></canvas>

From style attribute I need to extract two coordinates, so, just transform value:

width: 256px; height: 256px; transform: translate3d(613px, 246px, 0px); opacity: 1;

to

613 246

and set it like a key to Map object. And as value I need to set a buffer of encoded canvas data.

So, I add custom mand like this:

function convertCanvasMatrixToPictureCommand() {
  Cypress.Commands.add('renderCanvasMatrixToPng', { prevSubject: true }, (subject, savePath) => {
    const bufferMap = new Map();
    cy.wrap(subject)
      .each(canvas => {
        Cypress.Blob.canvasToBlob(canvas.get(0))
          .then(blob => Cypress.Blob.blobToArrayBuffer(blob))
          .then(buff => {
            const coordinates = extract(canvas.attr('style'));
            const buffer = Buffer.from(buff);
            bufferMap.set(coordinates, buffer);
          });
      // and here in some way I need to return bufferMap obj
      // to use it as input data in next cypress task:
      })
      .task('mergeImages', { buffers: bufferMap, savePath: 'cypress/snapshots' });
  });
}

mergeImages task will proceed the map and using specified sorting, merge all canvases to a single PNG image.

But is it possible in some way to return this map from each mand?

This bufferMap object valid only inside each mand. But out of each it still empty

cy.wprap() also not resolve this issue. Or I use it incorrect...

Thanks!

Share Improve this question asked Feb 17, 2020 at 10:23 Roman ShmandrovskyiRoman Shmandrovskyi 9834 gold badges11 silver badges22 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

A couple of problems with the custom mand

  • to make sure you wait on the results of .each(), must return the promise created bt Cypress.Blob.canvasToBlob() chain.

  • follow the .each() with a .then() to ensure pletion, and return `bufferMap here.

Problems with .task()

  • it does not like being called within the custom mand, so call it after

    CypressError: cy.then() failed because you are mixing up async and sync code.

  • it does not like a Map() object as a parameter, convert to a plain object

Test

describe('leaflet', () => {

  it('processes', () => {

    Cypress.Commands.add('renderCanvasMatrixToPng', {prevSubject: true}, (subjects, savePath) => {
      const bufferMap = new Map();
      cy.wrap(subjects)
        .each((canvas, i) => {
          return Cypress.Blob.canvasToBlob(canvas.get(0))   // <- add return here
            .then(blob => Cypress.Blob.blobToArrayBuffer(blob))
            .then(buff => {
              var view = new Int8Array(buff);  // not sure why this is needed
              const buffer = Buffer.from(view);

              // get coords here
              const coords = 1000 + i // for purpose of demo
              bufferMap.set(coords, buffer)
            })
        })
        .then(_ => {                           // <- wait for previous to plete
          console.log('bufferMap inside mand', bufferMap)  // [[Entries]]
                                                              //  0: {0 => Uint8Array(27209)}
                                                              //  1: {1 => Uint8Array(1179)}
          return bufferMap;
        })
    });

    cy.visit('http://cartodb.github.io/Leaflet.CanvasLayer/example.html')

    cy.get('canvas').renderCanvasMatrixToPng().then(bufferMap => {
      console.log('bufferMap outside mand', bufferMap)  // [[Entries]]
                                                           //    0: {1000 => Uint8Array(25218)}
                                                           //    1: {1001 => Uint8Array(1179)}
      const asObject = Object.fromEntries(bufferMap);
      cy.task('mergeImages', { buffers: asObject, savePath: 'cypress/snapshots' });
    })

  })
})

Task for demo

module.exports = (on, config) => {
  ...
  on('task', {
    mergeImages(options) {
      const { buffers, savePath } = options;

      console.log('buffers', buffers);
      /* In terminal

        buffers {
          '1000': {
            type: 'Buffer',
            data: [
              137,  80,  78,  71,  13,  10,  26,  10,   0,   0,   0,  13,
              ... 33137 more items
            ]
          },
          '1001': {
            type: 'Buffer',
            data: [
              137,  80,  78,  71,  13,  10,  26,  10,   0,   0,   0,  13,
              ... 1079 more items
            ]
          }
        }
      */

      return null;
    }
  })
}

Alternative mand (my preference)

Cypress.Commands.add('renderCanvasMatrixToPng', { prevSubject: true }, (subjects, savePath) => {
  const bufferPromises = Array.from(subjects).map(canvas => {
    return Cypress.Blob.canvasToBlob(canvas)
      .then(blob => Cypress.Blob.blobToArrayBuffer(blob))
      .then(buff => {
        const view = new Int8Array(buff);
        const buffer = Buffer.from(view);
        return buffer;
      })
  })
  return Promise.all(bufferPromises).then(buffers => {
    const bufferMap = new Map();
    buffers.forEach((buffer, i) => {
      // get coords here
      const coords = 1000 + i // for purpose of demo
      bufferMap.set(coords, buffer)
    })
    return bufferMap;
  })
});

So I found the solution!

Now it works pretty good for me. Code sample:

function convertCanvasMatrixToPictureCommand() {
  Cypress.Commands.add('renderCanvasMatrixToPng', { prevSubject: true }, (subject, writeTo) => {
    const imgArr = [];

    cy.wrap(subject)
      .each(canvas =>
        new Cypress.Promise(resolve => {
          Cypress.Blob.canvasToBlob(canvas.get(0))
            .then(blob => Cypress.Blob.blobToArrayBuffer(blob))
            .then(arrayBuffer => {
              const coordinates = extract(canvas.attr('style'));
              imgArr.push({ id: coordinates, buffer: arrayBuffer });
              resolve(true);
            });
        }))
      .then(() => {
        cy.task('mergeImages', {
          imageArrayBuffers: imgArr,
          outputFolder: writeTo,
        });
      });
  });
}
发布评论

评论列表(0)

  1. 暂无评论