How to dynamically access/ define a table row with pageobject gem? - watir-webdriver

I have a table like this
<iframe title="ManageLegs">
<table title="Leg Details">
<tr>
<th />
<th class="headerRow"><div>Dep Date</div></th>
<th class="headerRow"><div>ETD</div></th>
</tr>
<tr>
<td>1</td>
<td>2015-02-01</td>
<td>0900</td>
</tr>
<tr>
<td>2</td>
<td>2015-02-15</td>
<td>1100</td>
</tr>
</table>
</iframe>
Each row has its number in the first cell.
Thing is, that the number of rows varies, and when defining the PageObject for that site, I donĀ“t know how many rows there will be.
Currently I use this code on the PageObject to access the table cells
in_iframe(:title => 'ManageLegs') do |frame|
table(:leg_details, title: 'Leg Details', :frame => frame)
# 1st leg
text_field(:departure_date1) { leg_details_element['1']['Dep Date'].text_field_element }
# 2nd leg
text_field(:departure_date2) { leg_details_element['2']['Dep Date'].text_field_element }
# 3rd leg ...
# ...
end
But this is not DRY at all.
Any advice on how to simplify this?
Thx in advance,
Christian

Personally, I like to define the rows as widgets. This proivdes a descriptive API for the page.
The Leg class to represent a row:
class Leg < PageObject::Elements::TableRow
def index
cell_element(index: 0).text
end
def dep_date
cell_element(index: 1).text
end
def etd
cell_element(index: 2).text
end
end
PageObject.register_widget :leg, Leg, :tr
The page object:
class MyPage
include PageObject
in_iframe(:title => 'ManageLegs') do |frame|
legs(:leg) do
table_element(:title => 'Leg Details', :frame => frame)
.leg_elements(:tag_name => 'tr')[1..-1]
end
end
end
Example usage:
page = MyPage.new(browser)
page.leg_elements.each do |leg|
p leg.index
p leg.dep_date
p leg.etd
end
#=> "1"
#=> "2015-02-01"
#=> "0900"
#=> "2"
#=> "2015-02-15"
#=> "1100"

Just write a method in your page:
in_iframe(:title => 'ManageLegs') do |frame|
table(:leg_details, title: 'Leg Details', :frame => frame)
end
def departure_date(number)
leg_details_element[number]['Dep Date'].text_field_element
end

Related

how to get several rows out of my model

This is again an understanding issue, any explanation is appreciated:
I before had the issue to show a foreignkey table in my view, that now works, it looks like follows:
That's quite what I wanted, but:
I only get the first row, but there are of course several in the second collection (it is the row with filename).
It is because of my method in my model, which looks like follows:
public function getImportU($unitid)
{
$unitid = (int) $unitid;
$rowset = $this->tableGateway->select(['UnitID' => $unitid]);
$row = $rowset->current();
if (! $row) {
return null;
}
else{
return $row;
}
}
Of course I have a row object and it returns the current row. So I thought, ok I will try with a rowset, after that it looked like this:
public function getImportU($unitid)
{
$unitid = (int) $unitid;
$rowset = $this->tableGateway->select(['UnitID' => $unitid]);
//$row = $rowset->current();
if (! $rowset) {
return null;
}
else{
return $rowset;
}
}
I got some errors which said:
Notice: Undefined property: Zend\Db\ResultSet\ResultSet::$Importdate in
Blockquote
So how to get a recordcollection, all records there are in the table with the same unitid? And how to call them in the view. It is probably not a big deal, but I couldn't find anything usable in the documentation.
EDIT1: Adding related code.
Here I pass the ViewModel within my Controller indexAction:
return new ViewModel([
'projects' => $this->projectTable->fetchAll(),
'dcls' => $this->table,
//'id' =>$this->authService,
]);
And here a snippet of my index.phtml:
foreach ($projects as $project) :
//var_dump(get_object_vars($project));
?>
<tr>
<td><?= $project['Projectname']?></td>
<td><?= $project['ProjectShortcut']?></td>
<td><?= $project['ProjectCiNumber']?></td>
<td><?= $project['Unitname']?></td>
<td><?= $project['UnitShortcut']?></td>
<td><?= $project['UnitCiNumber']?></td>
<td><?= $project['UnitID']?></td>
</tr>
<?php
$dclsx=$dcls->getImportU($project['UnitID']);
// var_dump($dclss);
if ( empty ($dclsx)==false){ ?>
<tr>
<th></th>
<th>filename</th>
<th>importdate</th>
<th>importuser</th>
<th>importok</th>
</tr>
<?php
$dclss=array($dclsx);
// var_dump($dclss);
foreach ( $dclss as $dcl) :
?>
<tr>
<td> </td>
<td><?= $dcl->filename?></td>
<td><?= $dcl->Importdate?></td>
<td><?= $dcl->Importuser?></td>
</tr>
?php
endforeach;
}
endforeach; ?>
I believe you are pretty close to the solution.
"getImportU" returning a rowset is the correct solution as I see it:
public function getImportU($unitid)
{
$unitid = (int) $unitid;
$rowset = $this->tableGateway->select(['UnitID' => $unitid]);
if (! $rowset) {
return null;
}
else{
return $rowset;
}
}
Your view should be changed from:
<?php
$dclss=array($dclsx);
// var_dump($dclss);
foreach ( $dclss as $dcl) :
to:
<?php
foreach ( $dclsx as $dcl) :
$dclsx is a resultset and can be iterated, it does not make sense to put it in an array.
Your error also suggests that "Importdate" cannot be found in the blockquote table.
Please check if the column exists at the table(also check the name is case sensitive, is it "Importdate", "importdate" or "importDate"?)

Prestashop 1.6 add product's manufacturer name in mail template

I'd like to add the product's manufacturer name in the new order e-mail. Customer side and admin side.
So, I'd tried to edit the /mails/fr/order_conf_product_list.tpl file to add a new cell with
{$product['manufacturer_name']}
but with no chance.
I already tried severals tips from the forum like the following but the cell stayed empty...
https://www.prestash...turer-reference
Any help will be appreciate.
Thank you very much.
To realize this operation, you need before add the variable manufacturer
For your test you can edit the file [your_shop]/classes/PaymentModule.php(but the better solution is to use override):
1 - Keep manufacturer object
2 - add the manufacturer object in product_var_tpl
foreach ($order->product_list as $product) {
$manufacturer = new Manufacturer((int)$product['id_manufacturer']);
****
$product_var_tpl = array(
'manufacturer' => $manufacturer,
'reference' => $product['reference'],
'name' => $product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : ''),
'unit_price' => Tools::displayPrice($product_price, $this->context->currency, false),
'price' => Tools::displayPrice($product_price * $product['quantity'], $this->context->currency, false),
'quantity' => $product['quantity'],
'customization' => array()
);
}
And in your file /mails/fr/order_conf_product_list.tpl
you can use the object 'manufacturer'
{$product['manufacturer']->name}
The solution to get the manufacturer's name on the customer mail was, as #timactive wrote, to edit the PaymentModule.php.
So, to get the manufacturer's name in the customers mails :
PaymentModule.php :
foreach ($order->product_list as $product) {
$manufacturer = new Manufacturer((int)$product['id_manufacturer']);
$product_var_tpl = array(
'reference' => $product['reference'],
'name' => $product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : ''),
'unit_price' => Tools::displayPrice($product_price, $this->context->currency, false),
'price' => Tools::displayPrice($product_price * $product['quantity'], $this->context->currency, false),
'quantity' => $product['quantity'],
'customization' => array(),
'manufacturer' => $manufacturer->name
);
And than in the order_conf_product_list.html, call the product object like this :
{$product['manufacturer']}
It's a part of the solution because I want to add manufacturer's name on the admin new order mail too.
Add manufacturer's name on the admin new order mail :
To complete this, I had to edit the MailAlert module like this :
In mailalert.php, in the function "hookActionValidateOrder" :
foreach ($products as $key => $product)
{
$manufacturer = new Manufacturer($product['id_manufacturer'], $id_lang);
$items_table .=
'<tr style="background-color:'.($key % 2 ? '#DDE2E6' : '#EBECEE').';">
<td style="padding:0.6em 0.4em;">'.$product['product_reference'].'</td>
<td style="padding:0.6em 0.4em;">'.$manufacturer->name.'</td>
<td style="padding:0.6em 0.4em;">
<strong>'.$product['product_name'].''
.(isset($product['attributes_small']) ? ' '.$product['attributes_small'] : '')
.(!empty($customization_text) ? '<br />'.$customization_text : '')
.'</strong>
</td>
<td style="padding:0.6em 0.4em; text-align:right;">'.Tools::displayPrice($unit_price, $currency, false).'</td>
<td style="padding:0.6em 0.4em; text-align:center;">'.(int)$product['product_quantity'].'</td>
<td style="padding:0.6em 0.4em; text-align:right;">'
.Tools::displayPrice(($unit_price * $product['product_quantity']), $currency, false)
.'</td>
</tr>';
And now, to create to cell, go to mailalert/mails/fr/new-order.html and add this line around the line 114 :
<th style="border:1px solid #D6D4D4;background-color:#fbfbfb;font-family:Arial;color:#333;font-size:13px;padding:10px">Marque</th>

Querying postgres database with rails

I'm trying to search my database based on params from a search form. I had it working perfectly fine in SQLlite, but when I migrated to postgres, several things broke. in app/views/index.html.erb I defined a form:
<tr>
<%= form_tag(guidelines_path, :method => "get", id: "search-form") do %>
<td><%= label_tag(:invprogsearch, "Search by Investor and Program")%></td>
<td><%= text_field_tag :investor, nil, placeholder: "Enter investor" %></td>
<td><%= text_field_tag :program_code, nil, placeholder: "Enter program" %></td>
<td><%= submit_tag "Search", :name => nil %></td>
<% end %>
</tr>
and in my controller (app/controllers/guidelines_controller.rb) I defined the index action as such
def index
if params[:investor].present? && params[:program_code].present?
#guidelines = Guideline.where(investor: params[:investor], program: params[:program_code])
else
#guidelines = Guideline.all
end
end
Any idea why this wouldn't work? I'm out of ideas. Thanks!
app/models/guideline.rb:
class Guideline < ActiveRecord::Base
validates :guide_desc, presence: true
belongs_to :parent, class_name: 'Guideline'
has_many :children, class_name: 'Guideline', foreign_key: 'parent_id'
scope :top_level, where(:parent_id => nil)
def descendants
self_and_descendants - [self]
end
def self_and_descendants
self.class.tree_for(self)
end
def self.tree_for(instance)
where("#{table_name}.id IN (#{tree_sql_for(instance)})").order("#{table_name}.id")
end
def self.tree_sql_for(instance)
tree_sql = <<-SQL
WITH RECURSIVE search_tree(id, path) AS (
SELECT id, ARRAY[id]
FROM #{table_name}
WHERE id = #{instance.id}
UNION ALL
SELECT #{table_name}.id, path || #{table_name}.id
FROM search_tree
JOIN #{table_name} ON #{table_name}.parent_id = search_tree.id
WHERE NOT #{table_name}.id = ANY(path)
)
SELECT id FROM search_tree ORDER BY path
SQL
end
end

Passing variables in PHP Zend Framework

I think I have just been working too long and am tired. I have an application using the Zend Framework where I display a list of clubs from a database. I then want the user to be able to click the club and get the id of the club posted to another page to display more info.
Here's the clubs controller:
class ClubsController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$this->view->assign('title', 'Clubs');
$this->view->headTitle($this->view->title, 'PREPEND');
$clubs = new Application_Model_DbTable_Clubs();
$this->view->clubs = $clubs->fetchAll();
}
}
the model:
class Application_Model_DbTable_Clubs extends Zend_Db_Table_Abstract
{
protected $_name = 'clubs';
public function getClub($id) {
$id = (int) $id;
$row = $this->fetchRow('id = ' . $id);
if (!$row) {
throw new Exception("Count not find row $id");
}
return $row->toArray();
}
}
the view:
<table>
<?php foreach($this->clubs as $clubs) : ?>
<tr>
<td><a href=''><?php echo $this->escape($clubs->club_name);?></a></td>
<td><?php echo $this->escape($clubs->rating);?></td>
</tr>
<?php endforeach; ?>
</table>
I think I am just getting confused on how its done with the zend framework..
in your view do this
<?php foreach ($this->clubs as $clubs) : ?>
...
<a href="<?php echo $this->url(array(
'controller' => 'club-description',
'action' => 'index',
'club_id' => $clubs->id
));?>">
...
That way you'll have the club_id param available in index action of your ClubDescription controller. You get it like this $this->getRequest()->getParam('club_id')
An Example:
class ClubsController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$this->view->assign('title', 'Clubs');
$this->view->headTitle($this->view->title, 'PREPEND');
$clubs = new Application_Model_DbTable_Clubs();
$this->view->clubs = $clubs->fetchAll();
}
public function displayAction()
{
//get id param from index.phtml (view)
$id = $this->getRequest()->getParam('id');
//get model and query by $id
$clubs = new Application_Model_DbTable_Clubs();
$club = $clubs->getClub($id);
//assign data from model to view [EDIT](display.phtml)
$this->view->club = $club;
//[EDIT]for debugging and to check what is being returned, will output formatted text to display.phtml
Zend_debug::dump($club, 'Club Data');
}
}
[EDIT]display.phtml
<!-- This is where the variable passed in your action shows up, $this->view->club = $club in your action equates directly to $this->club in your display.phtml -->
<?php echo $this->club->dataColumn ?>
the view index.phtml
<table>
<?php foreach($this->clubs as $clubs) : ?>
<tr>
<!-- need to pass a full url /controller/action/param/, escape() removed for clarity -->
<!-- this method of passing a url is easy to understand -->
<td><a href='/index/display/id/<?php echo $clubs->id; ?>'><?php echo $clubs->club_name;?></a></td>
<td><?php echo $clubs->rating;?></td>
</tr>
<?php endforeach; ?>
an example view using the url() helper
<table>
<?php foreach($this->clubs as $clubs) : ?>
<tr>
<!-- need to pass a full url /controller/action/param/, escape() removed for clarity -->
<!-- The url helper is more correct and less likely to break as the application changes -->
<td><a href='<?php echo $this->url(array(
'controller' => 'index',
'action' => 'display',
'id' => $clubs->id
)); ?>'><?php echo $clubs->club_name;?></a></td>
<td><?php echo $clubs->rating;?></td>
</tr>
<?php endforeach; ?>
</table>
[EDIT]
With the way your current getClub() method in your model is built you may need to access the data using $club['data']. This can be corrected by removing the ->toArray() from the returned value.
If you haven't aleady done so you can activate error messages on screen by adding the following line to your .htaccess file SetEnv APPLICATION_ENV development.
Using the info you have supplied, make sure display.phtml lives at application\views\scripts\club-description\display.phtml(I'm pretty sure this is correct, ZF handles some camel case names in a funny way)
You can put the club ID into the URL that you link to as the href in the view - such as /controllername/club/12 and then fetch that information in the controller with:
$clubId = (int) $this->_getParam('club', false);
The 'false' would be a default value, if there was no parameter given. The (int) is a good practice to make sure you get a number back (or 0, if it was some other non-numeric string).

zend models for front end of website

I an using zend db table models for backend crud operations. However I think the model like this is meaningless for my front end data display like news by category , news and blog widgets and etc from various table or joining various table.
class Bugs extends Zend_Db_Table_Abstract {
protected $_name = 'bugs'; }
Model this way is perfect for my backend admin panel crud operation, How would i create model for front end operation, any example would be highly appreceated. Thanks
You can join on other tables even with a Zend_Db_Table-derived model. Just be sure to turn off integrity check.
Code (not tested) could look something like this:
class My_Model_News extends Zend_Db_Table
{
// Hate the 'tbl_' prefix. Just being explicit that this is a
// table name.
protected $_name = 'tbl_news';
public function fetchNewsByAuthor($authorId)
{
$select = $this->select();
$select->setIntegrityCheck(false)
->from(array('n' => 'tbl_news'), array('*'))
->join(array('a' => 'tbl_author'), array('n.author_id = a.id'), array('author_name' => 'a.name'))
->order('n.date_posted DESC');
return $this->fetchAll($select);
}
}
Then in your controller:
$authorId = $this->_getParam('authorId');
$newsModel = new My_Model_News();
$this->view->articles = $newsModel->fetchNewsByAuthor($authorId);
Truth be told, that's one of the things that leaves me flat about most TableGateway approaches, like Zend_Db_Table. I find that TableGateway is great for single-table queries, but I find that most of my real-life situations require multi-tables. As a result, I end up creating models that are not tied to a single table, but rather accept a Zend_Db_Adapter instance and then query/join whatever tables they need. Or, I push out to more complex ORM's, like Doctrine.
I think what you are asking about in ZF would be a View Helper, A view helper takes data from your models and allows you to dump it to the view without having to process it in the controller. Here is a simple example:
<?php
class Zend_View_Helper_Track extends Zend_View_Helper_Abstract
{
/**
*
* #param type $trackId
* #return type object
*/
public function Track($trackId) {
//this model just aggregates data from several DbTable models
$track = new Application_Model_TrackInfo();
$data = $track->getByTrackId($trackId);
return $data;
}
}
view helpers are characterized by returning some data (object, string, array, boolean) and can be used to supply data to views and partials.
The following is an example of a partial that uses several view helpers to present data in view.
<fieldset><legend>Dates and Qualifications</legend>
<table>
<tr>
<td>Birth Date: </td><td><?php echo $this->escape($this->FormatDate($this->bdate)) ?></td>
</tr>
<tr>
<td>Seniority Date: </td><td><?php echo $this->escape($this->FormatDate($this->sendate)) ?></td>
</tr>
</table>
<table>
<tr>
<td>I'm a Lead:</td><td><?php echo $this->escape(ucfirst($this->ToBool($this->lead))) ?></td>
</tr>
<tr>
<td>Lead Date:</td><td><?php echo $this->escape($this->FormatDate($this->ldate)) ?></td>
</tr>
<tr>
<td>I'm an Inspector:</td><td><?php echo $this->escape(ucfirst($this->toBool($this->inspector))) ?></td>
</tr>
<tr>
<td>Admin Login:</td><td><?php echo $this->escape(ucfirst($this->toBool($this->admin))) ?></td>
</tr>
</table>
</fieldset>
and finally I call this partial in a view with:
<?php echo $this->partial('_dates.phtml', $this->memberData) ?>
as far as DbTable models being useless for the frontend, you might be surprised. Once you have established the relationships between your tables properly in your DbTable classes the functionality of what they can do goes way up. However if you are like most people you will likely have at least one layer of domain models (mappers, service, repository) between your DbTable classes and your application.
This is a model with relationships, it's sole purpose is to supply the data to build navigation.
<?php
class Application_Model_DbTable_Menu extends Zend_Db_Table_Abstract {
protected $_name = 'menus';
protected $_dependentTables = array('Application_Model_DbTable_MenuItem');
protected $_referenceMap = array(
'Menu' => array(
'columns' => array('parent_id'),
'refTableClass' => 'Application_Model_DbTable_Menu',
'refColumns' => array('id'),
'onDelete' => self::CASCADE,
'onUpdate' => self::RESTRICT
)
);
public function createMenu($name) {
$row = $this->createRow();
$row->name = $name;
return $row->save();
}
public function getMenus() {
$select = $this->select();
$select->order('name');
$menus = $this->fetchAll($select);
if ($menus->count() > 0) {
return $menus;
} else {
return NULL;
}
}
public function updateMenu($id, $name) {
$currentMenu = $this->find($id)->current();
if ($currentMenu) {
//clear the cache entry for this menu
$cache = Zend_Registry::get('cache');
$id = 'menu_' . $id;
$cache->remove($id);
$currentMenu->name = $name;
return $currentMenu->save();
} else {
return FALSE;
}
}
public function deleteMenu($menuId) {
$row = $this->find($menuId)->current();
if ($row) {
return $row->delete();
} else {
throw new Zend_Exception("Error loading menu...");
}
}
}
Zend_Db_Table_Abstract supplies the interface for several data access patterns and you just have to supply the business logic and whatever level of abstraction you want.