2015-08-07 12 views
10

q library ha questa caratteristica pulito per risolvere e diffondere molteplici promesse in argomenti distinti:Diffondere promesse goniometro

Se si dispone di una promessa per una matrice, è possibile utilizzare diffondersi come un sostituto per allora. La funzione spread "diffonde" i valori su gli argomenti del gestore di evasione ordini.

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

    }); 

In goniometro, stiamo cercando di utilizzare il built-in protractor.promise provenienti da WebDriverJS.

la domanda:

E 'possibile avere la funzionalità "spread" con protractor.promise?

Esempio caso d'uso:

Abbiamo implementato un matcher gelsomino personalizzato per check if an element is focused. Qui dobbiamo risolvere due promesse prima di fare un confronto di uguaglianza. Attualmente, stiamo usando protractor.promise.all() e then():

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

che idealmente ci piacerebbe avere in uno stato più leggibile:

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

Come ti aspetti che ciò accada se queste sono due librerie diverse? A meno che la promessa di WebDriverJS non sia racchiusa in Q o Bluebird, non è possibile _getare la funzionalità_ di un'altra libreria –

+0

@KirillSlatin, ecco cosa sto chiedendo in realtà. Come possiamo estendere il 'protractor.promise' ed è fattibile? Inoltre, non l'ho ancora provato, ma cosa succede se sostituiamo 'protractor.promise' con' q' al volo, in che modo influenzerebbe l'esecuzione del test del goniometro ecc. – alecxe

+1

hmm, che potrebbe avere senso sostituire il motore di promessa dal principio. Ho pensato di avvolgere una specifica istanza di promessa. Qualcosa di simile a 'promisify 'di bluebird –

risposta

7

Essa può venire un po 'brutto da usare, ma è possibile definire una funzione di supporto indipendente, che può essere passata a then() come parametro e avere una richiamata, che di solito viene passata a then() da passarvi. Questa funzione sarà quindi convertire il valore gamma di funzionare argomenti:

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); 
    }; 
} 

È ancora possibile concatenare con un altro then() e fornire callback di rigetto; mantiene tutto il comportamento di Protractor promette lo stesso, ma converte semplicemente array di valori in argomenti.

svantaggi sono che esso è non ha un look perfetto, come nel tuo esempio (non .all().spread() ma .all().then(spread())) e avrete probabilmente per creare un modulo di questo helper o definire globalmente per essere in grado di utilizzare facilmente in più file di test.

Aggiornamento:

Con ES2015 è possibile utilizzare destructuring assignment insieme 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

Sì, grazie!Questo è qualcosa a cui stavo pensando di risolvere il problema: creare un wrapper per supportare la diffusione/decompressione/distruzione. Ho anche postato come l'ho risolto, ma c'è una domanda aperta se è davvero sicuro sostituire 'protractor.promise' con' q'..che cosa può andare storto? .. – alecxe

+2

Ho dato una breve occhiata al i codici sorgente e come uno sviluppatore ha detto nel tuo problema su Github, ha una cosa chiamata flusso di controllo usato all'interno dei metodi di promessa ([desc] (https://github.com/SeleniumHQ/selenium/blob/master/javascript/webdriver/promise. js # L1193)). Immagino sia responsabile dell'ordine delle specifiche e/o della capacità di eseguire test in parallelo in più istanze del browser, ma non ne sono sicuro. Questi flussi sono inizializzati su un livello elevato, [quando si collegano i driver] (https://github.com/SeleniumHQ/selenium/blob/01399fffecd5a20af6f31aed6cb0043c9c5cde65/javascript/node/selenium-webdriver/builder.js#L454) –

4

TL; DR A quanto pare, non è del tutto sicura per sostituire protractor.promise con q.Per esempio, ho una prova appeso una volta ho deciso di estendere ElementArrayFinder:


Vecchia risposta:

Ecco quello che ho' ho fatto per risolverlo

ho sostituito protractor.promise con q al volo (non so se in realtà è sicuro di fare):

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

Ma, niente di rotto finora e adesso sono in grado di utilizzare e spread() altri zuccheri sintattico fornita da q attraverso protractor.promise:

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); 
       }) 
      }; 
     } 
    }; 
} 

Rilevante filo github: protractor.promise to use q.