overriding actions for botium webdriverio connector

笑着哭i 提交于 2019-12-24 22:54:21

问题


edit: change topic to overriding basic functons on botium-webdriverio-connector


How to trigger button click ?

from this link: https://github.com/codeforequity-at/botium-core/wiki/Botium-Scripting

it says that you just need to put

#me
BUTTON btnTitle

but what actually happened is that it sends literal BUTTON btnTitle as text to the bot

for context, i implemented a custom WEBDRIVERIO_GETBOTMESSAGE and send back this

{
  "sender": "bot",
  "buttons": [
    {
      "text": "reply1"
    },
    {
      "text": "reply2"
    }
  ],
  "cards": [],
  "media": []
}

回答1:


i decided to override the WEBDRIVERIO_SENDTOBOT function. running on botium-cli 0.0.44, probably there are better solutions on newer versions.


edit: add more details, source code & implementation

in the end, i override these functions WEBDRIVERIO_OPENBOT WEBDRIVERIO_SENDTOBOT WEBDRIVERIO_GETBOTMESSAGE and also add a custom asserter to assert gallery messages

botium.json

{
  "botium": {
    "Capabilities": {
      "PROJECTNAME": "Production Test",
      "CONTAINERMODE": "webdriverio",
      "WEBDRIVERIO_OPTIONS": {  
        "desiredCapabilities": {
          "browserName": "chrome"      
        }
      },
      "WEBDRIVERIO_URL": "the bot url",
      "WEBDRIVERIO_OPENBOT": "./actions/open_test",
      "WEBDRIVERIO_IGNOREWELCOMEMESSAGES": 1,
      "WEBDRIVERIO_SENDTOBOT": "./actions/send",
      "WEBDRIVERIO_GETBOTMESSAGE": "./actions/parse_response",
      "WEBDRIVERIO_START_SELENIUM": true,
      "WEBDRIVERIO_START_SELENIUM_OPTS": {
        "drivers": {
          "chrome": {
            "version": "2.36"
          }
        }
      },
      "ASSERTERS": [
        {
          "ref": "GALLERY",
          "src": "./asserters/gallery",
          "global": true
        }
      ]
    }
  }
}

./actions/open_test

module.exports = (container, browser) => {
    return browser
        .waitForVisible('#toggle-chat', 20000)
        .click('#toggle-chat') // click chat button
        .pause(2000)
        .waitForVisible('#get-started', 20000)
        .click('#get-started') // click get started, initiate the chat
        .pause(2000)
}

./actions/send


module.exports = (container, browser, msg) => {

    if (msg.messageText && msg.messageText !== '' && msg.messageText.indexOf('BUTTON') !== 0) { // send text message
        return browser
            .waitForEnabled('#text-input', 10000)
            .setValue('#text-input', msg.messageText)
            .keys('Enter')
    } else if (msg.messageText.indexOf('BUTTON') === 0) { // if message started with "BUTTON xxx", safe to assume the tester want to click button xxx
        let buttonTitle = msg.messageText.split(' ')[1]
        if (!buttonTitle) throw new Error('BUTTON invalid (1)')

        return browser.waitForEnabled(`[chatmessagebuttontitle="${ buttonTitle }"]`, 10000)
        .click(`[chatmessagebuttontitle="${ buttonTitle }"]`)
    } else { // unhandled, send arbitary message
        return browser
            .waitForEnabled('#text-input', 10000)
            .setValue('#text-input', 'unhandled')
            .keys('Enter')
    }

}

./actions/parse_response

module.exports = (container, browser, elementId) => {

    const botMsg = { sender: 'bot', buttons: [], cards: [], media: [] }

    /**
    *
    * ... parsing some html here to populate buttons, media and cards
    * ... can't put all the code for security reasons, sorry
    * ... here are example
    *
    * btw, elementId is NOT an html id attribute, so cannot query with "#" + elementId
    * cannot find documentation for webdriver elementId, but this page helps
    * http://v4.webdriver.io/api/protocol/elementIdElements.html
    *
    */

    browser.elementIdElements(elementId, '.bot-bubble')
    .then(elements => elements.value)
    .then(elements => 
        Promise.all(
            elements.map(element => 
                browser.elementIdText(element.ELEMENT).then(text => text.value)
            )
        ).then(messages => {
            // i only need the first message, also this function only called for each bot message bubble, so safe to assume there is only 1 message
            if (messages.length > 0) botMsg.messageText = messages[0] 

            // send the bot response back to botium
            container.BotSays(botMsg)
        })
    )

}

./asserter/gallery

/**
 * @typedef Card
 * @property {String} image
 * @property {String} title
 * @property {String} subtitle
 * @property {Array<String>} buttons
 * 
 * @typedef BotMesage
 * @property {Array<Card>} cards
 */

/**
 * @typedef GalleryAssertStepParam
 * @property {*} convo
 * @property {Array<String>} args
 * @property {BotMesage} botMsg
 */

module.exports = class GalleryAsserter {

    /**
     * this function is called whenever parse_response.js finishes
     * @param {GalleryAssertStepParam} param
     */
    assertConvoStep(param) {
        let args = param.args
        let botMsg = param.botMsg

        // args needs to be an array, simple check
        if (!args.concat) return Promise.reject(new Error('args for GALLERY is not an array'))
        if (args.length > botMsg.cards.length) return Promise.reject(new Error('number of gallery cards doesnt match. expecting ' + args.length +'. Got ' + botMsg.cards.length))

        // basic logic to check if the card that is passed from parse_response.js is equals to card that is written in test scripts 
        for (var i = 0; i < args.length; i++) {

            // ParseGalleryString is a function that convert arbitary string to a Card object
            // example of the arbitary string: "( title=some title, subtitle= some subtitle, image=image url, buttons=btn1, btn2, btn3 )"
            // will be converted to JSON { title: "some title", subtitle: "some subtitle", ... }
            let card = ParseGalleryString(args[i])
            let testcard = botMsg.cards[i]

            if (card.image !== testcard.image) return Promise.reject(new Error(`card[${i}] doesn't pass. expecting image to be ${ card.image }, got ${ testcard.image }`))
            if (card.title !== testcard.title) return Promise.reject(new Error(`card[${i}] doesn't pass. expecting title to be ${ card.title }, got ${ testcard.title }`))
            if (card.subtitle !== testcard.subtitle) return Promise.reject(new Error(`card[${i}] doesn't pass. expecting subtitle to be ${ card.subtitle }, got ${ testcard.subtitle }`))

            if (card.buttons.length !== testcard.buttons.length) return Promise.reject(new Error(`card[${i}] doesn't pass. expecting ${ card.buttons.length }(${card.buttons.join(', ')}) buttons, got ${ testcard.buttons.length }(${testcard.buttons.join(', ')})`))
            if (card.buttons.join('_') !== testcard.buttons.join('_')) return Promise.reject(new Error(`card[${i}] doesn't pass. expecting buttons to be ${ card.buttons.join(', ') }, got ${ testcard.buttons.join(', ') }`))
        }

        return Promise.resolve()
    }

}

then to use the custom asserter testgallery.convo.txt

Test Gallery

#me
show me some cat breeds

#bot
here are some cat breeds

#bot
GALLERY (image=http://cat.pic/1.png, title=Alaskan Malmute, subtitle=This is actually not a cat, buttons=Pet, Give Food, Info) | (image=http://cat.pic/2.png, title=Cobra Kai, subtitle=This is actually a movie, buttons=Watch, Like, Dislike)

this setup works for botium-cli version 0.0.44 tried to update to botium 0.0.45 but got some error on selenium driver




回答2:


Triggering button clicks is part of Botium Core 1.4.8. For button clicks the result of WEBDRIVERIO_GETBOTMESSAGE is not considered, Botium just looks for button titles (source code with default selenium selector is here.

The described behaviour, that the literal text is sent to the bot, is most likely due to an older version of Botium Core. Please check the version you are using. If you are using version 1.4.8, please enable logging and extend your question with the log output.



来源:https://stackoverflow.com/questions/54645876/overriding-actions-for-botium-webdriverio-connector

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!