Robotframework - appium testing for hybrid android app (Angular) - xpath

I have a hard time testing our hybrid app with Robotframework tests using appium library. The application has 2 contexts:
Native (android)
Web (Angular)
The problem that I Have is when I'm in the web context and I'm trying to use XPath locators to locate elements that contain some text using the expression: Click Element //*[contains(#text,some_containing_text)] I would have the result of the root element which contains the element that I'm trying to locate. So in the end my test is clicking all the wrong way then it should be clicking because of that locator returning the root element of the HTML page.
This functionality of locating elements by just saying "Click element that contains something like this" is working with the selenium library on our Web application. But my question is why (or what I'm doing wrong) it doesn't work with appium Robotframework library.
Using appium 1.6.3.
I'm searching for span with the text Ukončit
<app-attendance-detail class="ng-star-inserted">
<div class="py-4">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="mb-4">
<div class="row">
<div class="col-12"><h4 class="fs-14 mb-1 font-weight-bold">úterý, 09:56:00 26.07.2022</h4>
</div>
</div>
<h4 class="fs-14 fs-md-16 mb-4 font-weight-bold text-gray-light ng-star-inserted">
<span>Začátek dnešní směny od</span> dnes v 9:45 </h4>
<div class="e-timer text-gray ng-star-inserted">00:10h</div>
<a href="#" title="#" preventdefault=""
class="btn btn-primary w-100 text-uppercase font-weight-bold px-9 mt-6 ng-star-inserted"><i
class="icon icon-stop position-relative bottom-1 mr-1"></i><span translate=""
ng-reflect-translate="">Ukončit</span></a>
<div class="row row-xs mt-2 ng-star-inserted">
<div class="col-6 px-1"><a href="#" title="#" preventdefault=""
class="btn btn-white border-primary-dark text-primary w-100 text-uppercase font-weight-bold px-9"><i
class="icon icon-pause position-relative bottom-1 mr-1"></i><span>Začátek<br>přestávky</span></a>
</div>
<div class="col-6 px-1"><a href="#" title="#" preventdefault=""
class="btn btn-white border-primary-dark text-primary w-100 text-uppercase font-weight-bold px-9"><span>Odchod<br>jiné</span></a>
</div>
</div>
</div>
<div class="mt-4"><h4 translate="" class="fs-14 fs-md-16 mb-2 font-weight-bold"
ng-reflect-translate="">Docházka</h4><a title="#" target="_blank"
class="d-block bg-white px-3 border-radius-sm box-shadow-sm mb-2 text-gray ng-star-inserted"
href="https://h5tws.cezdata.corp:44320/sap/bc/bsp/sap/zjd_dovol/overview.htm">
<div class="row">
<div class="col py-3 pb-3">
<div translate="" class="fs-16 font-weight-bold text-uppercase" ng-reflect-translate="">
Žádost o dovolenou
</div>
</div>
<div
class="col col-xs py-2 text-center border-left border-gray-light d-flex align-items-center justify-content-center">
<div class="text-gray"><i class="icon icon-forward"></i></div>
</div>
</div>
</a><a title="#" target="_blank"
class="d-block bg-white px-3 border-radius-sm box-shadow-sm mb-2 text-gray ng-star-inserted"
href="https://h5tws.cezdata.corp:44320/sap/bc/bsp/sap/zjd_doli/selection_screen.htm">
<div class="row">
<div class="col py-3 pb-3">
<div translate="" class="fs-16 font-weight-bold text-uppercase" ng-reflect-translate="">
Docházkový list
</div>
</div>
<div
class="col col-xs py-2 text-center border-left border-gray-light d-flex align-items-center justify-content-center">
<div class="text-gray"><i class="icon icon-forward"></i></div>
</div>
</div>
</a></div>
<div class="mt-4"><h4 translate="" class="fs-14 fs-md-16 mb-2 font-weight-bold"
ng-reflect-translate="">Záznamy</h4><a routinglink="attendance/records"
href="#" title="#"
class="d-block bg-white px-3 border-radius-sm box-shadow-sm mb-2 text-gray"
ng-reflect-routing-link="attendance/records">
<div class="row">
<div class="col py-3 pb-3">
<div translate="" class="fs-16 font-weight-bold text-uppercase" ng-reflect-translate="">
Přehled záznamů
</div>
</div>
<div
class="col col-xs py-2 text-center border-left border-gray-light d-flex align-items-center justify-content-center">
<div class="text-gray"><i class="icon icon-forward"></i></div>
</div>
</div>
</a></div>
</div>
</div>
</div>
<app-modal-dialog styleclass="shadow" ng-reflect-style-class="shadow" ng-reflect-show-header="false"
ng-reflect-dismissable-mask="false" ng-reflect-dialog-id="4">
<p-dialog class="p-element ng-tns-c30-7 ng-star-inserted" ng-reflect-style-class="shadow"
ng-reflect-visible="false" ng-reflect-modal="true" ng-reflect-dismissable-mask="false"
ng-reflect-transition-options="0ms" ng-reflect-show-header="false" ng-reflect-draggable="true"
ng-reflect-resizable="true" ng-reflect-close-on-escape="true" ng-reflect-base-z-index="1050">
</p-dialog>
</app-modal-dialog>
<app-modal-dialog styleclass="shadow" ng-reflect-style-class="shadow" ng-reflect-show-header="false"
ng-reflect-dialog-id="5" ng-reflect-dismissable-mask="false">
<p-dialog class="p-element ng-tns-c30-8 ng-star-inserted" ng-reflect-style-class="shadow"
ng-reflect-visible="false" ng-reflect-modal="true" ng-reflect-dismissable-mask="false"
ng-reflect-transition-options="0ms" ng-reflect-show-header="false" ng-reflect-draggable="true"
ng-reflect-resizable="true" ng-reflect-close-on-escape="true" ng-reflect-base-z-index="1050">
</p-dialog>
</app-modal-dialog>
</div>
This is the keyword in Robot testcase
Attendance_action
[Arguments] ${action}
Click element //*[contains(#text, "${action}")]
Sleep 2s

Thanks for updating the question to include the details of how the XPath is called. It seems to me that you will end up with an expression like //*[contains(#text, "Ukončit")]; I would not expect that to return anything because the expression #text is a refererence to an attribute with the name text. It's not a reference to the textual content of an element.
I suspect what you actually meant to enter was an expression like this:
//*[text()[contains(., "Ukončit")]]
Translation: any element which contains a text node which itself contains the string "Ukončit". That should return a single span element:
<span translate="" ng-reflect-translate="">Ukončit</span>

Related

bootstrap 5 Uncaught TypeError: this._element is undefined

I have database results (reviews) which reviews can also be reported by the logged user. Before I make these reviews load through AJAX call the bs stepper worked perfectly (it is used for steps while reporting a review). Now when the database results (reviews) are loaded through AJAX call the bs stepper is giving me the following error on page load.
error
Here is how I define bs steppers for each review
#extends('Profile.master')
#section('content')
<div class="container-fluid mt-5">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-9 fw-bold fs-3 mb-4">
<span class="me-2"><i class="fas fa-tv"></i></span>
<span>branch {{ $branch->title }}</span>
</div>
</div>
<div class="row">
#foreach($branch->users as $user)
<div class="col-lg-4 mb-3 px-3">
<div class="card">
<div class="card-body">
<div class="row g-0 py-3">
<div class="col-3">
<img src="{{ asset('storage/'.$user->image) }}" class="img-fluid" width="100" height="100" alt="{{ $user->full_name }}">
</div>
<div class="col-8 pe-3">
<div class="row pb-3">
<div class="col">
<span class="h5">{{ $user->full_name }}</span>
<span class="small">{{ jdate($user->created_at)->ago() }}</span>
</div>
</div>
</div>
<div class="col-1 mt-2 text-end">
<a href="{{ url('http://localhost:8000/chatify/'.$user->id) }}">
<i class="fas fa-arrow-left fa-lg text-dark"></i>
</a>
</div>
</div>
<div class="row g-0 pb-3">
<div class="col border-top pt-3">
<p>company address: {{ $user->company_address }}</p>
<p>state: {{ $user->state->name }}</p>
<p>city: {{ $user->city->name }}</p>
<p>mobile: {{ $user->mobile }}</p>
</div>
</div>
<div class="row g-0 pb-3">
<div class="col border-top pt-3">
get resume
</div>
</div>
</div>
</div>
</div>
#endforeach
</div>
</div>
</div>
</div>
<div class="modal fade" id="openResumes{{ $user->id }}" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="openResumesTitle{{ $user->id }}" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="openResumesTitle{{ $user->id }}">resume <span class="h5">{{ $user->full_name }}</span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
#foreach($user->resumes as $resume)
<div class="col-lg-3 mb-3">
<img src="{{ asset('storage/'.$resume->image) }}" alt="{{ $user->full_name }}" class="img-fluid">
</div>
#endforeach
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">close</button>
</div>
</div>
</div>
</div>
#endsection
Note: This code does not just execute the first ID. Executes the rest.

Laravel Livewire multiple components not started asyncronously

I have 4 livewire components, rendered in dashboard as:
#livewire('profits.stats')
#livewire('costs.stats')
#livewire('leads.stats')
#livewire('sales.stats')
However, when page loads they run one after another instead of asyncronously. I put a sleep(3) to test, and each starts after the previous ones 3 second delay. How to get them to all start same time?
toggleShowData below has the sleep method, and sets showData=true. I saw this in a tutorial for now to have a loading for individual components
I don't think its relevant, but here is my template:
<div wire:init="toggleShowData">
<div wire:loading.delay class="align-items-center">
<div class="flex items-center justify-center ">
<div class="w-40 h-40 border-t-4 border-b-4 border-brand-500 rounded-full animate-spin"></div>
</div>
</div>
<div class="flex-auto p-4 bg-brand-300 rounded" wire:loading.remove>
<div class="flex flex-wrap">
<div class="relative w-full pr-4 max-w-full flex-grow flex-1">
<h5 class="text-gray-100 uppercase font-bold text-xs"> Costs</h5>
<span class="font-semibold text-xl text-gray-300">$34,100</span>
</div>
<div class="relative w-auto pl-4 flex-initial">
<div
class="text-white p-3 text-center inline-flex items-center justify-center w-12 h-12 shadow-lg rounded-full bg-red-500">
<i class="fas fa-chart-bar"></i>
</div>
</div>
</div>
<p class="text-sm text-gray-100 mt-4">
<span class="text-emerald-500 mr-2"><i class="fas fa-arrow-up"></i> 2,99% </span>
<span class="whitespace-nowrap"> Since last month </span></p>
</div>
</div>
The first render of the livewire page happens inside the PHP process in the backend.
Blade sees that you are requesting a livewire component and replaces this with the result of your parse() method from your component.
This indeed happens in sync, once the page is rendered the components can render itself async

make a Grid system like bootstrap in Tailwind

i am using TailWind with blade template in laravel, how can i make those card like in the bootstrap, i mean every three items in the one column :
#section('content')
<div class="flex justify-center">
<div class="w-8/12 bg-white p-6 rounded-lg mt-10 ">
#forelse($products as $product)
<!-- Box -->
<div class="md:flex md:justify-center md:space-x-8 md:px-14">
<!-- box-1 -->
<div class="mt-16 py-4 px-4 bg-whit w-72 bg-white rounded-xl shadow-lg hover:shadow-xl transform hover:scale-110 transition duration-500 mx-auto md:mx-0">
<div class="w-sm">
<img class="w-64" src="{{asset('storage/images/products/'.$product->image)}}" alt="" />
<div class="mt-4 text-green-600 text-center">
<h1 class="text-xl font-bold">{{$product->name}}</h1>
<div class="mt-4 text-gray-600">{{$product->info}}</div>
<div class="mt-4 px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-300 text-green-800">{{$product->category->name}}</div>
<button class="mt-8 mb-4 py-2 px-14 rounded-full bg-green-600 text-white tracking-widest hover:bg-green-500 transition duration-200">MORE</button>
</div>
</div>
</div>
#empty
<h1 class="text-center">There is no Products</h1>
#endforelse
<div> {{$products->links()}}</div>
</div>
</div>
#endsection
Recreate the Bootstrap grid system in Tailwind CSS
<div class="grid grid-cols-12">Your column goes here</div>
You can follow this link for further details. https://shortbuzz.in/blog/shortbuzz.in/how-to-create-tailwind-css-grid-system-like-the-bootstrap-grid-system
Here's Peppermintology's comment in the form of an answer:
It sounds like you're looking for a 3 column grid. To do that in Tailwind CSS, use the grid classes like this:
<div class="grid grid-cols-3">
<!--- Generated cards go here --->
</div>
<div class="container mx-auto">
  <div class="grid grid-cols-12 gap-1">
    <div class="col-span-12 sm:col-span-12 md:col-span-3 lg:col-span-3 xl:col-span-3 2xl:col-span-3">Column</div>
    <div class="col-span-12 sm:col-span-12 md:col-span-3 lg:col-span-3 xl:col-span-3 2xl:col-span-3">Column</div>
    <div class="col-span-12 sm:col-span-12 md:col-span-3 lg:col-span-3 xl:col-span-3 2xl:col-span-3">Column</div>
  </div>
</div>

How to load data dynamically on template?

I have this model that I have multiple instances of it in a list. I want to pass this to my UI and have the UI figure out how to draw this.
data class InfoModel(val icon: String, val title: String, val text: String {
}
The controller.
#GetMapping("/index")
fun start(model: Model): String {
val list = getList()
model ["list"] = list
return "index"
}
Now in the UI I would like this to be duplicated but I don't know how.
<div class="row">
<div class="col-md-6 col-lg-3 d-flex align-self-stretch ftco-animate">
<div class="media block-6 services d-block text-center">
<div class="d-flex justify-content-center"><div class="icon color-1 d-flex justify-content-center mb-3"><span class="align-self-center icon-layers"></span></div></div>
<div class="media-body p-2">
<h3 class="heading">Title</h3>
<p>Text here.</p>
</div>
</div>
</div>
</div>
What I tried and it doesn't display anything.
{{#list}}
<div class="col-md-6 col-lg-3 d-flex align-self-stretch ftco-animate">
<div class="media block-6 services d-block text-center">
<div class="d-flex justify-content-center">
<div class="icon color-1 d-flex justify-content-center mb-3"><span
class="align-self-center icon-{{icon}}"></span></div>
</div>
<div class="media-body p-2">
<h3 class="heading">{{title}}</h3>
<p>{{text}}</p>
</div>
</div>
</div>
{{/list}}
Big thanks to JBNizet for helping me through this. (You should post the answer, you did all the hard work).
{{#list}}
<div class="col-md-6 col-lg-3 d-flex align-self-stretch ftco-animate">
<div class="media block-6 services d-block text-center">
<div class="d-flex justify-content-center">
<div class="icon color-1 d-flex justify-content-center mb-3"><span
class="align-self-center icon-{{icon}}"></span></div>
</div>
<div class="media-body p-2">
<h3 class="heading">{{title}}</h3>
<p>{{text}}</p>
</div>
</div>
</div>
{{/list}}
Reference:
https://scalate.github.io/scalate/documentation/mustache.html#Non_Empty_Lists

How to click on link using Selenium in Ruby on Rails?

HTML code:
<div class="card-body">
<div class="row align-items-center mb-4">
<div class="col">
<h1>Data and Tools</h1>
</div>
</div>
<a href="/reports">
<div class="row my-4 align-items-center clickable">
<div class="col my-3">
<span class="semi-bold">Reports</span>
<div class="stamp-md">
Create, run and schedule reports.
</div>
</div>
<div class="col-1 text-right">
<i class="fas fa-chevron-right gray-light small"></i>
</div>
</div>
</a>
<hr class="inner-divider">
Ruby code:
wait.until { #browser_def.find_element(css: ".card-body > a")}.attribute("href").text("Reports").click()
How can I click link which stands for 'Reports'?
I have found the correct answer for it:
wait.until { #browser_def.find_elements(css: 'a[href$="/reports"] div.clickable').first}.click()

Resources