Make a test to the route that uses it and assert it has the excepted data returned to the view
How to test filter query
Hello,
How can I test unit filter query?
To make this a little bit simpler to unit test, I add another parameter to the query scope:
public function scopeFilter($query, $search = null)
{
if ($search) {
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper($search) . '%']);
}
return $query;
}
Just to elaborate on @sinnbeck answer, you can write a simple test case like this for the scope.
public function test_filter_scope()
{
$first = CountryStatistics::factory()->create(['name' => 'England']);
$second = CountryStatistics::factory()->create(['name' => 'United States']);
$results = CountryStatistics::filter('United')->get();
$this->assertFalse($results->contains($first));
$this->assertTrue($results->contains($second));
}
@kevinbui you accidentally used the request.
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper($search)) . '%']);
I tried this:
public function test_filter_scope()
{
$first = CountryStatistics::factory()->create(['name' => 'England']);
$second = CountryStatistics::factory()->create(['name' => 'United States']);
$results = CountryStatistics::filter('United')->get();
$this->assertFalse($results->contains($first));
$this->assertTrue($results->contains($second));
}
I am getting error, when using dd($result->contains($first)) or contains($second) I'm getting true on both of them.
So error is : • Tests\Feature\ProjectsTest > filter scope Failed asserting that true is false.
Fixed the error, test works fine and coverage became 100% but now I cant filter on localhost. Would it be okay if I use 2 functions inside this model? One for test and one for actual search:
public function scopeFilter($query, $search = null)
{
if (request('search'))
{
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper(request('search')) . '%']);
}
if ($search)
{
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper($search) . '%']);
}
return $query;
}
@temo then you completely remove the idea of the test. Fix your code instead. Show how you are using it in the actual code and I can help
And what if you ever need the scope in a command or job? Those don't have any request so it will never work
It should be something like
->filter(request('search'))->get()
Sorry for stupid question, by using two functions I can't get coverage of 100%. So problem is that with
if (request('search'))
{
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper(request('search')) . '%']);
}
Filter works in project, and with :
if ($search)
{
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper($search) . '%']);
}
return $query;
Test is successful. How can I use the second one so that it works in project too?
So here's my Model filter:
public function scopeFilter($query, $search = null)
{
if ($search)
{
$query->whereRaw('UPPER(name) LIKE ?', ['%' . strtoupper($search) . '%']);
}
return $query;
}
As I mentioned above it gives 100% coverage but doesnt work in project.
There is search form:
<div class="mt-2 md:mt-10">
<section class="flex md:border h-[45px] md:w-[270px] p-1 rounded-lg md:border-2">
<form method="GET" action="#" class="flex">
<button type="submit">
<img
src="{{url('/images/search.png')}}"
alt="not found"
class="md:ml-2"/>
</button>
<input class="w-[200px] ml-3 placeholder:font-medium focus:outline-none"
type="text"
name="search"
placeholder="{{__('texts.search_by_country')}}"
value="{{ request('search') }}">
</form>
</section>
<x-table/>
</div>
@temo coverage cannot be 100 when you are not actually testing your code. See my last answer :)
@temo show the code that uses the filter scope
public $sortField;
public $sortAsc = true;
public function sortBy($field)
{
if ($this->sortField === $field)
{
$this->sortAsc = !$this->sortAsc;
}
else
{
$this->sortAsc = true;
}
$this->sortField = $field;
}
public function render()
{
return view('livewire.countries-table', [
'country_statistics' => CountryStatistics::filter()
->orderBy(isset($this->sortField) ? $this->sortField : 'created_at', $this->sortAsc ? 'asc' : 'desc')
->get(),
]);
}
@temo like this
CountryStatistics::filter(request('search'))
'country_statistics' => CountryStatistics::filter(request('search'))
->orderBy(isset($this->sortField) ? $this->sortField : 'created_at', $this->sortAsc ? 'asc' : 'desc')
->get(),
Like this?
@temo exactly. Now you are passing the search into the method
@Sinnbeck That woks! thanks!
@temo awesome :)
Maybe you can help me with this too? :D
public function store(LoginRequest $request)
{
$validated = $request->validated();
if (auth()->attempt($validated))
{
session()->regenerate(); -- this
$user = Auth::getProvider()->retrieveByCredentials($validated);
Auth::login($user, $request->get('remember'));
return redirect(route('worldwide.statistics'))->with('success', 'Welcome back!'); --this
}
How to test this two iines ? I got 55% coverage but need to hit 100% ;D
@temo please make a seperate thread and I will do my best to help
@Sinnbeck Thanks, I have updated my answer.
Please or to participate in this conversation.