https://laracasts.com/lessons/laravel-5-and-behat-driving-authentication
This is the tutorial by Jeoffery Way that I am testing
This is the scenario that I am trying to test
Scenario: Adding a new school
When I add a new school with "Narendra School" "This is a cool school"
Then I should see "Add School"
And a school is created
This is my feature context file,
/**
* #When I add a new school with :arg1 :arg2
*/
public function iAddANewSchoolWith($name , $description )
{
$this->visit('school/create');
$this->fillField( 'name', $name );
$this->fillField( 'description', $description );
$this->pressButton('register');
}
/**
* #Then a school is created
*/
public function aSchoolIsCreated()
{
$school = School::all();
PHPUnit::assertEquals($school->isEmpty(), false );
}
This is my html code
<form method="post">
<h2>Add School</h2>
<input type="hidden" name="_token" value="{!! Session::getToken() !!}"/>
<input type="text" name="name" placeholder="Name">
<textarea name="description" placeholder="Description"></textarea>
<button name="register">Register</button>
</form>
This is the controller method that i am using to create the object
function create( ) {
if ( \Request::isMethod( 'post' ) ) {
$this->school->add( \Input::all() );// I am using a repository and dependency injection so this code is fine, it will add a school
}
return view('school::school.add');
}
When I hit the url, fill the form and hit register in the browser, I save a new school but when I run the test, I cannot seem to create the school.
The test is running I can see the html when I do a printLastResponse()
Feature: Testing
In order to teach Behat
As a teacher
I want to add a new school
Scenario: Adding a new school # features\example.feature:6
When I add a new school with "Narendra School" "This is a cool school" # FeatureContext::iAddANewSchoolWith()
Then I should see "Add School" # FeatureContext::assertPageContainsText()
And a school is created # FeatureContext::aSchoolIsCreated()
Failed asserting that false matches expected true.
--- Failed scenarios:
features\example.feature:6
1 scenario (1 failed)
3 steps (2 passed, 1 failed)
0m3.10s (26.24Mb)
This is my terminal log
What am I doing wrong?
You can try replace:
$this->pressButton('register');
With something like:
$page = $this->getSession()->getPage();
$buttonElement = $page->find('css',".//button[#name='register']");
$buttonElement->click();
When you use Selenium Driver, sometimes you can find clue in Selenium Server logs or at least see an exception when something goes wrong.
Also this would be better ;-)
PHPUnit::assertNotEmpty($school->isEmpty());
Related
I am trying to fill out a field.
Why does Behat not find the field by id?
Input Field:
<input class="js-text-full text-full form-text required" data-drupal-selector="edit-field-article-nr-supplier-0-value" type="text" id="edit-field-article-nr-supplier-0-value" name="field_article_nr_supplier[0][value]" value="" size="60" maxlength="255" placeholder="" required="required" aria-required="true">
PHP Code:
public function fillField($field, $value)
{
$field = $this->fixStepArgument($field);
$value = $this->fixStepArgument($value);
$this->getSession()->getPage()->fillField($field, $value);
}
Behat:
When I fill in "edit-field-article-nr-supplier-0-value" with "12"
It says it doesn't find a field by id:
When I fill in "edit-field-article-nr-supplier-0-value" with "12" # Drupal\DrupalExtension\Context\MinkContext::fillField()
Form field with id|name|label|value|placeholder "edit-field-article-nr-supplier-0-value" not found. (Behat\Mink\Exception\ElementNotFoundException)
Mink's method fillField() uses findField() to find the field - and findField() uses name as selector and not id. That's why your initial approach didn't work. See source of Mink's class TraversableElement for details.
I found a work around. I filled out the input filed with javascript
/**
* #When I fill in :value on the field :field with javascript
*/
public function findAllInputFields($value, $field){
$javascript = "window.onload = function () {var e = document.getElementById('$field').value='$value';}";
$this->getSession()->executeScript($javascript);
}
Important, don't forget the #javascript annotation.
#javascript
Scenario: Fill out field
When I fill in 12 on the field "edit-field-article-nr-supplier-0-value" with javascript
If someone has a better solution, please share I would like to know.
I am working on a Laravel 4 project and I am trying to add a bunch of services to the services column in a simple service table. the columns are formatted as:
id userID services price
What I would like it to do is when a user selects the services all the services that user selects get's put into the services column to look like:
id userID services price
1 5 clean $4.95
2 5 unload $7.95
3 5 dance $1.95
4 5 vacuum $12.95
5 5 clean $4.95
basically all the services are in different input fields. So they aren't related.
I tried adding an array to the model but it gives an error:
Array to String conversion
Part of my Controller
$service = new Service();
$service->userID = $user->id;
$service->services = array(
Input::get('rooms'),
Input::get('pr_deodorizer'),
Input::get('pr_protectant') .
Input::get('pr_sanitzer'),
Input::get('fr_couch'),
Input::get('fr_chair'),
Input::get('fr_sectional'),
Input::get('fr_ottoman')
);
var_dump($service->services);die;
$service->save();
Laravel won't understand that you want to create various new instances of the model from just the array, so for each of the services, you'll have to create a separate instance of the Service model for each, eg.
$service = new Service();
$service->userID = $user->id;
$service->services = Input::get('rooms');
$service->save();
One idea.. perhaps you could group your services into a PHP array on your form using the square bracket notation:
<div>
<label for="room">Room</label>
<input type="text" id="room" name="services[]">
</div>
<div>
<label for="pr_deodorizer">Deodorizer</label>
<input type="text" id="pr_deodorizer" name="services[]">
</div>
<div>
<label for="pr_protectant">Protectant</label>
<input type="text" id="pr_protectant" name="services[]">
</div>
and then loop through the selected services in your Controller:
foreach(Input::get('services') as $service)
{
$service = new Service();
$service->userID = $user->id;
$service->services = $service;
$service->save();
}
... That's not tested, and I don't know what the format of your data is, but should give you a start on the problem..
Anyone know how to create a "remember me" checkbox in the joomla ADMIN login form? I am tired to "re-login" everytime that I need to change something in the backend.
I have created the checkbox, but I'm facing some issues to make it work. Thank you in advance
Am I donig something wrong? Still not working.
This is the code I added to the mod_login in default.php "\administrator\modules\mod_login\tmpl\default.php":
<!-- BEGIN - Trying to create Remember me-->
<p id="form-login-remember">
<label for="modlgn-remember"><?php echo 'Remember-me' ?> </label>
<input id="modlgn-remember" type="checkbox" name="remember" class="inputbox" value="yes"/>
</p>
<!-- END - Trying to create Remember me-->
And this is part of the controler:
/**
* Method to log in a user.
*
* #return void
*/
public function login()
{
// Check for request forgeries.
JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));
$app = JFactory::getApplication();
$model = $this->getModel('login');
$credentials = $model->getState('credentials');
$return = $model->getState('return');
$result = $app->login($credentials, array('action' => 'core.login.admin'));
if (!($result instanceof Exception)) {
$app->redirect($return);
}
parent::display();
}
You just Need to create a check box with name remember.
It will do the rest. when the admin login form submit the corresponding task is written on the
administrator/compoenets/com_login/controller.php
You can find a function with name login()
Just check that code something like this.
$options['remember'] = JRequest::getBool('remember', true);
Also make sure cookie path are correct ,If you are working with subdomain sometime path will create issue.
Hope this may help you..
You can try This plugin to keep alive the session, but is limited too.
Making a simple component. If I save a new record with the box checked, it saves fine. If I go back and uncheck a previously checked item it reverts back to checked. I thought it had something to do with a hidden field, played with putting one of those in manually but that didn't fix it either so took it out.
Here's where I'm at:
An xml snippet:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="1"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="1"
filter="intval"
/>
...
</fieldset>
The edit.php file:
<div class="width-45 fltlft">
<fieldset class="adminform">
<legend>Checkboxes</legend>
<ul class="adminformlist">
<?php foreach ($this->form->getFieldset('checks') as $field): ?>
<li>
<?php echo $field->label; ?>
<?php echo $field->input; ?>
</li>
<?php endforeach ?>
</ul>
</fieldset>
</div>
Also added this towards the end before the form.token:
<input type="hidden" name="task" id="task" value="completion.edit" />
I tried deleting the value="1" in the xml but then I had the opposite problem where the check wouldn't save at all.
Any ideas?
Thanks!
=============================
Edit:
Model:
<?php
defined( '_JEXEC' ) or die;
jimport('joomla.application.component.modeladmin');
class AssessModelCompletion extends JModelAdmin
{
//tells it what kind of record and the prefix
public function getTable($type = 'Completion', $prefix = 'AssessTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
//Load the data into the edit form
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_assess.edit.completion.data', array()); //first try to get the data from the session, not db
if (empty($data)) {
$data = $this->getItem(); //this gets the data
}
return $data;
}
//Stores data in a session in case a field is missed
public function getForm($data = array(), $loadData = true)
{
$form = $this->loadForm('com_assess.completion', 'completion', array('control' => 'jform', 'load_data' => $loadData));
return $form;
}
}
And table:
<?php
defined ( '_JEXEC' ) or die;
class AssessTableCompletion extends JTable
{
public function __construct(&$db)
{
parent::__construct('#__tablename_completions', 'completion_id', $db);
}
}
======================================
References:
https://stackoverflow.com/questions/6964333/joomla-1-6-admin-form-processing-grouped-checkboxes-in-form
Tutorial code is not working any more in Joomla 2.5
http://docs.joomla.org/Developing_a_Model-View-Controller_%28MVC%29_Component_for_Joomla!1.7_-_Part_09#Adding_a_toolbar
So this is a kind of odd situation in that the documentation you list makes it seem that you would have to write no code to handle the checkbox (because as you point out a checkbox is different then checkboxes). But this does not seem to be the case because of the way that html checkboxes are submitted.
A quick overview of this issue and one solution can be found here: http://planetozh.com/blog/2008/09/posting-unchecked-checkboxes-in-html-forms/.
To use this, you would need to get the field's name out of the $field variable (which I'm not sure if it will be easy to access) and then place the <input type=hidden name='name' value=0> before <?php echo $field->input; ?>.
The other method to fix this would be to process the form data during save and override elements. Joomla has a prepareTable function that you could add to your model to edit data as necessary during save. The following example assumes that your form elements are wrapped in a jform array. (Confirm this by looking at the name fields in the html generated and they should be 'jform[checkbox1]')
protected function prepareTable(&$table)
{
$jform = JRequest::getVar('jform'); // load all submitted data
if (!isset($jform['checkbox1'])) { // see if the checkbox has been submitted
$table->checkbox1 = 0; // if it has not been submitted, mark the field unchecked
}
if (!isset($jform['checkbox2'])) { // likewise for other checkboxes
$table->checkbox2 = 0;
}
}
In this case, you would want to keep "value=1" in your xml fields file.
The problem ultimately is that Joomla loads the current data from the database during saving and then binds the posted data over the top of it. Because an unchecked box is not submitted in the post data, it does not overwrite the databases information and is thus not saved.
Although the documentation states that you do not have to do any manual handeling of the checkbox this is not true.
As no value is sent in the $_POST array when a checkbox is not checked the value is not overwritten and thus not saved which makes it impossible to uncheck the checkbox. To fix this you have to write special handling for your checkboxes in your table bind() function like this:
class YourcomponentTableYourview extends JTable
{
/**
* Constructor
*
* #param JDatabase A database connector object
*/
public function __construct(&$db)
{
parent::__construct('#__your_table_name', 'id', $db);
}
public function bind($array, $ignore = '')
{
if (!isset($array['name_of_field']))
$array['name_of_field'] = 0 ;
return parent::bind($array, $ignore);
}
}
As you don't have any model/table code showing, I think you may be mistaking JForm's purpose - it is purely for rendering of the form. You still have to have in your model/table something to handle the array that is returned for multivalued fields.
As Sam Moffat put it:
there is no coupling between the form definitions used to render the data and the models and table structures used to persist them
So I had a lot of fields and wanted to simply loop through them in my edit.php field to keep it clean. While all the answers offered were right they weren't easy to implement - got really messy really quickly, had trouble getting it to work, or couldn't figure out a cleaner way around it. I chewed on this for awhile and then today came across what is basically a field override.
The key:
The standard form field types are located in
joomla/libraries/joomla/form/fields/. You should not store custom
fields there, nor should you have to use this path in your own code,
but the standard types are usually good examples.
The custom field types that belong to your component are usually
located in administrator/components//models/fields. You can specify this or another path in your
code
So, I copied checkbox.php to models/fields. Then, towards the end of the file I added the empty field before the checkbox tag:
<input type="hidden" name="'.$this->name.'" id="'.$this->id.'" value="0" /><input type="checkbox" .....
Now, whenever I need a checkbox the empty field is also written. May not be the most efficient solution but simple to implement and can hopefully help someone else.
[Edit]
As a note, with every Joomla update you would probably need to compare the versions in the core in case there was a change.
I know this is an old question, but the official answer is long winded and I think I have a better solution.
Try setting the default value for the checkbox to 0 rather than 1 in your xml like so:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="0"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="0"
filter="intval"
/>
...
</fieldset>
I just came across your question and tried setting it to 0 as I didn't want to tamper with the core and hey presto it works.
My guess is that Joomla sees no value and thus sets the default instead.
I am using Zend Framework I have a form that allows me to create a user. It has all of the necessary validation and it works well.
I was tasked with creating a single page that allows me to create up to 25 new users with a single submit.
example:
salutation / first name / last name / email
salutation / first name / last name / email
salutation / first name / last name / email
salutation / first name / last name / email
How can I leverage the form I created for a single user and allow for each new user to get validated separately?
Is there some way to have an array of forms or something else that will achieve the same thing?
Try something like this (untested):
class BulkUserForm extends Zend_Form
{
private $_howMany = 1;
public function __construct( $howMany, $options )
{
$this->_howMany = (int) $howMany;
parent::__construct( $options );
}
public function init()
{
for( $i = 1; $i <= $this->_howMany; $i++ )
{
$userForm = new YourOriginalUserForm();
$userForm->setElementsBelongTo( 'user' . $i ); // not sure this is actually necessary anymore, because of the second param to addSubForm
$this->addSubForm( $userForm, 'user' . $i, $i );
}
}
}
Usage:
$form = new BulkUserForm( 25 /* [, $options ] */ );
echo $form;
// validation:
$form->isValid( $this->getRequest()->getPost() ); // or something similar
Explanation:
The setElementsBelongTo() call on subforms should create notations similar to this (simplified of course):
<input type="radio" name="user1[salutation]">
<input type="text" name="user1[firstName]">
<input type="text" name="user1[lastName]">
<input type="text" name="user1[email]">
You form should be able to automatically recognize the submitted POST values when validating.
Of course you should probably also look into the laying out / decorating of the sub forms, but I'll leave that up to you as an exercise. ;-)
EDIT
Sorry, the second param to addSubForm() is mandatory (added it now, and also added the optional $order param). I believe it should also automatically set the sub form to belong to the correct namespace already. Not completely sure about that though. See what happens if you leave out the setElementsBelongTo() call on the sub form.