feat: offer the questionnaire for placements ended within a rolling window
This commit is contained in:
1 parent
9d0cdd7f52
commit
3c34cfa76a
8 files changed
+65
-55
No files matched your search
@@ -121,11 +121,10 @@ parameters:
|
|||||||
season_start: '11-01'
|
season_start: '11-01'
|
||||||
season_end: '04-01'
|
season_end: '04-01'
|
||||||
|
|
||||||
# The teamer questionnaire after a placement (config/questionnaires/teamer_assignment.yaml) is
|
# The teamer questionnaires after a placement (config/questionnaires/teamer_feedback.yaml, plus
|
||||||
# offered for placements ending on or after this day (Y-m-d). Set it to the deployment day:
|
# bus_feedback.yaml for a bus escort) are offered for placements that ended within this many
|
||||||
# without a cutoff every past placement would show up as pending on the teamers' dashboards.
|
# days. Without a window every past placement would show up as pending on the teamers' dashboards.
|
||||||
# null offers it to nobody.
|
questionnaire_window_days: 30
|
||||||
questionnaire_go_live: ~
|
|
||||||
|
|
||||||
# How far ahead of the destination's first travel day a season assignment's checklist
|
# How far ahead of the destination's first travel day a season assignment's checklist
|
||||||
# entries fall due. A relative date expression, applied to destination.dateFrom, and the
|
# entries fall due. A relative date expression, applied to destination.dateFrom, and the
|
||||||
@@ -190,7 +189,7 @@ services:
|
|||||||
$emailTextsFile: '%kernel.project_dir%/config/email_texts.yaml'
|
$emailTextsFile: '%kernel.project_dir%/config/email_texts.yaml'
|
||||||
# Likewise parsed on demand, by App\Config\QuestionnaireCatalog.
|
# Likewise parsed on demand, by App\Config\QuestionnaireCatalog.
|
||||||
$questionnaireDir: '%kernel.project_dir%/config/questionnaires'
|
$questionnaireDir: '%kernel.project_dir%/config/questionnaires'
|
||||||
$questionnaireGoLive: '%questionnaire_go_live%'
|
$questionnaireWindowDays: '%questionnaire_window_days%'
|
||||||
$mailingBusTransport: '%mailing_bus_transport%'
|
$mailingBusTransport: '%mailing_bus_transport%'
|
||||||
$seasonStart: '%season_start%'
|
$seasonStart: '%season_start%'
|
||||||
$seasonEnd: '%season_end%'
|
$seasonEnd: '%season_end%'
|
||||||
@@ -516,5 +515,3 @@ when@test:
|
|||||||
# a job profile id ListControllerTest inserts itself - db_test has no job profiles
|
# a job profile id ListControllerTest inserts itself - db_test has no job profiles
|
||||||
assignment_export.job_profile_ids: [ 900001 ]
|
assignment_export.job_profile_ids: [ 900001 ]
|
||||||
mailing_bus_transport: 'sync'
|
mailing_bus_transport: 'sync'
|
||||||
# the questionnaire tests need it offered; any day before the placements they create
|
|
||||||
questionnaire_go_live: '2026-01-01'
|
|
||||||
@@ -57,17 +57,17 @@ class QuestionnaireCatalog
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The services.yaml parameter questionnaire_go_live as a date: the teamer questionnaire is
|
* The first end date the teamer questionnaire is still offered for: the services.yaml
|
||||||
* offered for placements ending on or after it, and to nobody while it is null.
|
* parameter questionnaire_window_days, in days before today. Placements that ended earlier are neither
|
||||||
|
* pending nor open, so a deploy does not offer it for every past placement at once.
|
||||||
*/
|
*/
|
||||||
public static function parseGoLive(?string $goLive): ?\DateTimeImmutable
|
public static function windowStart(int $windowDays): \DateTimeImmutable
|
||||||
{
|
{
|
||||||
if (null === $goLive) {
|
if ($windowDays < 0) {
|
||||||
return null;
|
throw new \InvalidArgumentException(sprintf('questionnaire_window_days must not be negative, got %d', $windowDays));
|
||||||
}
|
}
|
||||||
|
|
||||||
return \DateTimeImmutable::createFromFormat('!Y-m-d', $goLive)
|
return new \DateTimeImmutable(sprintf('today -%d days', $windowDays));
|
||||||
?: throw new \InvalidArgumentException(sprintf('questionnaire_go_live "%s" is not a Y-m-d date', $goLive));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -72,12 +72,13 @@ class IndexController extends AbstractController
|
|||||||
|
|
||||||
$dispositionDocuments = $this->processDocuments($upcomingDispositions);
|
$dispositionDocuments = $this->processDocuments($upcomingDispositions);
|
||||||
|
|
||||||
// offered to nobody until the go-live date is configured, as in DispositionVoter
|
$pendingQuestionnaires = $this
|
||||||
$questionnaireGoLive = QuestionnaireCatalog::parseGoLive($this->getParameter('questionnaire_go_live'));
|
|
||||||
$pendingQuestionnaires = null === $questionnaireGoLive ? [] : $this
|
|
||||||
->entityManager
|
->entityManager
|
||||||
->getRepository(Disposition::class)
|
->getRepository(Disposition::class)
|
||||||
->findPendingQuestionnaireByTeamer($teamer, $questionnaireGoLive)
|
->findPendingQuestionnaireByTeamer(
|
||||||
|
$teamer,
|
||||||
|
QuestionnaireCatalog::windowStart((int) $this->getParameter('questionnaire_window_days')),
|
||||||
|
)
|
||||||
;
|
;
|
||||||
|
|
||||||
// the list merges in season assignments; the document notices above stay on dispositions
|
// the list merges in season assignments; the document notices above stay on dispositions
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
* The teamer's placements with a questionnaire still to be submitted - not started, or saved as
|
* The teamer's placements with a questionnaire still to be submitted - not started, or saved as
|
||||||
* a draft: the teamer feedback, and after a bus escort the bus feedback too
|
* a draft: the teamer feedback, and after a bus escort the bus feedback too
|
||||||
* (DispositionContext::questionnaires(), spelled out here in DQL). The rules are those of
|
* (DispositionContext::questionnaires(), spelled out here in DQL). The rules are those of
|
||||||
* DispositionVoter::QUESTIONNAIRE - over (today included), on or after go-live, neither called
|
* DispositionVoter::QUESTIONNAIRE - over (today included), on or after $windowStart, neither
|
||||||
* off nor skip-formalities - so every row shown on the dashboard can be opened.
|
* called off nor skip-formalities - so every row shown on the dashboard can be opened.
|
||||||
*
|
*
|
||||||
* The responses are joined as arbitrary entities because the association is one-way; the
|
* The responses are joined as arbitrary entities because the association is one-way; the
|
||||||
* questionnaire key has to be part of each JOIN condition, or one questionnaire's response
|
* questionnaire key has to be part of each JOIN condition, or one questionnaire's response
|
||||||
@@ -90,7 +90,7 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
* Rows are [0 => Disposition, 'teamerStatus' => ?QuestionnaireResponseStatus,
|
* Rows are [0 => Disposition, 'teamerStatus' => ?QuestionnaireResponseStatus,
|
||||||
* 'busStatus' => ?QuestionnaireResponseStatus].
|
* 'busStatus' => ?QuestionnaireResponseStatus].
|
||||||
*/
|
*/
|
||||||
public function getPendingQuestionnaireQuery(Teamer $teamer, \DateTimeImmutable $goLive): Query
|
public function getPendingQuestionnaireQuery(Teamer $teamer, \DateTimeImmutable $windowStart): Query
|
||||||
{
|
{
|
||||||
$qb = $this->createQueryBuilder('disposition');
|
$qb = $this->createQueryBuilder('disposition');
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
$qb->expr()->neq('disposition.status', ':dispositionCalledOff'),
|
$qb->expr()->neq('disposition.status', ':dispositionCalledOff'),
|
||||||
$qb->expr()->notIn('assignment.status', ':assignmentStatuses'),
|
$qb->expr()->notIn('assignment.status', ':assignmentStatuses'),
|
||||||
$qb->expr()->eq('assignment.skipFormalities', ':skipFormalities'),
|
$qb->expr()->eq('assignment.skipFormalities', ':skipFormalities'),
|
||||||
$qb->expr()->gte('destination.dateTo', ':goLive'),
|
$qb->expr()->gte('destination.dateTo', ':windowStart'),
|
||||||
$qb->expr()->lte('destination.dateTo', ':today'),
|
$qb->expr()->lte('destination.dateTo', ':today'),
|
||||||
$qb->expr()->orX(
|
$qb->expr()->orX(
|
||||||
$qb->expr()->isNull('teamer_response.id'),
|
$qb->expr()->isNull('teamer_response.id'),
|
||||||
@@ -138,7 +138,7 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
->setParameter('dispositionCalledOff', Disposition::STATUS_CALLED_OFF)
|
->setParameter('dispositionCalledOff', Disposition::STATUS_CALLED_OFF)
|
||||||
->setParameter('assignmentStatuses', [Assignment::STATUS_CALLED_OFF, Assignment::STATUS_DELETED])
|
->setParameter('assignmentStatuses', [Assignment::STATUS_CALLED_OFF, Assignment::STATUS_DELETED])
|
||||||
->setParameter('skipFormalities', false)
|
->setParameter('skipFormalities', false)
|
||||||
->setParameter('goLive', $goLive, Types::DATE_IMMUTABLE)
|
->setParameter('windowStart', $windowStart, Types::DATE_IMMUTABLE)
|
||||||
->setParameter('today', new \DateTimeImmutable('today'), Types::DATE_IMMUTABLE)
|
->setParameter('today', new \DateTimeImmutable('today'), Types::DATE_IMMUTABLE)
|
||||||
->setParameter('draft', QuestionnaireResponseStatus::DRAFT)
|
->setParameter('draft', QuestionnaireResponseStatus::DRAFT)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
@@ -148,7 +148,7 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
/**
|
/**
|
||||||
* @return list<array{disposition: Disposition, draft: bool}>
|
* @return list<array{disposition: Disposition, draft: bool}>
|
||||||
*/
|
*/
|
||||||
public function findPendingQuestionnaireByTeamer(Teamer $teamer, \DateTimeImmutable $goLive): array
|
public function findPendingQuestionnaireByTeamer(Teamer $teamer, \DateTimeImmutable $windowStart): array
|
||||||
{
|
{
|
||||||
return array_map(
|
return array_map(
|
||||||
static fn (array $row): array => [
|
static fn (array $row): array => [
|
||||||
@@ -156,7 +156,7 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
'draft' => QuestionnaireResponseStatus::DRAFT === $row['teamerStatus']
|
'draft' => QuestionnaireResponseStatus::DRAFT === $row['teamerStatus']
|
||||||
|| QuestionnaireResponseStatus::DRAFT === $row['busStatus'],
|
|| QuestionnaireResponseStatus::DRAFT === $row['busStatus'],
|
||||||
],
|
],
|
||||||
$this->getPendingQuestionnaireQuery($teamer, $goLive)->getResult(),
|
$this->getPendingQuestionnaireQuery($teamer, $windowStart)->getResult(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,16 +25,13 @@ class DispositionVoter extends Voter
|
|||||||
public const MANAGE_RECEIPTS = 'MANAGE_RECEIPTS';
|
public const MANAGE_RECEIPTS = 'MANAGE_RECEIPTS';
|
||||||
public const QUESTIONNAIRE = 'QUESTIONNAIRE';
|
public const QUESTIONNAIRE = 'QUESTIONNAIRE';
|
||||||
|
|
||||||
private readonly ?\DateTimeImmutable $questionnaireGoLive;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string|null $questionnaireGoLive Y-m-d, the services.yaml parameter questionnaire_go_live
|
* @param int $questionnaireWindowDays the services.yaml parameter questionnaire_window_days
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly Security $security,
|
private readonly Security $security,
|
||||||
?string $questionnaireGoLive,
|
private readonly int $questionnaireWindowDays,
|
||||||
) {
|
) {
|
||||||
$this->questionnaireGoLive = QuestionnaireCatalog::parseGoLive($questionnaireGoLive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supports(string $attribute, mixed $subject): bool
|
protected function supports(string $attribute, mixed $subject): bool
|
||||||
@@ -134,7 +131,7 @@ class DispositionVoter extends Voter
|
|||||||
*/
|
*/
|
||||||
private function assertQuestionnaireAllowed(TokenInterface $token, Disposition $disposition): bool
|
private function assertQuestionnaireAllowed(TokenInterface $token, Disposition $disposition): bool
|
||||||
{
|
{
|
||||||
if (null === $this->questionnaireGoLive || false === $this->assertTeamerAccess($token, $disposition)) {
|
if (false === $this->assertTeamerAccess($token, $disposition)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +143,7 @@ class DispositionVoter extends Voter
|
|||||||
$dateTo = $disposition->getAssignment()?->getDestination()?->getDateTo();
|
$dateTo = $disposition->getAssignment()?->getDestination()?->getDateTo();
|
||||||
|
|
||||||
return null !== $dateTo
|
return null !== $dateTo
|
||||||
&& $dateTo >= $this->questionnaireGoLive
|
&& $dateTo >= QuestionnaireCatalog::windowStart($this->questionnaireWindowDays)
|
||||||
&& $dateTo <= new \DateTimeImmutable('today');
|
&& $dateTo <= new \DateTimeImmutable('today');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,18 @@ class QuestionnaireCatalogTest extends TestCase
|
|||||||
$this->assertSame('Alte Frage', $catalog->get('sample', 1)->getQuestion('answer')->label);
|
$this->assertSame('Alte Frage', $catalog->get('sample', 1)->getQuestion('answer')->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTheWindowStartsTheGivenDaysBeforeToday(): void
|
||||||
|
{
|
||||||
|
$this->assertEquals(new \DateTimeImmutable('today -2 days'), QuestionnaireCatalog::windowStart(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testANegativeWindowFailsLoudly(): void
|
||||||
|
{
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
|
||||||
|
QuestionnaireCatalog::windowStart(-1);
|
||||||
|
}
|
||||||
|
|
||||||
public function testUnknownQuestionnaireIsRejected(): void
|
public function testUnknownQuestionnaireIsRejected(): void
|
||||||
{
|
{
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ class DispositionRepositoryQuestionnaireTest extends KernelTestCase
|
|||||||
{
|
{
|
||||||
use QuestionnaireFixturesTrait;
|
use QuestionnaireFixturesTrait;
|
||||||
|
|
||||||
private const string GO_LIVE = '2026-01-01';
|
|
||||||
|
|
||||||
private EntityManagerInterface $entityManager;
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
private DispositionRepository $repository;
|
private DispositionRepository $repository;
|
||||||
@@ -123,6 +121,13 @@ class DispositionRepositoryQuestionnaireTest extends KernelTestCase
|
|||||||
$this->assertSame([['disposition' => $disposition, 'draft' => false]], $this->pending());
|
$this->assertSame([['disposition' => $disposition, 'draft' => false]], $this->pending());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAnAssignmentEndingOnTheWindowsFirstDayIsPending(): void
|
||||||
|
{
|
||||||
|
$this->escort(dateTo: 'today -30 days');
|
||||||
|
|
||||||
|
$this->assertCount(1, $this->pending());
|
||||||
|
}
|
||||||
|
|
||||||
public function testAnAssignmentEndingTodayIsPending(): void
|
public function testAnAssignmentEndingTodayIsPending(): void
|
||||||
{
|
{
|
||||||
$this->escort(dateTo: 'today');
|
$this->escort(dateTo: 'today');
|
||||||
@@ -149,7 +154,7 @@ class DispositionRepositoryQuestionnaireTest extends KernelTestCase
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'not over yet' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('tomorrow'))],
|
'not over yet' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('tomorrow'))],
|
||||||
'ended before go-live' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('2025-12-31'))],
|
'ended before the window' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('today -31 days'))],
|
||||||
'skip formalities' => [static fn (Disposition $d) => $d->getAssignment()->setSkipFormalities(true)],
|
'skip formalities' => [static fn (Disposition $d) => $d->getAssignment()->setSkipFormalities(true)],
|
||||||
'called off' => [static fn (Disposition $d) => $d->setStatus(Disposition::STATUS_CALLED_OFF)],
|
'called off' => [static fn (Disposition $d) => $d->setStatus(Disposition::STATUS_CALLED_OFF)],
|
||||||
'assignment called off' => [static fn (Disposition $d) => $d->getAssignment()->setStatus(Assignment::STATUS_CALLED_OFF)],
|
'assignment called off' => [static fn (Disposition $d) => $d->getAssignment()->setStatus(Assignment::STATUS_CALLED_OFF)],
|
||||||
@@ -172,6 +177,6 @@ class DispositionRepositoryQuestionnaireTest extends KernelTestCase
|
|||||||
{
|
{
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|
||||||
return $this->repository->findPendingQuestionnaireByTeamer($this->teamer, new \DateTimeImmutable(self::GO_LIVE));
|
return $this->repository->findPendingQuestionnaireByTeamer($this->teamer, QuestionnaireCatalog::windowStart(30));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ class DispositionVoterTest extends TestCase
|
|||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
$expected ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_DENIED,
|
$expected ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_DENIED,
|
||||||
(new DispositionVoter($this->security, null))->vote($token, $disposition, [DispositionVoter::MANAGE_RECEIPTS]),
|
(new DispositionVoter($this->security, 30))->vote($token, $disposition, [DispositionVoter::MANAGE_RECEIPTS]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,15 +217,20 @@ class DispositionVoterTest extends TestCase
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'assignment not over yet' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('tomorrow'))],
|
'assignment not over yet' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('tomorrow'))],
|
||||||
'ended before go-live' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('2025-12-31'))],
|
'ended before the window' => [static fn (Disposition $d) => $d->getAssignment()->getDestination()->setDateTo(new \DateTimeImmutable('today -31 days'))],
|
||||||
'skip formalities' => [static fn (Disposition $d) => $d->getAssignment()->setSkipFormalities(true)],
|
'skip formalities' => [static fn (Disposition $d) => $d->getAssignment()->setSkipFormalities(true)],
|
||||||
'called off' => [static fn (Disposition $d) => $d->setStatus(Disposition::STATUS_CALLED_OFF)],
|
'called off' => [static fn (Disposition $d) => $d->setStatus(Disposition::STATUS_CALLED_OFF)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTheQuestionnaireIsOfferedToNobodyWithoutAGoLiveDate(): void
|
public function testTheQuestionnaireIsStillOfferedOnTheWindowsLastDay(): void
|
||||||
{
|
{
|
||||||
$this->assertQuestionnaire(false, $this->escortDisposition(), goLive: null);
|
$this->assertQuestionnaire(true, $this->escortDisposition(dateTo: 'today -30 days'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTheWindowIsConfigurable(): void
|
||||||
|
{
|
||||||
|
$this->assertQuestionnaire(false, $this->escortDisposition(dateTo: 'today -8 days'), windowDays: 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAnotherTeamerMayNotFillInTheQuestionnaire(): void
|
public function testAnotherTeamerMayNotFillInTheQuestionnaire(): void
|
||||||
@@ -247,18 +252,11 @@ class DispositionVoterTest extends TestCase
|
|||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
VoterInterface::ACCESS_DENIED,
|
VoterInterface::ACCESS_DENIED,
|
||||||
$this->questionnaireVote($disposition, (new User())->setTeamer($disposition->getTeamer()), '2026-01-01'),
|
$this->questionnaireVote($disposition, (new User())->setTeamer($disposition->getTeamer()), 30),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAMalformedGoLiveDateFailsLoudly(): void
|
private function assertQuestionnaire(bool $expected, Disposition $disposition, int $windowDays = 30, ?User $user = null): void
|
||||||
{
|
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
|
||||||
|
|
||||||
new DispositionVoter($this->security, '01.01.2026');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function assertQuestionnaire(bool $expected, Disposition $disposition, ?string $goLive = '2026-01-01', ?User $user = null): void
|
|
||||||
{
|
{
|
||||||
$this->security
|
$this->security
|
||||||
->method('isGranted')
|
->method('isGranted')
|
||||||
@@ -267,20 +265,20 @@ class DispositionVoterTest extends TestCase
|
|||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
$expected ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_DENIED,
|
$expected ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_DENIED,
|
||||||
$this->questionnaireVote($disposition, $user ?? (new User())->setTeamer($disposition->getTeamer()), $goLive),
|
$this->questionnaireVote($disposition, $user ?? (new User())->setTeamer($disposition->getTeamer()), $windowDays),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function questionnaireVote(Disposition $disposition, User $user, ?string $goLive): int
|
private function questionnaireVote(Disposition $disposition, User $user, int $windowDays): int
|
||||||
{
|
{
|
||||||
$token = $this->createStub(TokenInterface::class);
|
$token = $this->createStub(TokenInterface::class);
|
||||||
$token->method('getUser')->willReturn($user);
|
$token->method('getUser')->willReturn($user);
|
||||||
|
|
||||||
return (new DispositionVoter($this->security, $goLive))->vote($token, $disposition, [DispositionVoter::QUESTIONNAIRE]);
|
return (new DispositionVoter($this->security, $windowDays))->vote($token, $disposition, [DispositionVoter::QUESTIONNAIRE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bus escort that ended yesterday, after the go-live date the tests use.
|
* A bus escort that ended yesterday, well within the 30-day window the tests use.
|
||||||
*/
|
*/
|
||||||
private function escortDisposition(string $dateTo = 'yesterday'): Disposition
|
private function escortDisposition(string $dateTo = 'yesterday'): Disposition
|
||||||
{
|
{
|
||||||
@@ -296,7 +294,7 @@ class DispositionVoterTest extends TestCase
|
|||||||
|
|
||||||
private function vote(string $attribute, Disposition $disposition): int
|
private function vote(string $attribute, Disposition $disposition): int
|
||||||
{
|
{
|
||||||
return (new DispositionVoter($this->security, null))->vote(
|
return (new DispositionVoter($this->security, 30))->vote(
|
||||||
$this->createStub(TokenInterface::class),
|
$this->createStub(TokenInterface::class),
|
||||||
$disposition,
|
$disposition,
|
||||||
[$attribute],
|
[$attribute],
|
||||||
|
|||||||
Reference in new issue
Block a user