Skip to content

Commit fafc134

Browse files
committed
Updating tests to check for proper file link duplication/updates, when triggered by exercise/assignment updates.
1 parent dda336b commit fafc134

File tree

5 files changed

+215
-21
lines changed

5 files changed

+215
-21
lines changed

app/model/entity/base/ExerciseData.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ function (ExerciseTest $test) {
280280

281281
/**
282282
* @ORM\ManyToMany(targetEntity="ExerciseFile")
283-
* @var Collection
283+
* @var Collection<ExerciseFile>
284284
*/
285285
protected $exerciseFiles;
286286

app/model/repository/ExerciseFileLinks.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function __construct(EntityManagerInterface $em)
1616
}
1717

1818
/**
19-
* Load an associative array [ key => external-file-ID ] for all file links of the given exercise.
19+
* Load an associative array [ key => link-ID ] for all file links of the given exercise.
2020
* @param string $exerciseId
2121
* @return array<string, string>
2222
*/
@@ -26,13 +26,13 @@ public function getLinksMapForExercise(string $exerciseId): array
2626
$result = [];
2727
foreach ($links as $link) {
2828
/** @var ExerciseFileLink $link */
29-
$result[$link->getKey()] = $link->getExerciseFile()->getId();
29+
$result[$link->getKey()] = $link->getId();
3030
}
3131
return $result;
3232
}
3333

3434
/**
35-
* Load an associative array [ key => external-file-ID ] for all file links of the given assignment.
35+
* Load an associative array [ key => link-ID ] for all file links of the given assignment.
3636
* @param string $assignmentId
3737
* @return array<string, string>
3838
*/
@@ -42,7 +42,7 @@ public function getLinksMapForAssignment(string $assignmentId): array
4242
$result = [];
4343
foreach ($links as $link) {
4444
/** @var ExerciseFileLink $link */
45-
$result[$link->getKey()] = $link->getExerciseFile()->getId();
45+
$result[$link->getKey()] = $link->getId();
4646
}
4747
return $result;
4848
}

tests/Presenters/AssignmentsPresenter.phpt

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use App\Helpers\TmpFilesHelper;
2121
use App\Helpers\FileStorage\LocalFileStorage;
2222
use App\Helpers\FileStorage\LocalHashFileStorage;
2323
use App\V1Module\Presenters\AssignmentsPresenter;
24+
use App\Security\Roles;
2425
use Doctrine\ORM\EntityManagerInterface;
25-
use Nette\Utils\Json;
2626
use Tester\Assert;
2727
use App\Helpers\JobConfig;
2828
use App\Exceptions\NotFoundException;
@@ -628,6 +628,12 @@ class TestAssignmentsPresenter extends Tester\TestCase
628628
/** @var Exercise $exercise */
629629
$exercise = array_pop($exercises);
630630

631+
// original links of the exercise indexed by keys
632+
$exerciseLinks = [];
633+
foreach ($exercise->getFileLinks() as $link) {
634+
$exerciseLinks[$link->getKey()] = $link;
635+
}
636+
631637
/** @var Group $group */
632638
$group = $this->presenter->groups->findAll()[0];
633639

@@ -647,10 +653,24 @@ class TestAssignmentsPresenter extends Tester\TestCase
647653
$viewFactory->getAssignment($this->presenter->assignments->findOneBy(['id' => $payload["id"]])),
648654
$payload
649655
);
650-
Assert::count(2, $payload['localizedTextsLinks']);
651-
$keys = array_keys($payload['localizedTextsLinks']);
652-
sort($keys);
653-
Assert::same(['LIB', 'ORIG'], $keys);
656+
Assert::count(count($exerciseLinks), $payload['localizedTextsLinks']);
657+
foreach ($payload['localizedTextsLinks'] as $key => $linkId) {
658+
Assert::true(array_key_exists($key, $exerciseLinks));
659+
Assert::notEqual($exerciseLinks[$key]->getId(), $linkId); // new link should be created
660+
}
661+
662+
// verify the newly created file links in the assignment
663+
$assignment = $this->presenter->assignments->get($payload["id"]);
664+
Assert::count(count($exerciseLinks), $assignment->getFileLinks());
665+
foreach ($assignment->getFileLinks() as $link) {
666+
Assert::true(array_key_exists($link->getKey(), $exerciseLinks));
667+
$origLink = $exerciseLinks[$link->getKey()];
668+
Assert::notSame($origLink->getId(), $link->getId());
669+
Assert::null($link->getExercise());
670+
Assert::equal($origLink->getExerciseFile()->getId(), $link->getExerciseFile()->getId());
671+
Assert::equal($origLink->getSaveName(), $link->getSaveName());
672+
Assert::equal($origLink->getRequiredRole(), $link->getRequiredRole());
673+
}
654674
}
655675

656676
public function testCreateAssignmentFromLockedExercise()
@@ -755,22 +775,36 @@ class TestAssignmentsPresenter extends Tester\TestCase
755775
wall-time: 44
756776
";
757777

778+
$exercises = array_filter(
779+
$this->presenter->exercises->findAll(),
780+
function (Exercise $e) {
781+
return !$e->getFileLinks()->isEmpty(); // select the exercise with file links
782+
}
783+
);
784+
Assert::count(1, $exercises);
758785
/** @var Exercise $exercise */
759-
$exercise = $this->presenter->exercises->findAll()[0];
786+
$exercise = array_pop($exercises);
787+
760788
$exerciseLimits = new ExerciseLimits($environment, $hwGroup, $limits, $user);
761789
$this->em->persist($exerciseLimits);
762790

763791
$exercise->addExerciseLimits($exerciseLimits);
764792
$assignment = Assignment::assignToGroup($exercise, $group);
765793
$this->em->persist($assignment);
766-
767794
$this->em->flush();
768795

769796
$newExerciseLimits = new ExerciseLimits($environment, $hwGroup, $newLimits, $user);
770797
$this->em->persist($newExerciseLimits);
771798
$exercise->clearExerciseLimits();
772799
$exercise->addExerciseLimits($newExerciseLimits);
773800

801+
$exercise->getFileLinks()->removeElement($exercise->getFileLinks()->first());
802+
Assert::count(1, $exercise->getFileLinks());
803+
$link = $exercise->getFileLinks()->first();
804+
$link->setKey("NEW");
805+
$link->setRequiredRole(Roles::SUPERVISOR_ROLE);
806+
$this->em->persist($link);
807+
$this->em->persist($exercise);
774808
$this->em->flush();
775809

776810
$request = new Nette\Application\Request(
@@ -785,6 +819,12 @@ class TestAssignmentsPresenter extends Tester\TestCase
785819

786820
Assert::same($assignment->getId(), $data["id"]);
787821
Assert::same($newExerciseLimits, $assignment->getLimitsByEnvironmentAndHwGroup($environment, $hwGroup));
822+
Assert::count(1, $assignment->getFileLinks());
823+
$newLink = $assignment->getFileLinks()->first();
824+
Assert::equal("NEW", $newLink->getKey());
825+
Assert::equal(Roles::SUPERVISOR_ROLE, $newLink->getRequiredRole());
826+
Assert::equal($link->getExerciseFile()->getId(), $newLink->getExerciseFile()->getId());
827+
Assert::null($newLink->getExercise());
788828
}
789829

790830
public function testRemove()

tests/Presenters/ExerciseFilesPresenter.phpt

Lines changed: 131 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ use App\Helpers\FileStorage\LocalHashFileStorage;
88
use App\Helpers\FileStorage\LocalImmutableFile;
99
use App\Helpers\ExercisesConfig;
1010
use App\Helpers\TmpFilesHelper;
11+
use App\Model\Entity\Assignment;
1112
use App\Model\Entity\AttachmentFile;
1213
use App\Model\Entity\Exercise;
1314
use App\Model\Entity\ExerciseFileLink;
1415
use App\Model\Entity\UploadedFile;
16+
use App\Model\Repository\Assignments;
17+
use App\Model\Repository\AttachmentFiles;
18+
use App\Model\Repository\Exercises;
19+
use App\Model\Repository\ExerciseFiles;
20+
use App\Model\Repository\Groups;
21+
use App\Model\Repository\Logins;
1522
use App\V1Module\Presenters\ExerciseFilesPresenter;
1623
use App\Model\Entity\ExerciseFile;
1724
use Doctrine\ORM\EntityManagerInterface;
@@ -33,19 +40,24 @@ class TestExerciseFilesPresenter extends Tester\TestCase
3340
/** @var Nette\DI\Container */
3441
protected $container;
3542

36-
/** @var App\Model\Repository\ExerciseFiles */
43+
/** @var ExerciseFiles */
3744
protected $exerciseFiles;
3845

39-
/** @var App\Model\Repository\Logins */
46+
/** @var Logins */
4047
protected $logins;
4148

4249
/** @var Nette\Security\User */
4350
private $user;
4451

45-
/** @var App\Model\Repository\Exercises */
52+
/** @var Assignments */
53+
protected $assignments;
54+
/** @var Groups */
55+
protected $groups;
56+
57+
/** @var Exercises */
4658
protected $exercises;
4759

48-
/** @var App\Model\Repository\AttachmentFiles */
60+
/** @var AttachmentFiles */
4961
protected $attachmentFiles;
5062

5163
public function __construct()
@@ -54,10 +66,12 @@ class TestExerciseFilesPresenter extends Tester\TestCase
5466
$this->container = $container;
5567
$this->em = PresenterTestHelper::getEntityManager($container);
5668
$this->user = $container->getByType(\Nette\Security\User::class);
57-
$this->exerciseFiles = $container->getByType(\App\Model\Repository\ExerciseFiles::class);
58-
$this->logins = $container->getByType(\App\Model\Repository\Logins::class);
59-
$this->exercises = $container->getByType(App\Model\Repository\Exercises::class);
60-
$this->attachmentFiles = $container->getByType(\App\Model\Repository\AttachmentFiles::class);
69+
$this->assignments = $container->getByType(Assignments::class);
70+
$this->attachmentFiles = $container->getByType(AttachmentFiles::class);
71+
$this->exercises = $container->getByType(Exercises::class);
72+
$this->exerciseFiles = $container->getByType(ExerciseFiles::class);
73+
$this->groups = $container->getByType(Groups::class);
74+
$this->logins = $container->getByType(Logins::class);
6175

6276
// patch container, since we cannot create actual file storage manager
6377
$fsName = current($this->container->findByType(FileStorageManager::class));
@@ -142,6 +156,115 @@ class TestExerciseFilesPresenter extends Tester\TestCase
142156
}
143157
}
144158

159+
public function testExerciseFilesUploadOverload()
160+
{
161+
PresenterTestHelper::loginDefaultAdmin($this->container);
162+
163+
$user = $this->presenter->users->getByEmail(PresenterTestHelper::ADMIN_LOGIN);
164+
$exercise = current(array_filter(
165+
$this->presenter->exercises->findAll(),
166+
function ($exercise) {
167+
return !$exercise->getFileLinks()->isEmpty();
168+
}
169+
));
170+
Assert::truthy($exercise);
171+
172+
$oldFiles = [];
173+
foreach ($exercise->getExerciseFiles() as $file) {
174+
/** @var ExerciseFile $file */
175+
$oldFiles[$file->getName()] = $file->getId();
176+
}
177+
$oldFile = $exercise->getFileLinks()->first()->getExerciseFile();
178+
$oldLinks = [];
179+
foreach ($exercise->getFileLinks() as $link) {
180+
if ($link->getExerciseFile()->getId() === $oldFile->getId()) {
181+
$oldLinks[$link->getKey()] = $link;
182+
}
183+
}
184+
185+
// make an assignment (so we can check it is left unchanged)
186+
$group = current($this->groups->findAll());
187+
Assert::truthy($group);
188+
189+
$assignment = Assignment::assignToGroup($exercise, $group, true, null);
190+
$this->assignments->persist($assignment);
191+
$assignmentFiles = [];
192+
foreach ($assignment->getExerciseFiles() as $file) {
193+
/** @var ExerciseFile $file */
194+
$assignmentFiles[$file->getName()] = $file->getId();
195+
}
196+
$assignmentLinks = $this->presenter->fileLinks->getLinksMapForAssignment($assignment->getId());
197+
198+
// prepare a new file
199+
$filename = $oldFile->getName();
200+
$file = new UploadedFile($filename, new \DateTime(), 42, $user);
201+
$this->presenter->uploadedFiles->persist($file);
202+
$this->presenter->uploadedFiles->flush();
203+
204+
// Mock file server setup
205+
$fileStorage = Mockery::mock(FileStorageManager::class);
206+
$fileStorage->shouldReceive("storeUploadedExerciseFile")->with($file)->once();
207+
$this->presenter->fileStorage = $fileStorage;
208+
209+
$payload = PresenterTestHelper::performPresenterRequest(
210+
$this->presenter,
211+
"V1:ExerciseFiles",
212+
"POST",
213+
[
214+
"action" => 'uploadExerciseFiles',
215+
'id' => $exercise->getId()
216+
],
217+
[
218+
'files' => [$file->getId()]
219+
]
220+
);
221+
222+
// number of files hasn't changed
223+
Assert::count(count($oldFiles), $payload);
224+
foreach ($payload as $item) {
225+
Assert::type(App\Model\Entity\ExerciseFile::class, $item);
226+
}
227+
228+
// all files (except the overloaded one) are unchanged, the overloaded one is new
229+
$newFileId = null;
230+
$this->presenter->exercises->refresh($exercise);
231+
Assert::count(count($oldFiles), $exercise->getExerciseFiles());
232+
foreach ($exercise->getExerciseFiles() as $file) {
233+
/** @var ExerciseFile $file */
234+
Assert::true(array_key_exists($file->getName(), $oldFiles));
235+
if ($file->getName() !== $filename) {
236+
Assert::equal($oldFiles[$file->getName()], $file->getId());
237+
} else {
238+
Assert::notEqual($oldFiles[$file->getName()], $file->getId());
239+
Assert::equal(42, $file->getFileSize());
240+
$newFileId = $file->getId();
241+
}
242+
}
243+
Assert::truthy($newFileId);
244+
245+
// links has been properly updated
246+
foreach ($exercise->getFileLinks() as $link) {
247+
/** @var ExerciseFileLink $link */
248+
Assert::true(array_key_exists($link->getKey(), $oldLinks));
249+
$oldLink = $oldLinks[$link->getKey()];
250+
Assert::equal($oldLink->getSaveName(), $link->getSaveName());
251+
Assert::equal($oldLink->getRequiredRole(), $link->getRequiredRole());
252+
Assert::equal($newFileId, $link->getExerciseFile()->getId());
253+
}
254+
255+
// assignment is unchanged
256+
$this->presenter->assignments->refresh($assignment);
257+
Assert::count(count($assignmentFiles), $assignment->getExerciseFiles());
258+
foreach ($assignment->getExerciseFiles() as $file) {
259+
/** @var ExerciseFile $file */
260+
Assert::true(array_key_exists($file->getName(), $assignmentFiles));
261+
Assert::equal($assignmentFiles[$file->getName()], $file->getId());
262+
}
263+
264+
$newAssignmentLinks = $this->presenter->fileLinks->getLinksMapForAssignment($assignment->getId());
265+
Assert::same($assignmentLinks, $newAssignmentLinks);
266+
}
267+
145268
public function testUploadTooManyExerciseFiles()
146269
{
147270
$user = $this->presenter->users->getByEmail(PresenterTestHelper::ADMIN_LOGIN);

tests/Presenters/ExercisesPresenter.phpt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,9 +690,20 @@ class TestExercisesPresenter extends Tester\TestCase
690690
PresenterTestHelper::loginDefaultAdmin($this->container);
691691

692692
$user = $this->logins->getUser(PresenterTestHelper::ADMIN_LOGIN, PresenterTestHelper::ADMIN_PASSWORD, new Nette\Security\Passwords());
693-
$exercise = current($this->presenter->exercises->findAll());
694693
$group = current($this->presenter->groups->findAll());
695694

695+
$exercises = array_filter($this->presenter->exercises->findAll(), function ($e) {
696+
return !$e->isArchived() && !$e->getFileLinks()->isEmpty();
697+
});
698+
$exercise = current($exercises);
699+
Assert::truthy($exercise);
700+
701+
// original links of the exercise indexed by keys
702+
$exerciseLinks = [];
703+
foreach ($exercise->getFileLinks() as $link) {
704+
$exerciseLinks[$link->getKey()] = $link;
705+
}
706+
696707
$request = new Nette\Application\Request(
697708
'V1:Exercises',
698709
'POST',
@@ -715,6 +726,26 @@ class TestExercisesPresenter extends Tester\TestCase
715726
Assert::equal($user->getId(), $forked["authorId"]);
716727
Assert::equal(1, count($forked["groupsIds"]));
717728
Assert::equal($group->getId(), $forked["groupsIds"][0]);
729+
730+
Assert::count(count($exerciseLinks), $forked["localizedTextsLinks"]);
731+
foreach ($forked["localizedTextsLinks"] as $key => $link) {
732+
Assert::true(array_key_exists($key, $exerciseLinks));
733+
Assert::notEqual($exerciseLinks[$key]->getId(), $link); // different link
734+
}
735+
736+
$forked = $this->presenter->exercises->get($forked["id"]);
737+
Assert::truthy($forked);
738+
739+
Assert::count(count($exerciseLinks), $forked->getFileLinks());
740+
foreach ($forked->getFileLinks() as $link) {
741+
Assert::true(array_key_exists($link->getKey(), $exerciseLinks));
742+
$origLink = $exerciseLinks[$link->getKey()];
743+
Assert::notSame($origLink->getId(), $link->getId());
744+
Assert::null($link->getAssignment());
745+
Assert::equal($origLink->getExerciseFile()->getId(), $link->getExerciseFile()->getId());
746+
Assert::equal($origLink->getSaveName(), $link->getSaveName());
747+
Assert::equal($origLink->getRequiredRole(), $link->getRequiredRole());
748+
}
718749
}
719750

720751
public function testHardwareGroups()

0 commit comments

Comments
 (0)