Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/Http/Controllers/ItemRestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public function index(): Collection
'description',
'appid',
'appdescription',
'pinned',
'order',
];

return Item::with('parents')
Expand All @@ -45,6 +47,8 @@ public function index(): Collection
'description' => $item->description,
'appid' => $item->appid,
'appdescription' => $item->appdescription,
'pinned' => $item->pinned,
'pinned_order' => $item->order,
'tags' => $item->parents
->where('id', '!=', 0)
->pluck('title')
Expand Down
3 changes: 2 additions & 1 deletion public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4458,7 +4458,8 @@ var getCSRFToken = function getCSRFToken() {
*/
var mergeItemWithAppDetails = function mergeItemWithAppDetails(item, appDetails) {
return {
pinned: 1,
pinned: item.pinned !== undefined ? item.pinned : 1,
order: item.pinned_order !== undefined ? item.pinned_order : null,
tags: Array.isArray(item.tags) && item.tags.length ? item.tags : [0],
appid: item.appid,
title: item.title,
Expand Down
3 changes: 2 additions & 1 deletion resources/assets/js/itemImport.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ const getCSRFToken = () => {
* @returns {object}
*/
const mergeItemWithAppDetails = (item, appDetails) => ({
pinned: 1,
pinned: item.pinned !== undefined ? item.pinned : 1,
order: item.pinned_order !== undefined ? item.pinned_order : null,
tags: Array.isArray(item.tags) && item.tags.length ? item.tags : [0],

appid: item.appid,
Expand Down
32 changes: 32 additions & 0 deletions tests/Feature/ItemExportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function test_returns_exactly_the_defined_fields(): void
"appid" => "123",
"colour" => "#000",
"description" => "Description",
"pinned" => 1,
"pinned_order" => 0,
"title" => "Item Title",
"url" => "http://gorczany.com/nihil-rerum-distinctio-voluptate-assumenda-accusantium-exercitationem"
];
Expand All @@ -38,6 +40,36 @@ public function test_returns_exactly_the_defined_fields(): void
$response->assertExactJson([$exampleItem + ["tags" => []]]);
}

public function test_exports_pinned_status_for_items(): void
{
$pinnedItem = Item::factory()->create([
'title' => 'Pinned App',
'pinned' => 1,
]);
$unpinnedItem = Item::factory()->create([
'title' => 'Unpinned App',
'pinned' => 0,
]);

$response = $this->get('api/item');

$response->assertJsonCount(2);
$response->assertJsonPath('0.pinned', 1);
$response->assertJsonPath('1.pinned', 0);
}

public function test_exports_pinned_order_for_items(): void
{
Item::factory()->create(['title' => 'First', 'order' => 1]);
Item::factory()->create(['title' => 'Second', 'order' => 2]);

$response = $this->get('api/item');

$response->assertJsonCount(2);
$response->assertJsonPath('0.pinned_order', 1);
$response->assertJsonPath('1.pinned_order', 2);
}

public function test_exports_assigned_tag_titles_excluding_the_root_tag(): void
{
// Mirror the root/default dashboard row that production seeds (id 0),
Expand Down
80 changes: 80 additions & 0 deletions tests/Feature/ItemImportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,84 @@ public function test_import_with_root_tag_only_creates_no_tags(): void
ItemTag::where('item_id', $item->id)->where('tag_id', 0)->exists()
);
}

public function test_import_saves_unpinned_item(): void
{
$this->seed();

$response = $this->postJson('api/item', $this->importPayload([
'title' => 'Unpinned App',
'pinned' => 0,
]));

$response->assertStatus(200);

$item = Item::where('type', 0)->where('title', 'Unpinned App')->first();
$this->assertNotNull($item);
$this->assertEquals(0, $item->pinned);
}

public function test_import_saves_pinned_order(): void
{
$this->seed();

$response = $this->postJson('api/item', $this->importPayload([
'title' => 'Ordered App',
'order' => 5,
]));

$response->assertStatus(200);

$item = Item::where('type', 0)->where('title', 'Ordered App')->first();
$this->assertNotNull($item);
$this->assertEquals(5, $item->order);
}

public function test_import_defaults_order_to_zero_when_not_provided(): void
{
$this->seed();

$response = $this->postJson('api/item', $this->importPayload([
'title' => 'No Order App',
]));

$response->assertStatus(200);

$item = Item::where('type', 0)->where('title', 'No Order App')->first();
$this->assertNotNull($item);
$this->assertEquals(0, $item->order);
}

public function test_export_import_round_trip_preserves_pinned_and_order(): void
{
$this->seed();

// Create items with specific pinned/order values
$this->postJson('api/item', $this->importPayload([
'title' => 'App One',
'pinned' => 1,
'order' => 3,
]))->assertStatus(200);

$this->postJson('api/item', $this->importPayload([
'title' => 'App Two',
'pinned' => 0,
'order' => 7,
]))->assertStatus(200);

// Export
$export = $this->get('api/item');
$export->assertJsonCount(2);

$exported = $export->json();

// Verify the exported JSON has the right keys/values
$appOne = collect($exported)->firstWhere('title', 'App One');
$appTwo = collect($exported)->firstWhere('title', 'App Two');

$this->assertEquals(1, $appOne['pinned']);
$this->assertEquals(3, $appOne['pinned_order']);
$this->assertEquals(0, $appTwo['pinned']);
$this->assertEquals(7, $appTwo['pinned_order']);
}
}