简体   繁体   English

如何从 Cypress 返回 Map 对象?

[英]How to return Map object from Cypress each?

So, I write TAF to automate user cases using Cypress.所以,我编写了 TAF 来使用 Cypress 自动化用户案例。 I'm a novice in it.我是新手。

I need to return from Cypress each command a Map with some values to use it in next command as input value.我需要从 Cypress 返回each命令一个带有一些值的Map以在下一个命令中将其用作输入值。

In DOM there are some amount of canvas tags like this:在 DOM 中有一些像这样的canvas标签:

<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:style属性我需要提取两个坐标,所以,只需转换值:

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

to

613 246

and set it like a key to Map object.并将其设置为 Map 对象的键。 And as value I need to set a buffer of encoded canvas data.作为值,我需要设置一个编码画布数据的缓冲区。

So, I add custom command 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. mergeImages任务将处理地图并使用指定的排序,将所有画布合并为单个PNG图像。

But is it possible in some way to return this map from each command?但是有可能以某种方式从each命令返回这个映射吗?

This bufferMap object valid only inside each command.这个bufferMap对象只在每个命令内部有效。 But out of each it still emptyeach它仍然是空的

cy.wprap() also not resolve this issue. cy.wprap()也不能解决这个问题。 Or I use it incorrect...或者我用错了...

Thanks!谢谢!

A couple of problems with the custom command自定义命令的几个问题

  • to make sure you wait on the results of .each() , must return the promise created bt Cypress.Blob.canvasToBlob() chain.为了确保您等待.each()的结果,必须返回创建的承诺Cypress.Blob.canvasToBlob()链。

  • follow the .each() with a .then() to ensure completion, and return `bufferMap here.遵循.each().then()以确保完成,并回到这里`bufferMap。

Problems with .task() .task()

  • it does not like being called within the custom command, so call it after它不喜欢在自定义命令中被调用,所以在之后调用它

    CypressError: cy.then() failed because you are mixing up async and sync code. CypressError: cy.then() 失败,因为您混淆了异步和同步代码。

  • it does not like a Map() object as a parameter, convert to a plain object它不喜欢Map()对象作为参数,转换为普通对象

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 complete
          console.log('bufferMap inside command', 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 command', 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 command (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,
        });
      });
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何 map 对象数组并返回每个对象值的长度? - How to map Array of Objects and return the length of each Object's value? 从_.map()返回对象 - Return object from _.map() 如何从赛普拉斯中的自定义命令返回一个值 - how to return a value from custom command in cypress 如何从赛普拉斯的自定义 function 返回值? - How to return a value from custom function in Cypress? 如何使用.map/.reduce 从 object 返回 map - How to use .map/.reduce from object return a map 从数组映射返回对象 - return object from array map 如何在每个对象值具有唯一ID的对象上进行映射并将值返回给React组件 - How to map over an object which has a unique id for each object values and return the values to a React component 如何映射和对象,该对象包含要映射的另一个对象并从中返回JSX? - How can I map over and object, that contains another Object I want to map over and return JSX from it? 识别数组中的唯一值,每个值都将返回 object - 如何处理循环或 hash map - Identify unique values in the array and for each one will return an object - how to do with a loop or a hash map 使用map为每个对象返回一个带有句子的新数组 - Using map to return a new array with a sentence for each object
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM