diff --git a/sourcecode/apis/contentauthor/app/Article.php b/sourcecode/apis/contentauthor/app/Article.php index fd4285f2cc..255f8c7efd 100644 --- a/sourcecode/apis/contentauthor/app/Article.php +++ b/sourcecode/apis/contentauthor/app/Article.php @@ -43,8 +43,8 @@ * * @property Collection $collaborators * - * @method null|self noMaxScore() - * @method null|self ofBulkCalculated($type) + * @method static Builder|null|self noMaxScore() + * @method static Builder|null|self ofBulkCalculated($type) * @method static self find($id, $columns = ['*']) * @method static self findOrFail($id, $columns = ['*']) */ diff --git a/sourcecode/apis/contentauthor/app/Content.php b/sourcecode/apis/contentauthor/app/Content.php index 78dfd7d44f..08db50dcdd 100644 --- a/sourcecode/apis/contentauthor/app/Content.php +++ b/sourcecode/apis/contentauthor/app/Content.php @@ -341,7 +341,7 @@ public function getOwnerData(): ResourceUserDataObject if ($ownerData) { $user->firstname = $ownerData->getFirstName() ?? ''; - $user->lastName = $ownerData->getLastName() ?? ''; + $user->lastname = $ownerData->getLastName() ?? ''; $user->email = $ownerData->getEmail() ?? ''; } diff --git a/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php b/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php index 074955d33a..fecbe502e7 100644 --- a/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php +++ b/sourcecode/apis/contentauthor/app/H5PContentsMetadata.php @@ -57,7 +57,7 @@ public function convertToMetadataObject($title = null): H5PMetadataObject 'licenseVersion' => $this->license_version, 'licenseExtras' => $this->license_extras, 'authorComments' => $this->author_comments, - 'changes' => $this->changes, + 'changes' => $this->getAttribute('changes'), // 'changes' conflicts with Eloquent variable that holds changed model attributes 'defaultLanguage' => $this->default_language, ]); } diff --git a/sourcecode/apis/contentauthor/app/H5PLibrary.php b/sourcecode/apis/contentauthor/app/H5PLibrary.php index 434d0bca5d..6c4e9f563b 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibrary.php +++ b/sourcecode/apis/contentauthor/app/H5PLibrary.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; @@ -26,7 +27,29 @@ * @see H5PLibrary::scopeVersion() * @method static Builder|static version($majorVersion, $minorVersion) * - * @method static find($id, $columns = ['*']) + * @method static static find($id, $columns = ['*']) + * + * @property int $id + * @property Carbon $created_at + * @property Carbon $updated_at + * @property string $name H5P machinename + * @property string $title + * @property int $major_version + * @property int $minor_version + * @property int $patch_version + * @property int $runnable + * @property int $restricted + * @property int $fullscreen + * @property string $embed_types + * @property string $preloaded_js + * @property string $preloaded_css + * @property string $drop_library_css + * @property string $semantics + * @property string $tutorial_url + * @property int $has_icon + * @property string $metadata_settings + * @property string $add_to + * @property bool $patch_version_in_folder_name */ class H5PLibrary extends Model { diff --git a/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php b/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php index d58e53d531..85bcba0b09 100644 --- a/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php +++ b/sourcecode/apis/contentauthor/app/H5PLibraryLanguage.php @@ -3,11 +3,14 @@ namespace App; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class H5PLibraryLanguage extends Model { + use HasFactory; + protected $table = 'h5p_libraries_languages'; protected $fillable = [ diff --git a/sourcecode/apis/contentauthor/app/Http/Middleware/CheckOwnership.php b/sourcecode/apis/contentauthor/app/Http/Middleware/CheckOwnership.php index 84bd59e5a2..c8b38be855 100644 --- a/sourcecode/apis/contentauthor/app/Http/Middleware/CheckOwnership.php +++ b/sourcecode/apis/contentauthor/app/Http/Middleware/CheckOwnership.php @@ -29,13 +29,15 @@ public function handle($request, Closure $next) return $next($request); } } - Log::error(__METHOD__ . ': Access denied. H5P: ' . $this->request->h5p - . ' is not owned or shared with user:' . Session::get('authId', 'not-logged-in-user')); - Log::error([ - 'user' => Session::get('userId', 'not-logged-in-user'), - 'url' => request()->url(), - 'request' => request()->all() - ]); + Log::error( + __METHOD__ . ': Access denied. H5P: ' . $this->request->h5p + . ' is not owned or shared with user:' . Session::get('authId', 'not-logged-in-user'), + [ + 'user' => Session::get('userId', 'not-logged-in-user'), + 'url' => request()->url(), + 'request' => request()->all() + ] + ); abort(403, 'Access denied, you are not the owner of the resource or it is not shared with you.'); } diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/ContentType/BaseH5PContent.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/ContentType/BaseH5PContent.php index 757fc6df7a..be415d00e6 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/ContentType/BaseH5PContent.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/ContentType/BaseH5PContent.php @@ -29,7 +29,7 @@ public function __construct() public function setId($id, $hashId = true) { - $this->id = $this->libraryId . '-' . $hashId ? md5($id) : $id; + $this->id = $this->libraryId . '-' . ($hashId ? md5($id) : $id); return $this; } diff --git a/sourcecode/apis/contentauthor/app/Libraries/H5P/Framework.php b/sourcecode/apis/contentauthor/app/Libraries/H5P/Framework.php index 9c74f31dd2..67f31c48b8 100644 --- a/sourcecode/apis/contentauthor/app/Libraries/H5P/Framework.php +++ b/sourcecode/apis/contentauthor/app/Libraries/H5P/Framework.php @@ -414,18 +414,13 @@ public function getWhitelist($isLibrary, $defaultContentWhitelist, $defaultLibra /** * Is the library a patched version of an existing library? * - * @param object $library - * An associateve array containing: - * - machineName: The library machineName - * - majorVersion: The librarys majorVersion - * - minorVersion: The librarys minorVersion - * - patchVersion: The librarys patchVersion - * @return boolean + * @param array{machineName: string, majorVersion: int, minorVersion: int, patchVersion: int} $library + * @return bool * TRUE if the library is a patched version of an existing library * FALSE otherwise * TODO: Implement this for real.... */ - public function isPatchedLibrary($library) + public function isPatchedLibrary($library): bool { return H5PLibrary::fromLibrary([ $library['machineName'], @@ -433,8 +428,7 @@ public function isPatchedLibrary($library) $library['minorVersion'] ]) ->where('patch_version', "<", $library['patchVersion']) - ->get() - ->isNotEmpty(); + ->exists(); } /** @@ -1156,16 +1150,10 @@ public function getNumContent($libraryId, $skip = null) * Determines if content slug is used. * * @param string $slug - * @return boolean */ - public function isContentSlugAvailable($slug) + public function isContentSlugAvailable($slug): bool { - $sql = "select slug from h5p_contents where slug=?"; - $res = $this->db->prepare($sql)->execute([$slug])->fetch(PDO::FETCH_ASSOC); - if (sizeof($res) > 0) { - return false; - } - return true; + return H5PContent::where('slug', $slug)->doesntExist(); } /** diff --git a/sourcecode/apis/contentauthor/app/User.php b/sourcecode/apis/contentauthor/app/User.php index e010aa7170..0b719c47ae 100644 --- a/sourcecode/apis/contentauthor/app/User.php +++ b/sourcecode/apis/contentauthor/app/User.php @@ -14,6 +14,7 @@ /** * A dummy user that is not actually bound to a database table. * + * @property string $auth_id * @property string $name * @property string $email * @property string $password diff --git a/sourcecode/apis/contentauthor/database/factories/H5PLibraryLanguageFactory.php b/sourcecode/apis/contentauthor/database/factories/H5PLibraryLanguageFactory.php new file mode 100644 index 0000000000..d6a0f64ec5 --- /dev/null +++ b/sourcecode/apis/contentauthor/database/factories/H5PLibraryLanguageFactory.php @@ -0,0 +1,23 @@ + + */ +class H5PLibraryLanguageFactory extends Factory +{ + public function definition(): array + { + return [ + 'library_id' => $this->faker->numberBetween(), + 'language_code' => $this->faker->unique()->languageCode(), + 'translation' => '', + ]; + } +} diff --git a/sourcecode/apis/contentauthor/database/factories/UserFactory.php b/sourcecode/apis/contentauthor/database/factories/UserFactory.php index 201a0eebc2..b19c442659 100644 --- a/sourcecode/apis/contentauthor/database/factories/UserFactory.php +++ b/sourcecode/apis/contentauthor/database/factories/UserFactory.php @@ -2,8 +2,12 @@ namespace Database\Factories; +use App\User; use Illuminate\Database\Eloquent\Factories\Factory; +/** + * @template-extends Factory + */ class UserFactory extends Factory { public function definition(): array diff --git a/sourcecode/apis/contentauthor/phpstan-baseline.neon b/sourcecode/apis/contentauthor/phpstan-baseline.neon index 5c0020acc5..07fe1900ad 100644 --- a/sourcecode/apis/contentauthor/phpstan-baseline.neon +++ b/sourcecode/apis/contentauthor/phpstan-baseline.neon @@ -50,11 +50,6 @@ parameters: count: 1 path: app/Content.php - - - message: "#^Access to an undefined property App\\\\Libraries\\\\DataObjects\\\\ResourceUserDataObject\\:\\:\\$lastName\\.$#" - count: 1 - path: app/Content.php - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#" count: 3 @@ -285,11 +280,6 @@ parameters: count: 1 path: app/Http/Controllers/Admin/LibraryUpgradeController.php - - - message: "#^Parameter \\#1 \\$library of method H5PFrameworkInterface\\:\\:isPatchedLibrary\\(\\) expects object, array\\ given\\.$#" - count: 1 - path: app/Http/Controllers/Admin/LibraryUpgradeController.php - - message: "#^Expression on left side of \\?\\? is not nullable\\.$#" count: 1 @@ -610,11 +600,6 @@ parameters: count: 3 path: app/Libraries/H5P/AjaxRequest.php - - - message: "#^Ternary operator condition is always true\\.$#" - count: 1 - path: app/Libraries/H5P/ContentType/BaseH5PContent.php - - message: "#^Access to an undefined property App\\\\H5PLibrary\\:\\:\\$isOld\\.$#" count: 1 @@ -670,16 +655,6 @@ parameters: count: 3 path: app/Libraries/H5P/Framework.php - - - message: "#^Called 'isNotEmpty' on Laravel collection, but could have been retrieved as a query\\.$#" - count: 1 - path: app/Libraries/H5P/Framework.php - - - - message: "#^Cannot call method fetch\\(\\) on bool\\.$#" - count: 1 - path: app/Libraries/H5P/Framework.php - - message: "#^Expression on left side of \\?\\? is not nullable\\.$#" count: 1 @@ -736,11 +711,6 @@ parameters: count: 1 path: app/Libraries/H5P/Framework.php - - - message: "#^Call to method toArray\\(\\) on an unknown class Cerpus\\\\Helper\\\\Traits\\\\CreateTrait\\.$#" - count: 1 - path: app/Libraries/H5P/H5PCopyright.php - - message: "#^Left side of && is always true\\.$#" count: 1 @@ -1126,157 +1096,7 @@ parameters: count: 1 path: database/migrations/2020_12_07_133958_set_admin_password.php - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" - count: 10 - path: tests/Integration/Article/ArticleVersioningTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#" - count: 11 - path: tests/Integration/Article/ArticleVersioningTest.php - - - - message: "#^Called 'count' on Laravel collection, but could have been retrieved as a query\\.$#" - count: 2 - path: tests/Integration/Article/ArticleVersioningTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" - count: 2 - path: tests/Integration/Content/ContentTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" - count: 10 - path: tests/Integration/Content/LockStatusTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" - count: 5 - path: tests/Integration/Content/UnlockTest.php - - - - message: "#^Access to an undefined property App\\\\H5PLibrary\\:\\:\\$type\\.$#" - count: 1 - path: tests/Integration/Http/Controllers/ArticleCopyrightControllerTest.php - - - - message: "#^Parameter \\#1 \\$id of class App\\\\ApiModels\\\\User constructor expects string, int given\\.$#" - count: 2 - path: tests/Integration/Http/Controllers/GameControllerTest.php - - - - message: "#^Parameter \\#1 \\$id of class App\\\\ApiModels\\\\User constructor expects string, int given\\.$#" - count: 1 - path: tests/Integration/Http/Controllers/H5PControllerTest.php - - - - message: "#^Parameter \\#1 \\$id of class App\\\\ApiModels\\\\User constructor expects string, int given\\.$#" - count: 2 - path: tests/Integration/Http/Controllers/LinkControllerTest.php - - - - message: "#^Parameter \\#1 \\$id of class App\\\\ApiModels\\\\User constructor expects string, int given\\.$#" - count: 2 - path: tests/Integration/Http/Controllers/QuestionSetControllerTest.php - - - - message: "#^Variable \\$questionSetController in PHPDoc tag @var does not match assigned variable \\$questionsetController\\.$#" - count: 1 - path: tests/Integration/Http/Controllers/QuestionSetControllerTest.php - - - - message: "#^Property Tests\\\\Integration\\\\Jobs\\\\PingVideoApiTest\\:\\:\\$disk \\(Illuminate\\\\Filesystem\\\\FilesystemAdapter\\) does not accept Illuminate\\\\Contracts\\\\Filesystem\\\\Filesystem\\.$#" - count: 1 - path: tests/Integration/Jobs/PingVideoApiTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" - count: 7 - path: tests/Integration/Libraries/H5P/API/H5PImportControllerTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$auth_id\\.$#" - count: 18 - path: tests/Integration/Libraries/H5P/CRUTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$email\\.$#" - count: 27 - path: tests/Integration/Libraries/H5P/CRUTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$name\\.$#" - count: 14 - path: tests/Integration/Libraries/H5P/CRUTest.php - - - - message: "#^Access to an undefined property Tests\\\\Integration\\\\Libraries\\\\H5P\\\\CRUTest\\:\\:\\$editorFilesDirectory\\.$#" - count: 1 - path: tests/Integration/Libraries/H5P/CRUTest.php - - - - message: "#^Call to method toArray\\(\\) on an unknown class Cerpus\\\\Helper\\\\Traits\\\\CreateTrait\\.$#" - count: 4 - path: tests/Integration/Libraries/H5P/H5PCopyrightTest.php - - - - message: "#^Access to an undefined property Faker\\\\Generator\\:\\:\\$mimeType\\.$#" - count: 1 - path: tests/Integration/Libraries/H5P/Package/ColumnTest.php - - - - message: "#^Access to an undefined property Faker\\\\Generator\\:\\:\\$mimeType\\.$#" - count: 3 - path: tests/Integration/Libraries/H5P/Package/CoursePresentationTest.php - - message: "#^Unreachable statement \\- code above always terminates\\.$#" count: 1 path: tests/Integration/Libraries/H5P/Package/MultiChoiceTest.php - - - - message: "#^Access to an undefined property Faker\\\\Generator\\:\\:\\$mimeType\\.$#" - count: 1 - path: tests/Integration/Libraries/H5P/Package/VideoTest.php - - - - message: "#^Parameter \\$share of class App\\\\Libraries\\\\DataObjects\\\\ResourceMetadataDataObject constructor expects string\\|null, true given\\.$#" - count: 2 - path: tests/Integration/Libraries/QuestionSetConverterTest.php - - - - message: "#^Parameter \\#1 \\$attribution of method App\\\\Content\\:\\:setAttribution\\(\\) expects App\\\\Libraries\\\\DataObjects\\\\Attribution, string given\\.$#" - count: 1 - path: tests/Integration/Models/ContentAttributionTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$id\\.$#" - count: 2 - path: tests/Integration/Models/H5PContentRequestShouldBecomeNewVersionTest.php - - - - message: "#^Access to an undefined property Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$title\\.$#" - count: 6 - path: tests/Integration/Models/H5PContentRequestShouldBecomeNewVersionTest.php - - - - message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:getContentLicense\\(\\)\\.$#" - count: 7 - path: tests/Integration/Models/H5PContentRequestShouldBecomeNewVersionTest.php - - - - message: "#^Call to an undefined method Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:requestShouldBecomeNewVersion\\(\\)\\.$#" - count: 12 - path: tests/Integration/Models/H5PContentRequestShouldBecomeNewVersionTest.php - - - - message: "#^Call to an undefined method Tests\\\\TestCase\\:\\:setUpMockMQ\\(\\)\\.$#" - count: 1 - path: tests/TestCase.php - - - - message: "#^Method Tests\\\\TestCase\\:\\:setUpTraits\\(\\) should return array but return statement is missing\\.$#" - count: 1 - path: tests/TestCase.php diff --git a/sourcecode/apis/contentauthor/phpstan.neon.dist b/sourcecode/apis/contentauthor/phpstan.neon.dist index 53bae1bb18..67f08b24b3 100644 --- a/sourcecode/apis/contentauthor/phpstan.neon.dist +++ b/sourcecode/apis/contentauthor/phpstan.neon.dist @@ -17,6 +17,8 @@ parameters: stubFiles: - stubs/h5p-core/H5PCore.stub - stubs/h5p-core/H5PExport.stub + - stubs/h5p-core/H5PFrameworkInterface.stub + - stubs/cerpus/CreateTrait.stub banned_code: nodes: - diff --git a/sourcecode/apis/contentauthor/stubs/cerpus/CreateTrait.stub b/sourcecode/apis/contentauthor/stubs/cerpus/CreateTrait.stub new file mode 100644 index 0000000000..e313e7cc12 --- /dev/null +++ b/sourcecode/apis/contentauthor/stubs/cerpus/CreateTrait.stub @@ -0,0 +1,15 @@ +createPartialMock(ResourceManagerInterface::class, ['save']); app()->instance(ResourceManagerInterface::class, $manager); diff --git a/sourcecode/apis/contentauthor/tests/Helpers/MockRabbitMQPubsub.php b/sourcecode/apis/contentauthor/tests/Helpers/MockRabbitMQPubsub.php index 3f880f73e6..0585361cc3 100644 --- a/sourcecode/apis/contentauthor/tests/Helpers/MockRabbitMQPubsub.php +++ b/sourcecode/apis/contentauthor/tests/Helpers/MockRabbitMQPubsub.php @@ -6,7 +6,7 @@ trait MockRabbitMQPubsub { - public function setupRabbitMQPubSub() + public function setupMockRabbitMQPubsub(): void { $rabbitMQMock = $this->getMockBuilder(RabbitMQPubSub::class)->disableOriginalConstructor()->getMock(); $this->instance(RabbitMQPubSub::class, $rabbitMQMock); diff --git a/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleTest.php b/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleTest.php index 0512e6e97d..7a68bd0f1b 100755 --- a/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleTest.php @@ -25,7 +25,6 @@ class ArticleTest extends TestCase public function testRewriteUploadUrls(): void { - /** @var Article $article */ $article = Article::factory()->create([ 'content' => '

This is an image:

', ]); @@ -38,7 +37,6 @@ public function testRewriteUploadUrls(): void public function testLeavesNonUploadUrlsAlone(): void { - /** @var Article $article */ $article = Article::factory()->create([ 'content' => '

This is an image:

', ]); @@ -51,7 +49,6 @@ public function testLeavesNonUploadUrlsAlone(): void public function testRendersArticleWithBrokenHtml(): void { - /** @var Article $article */ $article = Article::factory()->create([ 'content' => '
Foo
bar', ]); @@ -181,7 +178,6 @@ public function testEditArticle() ]); Event::fake(); $authId = Str::uuid(); - /** @var Article $article */ $article = Article::factory()->create([ 'owner_id' => $authId, 'is_published' => 1, @@ -206,6 +202,7 @@ public function testEditArticle() 'license' => 'BY-NC', ]); + /** @var Article $newArticle */ $newArticle = Article::where('title', "Title") ->where('content', "Content") ->where('is_published', 1) @@ -264,6 +261,7 @@ public function testEditArticleWithDraftEnabled() 'license' => 'BY-ND', ]); + /** @var Article $article */ $article = Article::where('title', 'Title')->first(); $this->withSession(['authId' => $authId]) ->put(route('article.update', $article->id), [ @@ -274,6 +272,8 @@ public function testEditArticleWithDraftEnabled() 'isPublished' => 1, ])->assertStatus(Response::HTTP_CREATED); $this->assertDatabaseHas('articles', ['title' => 'Title', 'content' => 'Content', 'is_published' => 1]); + + /** @var Article $article */ $article = Article::where('title', 'Title') ->where('content', "Content") ->where('is_published', 1) @@ -287,7 +287,6 @@ public function testViewArticle() { $this->setupVersion(['getVersion' => false]); - /** @var Article $article */ $article = Article::factory()->create([ 'is_published' => 1, 'license' => 'BY', @@ -303,4 +302,82 @@ public function testMustBeLoggedInToCreateArticle() $this->get(route('article.create')) ->assertForbidden(); } + + public function testRewriteUrls() + { + $article = Article::factory()->create([ + 'content' => 'This is the original content', + ]); + + $originalUrl = 'original-url'; + $newUrl = 'new-url'; + + $article->content = 'This is the original content with the original URL: ' . $originalUrl; + $article->save(); + + $article->rewriteUrls($originalUrl, $newUrl); + + $this->assertStringNotContainsString($originalUrl, $article->content); + $this->assertStringContainsString($newUrl, $article->content); + } + + public function testParent() + { + $article = Article::factory()->create(); + + $parentArticle = Article::factory()->create(); + + $article->parent()->associate($parentArticle); + $article->save(); + + $retrievedParent = $article->parent; + + $this->assertEquals($parentArticle->id, $retrievedParent->id); + } + + public function testGetISO6393Language() + { + $article = Article::factory()->create(); + + $language = $article->getISO6393Language(); + + $this->assertEquals('eng', $language); + } + + public function testSetParentVersionId() + { + $article = Article::factory()->create([ + 'parent_version_id' => 'original_parent_version_id', + ]); + + $parentVersionId = 'new_parent_version_id'; + + $isChanged = $article->setParentVersionId($parentVersionId); + + $this->assertTrue($isChanged); + $this->assertEquals($parentVersionId, $article->parent_version_id); + } + + public function testScopeNoMaxScore() + { + Article::factory()->create(['max_score' => null]); + Article::factory()->create(['max_score' => 10]); + + $articles = Article::noMaxScore()->get(); + + $this->assertCount(1, $articles); + $this->assertNull($articles[0]->max_score); + } + + public function testScopeOfBulkCalculated() + { + Article::factory()->create(['bulk_calculated' => 0]); + Article::factory()->create(['bulk_calculated' => 1]); + Article::factory()->create(['bulk_calculated' => 2]); + + $articles = Article::ofBulkCalculated(1)->get(); + + $this->assertCount(1, $articles); + $this->assertEquals(1, $articles[0]->bulk_calculated); + } } diff --git a/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleVersioningTest.php b/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleVersioningTest.php index f31c0c9a01..0db6680eb0 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleVersioningTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Article/ArticleVersioningTest.php @@ -44,7 +44,7 @@ public function testDatabaseVersioning() ]); $authId = Str::uuid(); $article = Article::factory()->create(['owner_id' => $authId]); - $startCount = Article::all()->count(); + $startCount = Article::count(); $this->withSession(['authId' => $authId]) ->put(route('article.update', $article->id), [ 'title' => 'Title', @@ -58,7 +58,7 @@ public function testDatabaseVersioning() 'title' => $article->title, 'content' => $article->content, ]) - ->assertEquals($startCount + 1, Article::all()->count()) // New version added + ->assertEquals($startCount + 1, Article::count()) // New version added ; } @@ -198,6 +198,7 @@ public function testVersioning() $this->assertCount(3, Article::all()); $this->assertDatabaseHas('articles', ['title' => 'Another new title', 'owner_id' => $copyist->auth_id]); + /** @var Article $copiedArticle */ $copiedArticle = Article::where('owner_id', $copyist->auth_id)->first(); $this->assertDatabaseMissing('article_collaborators', ['article_id' => $copiedArticle->id]); $this->assertCount(2, ArticleCollaborator::all()); diff --git a/sourcecode/apis/contentauthor/tests/Integration/Content/ContentTest.php b/sourcecode/apis/contentauthor/tests/Integration/Content/ContentTest.php index da111b2e29..c93e7ccb05 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Content/ContentTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Content/ContentTest.php @@ -8,6 +8,7 @@ use App\H5PContent; use App\User; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Collection; use Tests\TestCase; class ContentTest extends TestCase @@ -23,9 +24,9 @@ public function setUp(): void public function test_ArticleIsCollaborator() { $user = User::factory()->make(); - /** @var Article $article */ $article = Article::factory()->create(['owner_id' => $user->auth_id]); - $collaborators =ArticleCollaborator::factory()->count(3)->make(); + /** @var Collection $collaborators */ + $collaborators = ArticleCollaborator::factory()->count(3)->make(); $article->collaborators()->saveMany($collaborators); $article = $article->fresh(); $this->assertCount(3, $article->collaborators); @@ -39,8 +40,8 @@ public function test_ArticleIsCollaborator() public function test_H5PIsCollaborator() { $user = User::factory()->make(); - /** @var H5PContent $h5p */ $h5p = H5PContent::factory()->create(['user_id' => $user->auth_id]); + /** @var Collection $collaborators */ $collaborators = H5PCollaborator::factory()->count(3)->make(); $h5p->collaborators()->saveMany($collaborators); $h5p = $h5p->fresh(); diff --git a/sourcecode/apis/contentauthor/tests/Integration/Content/LockStatusTest.php b/sourcecode/apis/contentauthor/tests/Integration/Content/LockStatusTest.php index b23a4a0cfc..89687ee3ab 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Content/LockStatusTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Content/LockStatusTest.php @@ -49,7 +49,7 @@ public function testLockStatusExpired() ] ); - $newArticle = Article::factory()->create([ + Article::factory()->create([ 'id' => '9655b7b5-0f2a-4664-a191-09d874a50cab', 'version_id' => '7313f894-4dba-4ea4-9896-9da549e2e88f', 'owner_id' => $user->auth_id, @@ -132,7 +132,7 @@ public function testYouNeedToBeLoggedIn() ->assertStatus(Response::HTTP_FORBIDDEN); } - private function setUpVersioningClient() + private function setUpVersioningClient(): void { $versionResponse = json_decode('{"data":{"id":"edb86ca1-0975-4a83-b19f-8d5df19d4919","externalSystem":"ContentAuthor","externalReference":"9655b7b5-0f2a-4664-a191-09d874a50cab","externalUrl":"http://content-author.local/article/9655b7b5-0f2a-4664-a191-09d874a50cab","children":[],"createdAt":1478589881606,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"7313f894-4dba-4ea4-9896-9da549e2e88f","externalSystem":"ContentAuthor","externalReference":"0800e3f5-d7a7-4add-a12a-16df86462837","externalUrl":"http://content-author.local/article/0800e3f5-d7a7-4add-a12a-16df86462837","createdAt":1478589812706,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"f86bcda0-743f-4c8d-9e95-c9549f2b2a2a","externalSystem":"ContentAuthor","externalReference":"f41325db-05ed-443d-9578-967d1ebc7854","externalUrl":"http://content-author.local/article/f41325db-05ed-443d-9578-967d1ebc7854","createdAt":1478589654506,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"5aae6917-a50b-4994-851b-8b9b1bf8033f","externalSystem":"ContentAuthor","externalReference":"b37b3fbc-723a-4d2d-a05b-7599a58ce727","externalUrl":"http://content-author.local/article/b37b3fbc-723a-4d2d-a05b-7599a58ce727","createdAt":1478589437523,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"65ae68cc-3d65-4330-9404-5cd839fda41b","externalSystem":"ContentAuthor","externalReference":"437f621e-dfd2-4e1d-a4fe-7b3498d61d3a","externalUrl":"http://content-author.local/article/437f621e-dfd2-4e1d-a4fe-7b3498d61d3a","createdAt":1478588405309,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"dc0c215b-0200-47fe-a94d-ad23ebfcf6ce","externalSystem":"ContentAuthor","externalReference":"46b91325-63b7-403d-851d-cff49e1ce208","externalUrl":"http://content-author.local/article/46b91325-63b7-403d-851d-cff49e1ce208","createdAt":1478588364003,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"2d588117-4e2f-4c58-a522-7a85f1e9fe2f","externalSystem":"ContentAuthor","externalReference":"eb6b3d62-2646-42d7-90c6-f29076fef595","externalUrl":"http://content-author.local/article/eb6b3d62-2646-42d7-90c6-f29076fef595","createdAt":1478588301779,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"e6f12a0e-2181-42b4-b56f-b8a3bcf2e0cb","externalSystem":"ContentAuthor","externalReference":"f79106b2-df61-4a18-ba5b-3edeeddf0665","externalUrl":"http://content-author.local/article/f79106b2-df61-4a18-ba5b-3edeeddf0665","createdAt":1478502495915,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"aaf48281-ea2f-4112-aec5-dbfe6cbb15d9","externalSystem":"ContentAuthor","externalReference":"23a3bd44-747d-4a04-b1ca-1dbe29c0603f","externalUrl":"http://content-author.local/article/23a3bd44-747d-4a04-b1ca-1dbe29c0603f","createdAt":1478502404055,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"b3d41080-1c09-42db-9112-d14ccfed4758","externalSystem":"ContentAuthor","externalReference":"6fa6f983-8837-4c89-a44c-2691c4c2eab5","externalUrl":"http://content-author.local/article/6fa6f983-8837-4c89-a44c-2691c4c2eab5","createdAt":1478262258218,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"8df35559-d03c-410c-b3c3-d977be29a51d","externalSystem":"ContentAuthor","externalReference":"488e383b-bc41-4793-ad44-1de8e21bbb64","externalUrl":"http://content-author.local/article/488e383b-bc41-4793-ad44-1de8e21bbb64","createdAt":1478261566014,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"fac65524-d683-4fce-87a9-32ac27590ded","externalSystem":"ContentAuthor","externalReference":"06731ef9-e7e9-451f-a1a3-511f0eda4573","externalUrl":"http://content-author.local/article/06731ef9-e7e9-451f-a1a3-511f0eda4573","createdAt":1478261455343,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"5933f730-160f-4ecc-a0e9-66091b37d56d","externalSystem":"ContentAuthor","externalReference":"37858341-0b5a-4531-920e-80673bc1e67e","externalUrl":"http://content-author.local/article/37858341-0b5a-4531-920e-80673bc1e67e","createdAt":1478255267412,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"15f06d83-98f2-4806-a5c9-6ff47d7499e8","externalSystem":"ContentAuthor","externalReference":"b1f2e737-1bb9-47b2-94c1-988e5dd660ab","externalUrl":"http://content-author.local/article/b1f2e737-1bb9-47b2-94c1-988e5dd660ab","createdAt":1478252474570,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"622244d8-fa03-4344-ae3f-538c0344b8bc","externalSystem":"ContentAuthor","externalReference":"9d671ae9-87b9-48e2-92ae-ced67fadd45e","externalUrl":"http://content-author.local/article/9d671ae9-87b9-48e2-92ae-ced67fadd45e","createdAt":1478165483705,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"8fcf8294-47e8-4071-9cce-7a184a145b42","externalSystem":"ContentAuthor","externalReference":"ee342b5e-4847-4411-a06b-c013bac4e995","externalUrl":"http://content-author.local/article/ee342b5e-4847-4411-a06b-c013bac4e995","createdAt":1478165386208,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"15c8c457-6293-4581-a10d-b46e81675c78","externalSystem":"ContentAuthor","externalReference":"1ac48d0d-8d08-415b-b6d6-4f0d4fb9d2c8","externalUrl":"http://content-author.local/article/1ac48d0d-8d08-415b-b6d6-4f0d4fb9d2c8","createdAt":1478073565703,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"ffaf8772-0375-4dee-b915-591be6615a6b","externalSystem":"ContentAuthor","externalReference":"45680171-ccb9-45c9-b6e2-3c5ed857eb04","externalUrl":"http://content-author.local/article/45680171-ccb9-45c9-b6e2-3c5ed857eb04","createdAt":1477988675074,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"afdccfa1-d6cb-4e1a-82a1-5c4d6580f382","externalSystem":"ContentAuthor","externalReference":"7ffbab30-8bed-40fd-8059-d1bcf1092e13","externalUrl":"http://content-author.local/article/7ffbab30-8bed-40fd-8059-d1bcf1092e13","createdAt":1477988628640,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"4a940f93-859b-40f1-967f-046869d30d4a","externalSystem":"ContentAuthor","externalReference":"14d45db2-af69-4962-b69f-80c338745ac1","externalUrl":"http://content-author.local/article/14d45db2-af69-4962-b69f-80c338745ac1","createdAt":1477987902990,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"117b521b-5324-4056-831e-8624b0edf06f","externalSystem":"ContentAuthor","externalReference":"5ca53073-a21f-4929-a979-b2c11e890ee1","externalUrl":"http://content-author.local/article/5ca53073-a21f-4929-a979-b2c11e890ee1","createdAt":1477984600460,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"ab4ac2c2-4331-4561-b820-5748cde13985","externalSystem":"ContentAuthor","externalReference":"a07c2ae5-1613-4b8c-a2b6-65e0d774ea2d","externalUrl":"http://content-author.local/article/a07c2ae5-1613-4b8c-a2b6-65e0d774ea2d","createdAt":1477983778237,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"21f412f3-1e31-4abf-b301-87ec84a163a1","externalSystem":"ContentAuthor","externalReference":"645b95ba-e974-4030-9109-474f5979cd79","externalUrl":"http://content-author.local/article/645b95ba-e974-4030-9109-474f5979cd79","createdAt":1477982700139,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"1b455aca-711c-4d17-994c-3d9c39545a0c","externalSystem":"ContentAuthor","externalReference":"82998233-ed0e-4346-bf0d-f30f97386ec8","externalUrl":"http://content-author.local/article/82998233-ed0e-4346-bf0d-f30f97386ec8","createdAt":1477917476398,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"4cfaa4f5-2028-48ef-9b46-db52665783e1","externalSystem":"ContentAuthor","externalReference":"78715a15-701b-41f5-84b9-9c5759c9a476","externalUrl":"http://content-author.local/article/78715a15-701b-41f5-84b9-9c5759c9a476","createdAt":1477916731250,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"4d263690-006a-4c9f-a8c7-9ef529f319cd","externalSystem":"ContentAuthor","externalReference":"3c149366-32ac-4176-9307-1bd037a1954a","externalUrl":"http://content-author.local/article/3c149366-32ac-4176-9307-1bd037a1954a","createdAt":1477916653149,"coreId":null,"versionPurpose":"Save","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":{"id":"92bd2205-af96-4bf9-826a-06e12cb86a1d","externalSystem":"ContentAuthor","externalReference":"1dca1890-998c-400c-990d-deea6f908d3c","externalUrl":"http://content-author.local/article/1dca1890-998c-400c-990d-deea6f908d3c","createdAt":1477916158420,"coreId":null,"versionPurpose":"Create","originReference":null,"originSystem":null,"userId":"90ab88d9-388b-40ec-b1a5-d4f2ff5fc084","parent":null}}}}}}}}}}}}}}}}}}}}}}}}}}},"errors":[],"type":"success","message":null}'); $versionData = (new VersionData())->populate($versionResponse->data); diff --git a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContentLockProcessorTest.php b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContentLockProcessorTest.php index 2b16ec4cea..6262851b63 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContentLockProcessorTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContentLockProcessorTest.php @@ -16,12 +16,6 @@ class ContentLockProcessorTest extends TestCase use RefreshDatabase; use MockRabbitMQPubsub; - public function setUp(): void - { - parent::setUp(); - $this->setupRabbitMQPubSub(); - } - public function testRemovesContentLocksBasedOnAuthId() { $authId = $this->faker->uuid; diff --git a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContextShareProcessorTest.php b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContextShareProcessorTest.php index 1806e0b6fa..37735fd81d 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContextShareProcessorTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ContextShareProcessorTest.php @@ -16,12 +16,6 @@ class ContextShareProcessorTest extends TestCase use RefreshDatabase; use MockRabbitMQPubsub; - public function setUp(): void - { - parent::setUp(); - $this->setupRabbitMQPubSub(); - } - public function testContextSharesAreRemoved() { $authId = $this->faker->uuid; diff --git a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/H5PResultsProcessorTest.php b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/H5PResultsProcessorTest.php index d6ea45e561..e17fe61775 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/H5PResultsProcessorTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/H5PResultsProcessorTest.php @@ -16,12 +16,6 @@ class H5PResultsProcessorTest extends TestCase use RefreshDatabase; use MockRabbitMQPubsub; - public function setUp(): void - { - parent::setUp(); - $this->setupRabbitMQPubSub(); - } - public function testResultsAreDeleted() { $authId = $this->faker->uuid; diff --git a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ShareProcessorTest.php b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ShareProcessorTest.php index 058132a547..f18ff12203 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ShareProcessorTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Gdpr/Handlers/ShareProcessorTest.php @@ -22,12 +22,6 @@ class ShareProcessorTest extends TestCase use RefreshDatabase; use MockRabbitMQPubsub; - public function setUp(): void - { - parent::setUp(); - $this->setupRabbitMQPubSub(); - } - public function testRemovesSharesFromArticles() { $email = 'test@example.com'; diff --git a/sourcecode/apis/contentauthor/tests/Integration/H5PContentTest.php b/sourcecode/apis/contentauthor/tests/Integration/H5PContentTest.php index 2ae26ac0b9..8f4281b378 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/H5PContentTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/H5PContentTest.php @@ -15,7 +15,6 @@ class H5PContentTest extends TestCase /** @dataProvider provider_getContentTypeInfo */ public function test_getContentTypeInfo_WithIcon($usePatch, $expectedPath): void { - /** @var H5PLibrary $library */ $library = H5PLibrary::factory()->create([ 'has_icon' => 1, 'patch_version_in_folder_name' => $usePatch, @@ -45,7 +44,6 @@ public function provider_getContentTypeInfo(): \Generator public function test_getContentTypeInfo_NoIcon(): void { - /** @var H5PLibrary $library */ $library = H5PLibrary::factory()->create(); $frameWork = $this->createMock(\H5PFrameworkInterface::class); diff --git a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminArticleControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminArticleControllerTest.php new file mode 100644 index 0000000000..8d8a96715c --- /dev/null +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminArticleControllerTest.php @@ -0,0 +1,51 @@ +createMock(AuthApiService::class); + $this->instance(AuthApiService::class, $authMock); + + $userId = $this->faker->uuid; + $user = new User($userId, 'Emily', 'QuackFaster', 'eq@duckburg.quack'); + + $authMock->expects($this->once()) + ->method('getUser') + ->willReturn($user); + + Article::factory()->create([ + 'bulk_calculated' => Article::BULK_UPDATED, + ]); + $failedResource = Article::factory()->create([ + 'bulk_calculated' => Article::BULK_FAILED, + ]); + + $result = app(AdminArticleController::class)->viewFailedCalculations(); + $this->assertInstanceOf(View::class, $result); + + $data = $result->getData(); + $this->assertCount(1, $data['resources']); + + $resource = $data['resources']->first(); + $this->assertSame($failedResource->id, $resource->id); + + $this->assertStringContainsString($user->getEmail(), $resource->ownerName); + } +} diff --git a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminControllerTest.php index 76000b7e8a..837400ad96 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminControllerTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminControllerTest.php @@ -2,15 +2,21 @@ namespace Tests\Integration\Http\Controllers\Admin; +use App\ApiModels\User; +use App\Apis\AuthApiService; +use App\ContentLock; use App\Events\ResourceSaved; use App\H5PContent; use App\H5PLibrary; use App\Http\Controllers\Admin\AdminController; use App\Libraries\H5P\H5PLibraryAdmin; +use Generator; +use H5PCore; use Illuminate\Auth\GenericUser; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Support\Facades\Storage; +use Illuminate\View\View; use Tests\TestCase; class AdminControllerTest extends TestCase @@ -20,8 +26,8 @@ class AdminControllerTest extends TestCase public function test_viewMaxScoreOverview(): void { - $core = $this->createMock(\H5PCore::class); - $this->instance(\H5PCore::class, $core); + $core = $this->createMock(H5PCore::class); + $this->instance(H5PCore::class, $core); $core->expects($this->once())->method('getLocalization')->willReturn([]); Storage::fake('test'); @@ -29,13 +35,10 @@ public function test_viewMaxScoreOverview(): void Storage::put('libraries/H5P.Foobar-1.42/presave.js', 'the content'); Storage::put('libraries/H5P.Toolbar-1.2/presave.js', 'the content'); - /** @var H5PLibrary $library1 */ $library1 = H5PLibrary::factory()->create(); - /** @var H5PLibrary $library2 */ $library2 = H5PLibrary::factory()->create([ 'minor_version' => 42, ]); - /** @var H5PLibrary $library3 */ $library3 = H5PLibrary::factory()->create([ 'name' => 'H5P.Toolbar', ]); @@ -85,9 +88,7 @@ public function test_viewMaxScoreOverview(): void public function test_updateMaxScore(): void { - /** @var H5PLibrary $library */ $library = H5PLibrary::factory()->create(); - /** @var H5PContent $content */ $content = H5PContent::factory()->create([ 'library_id' => $library->id, 'max_score' => null, @@ -115,4 +116,64 @@ public function test_updateMaxScore(): void 'bulk_calculated' => H5PLibraryAdmin::BULK_UPDATED, ]); } + + /** @dataProvider provider_index */ + public function test_index(int $lockCount): void + { + ContentLock::factory($lockCount)->create(); + $result = app(AdminController::class)->index(); + + $this->assertInstanceOf(View::class, $result); + $data = $result->getData(); + $this->assertEquals($lockCount, $data['editLockCount']); + } + + public function provider_index(): Generator + { + yield [0]; + yield [3]; + } + + public function test_viewFailedCalculations(): void + { + $authMock = $this->createMock(AuthApiService::class); + $this->instance(AuthApiService::class, $authMock); + + $userId = $this->faker->uuid; + $user = new User($userId, 'Emily', 'QuackFaster', 'eq@duckburg.quack'); + + $authMock->expects($this->once()) + ->method('getUser') + ->willReturn($user); + + $library = H5PLibrary::factory()->create(); + + H5PContent::factory()->create([ + 'bulk_calculated' => H5PLibraryAdmin::BULK_UPDATED, + 'user_id' => $userId, + 'library_id' => $library->id, + ]); + H5PContent::factory()->create([ + 'bulk_calculated' => H5PLibraryAdmin::BULK_UNTOUCHED, + 'user_id' => $userId, + 'library_id' => $library->id, + ]); + $failedResource = H5PContent::factory()->create([ + 'bulk_calculated' => H5PLibraryAdmin::BULK_FAILED, + 'user_id' => $userId, + 'library_id' => $library->id, + ]); + + $controller = app(AdminController::class); + $result = $controller->viewFailedCalculations(); + $this->assertInstanceOf(View::class, $result); + + $data = $result->getData(); + $this->assertCount(1, $data['resources']); + + $resource = $data['resources']->first(); + $this->assertSame($failedResource->id, $resource->id); + + $this->assertStringContainsString($user->getEmail(), $resource->ownerName); + } } diff --git a/sourcecode/apis/contentauthor/tests/Unit/Http/Controllers/AdminH5PDetailsControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminH5PDetailsControllerTest.php similarity index 95% rename from sourcecode/apis/contentauthor/tests/Unit/Http/Controllers/AdminH5PDetailsControllerTest.php rename to sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminH5PDetailsControllerTest.php index 855444842e..f73c4f2f6b 100644 --- a/sourcecode/apis/contentauthor/tests/Unit/Http/Controllers/AdminH5PDetailsControllerTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminH5PDetailsControllerTest.php @@ -1,6 +1,6 @@ create(); - /** @var H5PLibrary $libraryDep */ $libraryDep = H5PLibrary::factory()->create([ 'name' => 'H5P.EditorDep', 'major_version' => 2, 'minor_version' => 3, ]); - /** @var H5PLibrary $libraryPre */ $libraryPre = H5PLibrary::factory()->create([ 'name' => 'H5P.PreDep', 'major_version' => 5, 'minor_version' => 6, ]); - /** @var H5PLibrary $libraryDepX */ $libraryDepX = H5PLibrary::factory()->create([ 'name' => 'H5P.EditorDepX', 'major_version' => 2, 'minor_version' => 3, ]); - /** @var H5PLibrary $libraryPreX */ $libraryPreX = H5PLibrary::factory()->create([ 'name' => 'H5P.PreDepX', 'major_version' => 5, @@ -167,15 +162,12 @@ public function test_checkLibrary(): void public function test_contentForLibrary(): void { - /** @var H5PLibrary $library*/ $library = H5PLibrary::factory()->create(); - /** @var H5PContent $failedContent */ $failedContent = H5PContent::factory()->create([ 'version_id' => $this->faker->uuid, 'library_id' => $library->id, 'updated_at' => Carbon::now()->sub('1d'), ]); - /** @var H5PContent $versionContent */ $versionContent = H5PContent::factory()->create([ 'version_id' => $this->faker->uuid, 'library_id' => $library->id, @@ -233,9 +225,7 @@ public function test_contentForLibrary(): void public function test_contentHistory(): void { $f4mId = $this->faker->uuid; - /** @var H5PLibrary $library */ $library = H5PLibrary::factory()->create(); - /** @var H5PContent $content */ $content = H5PContent::factory()->create([ 'id' => 42, 'version_id' => $this->faker->uuid, diff --git a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminUserControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminUserControllerTest.php new file mode 100644 index 0000000000..692fde7f94 --- /dev/null +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/Admin/AdminUserControllerTest.php @@ -0,0 +1,105 @@ +username = 'emqu'; + $admin->password = 'abc123'; + $admin->name = 'Emily Quackfaster'; + $admin->save(); + + $user = new GenericUser([ + 'roles' => ['superadmin'], + 'name' => 'Just Testing', + ]); + + $ret = $this->withSession(['user' => $user]) + ->get(route('admin-users.index')) + ->assertOk() + ->assertViewHas('adminUsers'); + + $this->assertCount(1, $ret['adminUsers']); + $this->assertSame($admin->id, $ret['adminUsers'][0]->id); + } + + public function test_store(): void + { + $input = [ + 'name' => 'Emily Quackfaster', + 'username' => 'emqu', + 'password' => 'abcdefghijk0123456789', + ]; + + $ret = $this->withSession(['user' => new GenericUser(['roles' => ['superadmin']])]) + ->post(route('admin-users.store', $input)) + ->assertRedirectToRoute('admin-users.index'); + + $ret->assertSessionHas('message', 'User Emily Quackfaster created!'); + $this->assertDatabaseHas('administrators', [ + 'username' => $input['username'], + 'name' => $input['name'], + ]); + $this->assertDatabaseMissing('administrators', [ + 'password' => $input['password'], + ]); + } + + public function test_destroy_success(): void + { + $admin = new Administrator(); + $admin->username = 'emqu'; + $admin->password = 'abc123'; + $admin->name = 'Emily Quackfaster'; + $admin->save(); + + $ret = $this->withSession(['user' => new GenericUser(['id' => 42, 'roles' => ['superadmin']])]) + ->delete(route('admin-users.destroy', ['admin_user' => $admin->id])) + ->assertRedirectToRoute('admin-users.index'); + + $ret->assertSessionHas('message', 'Emily Quackfaster deleted!'); + $this->assertDatabaseMissing('administrators', ['id' => $admin->id]); + } + + public function test_destroy_failToDestroySelf(): void + { + $admin = new Administrator(); + $admin->username = 'emqu'; + $admin->password = 'abc123'; + $admin->name = 'Emily Quackfaster'; + $admin->save(); + + $user = new GenericUser([ + 'id' => $admin->id, + 'roles' => ['superadmin'] + ]); + + $ret = $this->withSession(['user' => $user]) + ->delete(route('admin-users.destroy', ['admin_user' => $admin->id])) + ->assertRedirectToRoute('admin-users.index'); + + $ret->assertSessionHas('message', 'You can not delete yourself!'); + $this->assertDatabaseHas('administrators', ['id' => $admin->id]); + } + + public function test_destroy_failToDestroyNonExistingUser(): void + { + $this->assertDatabaseMissing('administrators', ['id' => 10]); + + $this->withSession(['user' => new GenericUser(['id' => 42, 'roles' => ['superadmin']])]) + ->delete(route('admin-users.destroy', ['admin_user' => 10])) + ->assertNotFound(); + } +} diff --git a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleControllerTest.php index 25546e2e2b..653da591b8 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleControllerTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleControllerTest.php @@ -18,7 +18,7 @@ class ArticleControllerTest extends TestCase public function testCreate(): void { - $request = new Request([], [ + $request = Request::create('', parameters: [ 'lti_version' => 'LTI-1p0', 'lti_message_type' => 'basic-lti-launch-request', 'resource_link_id' => 'random_link_9364f20a-a9b5-411a-8f60-8a4050f85d91', @@ -31,7 +31,6 @@ public function testCreate(): void 'authId' => Uuid::uuid(), ]); - /** @var ArticleController $articleController */ $articleController = app(ArticleController::class); $result = $articleController->create($request); diff --git a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleCopyrightControllerTest.php b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleCopyrightControllerTest.php index fa703aa0f0..8005e16da3 100644 --- a/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleCopyrightControllerTest.php +++ b/sourcecode/apis/contentauthor/tests/Integration/Http/Controllers/ArticleCopyrightControllerTest.php @@ -17,7 +17,6 @@ class ArticleCopyrightControllerTest extends TestCase public function test_copyright_endpointIsWorking() { - /** @var Article $article */ $article = Article::factory()->create([ 'title' => 'This is a test article', 'license' => 'PRIVATE', @@ -39,7 +38,6 @@ public function test_copyright_endpointIsWorking() public function test_copyright_canFetchOriginators() { - /** @var Article $article */ $article = Article::factory()->create(); $article->setAttributionOrigin('http://en.wikipedia.org/'); $article->addAttributionOriginator('http://www.example.com', 'Source'); @@ -72,13 +70,11 @@ public function test_copyright_canFetchOriginators() public function test_copyright_canFetchSubresourceCopyright() { - /** @var H5PContent $h5pContent */ $h5pContent = H5PContent::factory()->create([ 'library_id' => H5PLibrary::factory()->create()->id, 'filtered' => '[]', ]); - /** @var Article $article */ $article = Article::factory()->create([ 'content' => '