hjortur17's avatar

Help with test

Hi, I can't get this to work.

/** @test */
    public function a_user_can_filter_threads_by_popularity()
    {
        $threadWithTwoReplies = create('App\Thread');
        create('App\Reply', ['thread_id' => $threadWithTwoReplies->id], 2);
        
        $threadWithThreeReplies = create('App\Thread');
        create('App\Reply', ['thread_id' => $threadWithThreeReplies->id], 3);
        
        $threadWithNoReplies = $this->thread;
        
        $response = $this->getJson('fréttir?vinsælt=1')->json();
        
        $this->assertEquals([3, 2, 0], array_column($response['data'], 'replies_count'));
    }

This is what the terminal says:

➜  project git:(master) ✗ pf ReadThreadsTest
PHPUnit 7.5.11 by Sebastian Bergmann and contributors.

...F..                                                              6 / 6 (100%)

Time: 424 ms, Memory: 28.00 MB

There was 1 failure:

1) Tests\Feature\ReadThreadsTest::a_user_can_filter_threads_by_popularity
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => 3
-    1 => 2
-    2 => 0
+    0 => '0'
+    1 => '2'
+    2 => '3'
 )

/Users/hjorturfreyrlarusson/websites/project/tests/Feature/ReadThreadsTest.php:63
/Users/hjorturfreyrlarusson/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:208
/Users/hjorturfreyrlarusson/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:164

FAILURES!
Tests: 6, Assertions: 10, Failures: 1.
0 likes
5 replies
wyatt44's avatar

Can you post your migrations, and models? It looks like when you retrieve 'replies_count' it is currently returning as a string. You can potentially add a protected $casts array to your model and force the field to return as an integer.

Hope this helps!

hjortur17's avatar

Here is my migration

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateThreadsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('threads', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('slug')->unique()->nullable();
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('channel_id');
            $table->unsignedInteger('replies_count')->default(0);
            $table->unsignedInteger('visits')->default(0);
            $table->string('title');
            $table->text('body');
            $table->boolean('locked')->default(false);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('threads');
    }
}

And here is my model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

use App\Filters\ThreadFilters;
use App\Notifications\ThreadWasUpdated;
use App\Events\ThreadReceviedNewReply;

class Thread extends Model
{
    use RecordsActivity;

    protected $guarded = [];

    protected $with = ['creator', 'channel'];

    protected $appends = ['isSubscribedTo'];

    protected $casts = [
        'locked' => 'boolean'
    ];

    protected static function boot() {
        parent::boot();

        static::addGlobalScope('replyCount', function ($builder) {
            $builder->withCount('replies');
        });

        static::deleting(function ($thread) {
            $thread->replies->each->delete();
        });

        static::created(function ($thread) {
            $thread->update(['slug' => $thread->title]);
        });
    }

    public function path()
    {
        return "/fréttir/{$this->channel->slug}/{$this->slug}";
    }

    public function creator()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function replies()
    {
        return $this->hasMany(Reply::class);
    }

    public function addReply($reply)
    {
        $reply = $this->replies()->create($reply);

        event(new ThreadReceviedNewReply($reply));
        
        return $reply;
    }

    public function channel()
    {
        return $this->belongsTo(Channel::class);
    }

    public function scopeFilter($query, ThreadFilters $filters)
    {
        return $filters->apply($query);
    }

    public function subscribe($userId = null)
    {
        $this->subscriptions()->create([
            'user_id' => $userId ?: auth()->id()
        ]);
        
        return $this;
    }

    public function unsubscribe($userId = null)
    {
        $this->subscriptions()
            ->where('user_id', $userId ?: auth()->id())
            ->delete();
    }

    public function subscriptions()
    {
        return $this->hasMany(ThreadSubscription::class);
    }

    public function getIsSubscribedToAttribute()
    {
        return $this->subscriptions()
            ->where('user_id', auth()->id())
            ->exists();
    }

    public function hasUpdatedFor($user = null)
    {
        $key = $user->visitedThreadCacheKey($this);
        
        return $this->updated_at > cache($key);
    }

    public function getRouteKeyName()
    {
        return 'slug';
    }

    public function setSlugAttribute($value)
    {
        $slug = str_slug($value);
        $original = $slug;
        $count = 2;

        while (static::whereSlug($slug)->exists()) {
            $slug = "{$original}-" . $count++;
        }

        $this->attributes['slug'] = $slug;
    }

    public function getBodyAttribute($body)
    {
        return \Purify::clean($body); 
    }
}

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

use Carbon\Carbon;

class Reply extends Model
{
    use Favoritable, RecordsActivity;

    protected $guarded = [];

    protected $with = ['owner', 'favorites'];

    protected $appends = ['favoritesCount', 'isFavorited'];
    
    public function owner()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function thread()
    {
        return $this->belongsTo(Thread::class);
    }

    public function wasJustPublished()
    {
        return $this->created_at->gt(Carbon::now()->subMinute());
    }

    public function mentionedUsers()
    {
        preg_match_all("/@([\w\-]+)/", $this->body, $matches);

        return $matches[1];
    }

    public function path()
    {
        return $this->thread->path() . "#athugarsemd-{$this->id}";
    }

    public function setBodyAttribute($body)
    {
        $this->attributes['body'] = preg_replace('/@([\w\-]+)/', '<a href="/notendur/">LARACASTS_SNIPPET_PLACEHOLDER</a>', $body);
    }
    
    public function getBodyAttribute($body)
    {
        return \Purify::clean($body); 
    }
}

hjortur17's avatar

@KEVINBUI - Here you go,

public function index(Channel $channel, ThreadFilters $filters, Trending $trending)
    {
        $threads = $this->getThreads($channel, $filters);

        if (request()->wantsJson()) {
            return $threads;
        }

        return view('threads.index', [
            'threads' => $threads,
            'trending' => $trending->get()
        ]);
    }
protected function getThreads(Channel $channel, ThreadFilters $filters)
    {
        $threads = Thread::latest()->filter($filters);
        
        if ($channel->exists) {
            $threads->where('channel_id', $channel->id);
        }
    
        return $threads->paginate(35);
    }
<?php

namespace App\Filters;

use App\User;

class ThreadFilters extends Filters
{
    protected $filters = [
        'nýjast',
        'vinsælt',
        'flestUmmæli'
    ];

    protected function nýjast()
    {
        $this->builder->getQuery()->orders = [];
        
        return $this->builder->orderBy('created_at', 'desc');
    }

    protected function vinsælt()
    {
        $this->builder->getQuery()->orders = [];
        
        return $this->builder->orderBy('visits', 'desc');
    }

    protected function flestUmmæli()
    {
        $this->builder->getQuery()->orders = [];
        
        return $this->builder->orderBy('replies_count', 'desc');
    }
}

Please or to participate in this conversation.