0

I have created a module in magento 2 for adding prefix to the url of all product and category.

here is the snippet code for the router :

   /**
     * Match route pages for handling cp / ip
     *
     * @param \Magento\Framework\App\RequestInterface|\Magento\Framework\App\Request\Http $request
     * @return bool
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        $pathInfo= trim($request->getPathInfo(), '/');
        $requestUri = trim($request->getRequestUri(), '/');

        $requestUriParts = explode('/', $requestUri);
        array_walk($requestUriParts, function (&$value) {
            $value = trim($value);
        });

        $pathInfoParts = explode('/', $pathInfo);
        array_walk($pathInfoParts, function (&$value) {
            $value = trim($value);
        });


        if ($requestUriParts[0] == $this->prefixCp || $requestUriParts[0]==$this->prefixIp) {
            // remove the cp or ip
            $requestUriFinal = '';
            unset($requestUriParts[0]);
            foreach ($requestUriParts as $r) {
                $requestUriFinal .= $r . '/';
            }

            // remove cp or ip
            unset($pathInfoParts[0]);
            $pathInfoFinal = '';
            foreach ($pathInfoParts as $p) {
                $pathInfoFinal .= $p . '/' ;
            }


            $request->setRequestUri($requestUriFinal);
            $request->setPathInfo($pathInfoFinal);
        } else {
            // No route math here
            return;
        }

        /*
         * We have match and now we will forward action
         */
        return $this->actionFactory->create(
            'Magento\Framework\App\Action\Forward',
            ['request' => $request]
        );
    }

How to test the logic in this match function ? and also for the plugin :

/**
 * this will modify the class Product in vendor/magento/module-catalog/Model/Product.php
 */
class ProductPlugin extends \Magento\Catalog\Model\Product
{
    /**
     * Returns request path
     *
     * @return string
     */
    public function afterGetRequestPath(\Magento\Catalog\Model\Product $subject, $result)
    {
        return 'ip/' . $result ;
    }
}

I just want to test a simple test case where my custom route handle the request. any idea ?

0

One thing to be concerned is the match function, I think it would be better to breakdown this function into smaller one so that it can be easily tested.

Here is the snipped code :

   /**
     * Match route pages for handling cp / ip
     *
     * @param \Magento\Framework\App\RequestInterface|\Magento\Framework\App\Request\Http $request
     *
     * @return \Magento\Framework\App\ActionInterface
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        $requestUri = trim($request->getRequestUri(), '/');
        $pathInfo= trim($request->getPathInfo(), '/');

        $result = $this->getCustomPath($requestUri, $pathInfo);
        if (is_array($result)) {
            $request->setRequestUri($result['requestUri']);
            $request->setPathInfo($result['pathInfo']);
        } else {
            // No route match here.
            return;
        }

        /*
         * We have match and now we will forward action
         */
        return $this->actionFactory->create(
            'Magento\Framework\App\Action\Forward',
            ['request' => $request]
        );
    }

    /**
     * @param string $pathInfo
     * @param string $requestUri
     *
     * @return array of two strings | null
     */
    public function getCustomPath($requestUri, $pathInfo)
    {
        $pathInfo= trim($pathInfo, '/');
        $requestUri = trim($requestUri, '/');

        $requestUriParts = explode('/', $requestUri);
        array_walk($requestUriParts, function (&$value) {
            $value = trim($value);
        });

        $pathInfoParts = explode('/', $pathInfo);
        array_walk($pathInfoParts, function (&$value) {
            $value = trim($value);
        });

        // remove cp/ip for requesrUri and pathInfo
        if (!empty($requestUriParts[0]) && in_array($requestUriParts[0], $this->prefixes) || !empty($pathInfoParts) && in_array($pathInfoParts[0], $this->prefixes)) {
            $resultRequestUri = $this->removePrefix($requestUriParts);
            $resultPathInfo = $this->removePrefix($pathInfoParts);

            return [
                'requestUri' => $resultRequestUri,
                'pathInfo' => $resultPathInfo
            ];
        }


        return [
            'requestUri' => $requestUri,
            'pathInfo' => $pathInfo
        ];
    }

    /**
     * @param array $parts
     * @return string
     */
    private function removePrefix(array $parts)
    {
        $result = '';
        unset($parts[0]);
        foreach ($parts as $index => $r) {
            if (sizeof($parts) == $index) {
                $result .= $r;
            } else {
                $result .= $r . '/';
            }
        }

        return $result;
    }

As you can see from above code I've created two smaller functions which return the values that change the request that being passed to the router. so I can easily test those two function without having to worry about the match.

And this is the unit test code :

class RouterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Magento\Framework\App\ActionFactory |\PHPUnit_Framework_MockObject_MockObject
     */
    private $actionFactoryMock;

    private $testCases = [
        // test 0
        [
            'requestUri'=>'ip/woman/on/top/someproduct.html',
            'pathInfo'=>'ip/woman/on/top/someproduct.html',
            'expected'=>'woman/on/top/someproduct.html'
        ],

        // test 1
        [
            'requestUri'=>'cp/men/top-jacket/product.html',
            'pathInfo'=>'cp/men/top-jacket/product.html',
            'expected'=>'men/top-jacket/product.html'
        ],

        // test 2
        [
            'requestUri'=>'test/one.html',
            'pathInfo'=>'test/one.html',
            'expected'=>'test/one.html'
        ],

    ];

    protected function setUp()
    {

        $this->actionFactoryMock= $this->getMock(
            'Magento\Framework\App\ActionFactory',
            [
                'create'
            ],
            [],
            '',
            false
        );
    }

    /**
     * Test match function for the router
     */
    public function testMatch()
    {
        $router  = new Router($this->actionFactoryMock);
        foreach ($this->testCases as $testCase) {
            $result = $router->getCustomPath($testCase['requestUri'], $testCase['pathInfo']);
            $this->assertEquals($testCase['expected'], $result['requestUri']);
            $this->assertEquals($testCase['expected'], $result['pathInfo']);
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.