使用 Selenium 确定印刷媒体元素的可见性

Posted

技术标签:

【中文标题】使用 Selenium 确定印刷媒体元素的可见性【英文标题】:Using Selenium to determine the visibility of elements for Print media 【发布时间】:2014-07-22 02:31:48 【问题描述】:

我想确定页面上的特定元素在受 CSS @media 规则控制时是否可见。

有没有办法用 Selenium 做到这一点?

我知道有 isDisplayed 方法,它考虑了 CSS,但我找不到任何东西告诉 Selenium 应用哪种媒体类型。

有没有办法做到这一点?

或者是否有另一种方法来测试网页以确保打印您想要的元素(以及您不想要的元素)?

更新:

为了清楚起见,没有计划提供 javascript 打印按钮。用户将使用浏览器(Chrome、FF 和 IE)的正常打印功能进行打印。 @media css 规则将用于控制显示和隐藏的内容。 我希望 Selenium 将它伪装成打印机而不是屏幕,这样我就可以测试某些元素是否会在页面的打印版本中可见。

【问题讨论】:

我环顾四周,但不幸的是,没有人在做你想要完成的事情。我什至查看了流行的 Web Developer 扩展的源代码,但它仅适用于在 <link type="stylesheet" rel="print" 标记上指定媒体类型而不是在 CSS 中指定媒体类型时。 【参考方案1】:

我已经设法编写了一个脚本,它可以满足您的需求:它隐藏仅屏幕样式并将仅打印样式设置为仅屏幕样式。

您需要使用 Selenium 注入以下 JavaScript:

(function pretendToBeAPrinter() 
    //For looking up if something is in the media list
    function hasMedia(list, media) 
        if (!list) return false;

        var i = list.length;
        while (i--) 
            if (list[i] === media) 
                return true;
            
        
        return false;
    

    //Loop though all stylesheets
    for (var styleSheetNo = 0; styleSheetNo < document.styleSheets.length; styleSheetNo++) 
        //Current stylesheet
        var styleSheet = document.styleSheets[styleSheetNo];

        //Output debug information
        console.info("Stylesheet #" + styleSheetNo + ":");
        console.log(styleSheet);

        //First, check if any media queries have been defined on the <style> / <link> tag

        //Disable screen-only sheets
        if (hasMedia(styleSheet.media, "screen") && !hasMedia(styleSheet.media, "print")) 
            styleSheet.disabled = true;
        

        //Display "print" stylesheets
        if (!hasMedia(styleSheet.media, "screen") && hasMedia(styleSheet.media, "print")) 
            //Add "screen" media to show on screen
            styleSheet.media.appendMedium("screen");
        

        // Get the CSS rules in a cross-browser compatible way
        var rules;
        try 
            rules = styleSheet.cssRules;
         catch (error) 
            console.log(error);
        

        try 
          rules = styleSheet.rules;
         catch (error) 
          console.log(error);
        

        // Handle cases where styleSheet.rules is null
        if (!rules) 
            continue;
        

        //Second, loop through all the rules in a stylesheet
        for (var ruleNo = 0; ruleNo < rules.length; ruleNo++) 
            //Current rule
            var rule = rules[ruleNo];

            //Hide screen-only rules
            if (hasMedia(rule.media, "screen") && !hasMedia(rule.media, "print")) 
                //Rule.disabled doesn't work here, so we remove the "screen" rule and add the "print" rule so it isn't shown
                console.info('Rule.media:');
                console.log(rule.media)
                rule.media.appendMedium(':not(screen)');
                rule.media.deleteMedium('screen');
                console.info('Rule.media after tampering:');
                console.log(rule.media)
            

            //Display "print" rules
            if (!hasMedia(rule.media, "screen") && hasMedia(rule.media, "print")) 
                //Add "screen" media to show on screen
                rule.media.appendMedium("screen");
            
        
    
)()

你可以see it in action at JSFiddle。

书签

你也可以install it as a bookmarklet。

更多信息:

About mediaList About document.styleSheets

注意:我只在 Google Chrome 和 Mozilla Firefox 中测试过。它在其他浏览器中可能有效,也可能无效。

【讨论】:

聪明。非常聪明。我喜欢它。谢谢! @TomHoward 我已经更新了脚本,所以它也可以在 Mozilla Firefox 中运行(也可能在其他浏览器中)。 我在 Chrome v64 中遇到了带有 DomException 的问题,因此我更新了访问 cssRules 来处理它。有更多 JS 知识的人可能知道更好的解决方法 这太棒了。正是我想要的!【参考方案2】:

在某些情况下,使用 applitools 等可视化自动化工具会很有用。 我们在一些测试中实现了它,到目前为止效果很好。

【讨论】:

我可以在它的文档中找到任何对印刷媒体的引用。可以吗? 不是专门用来打印的,但它可以帮助我们分析视觉成分。【参考方案3】:
      //jquery

     function printDetail() 
         window.print();
     
     //html
      <button type="button" class="btn" value="Print Div" onclick="printDetail()"><i class="icon-print"></i> &nbsp;Print</button>

      //css
      @media print
          .headerdisplay:none;
          .footerdisplay:none;
          .leftsidedisplay:none;
          .rightsidedisplay:block;

     

  // http://jsfiddle.net/kisspa/52H7g/

【讨论】:

是的,那么如何使用 selenium(或其他工具)检查打印时是否不显示标题? 是的,我的朋友,whitin @media print 使用 display:none 和 display:block;所以
使用 css media printheaderdisplay:none; 而另一个使用 display:none 和 display:block;
嗯,不,这就是你实现它的方式。这个问题是关于如何测试的。即如果有人将其更改为 @media printheaderdisplay:none; 我希望 CI 服务器上的测试失败,因此有人可以去修复它。 我不认为你理解我的问题。我已经知道如何使用@media 规则。我没有的是一个自动化测试,可以确认页面上的某些内容在打印时是否可见。例如,假设我团队中的开发人员更改了页面或 CSS,因此特定表格不再可见。在这些情况下,我希望测试失败。更重要的是,我们使用的是 TDD,我什至不知道从哪里开始这个测试。【参考方案4】:

我想我有一个聪明的方法可以做到这一点:

    我可以假设 PRINT 按钮将出现在 html 页面上,就像上面 jsfiddle.net 链接中的情况一样?

    基本上,我可以排除 FILE->PRINT 或 RIGHT CLICK->PRINT 选项吗,并且只假设有人可以打印您的页面的唯一方法是单击嵌入在您的 html 页面中的打印按钮,如图所示如果不是上面的 jsfiddle 链接,其他测试用例是什么?

    最后,我可以假设您的 selenium 测试只能在 Chrome 浏览器中运行,而不能在 firefox 中运行吗?这很重要,因为 PRINT 命令在 Chrome 中的行为与在 Firefox 中的行为不同。我的修复只适用于 Chrome。

【讨论】:

没有打印按钮的计划。用户将使用浏览器(Chrome、FF 和 IE)的正常打印功能进行打印。 @media css 规则将用于控制显示和隐藏的内容。我想让 Selenium 假装它是一台打印机而不是屏幕,这样我就可以测试某些元素是否会在页面上的打印版本中可见。

以上是关于使用 Selenium 确定印刷媒体元素的可见性的主要内容,如果未能解决你的问题,请参考以下文章

Selenium 不可见使用 XSLT 模板创建的元素

如何强制Selenium WebDriver点击当前不可见的元素?

selenium定位元素提示‘元素不可见’问题解决方法

如何使用 Selenium 和 Java 通过 PageFactory 等待元素不可见

selenium 常见操作,js操作-将元素滚动到页面可见区域

如何使用 Selenium 等待页面上的元素可见(然后转到其他内容)?