<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Backend\App;

use Magento\TestFramework\Bootstrap;

/**
 * Test class for \Magento\Backend\App\AbstractAction.
 * @magentoAppArea adminhtml
 */
class AbstractActionTest extends \Magento\TestFramework\TestCase\AbstractBackendController
{
    /**
     * Check redirection to startup page for logged user
     * @magentoConfigFixture current_store admin/security/use_form_key 1
     * @magentoAppIsolation enabled
     */
    public function testPreDispatchWithEmptyUrlRedirectsToStartupPage()
    {
        $this->markTestSkipped('Session destruction doesn\'t work');
        \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
            \Magento\Framework\Config\ScopeInterface::class
        )->setCurrentScope(
            \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE
        );
        $this->dispatch('backend');
        /** @var $backendUrlModel \Magento\Backend\Model\UrlInterface */
        $backendUrlModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
            \Magento\Backend\Model\UrlInterface::class
        );
        $url = $backendUrlModel->getStartupPageUrl();
        $expected = $backendUrlModel->getUrl($url);
        $this->assertRedirect($this->stringStartsWith($expected));
    }

    /**
     * Check login redirection
     *
     * @magentoDbIsolation enabled
     */
    public function testInitAuthentication()
    {
        /**
         * Logout current session
         */
        $this->_auth->logout();

        /** @var \Magento\Framework\Data\Form\FormKey $formKey */
        $formKey = $this->_objectManager->get(\Magento\Framework\Data\Form\FormKey::class);
        $postLogin = [
            'login' => [
                'username' => \Magento\TestFramework\Bootstrap::ADMIN_NAME,
                'password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
            ],
            'form_key' => $formKey->getFormKey(),
        ];

        $this->getRequest()->setPostValue($postLogin);
        $this->dispatch('backend/admin/system_account/index');

        $expected = 'backend/admin/system_account/index';
        $this->assertRedirect($this->stringContains($expected));
    }

    /**
     * Check layout attribute "acl" for check access to
     *
     * @param string $blockName
     * @param string $resource
     * @param bool $isLimitedAccess
     * @dataProvider nodesWithAcl
     */
    public function testAclInNodes($blockName, $resource, $isLimitedAccess)
    {
        /** @var $noticeInbox \Magento\AdminNotification\Model\Inbox */
        $noticeInbox = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
            \Magento\AdminNotification\Model\Inbox::class
        );
        if (!$noticeInbox->loadLatestNotice()->getId()) {
            $noticeInbox->addCritical('Test notice', 'Test description');
        }

        $this->_auth->login(
            \Magento\TestFramework\Bootstrap::ADMIN_NAME,
            \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD
        );

        /** @var $acl \Magento\Framework\Acl */
        $acl = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
            ->get(\Magento\Framework\Acl\Builder::class)
            ->getAcl();
        if ($isLimitedAccess) {
            $acl->deny(Bootstrap::ADMIN_ROLE_ID, $resource);
        }

        $this->dispatch('backend/admin/dashboard');

        $layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
            \Magento\Framework\View\LayoutInterface::class
        );
        $actualBlocks = $layout->getAllBlocks();

        $this->assertNotEmpty($actualBlocks);
        if ($isLimitedAccess) {
            $this->assertNotContains($blockName, array_keys($actualBlocks));
        } else {
            $this->assertContains($blockName, array_keys($actualBlocks));
        }
    }

    /**
     * Data provider with expected blocks with acl properties
     *
     * @return array
     */
    public static function nodesWithAcl()
    {
        return [
            ['notification_window', 'Magento_AdminNotification::show_toolbar', true],
            ['notification_window', 'Magento_AdminNotification::show_toolbar', false]
        ];
    }
}
