Skip to content

Commit

Permalink
test Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
battis committed Nov 28, 2022
1 parent 4154e4b commit b72898d
Show file tree
Hide file tree
Showing 21 changed files with 284 additions and 76 deletions.
27 changes: 14 additions & 13 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
{
"name": "battis/user-session",
"description": "User session management for Slim Framework",
"license": "MIT",
"autoload": {
"psr-4": {
"Battis\\UserSession\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Battis\\UserSession\\Tests\\": "tests"
}
},
"authors": [
{
"name": "Seth Battis",
"email": "seth@battis.net"
}
],
"license": "MIT",
"require": {
"bryanjhv/slim-session": "^4.0",
"slim/http": "^1.2",
"slim/php-view": "^3.0",
"slim/psr7": "^1.0"
},
"config": {
"sort-packages": true
"autoload": {
"psr-4": {
"Battis\\UserSession\\": "src"
}
},
"require-dev": {
"battis/data-utilities": "^1.1",
"ext-simplexml": "*",
"php-di/php-di": "^6.4",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.0"
},
"autoload-dev": {
"psr-4": {
"Battis\\UserSession\\Tests\\": "tests"
}
},
"config": {
"sort-packages": true
}
}
8 changes: 7 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="tests/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
Expand All @@ -10,4 +10,10 @@
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<ini name="session.use_cookies" value="0" />
<ini name="session.use_only_cookies" value="0" />
<ini name="session.use_trans_sid" value="0" />
<ini name="session.cache_limiter" value="" />
</php>
</phpunit>
2 changes: 2 additions & 0 deletions src/Actions/HandleLogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public function __invoke(ServerRequest $request, Response $response)
return $this->renderer->render($response, "login.php", [
"message" => "bad credentials",
"message_type" => "error",
"usernameFieldName" => $this->usernameFieldName,
"passwordFieldName" => $this->passwordFieldName
]);
}
}
15 changes: 10 additions & 5 deletions src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@

class Manager
{
public const DEFAULT_LOGIN_PATH = '/auth/login';
public const DEFAULT_REDIRECT = '/';

private const HEADER_LOCATION = 'Location';

private const USER = "battis.userSession.manager.user";
private const REDIRECT = "battis.userSession.manager.redirect";

Expand All @@ -19,8 +24,8 @@ class Manager

public function __construct(
Session $session,
string $loginPath = "/auth/login",
string $defaultRedirect = "/"
string $loginPath = self::DEFAULT_LOGIN_PATH,
string $defaultRedirect = self::DEFAULT_REDIRECT
) {
$this->session = $session;
$this->loginPath = $loginPath;
Expand All @@ -31,7 +36,7 @@ public function startUserLogin(RequestInterface $request): ResponseInterface
{
$this->session->set(self::REDIRECT, $request->getUri()->getPath());
$response = new Response();
return $response->withHeader("Location", $this->loginPath)->withStatus(302); // using status 302 forces the redirect to use the GET method
return $response->withHeader(self::HEADER_LOCATION, $this->loginPath)->withStatus(302); // using status 302 forces the redirect to use the GET method
}

public function startUserSession(
Expand All @@ -43,7 +48,7 @@ public function startUserSession(
$redirect = $this->session->get(self::REDIRECT, $this->defaultRedirect);
$this->session->delete(self::REDIRECT);
$response = new Response();
return $response->withHeader("Location", $redirect)->withStatus(302);
return $response->withHeader(self::HEADER_LOCATION, $redirect)->withStatus(302);
}

public function sessionIsActive(): bool
Expand All @@ -58,6 +63,6 @@ public function getCurrentUser(): ?UserEntityInterface

public function endUserSession(): void
{
$this->session->destroy();
$this->session->clear();
}
}
3 changes: 2 additions & 1 deletion src/Middleware/RequireAuthentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ class RequireAuthentication extends Session
{
private $manager;

public function __construct($settings = [], Manager $manager)
public function __construct($settings = [], Manager $manager = null)
{
parent::__construct($settings);
assert($manager !== null);
$this->manager = $manager;
}

Expand Down
4 changes: 2 additions & 2 deletions templates/login.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
<div class="field username">
<label>Username</label>
<input
name="username"
name="<?= $usernameFieldName ?>"
type="text"
/>
</div>
<div class="field password">
<label>Password</label>
<input
name="password"
name="<? $passwordFieldName ?>"
type="password"
/>
</div>
Expand Down
28 changes: 28 additions & 0 deletions tests/Actions/HandleLoginTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Battis\UserSession\Tests\Actions;

use Battis\UserSession\Manager;
use Battis\UserSession\Repositories\UserRepositoryInterface;
use Battis\UserSession\Tests\Fixtures\Reusable\User;
use Battis\UserSession\Tests\Fixtures\Reusable\UserRepository;
use Battis\UserSession\Tests\TestCase;

class HandleLoginTest extends TestCase
{
public function testHandleLogin()
{
$app = $this->getAppInstance();

$user = new User();

/** @var UserRepository $userRepo */
$userRepo = $app->getContainer()->get(UserRepositoryInterface::class);
$userRepo->addUser($user);

/** #var Manager $manager */
$manager = $app->getContainer()->get(Manager::class);

$response = $app->handle($this->createRequest('POST', Manager::DEFAULT_LOGIN_PATH));
}
}
35 changes: 35 additions & 0 deletions tests/Actions/ShowLoginViewTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Battis\UserSession\Tests\Actions;

use Battis\UserSession\Manager;
use Battis\UserSession\Tests\Fixtures\Reusable\User;
use Battis\UserSession\Tests\TestCase;
use SimpleXMLElement;

class ShowLoginViewTest extends TestCase
{
public function testLoginView()
{
$app = $this->getAppInstance();
$response = $app->handle($this->createRequest('GET', Manager::DEFAULT_LOGIN_PATH));
$payload = (string) $response->getBody();
$xml = new SimpleXMLElement($payload);
$this->assertNotEmpty($payload);
$this->assertCount(0, $xml->{'non-document-error'});
$this->assertCount(0, $xml->error);
$this->assertStringContainsString('<form class="form login" method="post" action="/auth/login">', $payload);
}

public function testLoginViewWithActiveuser()
{
$app = $this->getAppInstance();

/** @var Manager */
$manager = $app->getContainer()->get(Manager::class);
$manager->startUserSession(new User());

$response = $app->handle($this->createRequest('GET', Manager::DEFAULT_LOGIN_PATH));
$this->assertLocationHeader(Manager::DEFAULT_REDIRECT, $response);
}
}
29 changes: 0 additions & 29 deletions tests/Fixtures/ManagerTest/User.php

This file was deleted.

39 changes: 39 additions & 0 deletions tests/Fixtures/Reusable/PageRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Battis\UserSession\Tests\Fixtures\Reusable;

use Battis\UserSession\Manager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Views\PhpRenderer;

/**
* Render a web page using a template with the same name as the
* endpoint. Current user and query and URL params are passed as
* template variables.
*/
class PageRenderer
{
private $renderer;
private $manager;

public function __construct(PhpRenderer $renderer, Manager $manager)
{
$this->renderer = $renderer;
$this->manager = $manager;
}

public function __invoke(
ServerRequestInterface $request,
ResponseInterface $response,
array $args = []
) {
return $this->renderer->render(
$response,
basename($request->getUri()->getPath()) . ".php",
array_merge($args, $request->getQueryParams(), [
"user" => $this->manager->getCurrentUser(),
])
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Battis\UserSession\Tests\Fixtures\ManagerTest;
namespace Battis\UserSession\Tests\Fixtures\Reusable;

use SlimSession\Helper;

Expand Down
31 changes: 31 additions & 0 deletions tests/Fixtures/Reusable/User.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Battis\UserSession\Tests\Fixtures\Reusable;

use Battis\UserSession\Entities\UserEntityInterface;

class User implements UserEntityInterface
{
public $id;
public string $username;
public string $password;
public string $hash;

public function __construct($id = null, string $password = null)
{
$this->id = $id ?? random_int(1, 1000);
$this->username = md5(time() . 'username');
$this->password = $password ?? md5(time() . 'password');
$this->hash = password_hash($this->password, PASSWORD_DEFAULT);
}

public function getIdentifier()
{
return $this->id;
}

public function passwordVerify(string $password): bool
{
return password_verify($password, $this->hash);
}
}
21 changes: 21 additions & 0 deletions tests/Fixtures/Reusable/UserRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Battis\UserSession\Tests\Fixtures\Reusable;

use Battis\UserSession\Entities\UserEntityInterface;
use Battis\UserSession\Repositories\UserRepositoryInterface;

class UserRepository implements UserRepositoryInterface
{
private array $users = [];

public function addUser(User $user)
{
$this->users[$user->username] = $user;
}

public function getUserEntityByUsername(string $username): ?UserEntityInterface
{
return $this->users[$username] ?? null;
}
}
8 changes: 8 additions & 0 deletions tests/Fixtures/app/dependencies.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

use Battis\UserSession\Repositories\UserRepositoryInterface;
use Battis\UserSession\Tests\Fixtures\Reusable\UserRepository;

return [
UserRepositoryInterface::class => fn() => new UserRepository(),
];
12 changes: 12 additions & 0 deletions tests/Fixtures/app/middleware.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

use DI\Container;
use Slim\App;

/** @var App $app */
/** @var Container $container */

// prepare the $container with any middleware you might plan on using

// use the Slim body-parsing middleware for convenience
$app->addBodyParsingMiddleware();
20 changes: 20 additions & 0 deletions tests/Fixtures/app/routes.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

use Battis\UserSession;
use Battis\UserSession\Tests\Fixtures\Reusable\PageRenderer;
use DI\Container;
use Slim\App;

/** @var App $app */
/** @var Container $container */

// assign the UserSession endpoint(s) to the UserSession\Controller
$app->group(UserSession\Controller::ENDPOINT, UserSession\Controller::class);

$app
->get("/home", PageRenderer::class)
->add(UserSession\Middleware\Session::class);
$app->redirect("/", "/home");
$app
->get("/protected", PageRenderer::class)
->add(UserSession\Middleware\RequireAuthentication::class);
Loading

0 comments on commit b72898d

Please sign in to comment.