2015-08-07 11 views
10

q library dieses nette Feature hat zu lösen und mehrere Versprechen in getrennte Argumente verteilt:Verbreitung Versprechen in Protractor

Wenn Sie ein Versprechen für ein Array haben, können Sie sich als für dann Ersatz verbreitete Verwendung. Die Spread-Funktion "spreizt" die Werte über die Argumente des Fulfillment-Handlers.

return getUsername() 
    .then(function (username) { 
     return [username, getUser(username)]; 
    }) 
    .spread(function (username, user) { 

    }); 

In Winkelmesser, versuchen wir, den Einbau-protractor.promise kommt von WebDriverJS zu verwenden.

Die Frage:

Ist es möglich, die "Spread" Funktionalität mit protractor.promise zu haben? Use Case

Beispiel:

wir eine eigene Jasmin Matcher check if an element is focused implementiert haben. Hier müssen wir zwei Versprechen lösen, bevor wir einen Gleichheitsvergleich machen. Derzeit verwenden wir protractor.promise.all() und then():

protractor.promise.all([ 
    elm.getId(), 
    browser.driver.switchTo().activeElement().getId() 
]).then(function (values) { 
    jasmine.matchersUtil.equals(values[0], values[1]); 
}); 

die im Idealfall würden wir in einem besser lesbaren Zustand haben mag:

protractor.promise.all([ 
    elm.getId(), 
    browser.driver.switchTo().activeElement().getId() 
]).spread(function (currentElementID, activeElementID) { 
    return jasmine.matchersUtil.equals(currentElementID, activeElementID); 
}) 
+0

Wie erwarten Sie, dass dies geschieht, wenn es sich um zwei verschiedene Bibliotheken handelt? Wenn das WebDriverJS-Versprechen nicht in Q oder Bluebird verpackt ist, können Sie die _get-Funktionalität_ einer anderen Bibliothek –

+0

@KirillSlatin nicht abfragen, und darum frage ich eigentlich. Wie können wir den "Winkelmesser" erweitern und ist es machbar? Außerdem habe ich es noch nicht ausprobiert, aber was ist, wenn wir "Winkelmesser" mit "q" im laufenden Betrieb ersetzen, wie würde es den Winkelmesser-Testlauf usw. beeinflussen. – alecxe

+1

hmm, das könnte Sinn machen, die Versprechen-Engine zu ersetzen von Anfang an. Ich dachte daran, eine bestimmte Verheißungsinstanz einzupacken. Etwas Ähnliches wie "promisify" von bluebird –

Antwort

7

Es ist ein bisschen hässlich kommen kann zu verwenden, aber Sie können festlegen, eine unabhängige Hilfsfunktion, die als Parameter an then() übergeben werden kann und einen Callback hat, der normalerweise an then() übergeben wird, um an ihn übergeben zu werden. Diese Funktion wird dann Array-Wert konvertieren Argumente funktionieren:

protractor.promise.all([ 
    elm.getId(), 
    browser.driver.switchTo().activeElement().getId() 
]).then(spread(function (currentElementID, activeElementID) { 
    // ---^^^----- use helper function to spread args 
    jasmine.matchersUtil.equals(currentElementID, activeElementID); 
})); 


// helper function gets a callback 
function spread(callback) { 
    // and returns a new function which will be used by `then()` 
    return function (array) { 
     // with a result of calling callback via apply to spread array values 
     return callback.apply(null, array); 
    }; 
} 

Sie können es immer noch die Kette mit einem anderen then() und Ablehnung Rückrufe zur Verfügung stellen; Es hält das Verhalten des Winkelmessers gleich, verspricht aber nur das Konvertieren von Werten in Argumente.

Nachteile sind, dass es nicht ein perfektes Aussehen wie in Ihrem Beispiel (nicht .all().spread() aber .all().then(spread())) hat und Sie müssen wahrscheinlich ein Modul für diesen Helfer erstellen oder global definieren, um es problemlos in verwenden zu können mehrere Testdateien.

Update:

Mit ES2015 es möglich ist, destructuring assignment zu verwenden zusammen mit then():

protractor.promise.all([ 
    elm.getId(), 
    browser.driver.switchTo().activeElement().getId() 
]).then(function (values) { 
    // Destructure values to separate variables 
    const [currentElementID, activeElementID] = values; 
    jasmine.matchersUtil.equals(currentElementID, activeElementID); 
})); 
+0

Ja, danke!Dies ist etwas, worüber ich nachgedacht habe, um es zu umgehen - einen Wrapper erstellen, um das Ausbreiten/Entpacken/Zerstören zu unterstützen. Ich habe auch geschrieben, wie ich es gelöst habe, aber es ist eine offene Frage, ob es wirklich sicher ist zu ersetzen "Winkelmesser. Versprechen" mit "q" .. was kann schief gehen? .. – alecxe

+2

Ich warf einen kurzen Blick auf die Quellcode und wie ein Entwickler sagte in Ihrem Github Problem, es hat eine Sache namens Kontrollfluss verwendet innerhalb Versprechen Methoden ([desc] (https://github.com/SeleniumHQ/selenium/blob/master/javascript/webdriver/promise. js # L1193)). Ich denke, es ist verantwortlich für die Reihenfolge der Spezifikationen und/oder die Möglichkeit, Tests parallel in mehreren Browser-Instanzen auszuführen, aber ich bin mir nicht sicher. Diese Flüsse werden auf einer hohen Ebene initialisiert, [bei verbindlichen Treibern] (https://github.com/SeleniumHQ/selenium/blob/01399fffecd5a20af6f31aed6cb0043c9c5cde65/javascript/node/selenium-webdriver/builder.js#L454) –

4

TL; DR Offenbar ist es nicht ganz sicher protractor.promise mit q zu ersetzen.Zum Beispiel habe ich einen hängenden Testlauf bekam einmal habe ich mich entschlossen ElementArrayFinder zu verlängern:


Alte Antwort:

Hier ist, was ich getan, um es zu lösen.

Ich habe ersetzt protractor.promise mit q on the fly (nicht sicher, ob es wirklich sicher ist, zu tun):

onPrepare: { 
    protractor.promise = require("q"); 
}, 

Aber nichts brach so weit und jetzt bin ich in der Lage spread() zu verwenden und andere durch q durch protractor.promise bereitgestellt syntaktischen Zucker:

toBeActive: function() { 
    return { 
     compare: function(elm) { 
      return { 
       pass: protractor.promise.all([ 
        elm.getId(), 
        browser.driver.switchTo().activeElement().getId() 
       ]).spread(function (currentElementID, activeElementID) { 
        return jasmine.matchersUtil.equals(currentElementID, activeElementID); 
       }) 
      }; 
     } 
    }; 
} 

Relevant github thread: protractor.promise to use q.