How to assert an element is present after a click in Hound? - selenium

I'm using Hound as webdriver framework for leveraging Selenium in Elixir. I'm testing facebook account creation. After I fill out a negative test (firstname = Roberto, lastname = asdlkfj;)I click submit and I am trying to get an error for not having a correct last name. The problem is Hound isn't waiting for the element to be displayed and returns an element not found error. How can I handle this and have the test wait until the element is loaded? Here's my code:
test "Last name with random characters" do
counter = :rand.uniform(100)
navigate_to "https://www.facebook.com"
first_name = find_element(:name, "firstname")
fill_field(first_name, "Jorge")
last_name = find_element(:name, "lastname")
fill_field(last_name, "asdfja;lsdf")
email_input = "robbie#{counter}#gmail.com"
email = find_element(:name, "reg_email__")
fill_field(email, email_input)
confirm_email = find_element(:name, "reg_email_confirmation__")
fill_field(confirm_email, email_input)
password_input = "123456Test"
password = find_element(:name, "reg_passwd__")
fill_field(password, password_input)
#Birthday
birth_month = find_element(:css, "#month > option:nth-child(5)")
birth_day = find_element(:css, "#day > option:nth-child(25)")
birth_year = find_element(:css, "#year > option:nth-child(22)")
click(birth_month)
click(birth_day)
click(birth_year)
#gender
select_gender = find_element(:css, "#u_0_s > span:nth-child(2)")
click(select_gender)
sign_up_button = find_element(:name, "websubmit")
click(sign_up_button)
search = find_element(:id, "#reg_error_inner")
# found = element_displayed?("#reg_error_inner")
IO.puts(search)
# assert found == true
# :timer.sleep(10000)
end```

Use search_element instead of find_element. search_element will return {:ok, element} on success and {:error, error} on failure. If you just want to assert the element exists, then you can:
assert {:ok, _} = search_element(:id, "#reg_error_inner")
If you want to also have it in a variable for further processing, then:
assert {:ok, element} = search_element(:id, "#reg_error_inner")
If you want to convert it to a boolean, then:
match?({:ok, _}, search_element(:id, "#reg_error_inner"))

Related

how to run an external function with variables from State?

this function must be run in the file where the bot is located
def start_pars():
from mainaio import data
username_input = driver.find_element(By.XPATH,
'/html/body/div/div/main/div/div/div/div[1]/form/div[1]/div[1]/div/input')
username_input.clear()
username_input.send_keys(data["username"])
pass_input = driver.find_element(By.XPATH,
'/html/body/div/div/main/div/div/div/div[1]/form/div[1]/div[2]/div/input')
pass_input.clear()
pass_input.send_keys(data["password"])
driver.find_element(By.XPATH, '/html/body/div/div/main/div/div/div/div[1]/form/div[2]/button').click()
time.sleep(1)
username1 = driver.find_element(By.XPATH, '/html/body/div[1]/nav[2]/div[2]/div/div[2]/div[2]/div')
print(username1.text)
less1 = []
lessundscore = driver.find_elements(By.XPATH, '/html/body/div[1]/div/main/div/div[2]/div/div[3]/div[1]')
for value in zip(lessundscore):
less1 += value
for val in less1:
print(val.text)
return username1, less1
items from the state must be transferred to the sending keys
class Registration(StatesGroup):
username = State()
password = State()
username = message.text
await state.update_data(username=username)
assword = message.text
await state.update_data(password=password)
data = await state.get_data()
I tried to run in the last registration function start_pars(data['username'], data['password'])

pyTelegramBotAPI.How to edit/delete message with inline buttons only if message from the same step was already in chat?

I want my TG bot to have inlinebuttons with categories and subcategories in chat with dynamic change.
But how to send message with subcategories if it doesnt exist and edit message with subcategories if it already exists?
Also, I wish to have a "back" inlinebutton among categories that will delete messages with categories and subcategories and turn to main menu.
Attached my code and illustration of goal.
Help me please!
import telebot
from telebot import types
bot = telebot.TeleBot(TELEGRAM_TOKEN,
parse_mode=None)
markup_menu = types.ReplyKeyboardMarkup(resize_keyboard=True)
btns = ["Order"]
for btn in btns:
markup_menu.add(types.KeyboardButton(btn))
menu = {"Snacks": {"Sweet Snack": 150, "Salt snak": 320}, "Drinks": {"Cola": 100, "Sprite": 90},
"Meat": {"Pork": 228, "Beef": 56}}
#bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id,
f"Wellcome, <b>{message.from_user.first_name}</b>",
reply_markup=markup_menu,
parse_mode="html")
#bot.message_handler(content_types="text")
def order(message):
# These are variable values to help change next message after "Choose category:"
order_counter = 0
product_message = 0
switcher = {product_message: order_counter}
if message.text == 'Order':
order_menu = types.InlineKeyboardMarkup()
order_menu.row_width = 2
for category in menu:
order_menu.add(types.InlineKeyboardButton(category,
callback_data=f"{category}"))
bot.send_message(message.chat.id,
"Choose category:",
reply_markup=order_menu)
if order_counter == 0:
#bot.callback_query_handler(func=lambda call: call.data in menu.keys())
def callback_product(call):
product_menu = types.InlineKeyboardMarkup()
product_menu.row_width = 4
for product in menu[call.data]:
product_menu.add(types.InlineKeyboardButton
(f"{product}" +
f" - {menu[call.data][product]}",
callback_data=f"{product}")
)
product_message = bot.send_message(message.chat.id,
f'Choose {call.data}:',
reply_markup=product_menu,
)
product_message
order_counter == 1
switcher = {product_message: order_counter}
return switcher
elif switcher.keys() == 1:
#bot.callback_query_handler(func=lambda call: call.data in menu.keys())
def callback_product1(call):
product_menu = types.InlineKeyboardMarkup()
product_menu.row_width = 4
for product in menu[call.data]:
product_menu.add(types.InlineKeyboardButton
(f"{product}" +
f" - {menu[call.data][product]}",
callback_data=f"{product}")
)
product_message = bot.edit_message_text(chat_id=switcher[0][0].message.chat.id,
message_id=switcher[0][0].message_id,
text=f'Choose {call.data}:',
reply_markup=product_menu
)
product_message
order_counter == 1
return order_counter, product_message
#bot.message_handler(content_types="text")
def missunderstand(message):
bot.reply_to(message, "I don't understand you", reply_markup=markup_menu)
bot.infinity_polling()
I have tried to create a switcher that would signal to func. if message with subcategories exists, but it didn't work. (it's "switcher" in code)

Is it possible to define variables if a condition is satisfied in karate framework?

Eg. If insurance = true(in JSON response) then def variables(insurance_img_cancel, insurance_img_refund, insurance_details etc.) from api response (which will be used in next api in the chain) else throw message "Insurance unavailable".
Given url postEligibility
And def eligibilityRequestBody = read('eligibilityCPReq.json')
And request eligibilityRequestBody
And print eligibilityRequestBody
And def cookie = read('cookie.txt')
And header cookie = cookie
When method Post
Then status 200
And print response
And match **response.data.insuranceAvailable == 'true'**
And def insurance_img_cancel = response.data.img_cancel
And def insurance_img_refund = response.data.img_refund
And def insurance_details = response.data.insurance_details
And def insurance_end_date = response.data.insurance_end_date
And def insurance_id = response.data.insurance_details[0].insurance_id
And def insurance_premium = response.data.insurance_details[0].premium
And def insurance_type = response.data.insurance_type
And def insuranceAvailable = response.data.insuranceAvailable
Isn't that match sufficient:
And match response.data.insuranceAvailable == 'true'
So if it is not true it will fail the test. That's what you want right ?
Else please simplify the question: https://stackoverflow.com/help/minimal-reproducible-example

Telegram bot: How to get chosen inline result

I'm sending InlineQueryResultArticle to clients and i'm wondering how to get chosen result and it's data (like result_id,...).
here is the code to send results:
token = 'Bot token'
bot = telegram.Bot(token)
updater = Updater(token)
dispatcher = updater.dispatcher
def get_inline_results(bot, update):
query = update.inline_query.query
results = list()
results.append(InlineQueryResultArticle(id='1000',
title="Book 1",
description='Description of this book, author ...',
thumb_url='https://fakeimg.pl/100/?text=book%201',
input_message_content=InputTextMessageContent(
'chosen book:')))
results.append(InlineQueryResultArticle(id='1001',
title="Book 2",
description='Description of the book, author...',
thumb_url='https://fakeimg.pl/300/?text=book%202',
input_message_content=InputTextMessageContent(
'chosen book:')
))
update.inline_query.answer(results)
inline_query_handler = InlineQueryHandler(get_inline_results)
dispatcher.add_handler(inline_query_handler)
I'm looking for a method like on_inline_chosen(data) to get id of the chosen item. (1000 or 1001 for snippet above) and then send the appropriate response to user.
You should set /setinlinefeedback in #BotFather, then you will get this update
OK, i got my answer from here
Handling user chosen result:
from telegram.ext import ChosenInlineResultHandler
def on_result_chosen(bot, update):
print(update.to_dict())
result = update.chosen_inline_result
result_id = result.result_id
query = result.query
user = result.from_user.id
print(result_id)
print(user)
print(query)
print(result.inline_message_id)
bot.send_message(user, text='fetching book data with id:' + result_id)
result_chosen_handler = ChosenInlineResultHandler(on_result_chosen)
dispatcher.add_handler(result_chosen_handler)

All the links in the same row

I'm doing a database where it has 2 columns: event_name and event_URL. It doesn't get the name and puts all the urls on the event_URL column. Print: https://prnt.sc/fru1tr
Code:
import urllib2
from bs4 import BeautifulSoup
import psycopg2
page = urllib2.urlopen('https://www.meetup.com/find/outdoors-adventure/?allMeetups=false&radius=50&userFreeform=London%2C+&mcId=c1012717&change=yes&sort=default')
soup = BeautifulSoup(page, 'lxml')
events = soup.find('ul', class_='j-groupCard-list searchResults tileGrid tileGrid--3col tileGrid_atMedium--2col tileGrid_atSmall--1col')
A = []
B = []
try:
conn = psycopg2.connect("dbname='meetup' user='postgres' host='localhost' password='root'")
except:
print 'Unable to connect to the database.'
cur = conn.cursor()
for event in events.findAll('li'):
text = event.findAll('h3')
if len(text) != 0:
A.append(text[0].find(text = True))
url = event.find('a', href=True)
if len(url) != 0:
B.append(url['href'])
cur.execute("""INSERT INTO outdoors_adventure(event_name,event_url) VALUES(%s,%s)""", (tuple(A),tuple(B)))
conn.commit()
del A[:]
del B[:]
If the indentation is right in the posted code, the problem might be in the nested for-loop: for every event, you append the "B" list with all the links on the page. You could try:
for event in events.findAll('li'):
text = event.findAll('h3')
if len(text) != 0:
A.append(text[0].find(text = True))
for link in events.findAll('li'):
url = link.find('a', href=True)
if len(url) != 0:
B.append(url['href'])
Or better, keep the event-name and event-URL search in a single for-loop, fetching first the text and then the url of event
EDIT: You can simplify the name extraction, by using:
for event in events.findAll('li'):
text = event.h3.string.strip()
if len(text) != 0:
A.append(text)
url = event.find('a', href=True)
...
Let me know if that does the trick for you (it does on my side).
EDIT2: The problem might be just the fact that the extracted string starts with tabs (maybe that's why your DB seems "not to show the name" - its there, but you only see the tabs in the preview?). Just use strip() to remove them.