diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 1a4f188..85e486e 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -11,6 +11,9 @@
-->
tests/Integration/Client
+
+ tests/Unit/Client
+
diff --git a/tests/Unit/Client/Fixtures/get_notification_response.json b/tests/Unit/Client/Fixtures/get_notification_response.json
new file mode 100644
index 0000000..c3b36b3
--- /dev/null
+++ b/tests/Unit/Client/Fixtures/get_notification_response.json
@@ -0,0 +1,19 @@
+{
+ "id": "UUVVWWXX",
+ "user_id": "Dc7EYhxG",
+ "type": "project_update",
+ "title": "**My Project** has been updated!",
+ "text": "The project, My Project, has released a new version: 1.0.0",
+ "link": "mod/AABBCCDD/version/IIJJKKLL",
+ "read": false,
+ "created": "string",
+ "actions": [
+ {
+ "title": "Accept",
+ "action_route": [
+ "POST",
+ "team/{id}/join"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/Unit/Client/Fixtures/get_project_response.json b/tests/Unit/Client/Fixtures/get_project_response.json
new file mode 100644
index 0000000..1037d87
--- /dev/null
+++ b/tests/Unit/Client/Fixtures/get_project_response.json
@@ -0,0 +1,244 @@
+{
+ "id": "mOgUt4GM",
+ "slug": "modmenu",
+ "project_type": "mod",
+ "team": "VMz4FpgB",
+ "title": "Mod Menu",
+ "description": "Adds a mod menu to view the list of mods you have installed.",
+ "body": "![Mod Menu Banner](https://i.imgur.com/dMYWAjn.png)\nHard to be more descriptive than that. It enriches the standard Minecraft menu with an interface displaying a one-dimensional array of modifications\n\n\n\nMod Menu requires [Fabric Loader](https://fabricmc.net/use/) and [Fabric API](https://www.modrinth.com/mod/fabric-api)\n\nCheck out the [Terraformers Discord Server](https://discord.gg/jEGF5fb) to chat about Mod Menu and other Fabric mods!\n\nA picture's worth 2 words\n\n![Mod Menu Screenshot](https://i.imgur.com/wp83YOP.png)\n\n\n### Mod Menu is a mod for Fabric, and there are no plans to port this mod to Forge.",
+ "body_url": null,
+ "published": "2020-11-06T05:11:04.725058Z",
+ "updated": "2023-07-18T20:52:37.015257Z",
+ "approved": "2020-11-06T05:11:04.725058Z",
+ "queued": null,
+ "status": "approved",
+ "requested_status": null,
+ "moderator_message": null,
+ "license": {
+ "id": "MIT",
+ "name": "MIT License",
+ "url": null
+ },
+ "client_side": "required",
+ "server_side": "unsupported",
+ "downloads": 1697771,
+ "followers": 5359,
+ "categories": [
+ "utility"
+ ],
+ "additional_categories": [],
+ "game_versions": [
+ "1.14.4",
+ "1.15.2",
+ "1.16.1",
+ "1.16.4",
+ "1.16.5",
+ "1.17",
+ "1.17.1",
+ "1.17-pre1",
+ "1.18",
+ "1.18.1",
+ "1.18.1-pre1",
+ "1.18.1-rc1",
+ "1.18.1-rc2",
+ "1.18.1-rc3",
+ "1.18.2",
+ "1.18.2-pre1",
+ "1.18.2-pre2",
+ "1.18.2-pre3",
+ "1.18.2-rc1",
+ "1.19",
+ "1.19.1",
+ "1.19.1-pre2",
+ "1.19.1-rc1",
+ "1.19.2",
+ "1.19.3",
+ "1.19.4",
+ "1.19.4-pre1",
+ "1.19.4-pre2",
+ "1.19.4-pre3",
+ "1.19.4-pre4",
+ "1.19.4-rc1",
+ "1.19.4-rc2",
+ "1.19.4-rc3",
+ "1.19-pre1",
+ "1.19-pre2",
+ "1.19-pre3",
+ "1.19-pre4",
+ "1.20",
+ "1.20.1",
+ "1.20.1-rc1",
+ "1.20-pre1",
+ "1.20-pre2",
+ "1.20-pre3",
+ "1.20-pre4",
+ "1.20-pre5",
+ "1.20-pre6",
+ "1.20-pre7",
+ "1.20-rc1",
+ "21w06a",
+ "21w14a",
+ "21w37a",
+ "21w38a",
+ "22w03a",
+ "22w05a",
+ "22w06a",
+ "22w07a",
+ "22w15a",
+ "22w16b",
+ "22w17a",
+ "22w18a",
+ "22w19a",
+ "22w24a",
+ "22w43a",
+ "23w03a",
+ "23w05a",
+ "23w07a",
+ "23w12a",
+ "23w13a",
+ "23w13a_or_b",
+ "23w14a",
+ "23w16a",
+ "23w17a",
+ "23w18a"
+ ],
+ "loaders": [
+ "fabric",
+ "quilt"
+ ],
+ "versions": [
+ "M3KFXLhq",
+ "DgzrfgAZ",
+ "O90fUm3q",
+ "zC13OZD9",
+ "7QWIhei3",
+ "79rtoAM6",
+ "kBofQyu4",
+ "TleLdS1A",
+ "PqgXyy3N",
+ "Mnl0OeFI",
+ "pxj9L3Vy",
+ "6YvLIUDN",
+ "wb5nbuL5",
+ "bPE0GIoY",
+ "pqlMITZQ",
+ "RIf7gcLA",
+ "Gz5wa6j2",
+ "EDbIonje",
+ "wRE7Emzz",
+ "mzVbb1XI",
+ "bHODZExo",
+ "a8bewBQT",
+ "NyFB1gry",
+ "oQr5VO7q",
+ "u955lyFM",
+ "E4QBMVtO",
+ "c6uDXZX8",
+ "bojzkt4w",
+ "4Ar2wg0k",
+ "G8sCBZ1X",
+ "JyL5b75a",
+ "GOPQZTVp",
+ "Wr4GfZdy",
+ "tlM0eBmY",
+ "DOitjZ89",
+ "XtL1i60M",
+ "VaZTuVan",
+ "FMqdptUn",
+ "aH8qgnVM",
+ "9xECQHnM",
+ "LVxVja5i",
+ "JOqf8AZn",
+ "WKj0jgYj",
+ "jZQ0G78K",
+ "PN4NcBa1",
+ "WkUCkcQA",
+ "3CD6YUw1",
+ "JPP6w2U1",
+ "eueI9czw",
+ "4JrWqhWw",
+ "Ui2loaCY",
+ "fw5MM4c4",
+ "6f25OJ7w",
+ "E4VKK6kQ",
+ "y8cYdaYa",
+ "GYRoFp1I",
+ "Tk7mCRX1",
+ "aShj7736",
+ "dP3zrFbp",
+ "cx9D94fU",
+ "pnFEFiHq",
+ "ybXxCvz4",
+ "NsD1IoUs",
+ "oU5qfeR6",
+ "2Ys0a7JE",
+ "8TOgNwQL",
+ "kQDE01D3",
+ "3umfHb6R",
+ "Gbkn1raO",
+ "d86kV6wd",
+ "NAs8eiQa",
+ "RxrqnH1z",
+ "GI1HTA1O",
+ "sI3kiPZE",
+ "4dReZoTJ",
+ "7mdkE3Od",
+ "qDXCbEz4",
+ "IPLgxPn7",
+ "V4hnfgRO",
+ "nVxObSbX",
+ "7kh2ofyR",
+ "eIrlBn1Z",
+ "yA8g3pEj",
+ "oqeCO757",
+ "4LXaG2xg",
+ "5qqTBb38",
+ "7E8dbVv0",
+ "5aw4r6fS",
+ "pyDmgV07",
+ "jRqFAHRH",
+ "4EOA40rU",
+ "gSoPJyVn",
+ "RtaGQNyd",
+ "sXVmzBDB",
+ "U31K6311",
+ "JYTmttex",
+ "pged5sGx",
+ "5e62j63G",
+ "nM5QaZNo",
+ "aMxXwo9x",
+ "3gwnUSKz",
+ "yjjsLqbS",
+ "RdCGzY7B",
+ "EuNUYds8",
+ "iZRiOnnj",
+ "M7LIgtWJ",
+ "RTFDnTKf",
+ "CtMNOUcV",
+ "zv46i3PW",
+ "VHzvWfY2",
+ "sLzitH81",
+ "id0aLmxO",
+ "eTCL1uh8",
+ "lMqXEzUw"
+ ],
+ "icon_url": "https://cdn.modrinth.com/data/mOgUt4GM/icon.png",
+ "issues_url": "https://github.com/TerraformersMC/ModMenu/issues",
+ "source_url": "https://github.com/TerraformersMC/ModMenu",
+ "wiki_url": "https://github.com/TerraformersMC/ModMenu/wiki",
+ "discord_url": "https://discord.gg/jEGF5fb",
+ "donation_urls": [],
+ "gallery": [
+ {
+ "url": "https://cdn.modrinth.com/data/mOgUt4GM/images/5726bbaf7d0ea53e55b6e666af5d3e1861758334.png",
+ "featured": false,
+ "title": "Mod Menu",
+ "description": null,
+ "created": "2022-02-28T02:33:37.984225Z",
+ "ordering": 0
+ }
+ ],
+ "color": 1330428,
+ "thread_id": "mOgUt4GM",
+ "monetization_status": "monetized"
+}
\ No newline at end of file
diff --git a/tests/Unit/Client/Fixtures/get_user_response.json b/tests/Unit/Client/Fixtures/get_user_response.json
new file mode 100644
index 0000000..d1cb7e8
--- /dev/null
+++ b/tests/Unit/Client/Fixtures/get_user_response.json
@@ -0,0 +1,17 @@
+{
+ "id": "Dc7EYhxG",
+ "username": "Prospector",
+ "name": null,
+ "avatar_url": "https://cdn.modrinth.com/user/Dc7EYhxG/64d0b4c4cdcb33f3b7d4b31b140e83b199b00f3c.png",
+ "bio": "Lead Frontend Developer/Designer and Archivist at Modrinth. Founder of ModFest, co-founder of TerraformersMC. Creator of Traverse and Mod Menu.",
+ "created": "2020-11-06T04:56:05.014379Z",
+ "role": "admin",
+ "badges": 0,
+ "payout_data": null,
+ "auth_providers": null,
+ "email": null,
+ "email_verified": null,
+ "has_password": null,
+ "has_totp": null,
+ "github_id": null
+}
\ No newline at end of file
diff --git a/tests/Unit/Client/Models/NotificationTest.php b/tests/Unit/Client/Models/NotificationTest.php
new file mode 100644
index 0000000..8763933
--- /dev/null
+++ b/tests/Unit/Client/Models/NotificationTest.php
@@ -0,0 +1,43 @@
+getExampleNotificationModel();
+ $notification = new Notification(new ModrinthAPIClient(), $notificationModel);
+ $this->assertEquals($notificationModel, $notification->getData());
+ }
+
+ public function testGetUserReturnsCorrectUser(): void
+ {
+ // Here we must mock the client, because it requests the user from the API to get all details
+ $handler = new MockHandler([
+ new Response(200, [], file_get_contents(__DIR__ . "/../Fixtures/get_user_response.json")),
+ new Response(200, [], file_get_contents(__DIR__ . "/../Fixtures/get_user_response.json"))
+ ]);
+ $client = new ModrinthAPIClient(null, null, new Client(['handler' => HandlerStack::create($handler)]));
+
+ $notification = new Notification($client, $this->getExampleNotificationModel());
+ // Dc7EYhxG -> https://modrinth.com/user/Prospector
+ $user = $client->getUser("Dc7EYhxG");
+ $this->assertEquals($user, $notification->getUser());
+ }
+
+ protected function getExampleNotificationModel(): \Aternos\ModrinthApi\Model\Notification
+ {
+ $json = json_decode(file_get_contents(__DIR__ . "/../Fixtures/get_notification_response.json"), true);
+ return new \Aternos\ModrinthApi\Model\Notification($json);
+ }
+}
\ No newline at end of file
diff --git a/tests/Unit/Client/Models/ProjectTest.php b/tests/Unit/Client/Models/ProjectTest.php
new file mode 100644
index 0000000..22990fe
--- /dev/null
+++ b/tests/Unit/Client/Models/ProjectTest.php
@@ -0,0 +1,24 @@
+getExampleProjectModel();
+ $project = new Project(new ModrinthAPIClient(), $projectModel);
+ $this->assertEquals($projectModel, $project->getData());
+ }
+
+ protected function getExampleProjectModel(): \Aternos\ModrinthApi\Model\Project
+ {
+ $json = json_decode(file_get_contents(__DIR__ . "/../Fixtures/get_project_response.json"), true);
+ return new \Aternos\ModrinthApi\Model\Project($json);
+ }
+}
\ No newline at end of file