Laravel 5.1 PhpUnit Delete method not working - unit-testing

I am writing a simple test to create an element, see if it is there and then delete it to verify the integrity of my web app every time I build it.
I have a test:
$this->visit('admin/menu/samples')
->seePageIs('admin/menu/samples')
->click('New Sample')
->seePageIs('admin/menu/samples/new/create')
->type('test1', 'name')
->type('test2','description')
->type('test2','introduction')
->select(1, 'scenario_id')
->type('test','slug')
->press('Add')
->seePageIs('admin/menu/samples')
->delete('admin/menu/samples/'. \App\Sample::whereSlug('test')->first()->id )
->visit('admin/menu/samples')
->dontSee('test1');
it creates the Sample element fine, but as I have several Delete buttons ( for every Sample element in index, as they are in a list) I can't use the method click/press('Delete'). So I thought I'd just use the delete method, which I have already set up. The problem is that it will not delete the element that I have created. The delete request will not work.
I assure you that the route is there and the if I just press the Delete button my Sample element will be deleted.
Why can't I mimic this with PHPUnit, is there another way to delete?

I just had this same exact issue. Turns out its the CSRF token issue. Anytime you do a request other than the "GET" request, you will need to verify your CSRF token. Now Laravel does a good job already doing this when you are on the website itself, which is why submitting forms via "press" will work: http://laravel.com/docs/5.1/routing#csrf-protection. In my specific case, it seems my token is generated via an XSRF-Token cookie, which can be done via a simple check of the Request Headers.
However, if you use the url, you will need to generate a CSRF token manually. To do this, simply call csrf_token() and inject it into your call:
$this->visit('admin/menu/samples')
...
->delete('admin/menu/samples/'. \App\Sample::whereSlug('test')->first()->id,
['_token'=>csrf_token()],[] )
...;
Here was the article that helped me figure out how to inject the token, though dont confuse the method signatures of $this->call and $this->delete:
http://davejustdave.com/2015/02/08/laravel-5-unit-testing-with-csrf-protection/

Related

#mswjs/data question: why does RTK-Query sandbox example need separately handcoded POST and PUT mocks?

This is a question about the default behaviour of #mswjs/data.toHandlers function using this example with #mswjs/data to create mocks for RTK-Query calls.
https://codesandbox.io/s/github/reduxjs/redux-toolkit/tree/master/examples/query/react/mutations?from-embed
the file src/mocks/db.ts creates a mock database using #mswjs/data and defines default http mock responses using ...db.post.toHandlers('rest') but fails to work if I remove the additional PUT and POST mocks.
My understanding is that #mswjs/data toHandlers() function provides PUT and POST mock API calls for a defined database (in this case Posts) by default according to the github documentation so I am seeking advice to understand better why toHandlers does not work for PUT and POST in this example. i.e. if i remove PUT and POST mock API calls they fail.
What do the manual PUT and POST API mocks do that the default toHandlers dont?
You are correct to state that .toHandlers() generates both POST /posts and PUT /posts/:id request handlers. The RTK-Query example adds those handlers explicitly for the following reasons:
To emulate flaky error behavior by returning an error response based on the Math.random() value in the handler.
To set the id primary key to nanoid().
Adding a post fails if you remove the explicit POST /posts handler because the model definition for post does not define the initial value for the id primary key. You cannot create an entity without providing a primary key to it, which the example does not:
// PostManager.tsx
// The "post" state only contains the name of the new post.
const [post, setPost] = useState<Pick<Post, "name">>(initialValue);
// Only the "post" state is passed to the code that dispatches the
// "POST /posts" request handled by MSW.
await addPost(post).unwrap();
If we omit the random error behavior, I think the example should've used nanoid as the initial value of the id property in the model description:
import { nanoid } from "#reduxjs/toolkit";
const db = factory({
post: {
- id: primaryKey(String),
+ id: primaryKey(nanoid),
name: String
}
});
This way you would be able to create new posts by supplying the name only. The value of the id primary key would be generated using the value getter—the nanoid function.
The post edit operation functions correctly even if you remove the explicit PUT /posts/:id request handler because, unlike the POST handler, the PUT one is only there to implement a flaky error behavior (the edited post id is provided in the path parameters: req.params.id).

Django 1.11's signed_cookie session backend sets a new sessionid for every request

This makes the vary_on_cookie decorator useless because the coookie is different at every request, and also it makes the sessions never expire regardless of SESSION_COOKIE_AGE because every request pushes the expiration forward.
I did some digging, and process_response in sessions/backends/middleware.py does request.session.save(), which causes the signed_cookie backend to create a new session key with this code:
return signing.dumps(
self._session, compress=True,
salt='django.contrib.sessions.backends.signed_cookies',
serializer=self.serializer,
)
This code returns a different value even if called with the same argument (I guess it's built into the encryption).
Am I missing something? This doesn't sound right... any ideas?
Thanks!
Figured it out: one of my middlewares was modifying the session in process_request, which caused the session object to be modified, and therefore the chain of events explained in the question happened.

How to render a Django template with a transient variable?

I have an application that enforces a strict page sequence. If the user clicks the Back button, the application detects an out-of-order page access and sends the user back to the start.
I'd like to make this a bit more friendly, by redirecting the user back to the correct page and displaying a pop-up javascript alert box telling them not to use the Back button.
I'm already using a function that does a lot of validity checking which returns None if the request is okay, or an HttpResponseRedirect to another page (generally the error page or login page) if the request is invalid. All of my views have this code at the top:
response = validate(request)
if response:
return response
So, since I have this validate() function already, it seems like a good place to add this extra code for detecting out-of-order access.
However, since the out-of-order detection flag has to survive across a redirect, I can't just set a view variable; I have to set the flag in the session data. But of course I don't want the flag to be set in the session data permanently; I want to remove the flag from the session data after processing the template.
I could add code like this to all of my render calls:
back_button = request.session.get('back_button', False)
response = render(request, 'foo.html', { 'back_button': back_button } )
if back_button:
del request.session['back_button']
return response
But this seems a bit messy. Is there some way to automatically remove the session key after processing the template? Perhaps a piece of middleware?
I'm using function-based views, not class-based, btw.
The session object uses the dictionary interface, so you can use pop instead of get to retrieve and delete the key at the same time:
back_button = request.session.pop('back_button', False)

OTRS Webservice as Requestor Test

I'm new to OTRS (3.2) and also new to PERL but I have been given the task of setting up OTRS so that it will make a call to our remote webservice so a record can be created on our end when a ticket is set as "Closed".
I set up various dynamic fields so the customer service rep can fill in additional data that will be passed into the webservice call along with ticket details.
I couldn't get the webservice call to trigger when the ticket was "Closed" but I did get it to trigger when the "priority" was changed so I'm just using that now to test the webservice.
I'm just using the Test.pm and TestSimple.pm files that were included with OTRS.
When I look at the Debugger for the Webserice, I can see that the calls were being made:
$VAR1 = {
'TicketID' => '6'
};
My webservice currently just has one method "create" which just returns true for testing.
however I get the following from the Test.pm
"Got no TicketNumber (2014-09-02 09:20:42, error)"
and the following from the TestSimple.pm
"Error in SOAP call: 404 Not Found at /TARGET/SHARE/var/otrs/Kernel/GenericInterface/Transport/HTTP/SOAP.pm line 578 (2014-09-02 09:20:43, error)
I've spent countless hours on Google but couldn't find anything on this. All I could find is code for the Test.pm and TestSimple.pm but nothing really helpful to help me create a custom invoker for my needs and configure the webservice in OTRS to get it to work.
Does anyone have any sample invokers that I can look at to see how to set it up?
Basically I need to pass the ticket information along with my custom dynamic fields to my webservice. From there I can create the record on my end and do whatever processing.
I'm not sure how to setup the Invoker to pass the necessary ticket fields and dynamic fields and how to make it call a specific method in my remote webservice.
I guess getting the Test.pm and TestSimple.pm to work is the first step then I can modify those for my needs. I have not used PERL at all so any help is greatly appreciated.
I'm also struggling with similar set of requirements too. I've also never programmed in PERL, but I can tell you at least that the "Got no TicketNumber" in the Test.pm is right from the PrepareRequest method, there you can see this block of code:
# we need a TicketNumber
if ( !IsStringWithData( $Param{Data}->{TicketNumber} ) ) {
return $Self->{DebuggerObject}->Error( Summary => 'Got no TicketNumber' );
}
You should change all references to TicketNumber to TicketID, or remove the validation whatsoever (also there is mapping to ReturnedData variable).
Invoking specific methods on your WS interface is quite simple (but poorly documented). The Invoker name that you specify in the "OTRS as requester" section of web service configuration corresponds to the WS method that will be called. So if you have WS interface with a method called "create" just name the Invoker "create" too.
As far as the gathering of dynamic field goes, can't help you on that one yet, sorry.
Cheers

Getting "Error: Assertion Failed: calling set on destroyed object" when trying to rollback a deletion

I am looking into how to show proper deletion error message in ember when there is an error coming back from the server. I looked at this topic and followed its suggestion:
Ember Data delete fails, how to rollback
My code is just like it, I return a 400 and my catch fires and logs, but nothing happens, when I pause it in the debugger though and try to rollback, I get Error: Assertion Failed: calling set on destroyed object
So A) I cannot rollback B) the error is eaten normally.
Here is my code
visitor.destroyRecord().then(function() {
console.log('SUCCESS');
}).catch(function(response) {
console.log('failed to remove', response);
visitor.rollback();
});
In case it's relevant, my model does have multiple relationships. What am I doing wrong? Ember-data version is 1.0.0.8 beta (previous one from the release a few days ago).
Thanks in advance.
EDIT
I discovered now that the record actually is restored currently inside the cache according to ember inspector, but the object will not reappear in the rendering of the visitors. I need some way to force it to reload into the template...
After destroyRecord, the record is gone and the deletion cannot be rolled back. The catch clause will just catch a server error. If you want the record back, and think it's still on the server, you'll have to reload it.
See the following comment on deleteRecord from the Ember Data source:
Marks the record as deleted but does not save it. You must call
`save` afterwards if you want to persist it. You might use this
method if you want to allow the user to still `rollback()` a
delete after it was made.
This implies that a rollback after save is not possible. There is also no sign anywhere I can see in the Ember Data code for somehow reverting a record deletion when the DELETE request fails.
In theory you might be able to muck with the isDeleted flag, or override various internal hooks, but I'd recommend against that unless you really know how things work.
Try reloading the model after the rollback. It will reload from the server but it was the only way around this that I could find.
visitor.destroyRecord().then(function() {
console.log('SUCCESS');
}).catch(function(response) {
console.log('failed to remove', response);
visitor.rollback();
visitor.reload().then(function(vis)
{
console.log('visitor.reload :: ' + JSON.stringify(vis));
});
});
Hope that helps.