Domanda

Ho un'applicazione Web solo per Internet Explorer.

Sto esplorando cosa possiamo fare per automatizzare i test.

Il selenio sembra un buon strumento, ma per essere in grado di attivare i collegamenti ecc. Devo dirgli dove sono. L'applicazione non è stata creata pensando a questo tipo di test, quindi generalmente non ci sono attributi id sugli elementi chiave.

Nessun problema, penso, posso usare espressioni XPath. Ma trovare l'XPath corretto per, diciamo, un pulsante, è un dolore reale se fatto ispezionando la fonte della pagina.

Con Firefox / Firebug, posso selezionare l'elemento quindi usare " Copia XPath " per ottenere l'espressione.

Ho IE Developer Toolbar ed è frustrantemente vicino. Posso fare clic per selezionare l'elemento di interesse e visualizzare tutti i tipi di informazioni al riguardo. ma non riesco a vedere alcun modo conveniente per determinare l'XPath per questo.

Quindi c'è un modo per farlo con IE?

È stato utile?

Soluzione

Vorrei usare i bookmarklet. Ho un XPath correlato, ma non so se funziona in IE. Devo andare ma lo proverò e lo darò se funziona su Internet Explorer.

Due siti di bookmarklet per sviluppatori Web dai miei segnalibri: Bookmarklet del sottomarino e Bookmarklets di Squarefree . Molte cose utili lì ...

[EDIT] OK, sono tornato. Il bookmarklet che avevo era solo per FF e non era ottimale. Alla fine l'ho riscritto, anche se ho usato idee originali. Impossibile trovare dove l'ho trovato.

JS espanso:

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.

Devi selezionare l'elemento e attivare il bookmarklet per ottenere XPath.

Ora, le versioni dei bookmarklet (grazie a Bookmarklet Builder ):

IE
(Ho dovuto romperlo in due parti, perché a IE non piacciono i bookmarklet molto lunghi (la dimensione massima varia a seconda delle versioni di IE!). Devi attivare il primo (def. Funzione) quindi il secondo. Testato con 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();

Altri suggerimenti

Dato che il bookmarklet usa Paul perplesso, ho pensato di aggiungere una piccola introduzione al loro utilizzo. Lo faccio in un messaggio separato per evitare di mescolare cose.

I bookmarklet (chiamati anche favlet) sono piccoli script JavaScript (sic) progettati per essere incollati nella barra degli indirizzi del browser (come qualsiasi altro URL) e quindi per essere eseguiti sulla pagina corrente.
Dopo averlo eseguito (incolla, premi Invio), puoi aggiungerlo ai preferiti per riutilizzarlo (aggiungilo ai preferiti in IE). Si noti che il browser potrebbe invece aggiungere l'URL originale ai segnalibri, quindi è necessario modificare il segnalibro e sostituire l'URL con lo script.
Ovviamente, puoi aggiungerlo alla barra degli URL anche per un rapido accesso.

Questi script agiscono come parte della pagina corrente, accedono a variabili e funzioni JS globali, oggetti Dom, ecc.
Possono essere super semplici, come il seminale javascript: alert (" Hello world! & Quot;); o abbastanza complesso come quello sopra. Se restituisce un valore (o se l'ultima espressione ha un valore), il valore sostituisce la pagina corrente. Per evitarlo, è possibile completare lo script con alert (per visualizzare un risultato) o avvolgere lo script in una definizione di funzione e chiamare questa funzione, come ho fatto sopra. (Alcuni mettono anche void (0); alla fine, ma ho visto che è visto come una cattiva pratica.)

La soluzione funzionale ha il vantaggio di rendere tutte le variabili dello script locali all'applet (se dichiarate con var , ovviamente), evitando interferenze / effetti collaterali con gli script nella pagina locale. Questo è anche il motivo per cui la funzione di wrapping dovrebbe avere un nome che difficilmente si scontrerà con uno script locale.

Nota che alcuni browser (leggi: " IE ") possono limitare la dimensione dei favlet, il massimo. lunghezza variabile con la versione (tendente a diminuire). Questo è il motivo per cui tutti gli spazi bianchi inutili vengono rimossi (il generatore di bookmarlet collegato sopra fa bene) e ho rimosso i paragoni espliciti con null e indefiniti che di solito faccio. Ho anche dovuto dividere il favlet in due, prima parte definendo una funzione (vivendo fino a quando la pagina non è cambiata / aggiornata), seconda parte usandola.

Strumento utile, in particolare sui browser che non consentono gli script utente (alla Greasemonkey) o senza questa estensione.

Ho riscritto il codice del bookmarklet in C #, quindi se lo trovi utile, usalo ;-)

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;
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top