<?php declare(strict_types=1); /** * SPDX-FileCopyrightText: 2016-2023 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\AppFramework\Middleware; use OC\AppFramework\Middleware\SessionMiddleware; use OC\AppFramework\Utility\ControllerMethodReflector; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\Response; use OCP\IRequest; use OCP\ISession; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class SessionMiddlewareTest extends TestCase { private ControllerMethodReflector|MockObject $reflector; private ISession|MockObject $session; private Controller $controller; private SessionMiddleware $middleware; protected function setUp(): void { parent::setUp(); $this->reflector = $this->createMock(ControllerMethodReflector::class); $this->session = $this->createMock(ISession::class); $this->controller = new class('app', $this->createMock(IRequest::class)) extends Controller { /** * @UseSession */ public function withAnnotation() { } #[UseSession] public function withAttribute() { } public function without() { } }; $this->middleware = new SessionMiddleware( $this->reflector, $this->session, ); } public function testSessionNotClosedOnBeforeController(): void { $this->configureSessionMock(0, 1); $this->reflector->expects(self::once()) ->method('hasAnnotation') ->with('UseSession') ->willReturn(true); $this->middleware->beforeController($this->controller, 'withAnnotation'); } public function testSessionNotClosedOnBeforeControllerWithAttribute(): void { $this->configureSessionMock(0, 1); $this->reflector->expects(self::once()) ->method('hasAnnotation') ->with('UseSession') ->willReturn(false); $this->middleware->beforeController($this->controller, 'withAttribute'); } public function testSessionClosedOnAfterController(): void { $this->configureSessionMock(1); $this->reflector->expects(self::once()) ->method('hasAnnotation') ->with('UseSession') ->willReturn(true); $this->middleware->afterController($this->controller, 'withAnnotation', new Response()); } public function testSessionClosedOnAfterControllerWithAttribute(): void { $this->configureSessionMock(1); $this->reflector->expects(self::once()) ->method('hasAnnotation') ->with('UseSession') ->willReturn(true); $this->middleware->afterController($this->controller, 'withAttribute', new Response()); } public function testSessionReopenedAndClosedOnBeforeController(): void { $this->configureSessionMock(1, 1); $this->reflector->expects(self::exactly(2)) ->method('hasAnnotation') ->with('UseSession') ->willReturn(true); $this->middleware->beforeController($this->controller, 'withAnnotation'); $this->middleware->afterController($this->controller, 'withAnnotation', new Response()); } public function testSessionReopenedAndClosedOnBeforeControllerWithAttribute(): void { $this->configureSessionMock(1, 1); $this->reflector->expects(self::exactly(2)) ->method('hasAnnotation') ->with('UseSession') ->willReturn(false); $this->middleware->beforeController($this->controller, 'withAttribute'); $this->middleware->afterController($this->controller, 'withAttribute', new Response()); } public function testSessionClosedOnBeforeController(): void { $this->configureSessionMock(0); $this->reflector->expects(self::once()) ->method('hasAnnotation') ->with('UseSession') ->willReturn(false); $this->middleware->beforeController($this->controller, 'without'); } public function testSessionNotClosedOnAfterController(): void { $this->configureSessionMock(0); $this->reflector->expects(self::once()) ->method('hasAnnotation') ->with('UseSession') ->willReturn(false); $this->middleware->afterController($this->controller, 'without', new Response()); } private function configureSessionMock(int $expectedCloseCount, int $expectedReopenCount = 0): void { $this->session->expects($this->exactly($expectedCloseCount)) ->method('close'); $this->session->expects($this->exactly($expectedReopenCount)) ->method('reopen'); } }