Typescript 如何使用jest动态测试创建元素

Typescript 如何使用jest动态测试创建元素,typescript,unit-testing,jestjs,Typescript,Unit Testing,Jestjs,我正在使用typescript测试动态元素。但我对此一无所知。有人帮我吗 这是我的ts文件: export default class MyClass { constructor(){ this.render(); } render() { const el:HTMLInputElement = document.createElement('input') as HTMLInputElement; const link

我正在使用typescript测试动态元素。但我对此一无所知。有人帮我吗

这是我的ts文件:

export default class MyClass {
    constructor(){
        this.render();
    }

    render() {

        const el:HTMLInputElement = document.createElement('input') as HTMLInputElement;
        const link:HTMLAnchorElement = document.createElement('a') as HTMLAnchorElement;
        const container:HTMLBodyElement = document.querySelector('body') as HTMLBodyElement;

        link.innerHTML = "Click Me!";
        link.setAttribute('href', '#');
        link.setAttribute('target', '_blank');

        el.setAttribute('type', 'file');
        container.appendChild(el);
        container.appendChild(link);

        el.addEventListener('change', (event) => {
            if('files' in el) {
                const availFile = el.files[0];
                const blob = new Blob([availFile], { type: availFile.type});

                const objectURL = window.URL.createObjectURL(blob);
                link.setAttribute('href', objectURL);

            }
        })
    }
}


new MyClass();
我的test.spec文件:

import MyClass from "./index";
jest.mock('./index');

describe("testing as first", () => {

    it("we can test the constructor", () => {
        const myClass = new MyClass();
        expect(MyClass).toHaveBeenCalledTimes(1);
    });

    it('will render element', () => {
        const myClass = new MyClass();
        myClass.render();
        expect(document.querySelector('input')).toBeTruthy();
        expect(document.querySelector('a')).toBeTruthy();
    })

    it('will render element', () => {
        const myClass = new MyClass();
        myClass.render();

    })

});
覆盖率结果:

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |       75 |        0 |       75 |       75 |                   |
 index.ts |       75 |        0 |       75 |       75 |    21,22,23,25,26 |
----------|----------|----------|----------|----------|-------------------|

但是如何测试未覆盖的线?请帮助我。

这是单元测试解决方案:

index.ts

导出默认类MyClass{
构造函数(){
这个。render();
}
render(){
const el:HTMLInputElement=document.createElement('input')作为HTMLInputElement;
常量链接:htmlanchoreElement=document.createElement('a')作为htmlanchoreElement;
const容器:HTMLBodyElement=document.querySelector('body')作为HTMLBodyElement;
link.innerHTML='单击我!';
link.setAttribute('href','#');
link.setAttribute('target','u blank');
el.setAttribute('type','file');
子容器(el);
container.appendChild(link);
el.addEventListener('变更',(事件)=>{
如果(el中的“文件”){
const availFile:File=el.files![0];
const blob=new blob([availFile],{type:availFile.type});
const objectURL=window.URL.createObjectURL(blob);
link.setAttribute('href',objectURL);
}
});
}
}
index.test.ts

从“/index”导入MyClass;
描述('先测试',()=>{
让我们创建元素;
让查询选择器;
让createObjectURL;
在每个之前(()=>{
createElement=document.createElement;
querySelector=document.querySelector;
createObjectURL=window.URL.createObjectURL;
});
之后(()=>{
开玩笑。恢复记忆();
document.createElement=createElement;
document.querySelector=querySelector;
window.URL.createObjectURL=createObjectURL;
});
它('应该调用呈现方法',()=>{
spyOn(MyClass.prototype,'render').mockReturnValueOnce();
const myClass=new myClass();
expect(myClass.render).toBeCalledTimes(1);
});
它('如果输入有文件,则应呈现元素并处理更改事件',()=>{
const myClass=new myClass();
const mAvailFile=new Blob(['I am file'],{type:'text/html'});
const mInput={setAttribute:jest.fn(),addEventListener:jest.fn(),files:[mAvailFile]};
const mLink={setAttribute:jest.fn(),innerHTML:'};
const mContainer={appendChild:jest.fn()};
document.createElement=jest.fn().mockImplementation((标记名)=>{
开关(标记名){
案例“输入”:
回输;
案例“a”:
返回链接;
}
});
document.querySelector=jest.fn().mockReturnValueOnce(mContainer);
mInput.addEventListener.mockImplementationOnce((事件,回调)=>{
回调();
});
const mObjectURL='blob:https://www.google.com/6e165b50-979b-43f6-b685-7163413f0faf';
window.URL.createObjectURL=jest.fn().mockReturnValueOnce(mObjectURL);
myClass.render();
expect(document.createElement).toBeCalledTimes(2);
expect(document.querySelector).toBeCalledWith('body');
expect(mLink.innerHTML).toBe('Click Me!');
expect(mLink.setAttribute.mock.calls[0]).toEqual(['href','#']);
expect(mLink.setAttribute.mock.calls[1]).toEqual(['target','u blank']);
expect(mInput.setAttribute).toBeCalledWith('type','file');
expect(mContainer.appendChild.mock.calls[0]).toEqual([mInput]);
expect(mContainer.appendChild.mock.calls[1]).toEqual([mLink]);
expect(mInput.addEventListener).toBeCalledWith('change',expect.any(函数));
expect(window.URL.createObjectURL).toBeCalledWith(新Blob([mAvailFile],{type:mAvailFile.type}));
expect(mLink.setAttribute.mock.calls[2]).toEqual(['href',mObjectURL]);
});
它('应该呈现元素',()=>{
const myClass=new myClass();
const mInput={setAttribute:jest.fn(),addEventListener:jest.fn()};
const mLink={setAttribute:jest.fn(),innerHTML:'};
const mContainer={appendChild:jest.fn()};
document.createElement=jest.fn().mockImplementation((标记名)=>{
开关(标记名){
案例“输入”:
回输;
案例“a”:
返回链接;
}
});
document.querySelector=jest.fn().mockReturnValueOnce(mContainer);
mInput.addEventListener.mockImplementationOnce((事件,回调)=>{
回调();
});
myClass.render();
expect(document.createElement).toBeCalledTimes(2);
expect(document.querySelector).toBeCalledWith('body');
expect(mLink.innerHTML).toBe('Click Me!');
expect(mLink.setAttribute.mock.calls[0]).toEqual(['href','#']);
expect(mLink.setAttribute.mock.calls[1]).toEqual(['target','u blank']);
expect(mInput.setAttribute).toBeCalledWith('type','file');
expect(mContainer.appendChild.mock.calls[0]).toEqual([mInput]);
expect(mContainer.appendChild.mock.calls[1]).toEqual([mLink]);
expect(mInput.addEventListener).toBeCalledWith('change',expect.any(函数));
});
});
100%覆盖率的单元测试结果:

通过src/stackoverflow/59833555/index.test.ts(14.002s)
首先测试
✓ 应调用渲染方法(6ms)
✓ 如果输入有文件(19ms),则应呈现元素并处理更改事件
✓ 应渲染元素(13ms)
----------|----------|----------|----------|----------|-------------------|
文件|%Stmts |%Branch |%Funcs |%Line |未覆盖行|s|
----------|----------|----------|----------|----------|-------------------|
所有文件| 100 | 100 | 100 | 100 ||
index.ts | 100 | 100 | 100 | 100 ||
----------|----------|----------|----------|----------|-------------------|
测试套件:1个通过,共1个
测试:3次通过,共3次
快照:共0个
时间:16.304s,估计17s

源代码:

以下是单元测试解决方案:

index.ts

导出默认类MyC