修改后无法在规范中看到更新的 DOM

unable to see the updated DOM in spec after its getting modified

我正在使用 Mocha/JSDOM 编写功能规范并使用 'chai' 断言。

用例是当我调用函数时:updateContent,

  1. 它会在内部调用另一个函数来获取一些 HTML 内容。
  2. 稍后我会处理 HTML 内容并将其添加到现有的 DOM 元素中。

当我在服务器上 运行 时,这工作正常,但问题是当我尝试编写规范时,无法看到更新的 DOM。我通过放置控制台语句检查了 updateContent 函数,我看到了更新的内容,但是一旦控制转移到 spec 函数,我看到原始的 DOM 添加到 JSDOM.

这是使用 Typescript、js 组合编写的,JQuery 用于 DOM 操作

你能帮我解决一下我在这里遗漏了什么吗?任何 suggestion/info 都会有所帮助。 我在访问

时尝试使用全局

updateContent 函数在 helper.js 文件

中可用
function updateContent(year, fetchAge) {
    Promise.all([fetchAge("age")]).then((data) => {
        console.log("DOM before update ="+$('html').html());
        data = data[0].replace(/{{age}}/g, year);
        $('.mybenifits .content').html(data);
        console.log("DOM after update ="+$('html').html());//Able to see the updated DOM
        console.log("$('.mybenifits .content').html="+global.$('.mybenifits .content').html());
    }).catch((error) => {
        console.log(" ******* Error while fetching age info");
    });
}

规格代码片段:helper.test.js


const expect = require('chai').expect;
const assert = require('chai').assert;
const sinon = require('sinon');
const { JSDOM } = require('jsdom');


const { updateContent } = require('../../main/webpack/common/helper.js');

describe('Helper - Example',  () => {
    it('should update the content', () => {  
        let htmlStr = '<!doctype html><html><body><div class="mybenifits"><div class="content"></div></div></body></html>';
        const jsdom = new JSDOM(htmlStr, {
            url: 'http://localhost/',
        });
        //Setting Global variables - start
        global.window = jsdom.window;
        global.document = jsdom.window.document;
        global.$ = require('jquery');
        //Setting GLobal variables - end
        
        //Mocking fetchAge function
        function fetchAge(featurename) {
            return '<p id="fcontent">Current Age is {{age}}</p>';
        }
        updateContent("2020",fetchAge);
        console.log("Total html file ="+$('html').html());
        //expect($('.mybenifits .content').html()).to.be.equal('<p id="fcontent">Current Age is 2020</p>');
        //expect(global.$('.mybenifits .content').html()).to.be.equal('<p id="fcontent">Current Age is 2020</p>');//Not working even if I use global 
    });
});

    

您的错误可能是因为您的 updateContent 函数在其余代码继续执行的同时异步执行其操作。这可能意味着 expect 断言在 updateContent 完成规范更新之前被调用。

首先,我怎么强调都不为过 - 充分了解 Promises 及其工作原理以及 async/await 关键字将非常有用(并且可能必不可少的)在长 运行.

这是未测试的,但应该会让您走上正确的道路。我假设您的 fetchAge() 函数正在返回一个 Promise - 即调用 API 来检索年龄 - 或类似的?

// Since you're only resolving one promise, you don't need `Promise.all`. `fetchAge` returns a promise and so you can chain `then` directly onto it.
// Also, we can `return` the promise here in case you want to do `updateContent().then(...)` later
function updateContent(year, fetchAge) {
    return fetchAge("age")
        .then((data) => {
            // ...
            data = data[0].replace(/{{age}}/g, year);
            $('.mybenifits .content').html(data);
            // ...
        })
        .catch(/* ... */);
}

进行上述更改应该允许您像这样进行测试 此外,由于我们正在使用 then 链测试异步代码,因此您需要确保使用 done 参数,以便我们可以在测试完成时告诉 jest 运行ning .参见 https://jestjs.io/docs/en/asynchronous

it('should update the content', (done) => {  
    // ...

    // Since you're mocking a function that returns a promise, your mock function needs to aswell
    function fetchAge(featurename) {
        return Promise.resolve('<p id="fcontent">Current Age is {{age}}</p>');
    }

    updateContent("2020", fetchAge)
      .then(() => {
          console.log("Total html file ="+$('html').html());
          expect($('.mybenifits .content').html()).to.be.equal('<p id="fcontent">Current Age is 2020</p>');
          expect(global.$('.mybenifits .content').html()).to.be.equal('<p id="fcontent">Current Age is 2020</p>');
          done();
      })
      .catch(error => done(e));
});

编辑: 仅供参考,这是关于如何使用 async/await(使用内联类型)重写 updateContent 函数的建议。同样,未在本地测试,因此可能需要进行一两次调整 :)

// Note the `async` keyword
async function updateContent(year: string, fetchAge: () => Promise<string>): Promise<void> {
    // Using async/await, we can now use `try/catch` blocks
    // instead of `<Promise>.catch()`!
    try {
        // Note `await`. Since `fetchAge` returns a Promise, we can `await` it!
        const data = await fetchAge("age");
        const htmlData = data[0].replace(/{{age}}/g, year);
        $('.mybenifits .content').html(htmlData);
    } catch (error) {
        // Add your error handling / logging here
        console.error(error);
    }
}

然后在您的测试中,您可以简单地等待 updateContent 完成,然后再断言 DOM 值匹配!

it('should update the content', async () => {
    // ...
    await updateContent("2020", fetchAge);
    expect($('.mybenifits .content').html()).to.be.equal('<p id="fcontent">Current Age is 2020</p>');
    expect(global.$('.mybenifits .content').html()).to.be.equal('<p id="fcontent">Current Age is 2020</p>');
    // ...
});