matmanjs / matman

Web 端对端测试(E2E,End-to-End Testing)解决方案
https://matmanjs.github.io/matman
MIT License
46 stars 10 forks source link

增加对 jsbridge 形态下的测试 #179

Closed helinjiang closed 4 years ago

helinjiang commented 4 years ago

在 Hybrid 应用中,经常会有调用 jsbridge,需要有场景支持

测试代码如下:

function getUrl(url, param) {
    if (param) {
        url = url + (url.match(/\?/) ? '&' : '?') + getParam(param);
    }
    return url;
}

function getParam(obj) {
    var str = [];
    for (var k in obj) {
        if (obj.hasOwnProperty(k)) {
            var v = typeof obj[k] !== 'undefined' ? obj[k] : '';
            str.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
        }
    }
    return str.join('&');
};

function callByLocaiton(url, param) {
    url = getUrl(url, param);
    window.location = url;
    return url;
}

function callByIframe(url, param) {
    url = getUrl(url, param);
    const iframe = document.createElement('iframe'),
        body = document.getElementsByTagName('body')[0];

    body.appendChild(iframe);

    const style = {
        position: 'fixed',
        zIndex: -1,
        left: 0,
        right: 0,
        width: 0,
        height: 0,
        margin: 0,
        padding: 0,
        border: 'none',
        opacity: 0,
        visibility: 'hidden'
    };
    for (let k in style) {
        iframe.style[k] = style[k];
    }
    iframe.src = url;

    setTimeout(function () {
        try {
            // 有可能某些情况下执行 jsbridge,但是在 2s 内用户可能跳走,
            // 如果 webview 本身未做释放,则可能会继续执行该逻辑,从而导致出错
            if (body && body.removeChild) {
                body.removeChild(iframe);
            }
        } catch (e) {

        }
    }, 2000);

    return url;
}

function testJSBridge() {
    console.log('=====testJSBridge======');
    callByLocaiton('tnow://callByLocaiton');
}

function testJSBridgeIframe() {
    console.log('=====testJSBridgeIframe======');
    callByIframe('tnow://callByIframe');
}

function testJumpUrl() {
    console.log('=====testJumpUrl======');
    window.location.href = 'https://now.qq.com';
}
helinjiang commented 4 years ago

使用 location.href 的场景下,可以监听 will-navigate 事件,在第二个参数即为跳转的地址, 详见 https://github.com/electron/electron/blob/v2.0.18/docs/api/web-contents.md#event-will-navigate

使用 location.href 之后,会有以下事件

will-navigate {} tnow://callByLocaiton
did-start-loading {}
did-stop-loading {}
helinjiang commented 4 years ago

使用 iframe 场景下,有以下事件:

did-start-loading {}
did-frame-finish-load {} false
did-stop-loading {}
did-start-loading {}
did-stop-loading {}

通过注入特定代码来监听iframe的创建和消除

var observe = new MutationObserver(function (mutations, observer) {
    console.log('===MutationObserver====');
    console.log('===mutations====', mutations);
    console.log('===observer====', observer);

    try {
        // iframe
        // tnow://callByIframe
        console.log(mutations[0].removedNodes[0].src);
    } catch (e) {

    }
});
var el = document.querySelector('body');
var options = {
    'childList': true,
    'attributes': true
};
observe.observe(el, options);

image

注意,在 electron v2.0.18 中没法获得 addedNodes,但在 8.3.0 以上是可以的

helinjiang commented 4 years ago

使用 DEBUG=nightmare* node xx.js 方式打印可以发现规律,可以使用 did-fail-provisional-load 事件来监听



其中,上述的错误码 `-3` 含义可以参考 https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h;l=1?q=net_error_li&ss=chromium%2Fchromium%2Fsrc&originalUrl=https:%2F%2Fcs.chromium.org%2F
helinjiang commented 4 years ago

已支持,详见

matmanResult.isExistJSBridge('tnow://callByLocation')

升级 matman 到 5.0.7 及以上版本即可