Question

J'ai une application Web uniquement pour Internet Explorer.

J'explore ce que nous pouvons faire pour automatiser les tests.

Le sélénium semble être un bon outil, mais pour pouvoir activer des liens, etc., il faut que je le dise où ils se trouvent. L’application n’ayant pas été conçue avec ce type de tests, il n’ya généralement pas d’attribut id sur les éléments clés.

Pas de problème, je pense, je peux utiliser les expressions XPath. Mais trouver le bon XPath pour, par exemple, un bouton est une douleur royale si cela est fait en inspectant la source de la page.

Avec Firefox / Firebug, je peux sélectionner l'élément, puis utiliser "Copier XPath". pour obtenir l'expression.

J'ai la barre d'outils de développeur IE et elle est frustrante. Je peux cliquer pour sélectionner l'élément d'intérêt et afficher toutes sortes d'informations à ce sujet. mais je ne vois aucun moyen pratique de déterminer le XPath pour cela.

Alors, y a-t-il un moyen de faire cela avec IE?

Était-ce utile?

La solution

Je voudrais utiliser bookmarklets. J'ai un XPath lié, mais je ne sais pas si cela fonctionne dans IE. Je dois y aller mais je vais le tester et le donner si cela fonctionne sur IE.

Deux sites de favoris pour les développeurs Web parmi mes favoris: Les bookmarklets de Subsimple et les bookmarklets de Squarefree . Beaucoup de choses utiles là-bas ...

[EDIT] OK, je suis de retour. Le bookmarklet que j'avais était pour FF seulement, et n'était pas optimal. Je l'ai finalement réécrit, en utilisant toutefois les idées de l'original. Je ne trouve pas où je l'ai trouvé.

JS développé:

function getNode(node)
{
  var nodeExpr = node.tagName;
  if (nodeExpr == null)  // Eg. node = #text
    return null;
  if (node.id != '')
  {
    nodeExpr += "[@id='" + node.id + "']";
    // We don't really need to go back up to //HTML, since IDs are supposed
    // to be unique, so they are a good starting point.
    return "/" + nodeExpr;
  }
// We don't really need this
//~   if (node.className != '')
//~   {
//~     nodeExpr += "[@class='" + node.className + "']";
//~   }
  // Find rank of node among its type in the parent
  var rank = 1;
  var ps = node.previousSibling;
  while (ps != null)
  {
    if (ps.tagName == node.tagName)
    {
      rank++;
    }
    ps = ps.previousSibling;
  }
  if (rank > 1)
  {
    nodeExpr += '[' + rank + ']';
  }
  else
  {
    // First node of its kind at this level. Are there any others?
    var ns = node.nextSibling;
    while (ns != null)
    {
      if (ns.tagName == node.tagName)
      {
        // Yes, mark it as being the first one
        nodeExpr += '[1]';
        break;
      }
      ns = ns.nextSibling;
    }
  }
  return nodeExpr;
}

var currentNode;
// Standard (?)
if (window.getSelection != undefined) 
  currentNode = window.getSelection().anchorNode;
// IE (if no selection, that's BODY)
else 
  currentNode = document.selection.createRange().parentElement();
if (currentNode == null)
{
  alert("No selection");
  return;
}
var path = [];
// Walk up the Dom
while (currentNode != undefined)
{
  var pe = getNode(currentNode);
  if (pe != null)
  {
    path.push(pe);
    if (pe.indexOf('@id') != -1)
      break;  // Found an ID, no need to go upper, absolute path is OK
  }
  currentNode = currentNode.parentNode;
}
var xpath = "/" + path.reverse().join('/');
alert(xpath);
// Copy to clipboard
// IE
if (window.clipboardData) clipboardData.setData("Text", xpath);
// FF's code to handle clipboard is much more complex 
// and might need to change prefs to allow changing the clipboard content.
// I omit it here as it isn't part of the original request.

Vous devez sélectionner l'élément et activer le bookmarklet pour obtenir son XPath.

Maintenant, les versions de bookmarklet (grâce à Bookmarklet Builder ):

IE
(Je devais le séparer en deux parties, car IE n'aimait pas les bookmarklets très longs (la taille maximale varie en fonction des versions d'IE!). Vous devez activer la première (fonction def) puis la seconde. Testé avec IE6. )

javascript:function getNode(node){var nodeExpr=node.tagName;if(!nodeExpr)return null;if(node.id!=''){nodeExpr+="[@id='"+node.id+"']";return "/"+nodeExpr;}var rank=1;var ps=node.previousSibling;while(ps){if(ps.tagName==node.tagName){rank++;}ps=ps.previousSibling;}if(rank>1){nodeExpr+='['+rank+']';}else{var ns=node.nextSibling;while(ns){if(ns.tagName==node.tagName){nodeExpr+='[1]';break;}ns=ns.nextSibling;}}return nodeExpr;}
javascript:function o__o(){var currentNode=document.selection.createRange().parentElement();var path=[];while(currentNode){var pe=getNode(currentNode);if(pe){path.push(pe);if(pe.indexOf('@id')!=-1)break;}currentNode=currentNode.parentNode;}var xpath="/"+path.reverse().join('/');clipboardData.setData("Text", xpath);}o__o();

FF

javascript:function o__o(){function getNode(node){var nodeExpr=node.tagName;if(nodeExpr==null)return null;if(node.id!=''){nodeExpr+="[@id='"+node.id+"']";return "/"+nodeExpr;}var rank=1;var ps=node.previousSibling;while(ps!=null){if(ps.tagName==node.tagName){rank++;}ps=ps.previousSibling;}if(rank>1){nodeExpr+='['+rank+']';}else{var ns=node.nextSibling;while(ns!=null){if(ns.tagName==node.tagName){nodeExpr+='[1]';break;}ns=ns.nextSibling;}}return nodeExpr;}var currentNode=window.getSelection().anchorNode;if(currentNode==null){alert("No selection");return;}var path=[];while(currentNode!=undefined){var pe=getNode(currentNode);if(pe!=null){path.push(pe);if(pe.indexOf('@id')!=-1)break;}currentNode=currentNode.parentNode;}var xpath="/"+path.reverse().join('/');alert(xpath);}o__o();

Autres conseils

Depuis que bookmarklet a embarrassé Paul, je me suis dit que je devrais ajouter une petite introduction à leur utilisation. Je le fais dans un message séparé pour éviter de mélanger des choses.

Les bookmarklets (également appelés favlets) sont de petits scripts JavaScript (sic) conçus pour être collés dans la barre d'adresse du navigateur (comme toute autre URL) et par conséquent être exécutés sur la page en cours.
Après l'avoir exécuté (coller, appuyez sur Entrée), vous pouvez le marquer pour le réutiliser (l'ajouter aux favoris dans IE). Notez que le navigateur peut à la place marquer l’URL originale dans vos favoris, vous devez alors modifier le signet et remplacer l’URL par votre script.
Vous pouvez bien sûr l’ajouter à la barre d’URL pour un accès rapide également.

Ces scripts agissent comme s'ils faisaient partie de la page en cours, accédant aux variables et fonctions globales JS, aux objets Dom, etc.

Ils peuvent être super simples, comme le javascript: alert ("Hello world!"); ou assez complexes comme celui ci-dessus. Si elle renvoie une valeur (ou si la dernière expression a une valeur), la valeur remplace la page en cours. Pour éviter cela, vous pouvez terminer le script avec alert (pour afficher un résultat) ou l'envelopper dans une définition de fonction et appeler cette fonction, comme je l'ai fait ci-dessus. (Certains ont également mis void (0); à la fin, mais j’ai vu que c’était vu comme une mauvaise pratique.)

La solution de fonction présente l'avantage de rendre toutes les variables du script locales à l'applet (si elles sont déclarées avec var , bien sûr), en évitant les interférences / effets secondaires avec les scripts de la page locale. C’est aussi pourquoi la fonction d’emballage devrait avoir un nom peu susceptible de se heurter à un script local.

Notez que certains navigateurs (lire: "IE") peuvent limiter la taille des favlets, la taille maximale autorisée. longueur variant avec la version (ayant tendance à diminuer). C'est pourquoi tous les espaces inutiles sont supprimés (le constructeur de bookmarlet lié ci-dessus est bon pour cela) et j'ai supprimé les comparaisons explicites avec null et undefined que je fais habituellement. Je devais aussi diviser la favlet en deux, la première partie définissant une fonction (vivant tant que la page n’était pas modifiée / actualisée), la seconde partie l’utilisant.

Outil utile, en particulier sur les navigateurs n'autorisant pas les scripts utilisateur (à la Greasemonkey) ou sans cette extension.

J'ai réécrit le code du bookmarklet en C #, donc si vous le trouvez utile, utilisez-le; -)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Anotation.Toolbar
{
    class XPath
    {
        public static string getXPath(mshtml.IHTMLElement element)
        {
            if (element == null)
                return "";
            mshtml.IHTMLElement currentNode = element;
            ArrayList path = new ArrayList();

            while (currentNode != null)
            {
                string pe = getNode(currentNode);
                if (pe != null)
                {
                    path.Add(pe);
                    if (pe.IndexOf("@id") != -1)
                        break;  // Found an ID, no need to go upper, absolute path is OK
                }
                currentNode = currentNode.parentElement;
            }
            path.Reverse();
            return join(path, "/");
        }

        private static string join(ArrayList items, string delimiter)
        {
          StringBuilder sb = new StringBuilder();
          foreach (object item in items)
          {
            if (item == null)
                continue;

            sb.Append(delimiter);
            sb.Append(item);
          }
          return sb.ToString();
        }

        private static string getNode(mshtml.IHTMLElement node)
        {
            string nodeExpr = node.tagName;
            if (nodeExpr == null)  // Eg. node = #text
                return null;
            if (node.id != "" && node.id != null)
            {
                nodeExpr += "[@id='" + node.id + "']";
                // We don't really need to go back up to //HTML, since IDs are supposed
                // to be unique, so they are a good starting point.
                return "/" + nodeExpr;
            }

            // Find rank of node among its type in the parent
            int rank = 1;
            mshtml.IHTMLDOMNode nodeDom = node as mshtml.IHTMLDOMNode;
            mshtml.IHTMLDOMNode psDom = nodeDom.previousSibling;
            mshtml.IHTMLElement ps = psDom as mshtml.IHTMLElement;
            while (ps != null)
            {
                if (ps.tagName == node.tagName)
                {
                    rank++;
                }
                psDom = psDom.previousSibling;
                ps = psDom as mshtml.IHTMLElement;
            }
            if (rank > 1)
            {
                nodeExpr += "[" + rank + "]";
            }
            else
            { // First node of its kind at this level. Are there any others?
                mshtml.IHTMLDOMNode nsDom = nodeDom.nextSibling;
                mshtml.IHTMLElement ns = nsDom as mshtml.IHTMLElement;
                while (ns != null)
                {
                    if (ns.tagName == node.tagName)
                    { // Yes, mark it as being the first one
                        nodeExpr += "[1]";
                        break;
                    }
                    nsDom = nsDom.nextSibling;
                    ns = nsDom as mshtml.IHTMLElement;
                }
            }
            return nodeExpr;
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top