Skip to content
This repository has been archived by the owner on Jul 8, 2019. It is now read-only.

Commit

Permalink
Add Eventim and agent setup with tests
Browse files Browse the repository at this point in the history
#12 Add Eventim and agent setup with tests
  • Loading branch information
mattias-persson committed May 30, 2018
1 parent 42a6900 commit 2a3694c
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 24 deletions.
62 changes: 50 additions & 12 deletions app/Agents/BaseAgent.php → app/Agents/Agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace App\Agents;

use ReflectionClass;
use App\Contracts\AgentContract;

class BaseAgent
class Agent implements AgentContract
{
/**
* The name of the agent.
Expand Down Expand Up @@ -77,17 +78,6 @@ public function trackback() : string
return $this->config('trackback');
}

/**
* Cleans up after each sync if necessary. Sometimes we have to store temp files while parsing the
* data, this method cleans it all up afterwards.
*
* @return void
*/
public function cleanup() : void
{
//
}

/**
* Returns the selected configuration value for the agent.
*
Expand All @@ -110,4 +100,52 @@ public function buildEventFilename($eventName, $url)
{
return str_slug($eventName) . '.' . pathinfo($url, PATHINFO_EXTENSION);
}

/**
* {@inheritdoc}
*/
public function gatherEvents() : array
{
return [];
}

/**
* {@inheritdoc}
*/
public function mapEvent($event) : array
{
return [];
}

/**
* {@inheritdoc}
*/
public function mapVenue($event) : array
{
return [];
}

/**
* {@inheritdoc}
*/
public function mapPrices($event): array
{
return [];
}

/**
* {@inheritdoc}
*/
public function downloadAndMapImage($event): array
{
return [];
}

/**
* {@inheritdoc}
*/
public function cleanup() : void
{
//
}
}
3 changes: 1 addition & 2 deletions app/Agents/Eventim.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

namespace App\Agents;

use App\Contracts\Agent;
use GuzzleHttp\Client;
use \File;
use ZipArchive;
use SimpleXMLElement;
use Illuminate\Support\Facades\Storage;

class Eventim extends BaseAgent implements Agent
class Eventim extends Agent
{
/**
* {@inheritdoc}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace App\Contracts;

interface Agent
interface AgentContract
{
/**
* Retrieves the events from the server and parse them into a single leveled array.
Expand Down
6 changes: 3 additions & 3 deletions app/Jobs/StoreEvents.php → app/Jobs/DownloadEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Models\Event;
use App\Contracts\Agent;
use App\Contracts\AgentContract;
use App\Models\Venue;

class StoreEvents implements ShouldQueue
class DownloadEvents implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

Expand All @@ -22,7 +22,7 @@ class StoreEvents implements ShouldQueue
*
* @return void
*/
public function __construct(Agent $agent)
public function __construct(AgentContract $agent)
{
$this->agent = $agent;
}
Expand Down
4 changes: 2 additions & 2 deletions app/Models/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Event extends Model
/**
* Makes the agent available on the event object.
*
* @return App\Contracts\Agent
* @return App\Contracts\AgentContract
*/
public function getAgentAttribute()
{
Expand All @@ -42,7 +42,7 @@ public function getAgentAttribute()
/**
* Returns an instance of the ticket agent for the event.
*
* @return App\Contracts\Agent
* @return App\Contracts\AgentContract
*/
public function agent()
{
Expand Down
2 changes: 1 addition & 1 deletion database/factories/EventFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
'venue_id' => function () {
return factory(Venue::class)->create()->id;
},
'agent_class' => 'App\Agents\BaseAgent',
'agent_class' => 'App\Agents\Agent',
'agent_event_id' => uniqid(),
'title' => $faker->sentence,
'description' => $faker->paragraph,
Expand Down
5 changes: 5 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<testsuite name="Integration">
<directory suffix="Integration.php">./tests</directory>
</testsuite>

<testsuite name="All">
<directory suffix="Test.php">./tests</directory>
<directory suffix="Integration.php">./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
Expand Down
6 changes: 3 additions & 3 deletions tests/Agents/EventAgentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class EventAgentTest extends TestCase
/** @test */
public function the_agent_is_available_on_the_event()
{
$event = factory(Event::class)->create(['agent_class' => 'App\Agents\BaseAgent']);
$event = factory(Event::class)->create(['agent_class' => 'App\Agents\Agent']);

$this->assertNotNull($event->agent);
$this->assertEquals('BaseAgent', $event->agent->name);
$this->assertEquals('Agent', $event->agent->name);
$this->assertEquals('', $event->agent->website);
$this->assertEquals('baseagent', $event->agent->identifier);
$this->assertEquals('agent', $event->agent->identifier);
$this->assertEquals('', $event->agent->trackback());
}
}
104 changes: 104 additions & 0 deletions tests/Feature/DownloadEventsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Models\Event;
use Mockery;
use App\Agents\Agent;
use App\Jobs\DownloadEvents;
use App\Models\Venue;

class DownloadEventsTest extends TestCase
{
use RefreshDatabase;

/** @test */
public function it_stores_the_events_properly()
{
$events = factory(Event::class, 2)->make();
$agent = Mockery::mock(Agent::class);

// The correct method chain is being run. Yes, it's an implementation detail but
// it assures that any implementation of an agent will be correctly run.
$this->assertRunsCorrectMethods($agent, $events);

$this->assertEquals(0, Event::count());
(new DownloadEvents($agent))->handle();

// The events were properly stored.
$this->assertEquals(2, Event::count());

// Test that the various attributes are stored properly.
$firstEvent = Event::first();
$this->assertEquals(
$events->first()->only('title', 'description', 'url', 'agent_event_id'),
$firstEvent->only('title', 'description', 'url', 'agent_event_id')
);
$this->assertEquals($events->first()->event_starts_at->format('Y-m-d H:i:s'), $firstEvent->event_starts_at);
$this->assertEquals($events->first()->sale_starts_at->format('Y-m-d H:i:s'), $firstEvent->sale_starts_at);

$lastEvent = Event::skip(1)->first();
$this->assertEquals(
$events->last()->only('title', 'description', 'url', 'agent_event_id'),
$lastEvent->only('title', 'description', 'url', 'agent_event_id')
);
$this->assertEquals($events->last()->event_starts_at->format('Y-m-d H:i:s'), $lastEvent->event_starts_at);
$this->assertEquals($events->last()->sale_starts_at->format('Y-m-d H:i:s'), $lastEvent->sale_starts_at);
}

/** @test */
public function it_uses_existing_venue_if_match_is_found()
{
$venue = factory(Venue::class)->create();
$events = factory(Event::class, 2)->make(['venue_id' => $venue->id]);
$agent = Mockery::mock(Agent::class);

$this->assertEquals(1, Venue::count());

// The correct method chain is being run. Yes, it's an implementation detail but
// it assures that any implementation of an agent will be correctly run.
$this->assertRunsCorrectMethods($agent, $events, $venue->toArray());

(new DownloadEvents($agent))->handle();

$this->assertEquals(1, Venue::count());
}

/** @test */
public function it_creates_new_venue_if_no_match_is_found()
{
$venue = factory(Venue::class)->create();
$venueData = factory(Venue::class)->make(['title' => 'New venue']);
$events = factory(Event::class, 2)->make(['venue_id' => $venue->id]);
$agent = Mockery::mock(Agent::class);

$this->assertEquals(1, Venue::count());

// The correct method chain is being run. Yes, it's an implementation detail but
// it assures that any implementation of an agent will be correctly run.
$this->assertRunsCorrectMethods($agent, $events, $venueData->toArray());

(new DownloadEvents($agent))->handle();

$this->assertEquals(2, Venue::count());
}

/**
* This assures any agent that implements the required functionality should work.
*/
public function assertRunsCorrectMethods($agent, $events, $venue = null)
{
$venue = ($venue) ?: factory(Venue::class)->make()->toArray();

$agent->shouldReceive('gatherEvents')->once()->andReturn($events->toArray());
$agent->shouldReceive('mapEvent')->once()->andReturn($events->first()->toArray());
$agent->shouldReceive('mapEvent')->once()->andReturn($events->last()->toArray());
$agent->shouldReceive('mapPrices')->twice();
$agent->shouldReceive('downloadAndMapImage')->twice();
$agent->shouldReceive('mapVenue')->twice()->andReturn($venue);
$agent->shouldReceive('fullyQualifiedClassName')->twice()->andReturn('App\Agents\Agent');
$agent->shouldReceive('cleanup')->once();
}
}

0 comments on commit 2a3694c

Please sign in to comment.