Selenium und WordPress: Neuer Post-Test

Lesezeit: 8 Minuten

Ich habe mir Selenium ein wenig angesehen, und ich fange an, es zu mögen, da ich etwas Java-Programmierung kenne und sowohl Java als auch C# für einfache Dinge wie diese ziemlich unkompliziert finde.

Ich habe jedoch Probleme mit einem Test, der auf der Dashboard-Seite einen neuen Beitrag in WordPress erstellt:

Dies ist der Selenium-Code (in C#): (Die Treiberinstanz ist offensichtlich eine Treiberklasse, die ich erstellt habe – zum Starten des Browsers und zum Verbinden mit der WordPress-Site.)

1: Driver.Instance.FindElement(By.Id("title)).SendKeys(title);
2: Thread.Sleep(1000);
3: 
4: Instance.SwitchTo().Frame("content_ifr");
5: Thread.Sleep(1000);
6: 
7: Driver.Instance.SwitchTo().ActiveElement().SendKeys("something");

Was nun passiert, ist, dass der Titel leicht gefunden wird (durch ID, also würde ich dort keine Probleme erwarten) und ich kann den Titeltext einfach einfügen (Zeile 1).

Doch der Inline-Rahmen für den Pfostenkörper macht Probleme. Beim Ausführen des Tests wechselt der Cursor nach dem Ausfüllen des Themas wie geplant in den Körperbereich (Zeile 4). Allerdings passiert nichts mehr. Die Methode SendKeys(“string”) (ine 7) scheint dort nicht zu funktionieren.

Irgendwelche Ideen?

EDIT: Natürlich – eine wichtige Information ist, dass der iframe in WordPress einfach einen TinyMCE-Editor lädt. In der Seitenquelle gibt es also nur ein Body-Tag mit dem Javascript-Laden des Editors.

EDIT2: Natürlich hat sich plötzlich etwas geändert. Ohne JEDE Änderung an der WordPress-Seite fehlt jetzt plötzlich “content_ifr” (?!!!!!?) Der Selenium-Test schlägt fehl mit “Frame kann nicht gefunden werden …”, und es fehlt auch plötzlich in der Seitenquelle.

Geben Sie hier die Bildbeschreibung ein

EDIT3: Mir ist auch etwas aufgefallen:

Driver.Instance.SwitchTo().Frame(iframe);
Driver.Instance.FindElement(By.Id("tinymce")).SendKeys("message body");

Es ist die ZWEITE Zeile, die den Cursor zum mce-Feld wechselt, nicht die Zeile mit .SwitchTo(). Ich brauche jedoch die erste Zeile – die zweite Zeile macht alleine nichts. Das nähert sich etwas wirklich Dummem. Ich suche seit einer Woche nach einer Lösung dafür – das verheißt nicht gerade etwas Gutes für Selenium. Die Selenium-Benutzergruppe will nicht einmal antworten, wenn ich sie frage.

Auch – wenn ich die Methode SendKeys() in der zweiten Zeile überspringe, passiert nichts. Es scheint also, dass die beiden Zeilen ALLES tun, was sie sollten, bis hin zum Platzieren des Cursors an der richtigen Stelle. Aber es sendet nie einen Text.

EDIT4 (zuletzt): Nachdem Sie tatsächlich herausgefunden haben, wie IJavaScriptExecutor verwendet wird, funktioniert es mit den folgenden Lösungen.

  • Die Frame-ID lautet: driver.switchTo().frame("ipteditor_ifr"). AFAIK war das schon immer so.

    – SiKing

    5. Juni 2014 um 14:51 Uhr

  • Das ist jetzt definitiv falsch. Bei Verwendung von “content_ifr” wechselt der Cursor tatsächlich zum Editor. Wenn ich zu “ipteditor_ifr” wechsle, bleibt der Cursor auf dem Titel stehen und der Test schlägt fehl.

    Benutzer2119841

    5. Juni 2014 um 21:25 Uhr

  • Ich vermute, WordPress hat mehr als einen Einstiegspunkt für einen neuen Beitrag und damit den Editor. Die offizielle Seite für TinyMCE tinymce.com/tryit/basic.php Verwendet content_ifraber das bedeutet nichts.

    – SiKing

    5. Juni 2014 um 21:44 Uhr

  • Könnten Sie vielleicht einige Quellen/Screenshots/Plugins/Wordpress-Versionen bereitstellen, die verwendet werden? In meinem WordPress 3.9.1 gibt es nur einen Abschnitt „Quick Draft“ auf der Dashboard-Seite, der keinen TinyMCE-Editor hat, sondern nur einen Textbereich

    – das Weizen

    5. Juni 2014 um 21:48 Uhr

  • Ich habe einen Screenshot hinzugefügt :-9

    Benutzer2119841

    6. Juni 2014 um 8:34 Uhr

1646641749 906 Selenium und WordPress Neuer Post Test
oliv

Die Java-Methode zur Handhabung des TinyMCE-Editors würde folgendermaßen aussehen:

public void entersTopicOfBody(String textToBeTyped, WebDriver driver) {
        driver.switchTo().frame("content_ifr");
        WebElement body = driver.findElement(By.xpath("//body"));
        body.click();
        JavascriptExecutor executor = (JavascriptExecutor)driver;
        executor.executeScript("arguments[0].innerHTML = '"+ textToBeTyped+"'", body);
        driver.switchTo().defaultContent();
    }

  • Was ist JavascriptExecutor executor = (JavascriptExecutor)getDriver(); Sollte sein? Es wird nicht einmal kompiliert.

    – SiKing

    5. Juni 2014 um 14:23 Uhr

  • Entschuldigung, es sollte eine Instanz des Treibers sein. Es war ein Codeschnipsel aus meinem letzten Projekt 🙂

    – oliv

    5. Juni 2014 um 14:39 Uhr

  • Wie verwende ich JavaScriptExecutor (oder IJavaScriptExecutor) in .Net? Wie in welcher “using …”-Anweisung?

    Benutzer2119841

    5. Juni 2014 um 21:21 Uhr

  • Tatsächlich verwende ich WebDriver mit Java. Aber ich hoffe, dass diese Antwort stackoverflow.com/a/23244164/2504101 Ihnen einen Hinweis gibt, wie Sie JavaScript über C# ausführen können.

    – oliv

    6. Juni 2014 um 7:16 Uhr

  • Danke. Das Problem ist jedoch, dass NOWHERE sich die Mühe zu machen scheint, zu erwähnen, welche Bibliothek ich “importieren” muss. Wie import-Anweisungen in Java benötigt C# „using“-Anweisungen. Und ich kann Visual Studio nicht dazu bringen, mir dabei zu helfen, Bibliotheken vorzuschlagen, wie es scheint.

    Benutzer2119841

    6. Juni 2014 um 8:38 Uhr

1646641750 857 Selenium und WordPress Neuer Post Test
das Weizen

Unten ist ein C#-Code, der einen Beitrag veröffentlicht. Ich denke, die Hauptprobleme, die Sie haben, sind auf Timing-Probleme zurückzuführen.

Ich habe kürzlich ein bisschen Selenium gemacht und ich bevorzuge es implizite Wartezeiten: Es wartet eine maximale Zeitspanne, bis der Artikel verfügbar ist, kehrt aber so schnell wie möglich zurück. Sie können also eine maximale Wartezeit von 100 Sekunden angeben, aber wenn es in 1 Sekunde gefunden wird, wird nur 1 Sekunde gewartet. Viel effizienter als beliebig lange zu schlafen. Sehen Dieser Beitrag über implizite und explizite Wartezeiten

Aber selbst mit impliziten Wartezeiten werden möglicherweise nicht alle Probleme gelöst. Beim Codieren des folgenden Beispiels stieß ich auf das Problem, dass die Schaltfläche „Veröffentlichen“ deaktiviert und nach einiger Zeit wieder aktiviert wurde. Und dann müssen Sie sich auch den Code ansehen, um zu sehen, was er tut. In Zeiten wie diesen können Sleeps Ihnen helfen, das Problem schnell zu beheben, wenn Sie nicht zu viel debuggen möchten: Stellen Sie einfach sicher, dass Sie eine ausreichend lange Sleep-Zeit einstellen und seien Sie vorsichtig, dass sie in Zukunft inkonsistent sein könnte.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.Events;

namespace SeleniumTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IWebDriver driver = new OpenQA.Selenium.Firefox.FirefoxDriver();
            driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));

            // enter your configurations here 
            driver.Navigate().GoToUrl("http://localhost/wordpress/wp-admin/post-new.php");
            driver.FindElement(By.Id("user_login")).SendKeys("admin");
            driver.FindElement(By.Id("user_pass")).SendKeys("yourpassword");

            driver.FindElement(By.Id("wp-submit")).Click();

            driver.FindElement(By.Id("title")).SendKeys("the title");
            var iframe = driver.FindElement(By.Id("content_ifr"));
            driver.SwitchTo().Frame(iframe);


            // your solution which works in my instance
            //driver.SwitchTo().ActiveElement().SendKeys("hello tiny mce from selenium");

            // send keys with exact element
            //driver.FindElement(By.Id("tinymce")).SendKeys("hello tiny mce from selenium");

            // javascript - 1
            IJavaScriptExecutor js = driver as IJavaScriptExecutor;
            var tinymce = driver.FindElement(By.Id("tinymce"));
            IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
            executor.ExecuteScript("arguments[0].innerHTML = 'hello tiny mce via javascript'", tinymce);
            // javascript - 0



            driver.SwitchTo().DefaultContent();

            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(11));
            wait.Until((d) => { return !d.FindElement(By.Id("publish")).GetAttribute("class").Contains("disabled"); }); // wait for publish button to be enabled
            driver.FindElement(By.Id("publish")).Click();
            driver.FindElement(By.Id("message")); // wait for message on next page to verify it is posted
            driver.Close();
        }
    }
}

  • Ich sehe die nicht By.Id("tinymce"). Alles ist einfach <body><p><br data-mce-bogus="1"></br></p></body>.

    – SiKing

    5. Juni 2014 um 14:28 Uhr

  • Danke, aber das macht nichts weiter als den Code, den ich gepostet habe (der eigentlich nicht viel anders ist). Ich verwende implizite Wartezeiten, die in der Driver-Klasse implementiert sind. Dies macht dasselbe wie mein Code: Es gibt den Titel ein, dann wechselt der Cursor zum mce-Editor (wie in, im Editor blinkend, bereit zum Tippen). Dann nichts mehr. Die Methode SendKeys() tut anscheinend nichts.

    Benutzer2119841

    5. Juni 2014 um 21:00 Uhr

  • Oh, ich dachte aufgrund Ihres Schlafs, dass Sie keine impliziten Wartezeiten verwenden und dass es ein Inkonsistenzproblem sein könnte, da Sie erwähnt haben, dass “content_ifr” fehlt, nachdem es angeblich zuvor funktioniert hat. Ich dachte auch, dass Ihr .SwitchTo().ActiveElement() möglicherweise nicht genau ist und das Auffinden des Elements anhand der ID prägnanter wäre. Ich werde versuchen, das Update mit dem oben vorgeschlagenen Javascript zu aktualisieren. Sie erwähnen auch das Dashboard, verweisen aber auf „content_ifr“, das ich nicht in meinem Dashboard sehe, sondern auf der Seite „Neuen Beitrag hinzufügen“, also nehme ich an, dass es die Seite „Neuer Beitrag“ ist?

    – das Weizen

    5. Juni 2014 um 21:43 Uhr

  • Yah, es ist die Seite “Neuer Beitrag”, aber über das Dashboard aufgerufen, als Administrator angemeldet.

    Benutzer2119841

    6. Juni 2014 um 6:38 Uhr

  • Wenn Sie den Fehler “Frame kann nicht gefunden werden …” erhalten, sehen Sie, dass der TinyMCE-Editor initialisiert ist? Auch scheitert es bei diesem Schritt immer konsequent? Denn ein Blick auf die Quelle der Seite “Neuer Beitrag” zeigt keinen Verweis auf ein Iframe, was bedeutet, dass es wahrscheinlich über Javascript generiert wird. Und wenn Sie es auf der Seite sehen, aber es schlägt fehl, verleitet es mich zu der Annahme, dass es sich um ein Zeitproblem handelt. Hat mein obiger Code den gleichen Fehler wie deiner ausgegeben?

    – das Weizen

    7. Juni 2014 um 11:01 Uhr

Selenium und WordPress Neuer Post Test
Patrick 68

Eine PHP-Version der olyv-Lösung:

$content="my text";
$this->frame( 'content_ifr' );
$body = $this->byXPath( '//body' );
$body->click();
$script="arguments[0].innerHTML = "" + arguments[1] + ""; ";
$this->execute( [
            'script' => $script,
            'args'   => [ $body->toWebDriverObject(), $content ],
        ]
    );
$this->frame( null );

Ich weiß, dass ich etwas spät zur Party komme, aber ich habe gerade eine Lösung gefunden, die (glaube ich) viel einfacher ist als die bisher gegebenen Antworten. Also habe ich beschlossen, es hier zu posten, falls es jemand anderem helfen könnte.

Hier müssen keine Rahmen gewechselt werden. Was Sie tun möchten, ist auf die Schaltfläche in der oberen rechten Ecke des Texteditors zu klicken, die “Text” sagt, die id = “content-html” hat. Jetzt können Sie Schlüssel an das Textfeld senden, das id = “content” hat.

Hier ist ein Python-Code, der genau das tut:

driver.find_element_by_id("content-html").click()
driver.find_element_by_id("content").send_keys("Some text...")

Ich hoffe es hilft

964390cookie-checkSelenium und WordPress: Neuer Post-Test

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy