首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从Puppeteer客户端环境运行Node包以进行测试

如何从Puppeteer客户端环境运行Node包以进行测试
EN

Stack Overflow用户
提问于 2020-10-06 23:08:56
回答 1查看 751关注 0票数 0

我使用木偶师来测试function环境中的客户端函数--该函数本身并不使用function,而是要导入es6 function模块并在最终用户DOM环境中运行。我需要Puppeteer,因为这个函数依赖于诸如innerText这样的属性,这些属性在jsdom中是不可用的。

这个函数使用DOM元素作为参数,但是我很难为它编写测试文件。下面是我的代码示例:

代码语言:javascript
运行
复制
import path from 'path';
import puppeteer from 'puppeteer';
import {getSelectionRange, setSelectionRange} from './selection';

describe(
  'getSelection should match setSelection',
  () => {
    let browser;
    let page;

    beforeAll(async done => {
      try {
        browser = await puppeteer.launch();
        page = await browser.newPage();
        await page.goto(
          `file://${path.join(process.env.ROOT,
          'testFiles/selection_range_test.html')}`
        );
        await page.exposeFunction(
          'setSelectionRange', 
          (el, start, end) => setSelectionRange(el, start, end)
        );
        await page.exposeFunction(
          'getSelectionRange', 
          el => getSelectionRange(el)
        );
      } catch(error) {
        console.error(error);
      }

      done();
    });

    afterAll(async done => {
      await browser.close();
      done();
    });

    it('should match on a node with only one text node children', async () => {
      const {selection, element, argEl} = await page.evaluate(async () => {
        const stn = document.getElementById('single-text-node');

        // Since console.log will output in the Puppeteer browser and not in node console,
        // I added a line inside the selectionRange function to return the element it receives
        // as an argument.
        const argEl = await window.setSelectionRange(stn, 1, 10);

        const selectionRange = await window.getSelectionRange(stn);
        return {selection: selectionRange, element: stn, argEl};
      });

      // Outputs <div id="single-text-node">...</div> 
      // (the content is long so I skipped it, but it displays the correct value here)
      console.log(element.outerHTML);

      // Outputs {}
      console.log(argEl);
    });
  }
);

正如注释中所描述的,直接从page.evaluate()返回的元素是正确的,但是当作为参数传递时,函数会接收一个空对象。我怀疑这是一个范围问题,但我完全没有解决办法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-10 19:56:39

遗憾的是,我找不到任何解决方案不能调用转换我的文件,但希望我设法使它正确工作。

关键是创建第二个transpile配置,该配置将生成一个代码,由web浏览器使用UMD格式直接使用。由于我使用了rollup,下面是我的rollup,config.js文件:

代码语言:javascript
运行
复制
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import resolve from 'rollup-plugin-node-resolve';
import pkg from './package.json';

// The content that is actually exported to be used within a React or Node application.
const libConfig = [
    {
        inlineDynamicImports: true,
        input: './src/index.js',
        output: [
            {
                file: './lib/index.js',
                format: 'cjs'
            },
        ],
        external: [...Object.keys(pkg.dependencies || {})],
        plugins: [
            commonjs(),
            resolve(),
            babel({exclude: 'node_modules/**'})
        ]
    }
];

// Used to generate a bundle that is directly executable within a browser environment, for E2E testing.
const testConfig = [
    {
        inlineDynamicImports: true,
        input: './src/index.js',
        output: [
            {
                file: './dist/index.js',
                format: 'umd',
                name: 'tachyon'
            },
        ],
        external: [...Object.keys(pkg.dependencies || {})],
        plugins: [
            commonjs(),
            resolve(),
            babel({runtimeHelpers: true})
        ]
    }
];

const config = process.env.NODE_ENV === 'test' ? testConfig : libConfig;
export default config;

然后,我稍微重写了我的脚本,以便在每次测试运行时生成我的测试包。

package.json

代码语言:javascript
运行
复制
{
  "scripts": {
    "build:test": "NODE_ENV=test rollup -c && NODE_ENV=",
    "build": "rollup -c",
    "test": "yarn build:test && jest"
  },
}

最后,我将转换脚本添加到我的selection_test.html文件中:

代码语言:javascript
运行
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Selection range test</title>
    <script src="../dist/index.js"></script>
</head>
...

它允许我像这样编写测试文件:

代码语言:javascript
运行
复制
import path from 'path';
import puppeteer from 'puppeteer';
import {describe, beforeAll, afterAll, it} from '@jest/globals';

describe(
    'getSelection should match setSelection',
    () => {
        let browser;
        let page;

        beforeAll(async done => {
            try {
                browser = await puppeteer.launch({
                    headless: true,
                    args: ['--disable-web-security', '--disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure'],
                });
                page = await browser.newPage();
                await page.goto(`file://${path.join(process.env.ROOT, 'tests/selection_test.html')}`, {waitUntil: 'networkidle0'});
                await page.setBypassCSP(true);
            } catch(error) {
                console.error(error);
            }

            done();
        });

        afterAll(async done => {
            await browser.close();
            done();
        });

        it('should match on a node with only one text node children', async () => {
            const data = await page.evaluate(() => {
                // Fix eslint warnings.
                window.tachyon = window.tachyon || null;
                if (window.tachyon == null) {
                    return new Error(`cannot find tachyon module`);
                }

                const stn = document.getElementById('single-text-node');
                const witnessRange = tachyon.setRange(stn, 1, 10);
                const selectionRange = tachyon.getRange(stn);

                return {witnessRange, selectionRange, element: stn.outerHTML};
            });

            console.log(data); // Outputs the correct values
            /*
            {
                witnessRange: { start: 1, end: 10 },
                selectionRange: {
                    absolute: { start: 1, end: 10 },
                    start: { container: {}, offset: 1 },
                    end: { container: {}, offset: 10 }
                },
                element: '<div id="single-text-node">Lorem ... sem.</div>'
            }
             */
        });
    }
);

剩下的唯一问题是,start.containerend.containergetRange的结果中是未定义的,但似乎更有可能是木偶师无法处理范围startContainerendContainer属性的问题--我能够在page.evaluate的内容和我的模块函数之间传递DOM引用,而没有任何问题,所以看起来不再像问题了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64234975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档