prophet = new \Prophecy\Prophet(); } protected function tearDown(): void { $this->prophet->checkPredictions(); } public function testAggregatorsApplyingOn() { $center = $this->prepareCenter(100, 'center'); $centers = [$center]; $user = $this->prepareUser([]); $authorizationChecker = $this->prophet->prophesize(); $authorizationChecker->willImplement(AuthorizationCheckerInterface::class); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $center) ->willReturn(true); $exportManager = $this->createExportManager( null, null, $authorizationChecker->reveal(), null, $user ); $exportFooBar = $this->prophet->prophesize(); $exportFooBar->willImplement(ExportInterface::class); $exportFooBar->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $exportFooBar->supportsModifiers()->willReturn(['foo', 'bar']); $aggregatorBar = $this->prophet->prophesize(); $aggregatorBar->willImplement(AggregatorInterface::class); $aggregatorBar->applyOn()->willReturn('bar'); $aggregatorBar->addRole()->willReturn(null); $exportManager->addAggregator($aggregatorBar->reveal(), 'bar'); $exportBar = $this->prophet->prophesize(); $exportBar->willImplement(ExportInterface::class); $exportBar->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $exportBar->supportsModifiers()->willReturn(['bar']); $aggregatorFoo = $this->prophet->prophesize(); $aggregatorFoo->willImplement(AggregatorInterface::class); $aggregatorFoo->applyOn()->willReturn('foo'); $aggregatorFoo->addRole()->willReturn(null); $exportManager->addAggregator($aggregatorFoo->reveal(), 'foo'); $exportFoo = $this->prophet->prophesize(); $exportFoo->willImplement(ExportInterface::class); $exportFoo->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $exportFoo->supportsModifiers()->willReturn(['foo']); $obtained = iterator_to_array($exportManager->getAggregatorsApplyingOn($exportFoo->reveal(), $centers)); $this->assertEquals(1, count($obtained)); $this->assertContains('foo', array_keys($obtained)); $obtained = iterator_to_array($exportManager->getAggregatorsApplyingOn($exportBar->reveal(), $centers)); $this->assertEquals(1, count($obtained)); $this->assertContains('bar', array_keys($obtained)); $obtained = iterator_to_array($exportManager->getAggregatorsApplyingOn($exportFooBar->reveal(), $centers)); $this->assertEquals(2, count($obtained)); $this->assertContains('bar', array_keys($obtained)); $this->assertContains('foo', array_keys($obtained)); // test with empty centers $obtained = iterator_to_array($exportManager->getAggregatorsApplyingOn($exportFooBar->reveal(), [])); $this->assertEquals(0, count($obtained)); } public function testFiltersApplyingOn() { $center = $this->prepareCenter(100, 'center'); $centers = [$center]; $user = $this->prepareUser([]); $authorizationChecker = $this->prophet->prophesize(); $authorizationChecker->willImplement(AuthorizationCheckerInterface::class); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $center) ->willReturn(true); $exportManager = $this->createExportManager( null, null, $authorizationChecker->reveal(), null, $user ); $exportFooBar = $this->prophet->prophesize(); $exportFooBar->willImplement(ExportInterface::class); $exportFooBar->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $exportFooBar->supportsModifiers()->willReturn(['foo', 'bar']); $filterBar = $this->prophet->prophesize(); $filterBar->willImplement(FilterInterface::class); $filterBar->applyOn()->willReturn('bar'); $filterBar->addRole()->willReturn(null); $filterBar->describeAction(Argument::cetera())->willReturn('string'); $exportManager->addFilter($filterBar->reveal(), 'bar'); $exportBar = $this->prophet->prophesize(); $exportBar->willImplement(ExportInterface::class); $exportBar->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $exportBar->supportsModifiers()->willReturn(['bar']); $filterFoo = $this->prophet->prophesize(); $filterFoo->willImplement(FilterInterface::class); $filterFoo->applyOn()->willReturn('foo'); $filterFoo->addRole()->willReturn(null); $filterFoo->describeAction(Argument::cetera())->willReturn('string'); $exportManager->addFilter($filterFoo->reveal(), 'foo'); $exportFoo = $this->prophet->prophesize(); $exportFoo->willImplement(ExportInterface::class); $exportFoo->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $exportFoo->supportsModifiers()->willReturn(['foo']); $obtained = iterator_to_array($exportManager->getFiltersApplyingOn($exportFoo->reveal(), $centers)); $this->assertEquals(1, count($obtained)); $this->assertContains('foo', array_keys($obtained)); $obtained = iterator_to_array($exportManager->getFiltersApplyingOn($exportBar->reveal(), $centers)); $this->assertEquals(1, count($obtained)); $this->assertContains('bar', array_keys($obtained)); $obtained = iterator_to_array($exportManager->getFiltersApplyingOn($exportFooBar->reveal(), $centers)); $this->assertEquals(2, count($obtained)); $this->assertContains('bar', array_keys($obtained)); $this->assertContains('foo', array_keys($obtained)); $obtained = iterator_to_array($exportManager->getFiltersApplyingOn($exportFooBar->reveal(), [])); $this->assertEquals(0, count($obtained)); } public function testFormattersByTypes() { $exportManager = $this->createExportManager(); //create a formatter $formatterFoo = $this->prophet->prophesize(); $formatterFoo->willImplement('Chill\MainBundle\Export\FormatterInterface'); $formatterFoo->getType()->willReturn('foo'); $formatterBar = $this->prophet->prophesize(); $formatterBar->willImplement('Chill\MainBundle\Export\FormatterInterface'); $formatterBar->getType()->willReturn('bar'); $exportManager->addFormatter($formatterFoo->reveal(), 'foo'); $exportManager->addFormatter($formatterBar->reveal(), 'bar'); $obtained = $exportManager->getFormattersByTypes(['foo']); $this->assertContains($formatterFoo->reveal(), $obtained); $this->assertNotContains($formatterBar->reveal(), $obtained); } /** * Test the generation of an export. */ public function testGenerate() { $center = $this->prepareCenter(100, 'center'); $user = $this->prepareUser([]); $authorizationChecker = $this->prophet->prophesize(); $authorizationChecker->willImplement(AuthorizationCheckerInterface::class); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $center) ->willReturn(true); $exportManager = $this->createExportManager( null, null, $authorizationChecker->reveal(), null, $user ); $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $em = self::$container->get('doctrine.orm.entity_manager'); $export->initiateQuery( Argument::is(['foo']), Argument::Type('array'), Argument::is(['a' => 'b']) ) ->will(static function () use ($em) { $qb = $em->createQueryBuilder(); return $qb->addSelect('COUNT(user.id) as export') ->from('ChillMainBundle:User', 'user'); }); //$export->initiateQuery()->shouldBeCalled(); $export->supportsModifiers()->willReturn(['foo']); $export->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $export->getResult(Argument::Type(QueryBuilder::class), Argument::Type('array'))->willReturn([ [ 'aggregator' => 'cat a', 'export' => 0, ], [ 'aggregator' => 'cat b', 'export' => 1, ], ]); $export->getLabels( Argument::is('export'), Argument::is([0, 1]), Argument::Type('array') ) ->willReturn(static function ($value) { switch ($value) { case 0: case 1: return $value; case '_header': return 'export'; default: throw new RuntimeException(sprintf('The value %s is not valid', $value)); } }); $export->getQueryKeys(Argument::Type('array'))->willReturn(['export']); $export->getTitle()->willReturn('dummy title'); $exportManager->addExport($export->reveal(), 'dummy'); $filter = $this->prophet->prophesize(); $filter->willImplement(FilterInterface::class); //$filter->alterQuery()->shouldBeCalled(); $filter->alterQuery(Argument::Type(QueryBuilder::class), Argument::Type('array')) ->willReturn(null); $filter->addRole()->shouldBeCalled(); //$filter->addRole()->shouldBeCalled(); $filter->applyOn()->willReturn('foo'); $filter->describeAction(Argument::cetera())->willReturn('filtered string'); $exportManager->addFilter($filter->reveal(), 'filter_foo'); $aggregator = $this->prophet->prophesize(); $aggregator->willImplement(AggregatorInterface::class); $aggregator->applyOn()->willReturn('foo'); $aggregator->alterQuery(Argument::Type(QueryBuilder::class), Argument::Type('array')) ->willReturn(null); //$aggregator->alterQuery()->shouldBeCalled(); $aggregator->getQueryKeys(Argument::Type('array'))->willReturn(['aggregator']); $aggregator->getLabels( Argument::is('aggregator'), Argument::is(['cat a', 'cat b']), Argument::is([]) ) ->willReturn(static function ($value) { switch ($value) { case '_header': return 'foo_header'; case 'cat a': return 'label cat a'; case 'cat b': return 'label cat b'; default: throw new RuntimeException(sprintf('This value (%s) is not valid', $value)); } }); $aggregator->addRole()->willReturn(null); //$aggregator->addRole()->shouldBeCalled(); $exportManager->addAggregator($aggregator->reveal(), 'aggregator_foo'); //add formatter interface $formatter = new \Chill\MainBundle\Export\Formatter\SpreadSheetFormatter( self::$container->get('translator'), $exportManager ); $exportManager->addFormatter($formatter, 'spreadsheet'); //ob_start(); $response = $exportManager->generate( 'dummy', [$center], [ ExportType::FILTER_KEY => [ 'filter_foo' => [ 'enabled' => true, 'form' => [], ], ], ExportType::AGGREGATOR_KEY => [ 'aggregator_foo' => [ 'enabled' => true, 'form' => [], ], ], ExportType::PICK_FORMATTER_KEY => [ 'alias' => 'spreadsheet', ], ExportType::EXPORT_KEY => [ 'a' => 'b', ], ], [ 'format' => 'csv', 'aggregator_foo' => [ 'order' => 1, ], ] ); //$content = ob_get_clean(); $this->assertInstanceOf(Response::class, $response); $expected = <<<'EOT' "dummy title","" "","" "filtered string","" "foo_header","_header" "label cat a","" "label cat b","1" EOT; $this->assertEquals($expected, $response->getContent()); } public function testGetAggregator() { $exportManager = $this->createExportManager(); //create a filter and add it to ExportManager $agg = $this->prophet->prophesize(); $agg->willImplement('Chill\MainBundle\Export\AggregatorInterface'); $exportManager->addAggregator($agg->reveal(), 'dummy'); $obtained = $exportManager->getAggregator('dummy'); $this->assertInstanceof('Chill\MainBundle\Export\AggregatorInterface', $obtained); } public function testGetAggregatorNonExistant() { $this->expectException(RuntimeException::class); $exportManager = $this->createExportManager(); $exportManager->getAggregator('non existing'); } public function testGetAggregators() { $exportManager = $this->createExportManager(); //create three filters and add them to ExportManager $aggFoo = $this->prophet->prophesize(); $aggFoo->willImplement('Chill\MainBundle\Export\AggregatorInterface'); $aggBar = $this->prophet->prophesize(); $aggBar->willImplement('Chill\MainBundle\Export\AggregatorInterface'); $aggFooBar = $this->prophet->prophesize(); $aggFooBar->willImplement('Chill\MainBundle\Export\AggregatorInterface'); $exportManager->addAggregator($aggFoo->reveal(), 'foo'); $exportManager->addAggregator($aggBar->reveal(), 'bar'); $exportManager->addAggregator($aggFooBar->reveal(), 'foobar'); $obtained = iterator_to_array($exportManager->getAggregators(['foo', 'bar'])); $this->assertContains($aggBar->reveal(), $obtained); $this->assertContains($aggFoo->reveal(), $obtained); $this->assertNotContains($aggFooBar->reveal(), $obtained); } public function testGetExistingExportsTypes() { $exportManager = $this->createExportManager(); //create an export and add it to ExportManager $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $export->getType()->willReturn('my_type'); $exportManager->addExport($export->reveal(), 'dummy'); $this->assertContains('my_type', $exportManager->getExistingExportsTypes()); } public function testGetExport() { $exportManager = $this->createExportManager(); //create an export and add it to ExportManager $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $exportManager->addExport($export->reveal(), 'dummy'); $obtained = $exportManager->getExport('dummy'); $this->assertInstanceof(ExportInterface::class, $obtained); } public function testGetExportNonExistant() { $this->expectException(RuntimeException::class); $exportManager = $this->createExportManager(); $exportManager->getExport('non existing'); } public function testGetExportsWithoutGranting() { $exportManager = $this->createExportManager(); //create an export and add it to ExportManager $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $exportManager->addExport($export->reveal(), 'dummy'); $exports = iterator_to_array($exportManager->getExports(false)); $this->assertGreaterThan(0, count($exports)); $this->assertContains($export->reveal(), $exports); $this->assertContains('dummy', array_keys($exports)); } public function testGetFilter() { $exportManager = $this->createExportManager(); //create a filter and add it to ExportManager $filter = $this->prophet->prophesize(); $filter->willImplement('Chill\MainBundle\Export\FilterInterface'); $exportManager->addFilter($filter->reveal(), 'dummy'); $obtained = $exportManager->getFilter('dummy'); $this->assertInstanceof('Chill\MainBundle\Export\FilterInterface', $obtained); } public function testGetFilterNonExistant() { $this->expectException(RuntimeException::class); $exportManager = $this->createExportManager(); $exportManager->getFilter('non existing'); } public function testGetFilters() { $exportManager = $this->createExportManager(); //create three filters and add them to ExportManager $filterFoo = $this->prophet->prophesize(); $filterFoo->willImplement('Chill\MainBundle\Export\FilterInterface'); $filterBar = $this->prophet->prophesize(); $filterBar->willImplement('Chill\MainBundle\Export\FilterInterface'); $filterFooBar = $this->prophet->prophesize(); $filterFooBar->willImplement('Chill\MainBundle\Export\FilterInterface'); $exportManager->addFilter($filterFoo->reveal(), 'foo'); $exportManager->addFilter($filterBar->reveal(), 'bar'); $exportManager->addFilter($filterFooBar->reveal(), 'foobar'); $obtained = iterator_to_array($exportManager->getFilters(['foo', 'bar'])); $this->assertContains($filterBar->reveal(), $obtained); $this->assertContains($filterFoo->reveal(), $obtained); $this->assertNotContains($filterFooBar->reveal(), $obtained); } public function testGetFormatter() { $exportManager = $this->createExportManager(); //create a formatter $formatter = $this->prophet->prophesize(); $formatter->willImplement('Chill\MainBundle\Export\FormatterInterface'); $exportManager->addFormatter($formatter->reveal(), 'dummy'); $obtained = $exportManager->getFormatter('dummy'); $this->assertInstanceOf('Chill\MainBundle\Export\FormatterInterface', $obtained); } public function testIsGrantedForElementWithExportAndUserIsGranted() { $center = $this->prepareCenter(100, 'center A'); $user = $this->prepareUser([]); $authorizationChecker = $this->prophet->prophesize(); $authorizationChecker->willImplement('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface'); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $center) ->willReturn(true); $exportManager = $this->createExportManager( null, null, $authorizationChecker->reveal(), null, $user ); $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $export->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $result = $exportManager->isGrantedForElement($export->reveal(), null, [$center]); $this->assertTrue($result); } public function testIsGrantedForElementWithExportAndUserIsGrantedNotForAllCenters() { $center = $this->prepareCenter(100, 'center A'); $centerB = $this->prepareCenter(102, 'center B'); $user = $this->prepareUser([]); $authorizationChecker = $this->prophet->prophesize(); $authorizationChecker->willImplement('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface'); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $center) ->willReturn(true); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $centerB) ->willReturn(false); $exportManager = $this->createExportManager( null, null, $authorizationChecker->reveal(), null, $user ); $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $export->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $result = $exportManager->isGrantedForElement($export->reveal(), null, [$center, $centerB]); $this->assertFalse($result); } public function testIsGrantedForElementWithExportEmptyCenters() { $user = $this->prepareUser([]); $exportManager = $this->createExportManager( null, null, null, null, $user ); $export = $this->prophet->prophesize(); $export->willImplement(\Chill\MainBundle\Export\ExportInterface::class); $export->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $result = $exportManager->isGrantedForElement($export->reveal(), null, []); $this->assertFalse($result); } public function testIsGrantedForElementWithModifierFallbackToExport() { $center = $this->prepareCenter(100, 'center A'); $centerB = $this->prepareCenter(102, 'center B'); $user = $this->prepareUser([]); $authorizationChecker = $this->prophet->prophesize(); $authorizationChecker->willImplement(AuthorizationCheckerInterface::class); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $center) ->willReturn(true); $authorizationChecker->isGranted('CHILL_STAT_DUMMY', $centerB) ->willReturn(false); $exportManager = $this->createExportManager( null, null, $authorizationChecker->reveal(), null, $user ); $modifier = $this->prophet->prophesize(); $modifier->willImplement(\Chill\MainBundle\Export\ModifierInterface::class); $modifier->addRole()->willReturn(null); $export = $this->prophet->prophesize(); $export->willImplement(ExportInterface::class); $export->requiredRole()->willReturn(new Role('CHILL_STAT_DUMMY')); $result = $exportManager->isGrantedForElement( $modifier->reveal(), $export->reveal(), [$center, $centerB] ); $this->assertFalse($result); } public function testNonExistingFormatter() { $this->expectException(RuntimeException::class); $exportManager = $this->createExportManager(); $exportManager->getFormatter('non existing'); } /** * Create an ExportManager where every element may be replaced by a double. * * If null is provided for an element, this is replaced by the equivalent * from the container; if the user provided is null, this is replaced by the * user 'center a_social' from database. */ protected function createExportManager( ?LoggerInterface $logger = null, ?EntityManagerInterface $em = null, ?AuthorizationCheckerInterface $authorizationChecker = null, ?AuthorizationHelper $authorizationHelper = null, ?UserInterface $user = null ): ExportManager { $localUser = $user ?? self::$container->get( 'doctrine.orm.entity_manager' ) ->getRepository('ChillMainBundle:User') ->findOneBy(['username' => 'center a_social']); $token = new UsernamePasswordToken($localUser, 'password', 'provider'); $tokenStorage = new TokenStorage(); $tokenStorage->setToken($token); return new ExportManager( $logger ?? self::$container->get('logger'), $em ?? self::$container->get('doctrine.orm.entity_manager'), $authorizationChecker ?? self::$container->get('security.authorization_checker'), $authorizationHelper ?? self::$container->get('chill.main.security.authorization.helper'), $tokenStorage ); } }