Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
19 kB
3
Indexable
Never
<?php

use App\Models\Listing;
use App\Models\OauthToken;
use App\Models\Shop;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Client\Response;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use function Pest\Laravel\{actingAs};

uses(RefreshDatabase::class);

test('user can see all listings it belongs to', function () {
    // Add user with shop
    $user = User::factory()->withShop()->create();

    // take first shop.
    $shop = $user->shops->first();

    // Add listings to shop
    $shop->listings()->createMany(
        Listing::factory()->count(3)->make()->toArray()
    );

    // Get listings
    actingAs($user)->get(route('listings.index', ['shopID' => $shop->id]))
        ->assertStatus(200)
        ->assertSee('Listings');
});

test('user can not see all listings it dont belongs to', function () {
    // Add user with shop
    $user = User::factory()->withShop()->create();

    // take first shop.
    $shop = $user->shops->first();

    // Add listings to shop
    $shop->listings()->createMany(
        Listing::factory()->count(3)->make()->toArray()
    );

    // Get listings
    actingAs($user)->get(route('listings.index', ['shopID' => 2]))
        ->assertStatus(403);
});

test('listings can be imported from etsy', function () {
});

test('listings can be updated from etsy', function () {
});

test('user can update a listing', function () {
    $user = User::factory()->withShop()->create();

    $shop = $user->shops->first();

    $shop->listings()->createMany(
        Listing::factory()->count(1)->make()->toArray()
    );

    $listing = $shop->listings->first();

    actingAs($user)->patch(route('listings.update', $listing->id), [
        'title' => 'New Title',
        'description' => 'New Description',
        'price' => 10.66,
        'quantity' => 10,
        'tags' => 'tag1, tag2, tag3',
        'materials' => 'material1, material2, material3',
        'image_1' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
        'image_2' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
        'image_3' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
        'image_4' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
        'image_5' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
    ])->assertStatus(200);

    expect($listing->fresh()->toArray())->toMatchArray(
        [
            'title' => 'New Title',
            'description' => 'New Description',
            'price' => '10.66',
            'quantity' => 10,
            'tags' => 'tag1, tag2, tag3',
            'materials' => 'material1, material2, material3',
            'image_1' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
            'image_2' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
            'image_3' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
            'image_4' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
            'image_5' => 'https://i.etsystatic.com/12345678/d/il/12345678/12345678/il_340x270.12345678_1234.jpg?version=0',
        ]
    );
});

test('user can update multiple listings', function () {
})->markTestSkipped('Handle in the frontend.');

test('user can delete one listing', function () {
    $user = User::factory()->withShop()->create();

    $shop = $user->shops->first();

    $shop->listings()->createMany(
        Listing::factory()->count(1)->make()->toArray()
    );

    $listing = $shop->listings->first();

    actingAs($user)->delete(route('listings.destroy', $listing->id))
        ->assertStatus(200);

    expect($listing->fresh())->toBeNull();
});

test('user can update 10.00 as price', function () {
    $user = User::factory()->withShop()->create();

    $shop = $user->shops->first();

    $shop->listings()->createMany(
        Listing::factory()->count(1)->make()->toArray()
    );

    $listing = $shop->listings->first();

    actingAs($user)->patch(route('listings.update', $listing->id), [
        'title' => $listing->title,
        'description' => $listing->description,
        'price' => '10.00',
        'quantity' => $listing->quantity,
        'image_1' => $listing->image_1,
    ])->assertStatus(200);

    expect($listing->fresh()->toArray())->toMatchArray(
        [
            'price' => '10.00',
        ]
    );
});

test('user can add 10.99 as price', function () {
    $user = User::factory()->withShop()->create();

    $shop = $user->shops->first();

    $shop->listings()->createMany(
        Listing::factory()->count(1)->make()->toArray()
    );

    $listing = $shop->listings->first();

    actingAs($user)->patch(route('listings.update', $listing->id), [
        'title' => $listing->title,
        'description' => $listing->description,
        'price' => '10.99',
        'quantity' => $listing->quantity,
        'image_1' => $listing->image_1,
    ])->assertStatus(200);

    expect($listing->fresh()->toArray())->toMatchArray(
        [
            'price' => '10.99',
        ]
    );
});

test('user can copy multiple listings to selected shops', function () {
    $user = User::factory()->create();
    $shop_1 = Shop::factory()->create([
        'shop_name' => 'shop 1',
        'user_id' => $user->id,
    ]);

    $shop_2 = Shop::factory()->create([
        'shop_name' => 'shop 2',
        'user_id' => $user->id,
    ]);

    $shop_3 = Shop::factory()->create([
        'shop_name' => 'shop 3',
        'user_id' => $user->id,
    ]);

    $listing_1 = Listing::factory()->create([
        'shop_id' => $shop_1->id,
    ]);

    $listing_2 = Listing::factory()->create([
        'shop_id' => $shop_1->id,
    ]);

    actingAs($user)->post(route('listings.copy', [
        'listing_ids' => [$listing_1->id, $listing_2->id],
        'shop_ids' => [$shop_2->id, $shop_3->id],
    ]))->assertStatus(200);

    expect($shop_2->listings->count())->toBe(2);
    expect($shop_3->listings->count())->toBe(2);
});

test('deleted listings will be soft deleted', function () {
    $user = User::factory()->withShop()->create();

    $shop = $user->shops->first();

    $shop->listings()->createMany(
        Listing::factory()->count(5)->make()->toArray()
    );

    $listingIds = $shop->listings->pluck('id')->flatten()->all();

    actingAs($user)->delete(route('listings.destroy'), [
        'listing_ids' => [$listingIds[0], $listingIds[1], $listingIds[2], $listingIds[3], $listingIds[4]],
    ])->assertStatus(302);

    expect($shop->listings()->onlyTrashed()->count())->toBe(5);
});

test('user can create listing to multiple shops', function () {
    Http::fake([
        // Mock the response for the createDraftListing method.
        'https://openapi.etsy.com/v3/application/shops/*/listings' => Http::response([
            'listing_id' => 123456789,
            'state' => 'draft',
        ], 201),
    ]);

    $user = User::factory()->hasShops(3)->create();
    foreach ($user->shops as $shop) {
        OauthToken::factory()->create([
            'shop_id' => $shop->id,
            'user_id' => $user->id,
            'access_token' => 'valid-access-token',
            'refresh_token' => 'valid-refresh-token',
            'expires_at' => now()->addHour(),
        ]);
    }

    Storage::fake('local');
    $fakeImage = UploadedFile::fake()->image('photo1.jpg');

    // Prepare the payload simulating what the frontend would send
    $payload = [
        'shops' => [
            $user->shops[0]->id => [
                'shopData' => [
                    'title' => 'Halloween, shirt',
                    'description' => 'Description 1',
                    'tags' => ['tag1', 'tag2'],
                    'materials' => ['wood', 'metal'],
                    'price' => 100.00,
                    'quantity' => 10,
                    'who_made' => 'i_did',
                    'when_made' => 'made_to_order',
                    'taxonomy_id' => 1,
                    'processing_min' => 1,
                    'processing_max' => 5,
                    'is_published' => false,
                    'state' => 'active',
                    'variants' => [
                        0 => [
                            'name' => 'colors',
                            'options' => [
                                0 => [
                                    'name' => 'green',
                                    'sku' => null,
                                    'price' => '0',
                                    'quantity' => '0',
                                ],
                                1 => [
                                    'name' => 'blue',
                                    'sku' => null,
                                    'price' => '0',
                                    'quantity' => '0',
                                ],
                                2 => [
                                    'name' => 'yellow',
                                    'sku' => null,
                                    'price' => '0',
                                    'quantity' => '0',
                                ],
                            ],
                        ],
                        1 => [
                            'name' => 'size',
                            'options' => [
                                0 => [
                                    'name' => 'M',
                                    'sku' => null,
                                    'price' => '0',
                                    'quantity' => '0',
                                ],
                                1 => [
                                    'name' => 'L',
                                    'sku' => null,
                                    'price' => '0',
                                    'quantity' => '0',
                                ],
                                2 => [
                                    'name' => 'S',
                                    'sku' => null,
                                    'price' => '0',
                                    'quantity' => '0',
                                ],
                            ],
                        ],
                    ],
                    'variantsInputs' => [
                        'size' => ['M', 'L', 'S'],
                        'color' => ['green', 'blue', 'yellow'],
                    ],
                    'variantsVary' => false,
                    'images' => array_fill(0, 10, ['url' => 'localhost://test.jpg', 'file' => $fakeImage, 'name' => 'test image 1', 'type' => 'image/jpeg']),
                    'video' => ['src' => null],
                    'should_auto_renew' => false,
                    'is_personalizable' => false,
                    'personalization_is_required' => false,
                    'sku' => 'SKU123',
                    'shipping_profile' => ['id' => 123456, 'processingDays' => '1-2 days', 'title' => 'Fixed pices', 'type' => 'fixed'],
                    'shop_id' => $user->shops[1]->id,
                ],
            ],
            $user->shops[1]->id => [
                'shopData' => [
                    'title' => 'Halloween, shirt',
                    'description' => 'Description 1',
                    'tags' => ['tag1', 'tag2'],
                    'materials' => ['wood', 'metal'],
                    'price' => 100.00,
                    'quantity' => 10,
                    'who_made' => 'i_did',
                    'when_made' => 'made_to_order',
                    'taxonomy_id' => 1,
                    'processing_min' => 1,
                    'processing_max' => 5,
                    'is_published' => false,
                    'state' => 'active',
                    'variants' => [
                        [
                            'title' => 'Small, Blue',
                            'price' => 100.00,
                            'sku' => 'SKU123-SB',
                            'quantity' => 5,
                        ],
                        [
                            'title' => 'Medium, Blue',
                            'price' => 100.00,
                            'sku' => 'SKU123-MB',
                            'quantity' => 5,
                        ],
                        [
                            'title' => 'Large, Blue',
                            'price' => 100.00,
                            'sku' => 'SKU123-LB',
                            'quantity' => 5,
                        ],
                    ],
                    'variantsInputs' => [
                        'size' => ['Small', 'Medium', 'Large'],
                        'color' => ['Blue'],
                    ],
                    'variantsVary' => true,
                    'images' => array_fill(0, 10, ['url' => null]),
                    'video' => ['src' => null],
                    'should_auto_renew' => false,
                    'is_personalizable' => false,
                    'personalization_is_required' => false,
                    'sku' => 'SKU123',
                    'shipping_profile' => ['id' => 123456, 'processingDays' => '1-2 days', 'title' => 'Fixed pices', 'type' => 'fixed'],
                    'shop_id' => $user->shops[1]->id,
                ],
            ],
        ],
    ];

    actingAs($user)
        ->post(route('listings.store'), $payload);

    Http::assertSentCount(2);
    expect($user->shops[0]->listings()->count())->toBe(1);
    expect($user->shops[1]->listings()->count())->toBe(1);
    Storage::disk('local')->assertExists('/public/listing-images/'.$fakeImage->hashName());
});

test('if shipping profile is calculated all item fields should be required', function () {
    $user = User::factory()->hasShops(3)->create();

    // Prepare the payload simulating what the frontend would send.
    $payload = [
        'shops' => [
            $user->shops[0]->id => [
                'shopData' => [
                    'title' => 'Halloween, shirt',
                    'description' => 'Description 1',
                    'tags' => ['tag1', 'tag2'],
                    'materials' => ['wood', 'metal'],
                    'price' => 100.00,
                    'quantity' => 10,
                    'who_made' => 'i_did',
                    'when_made' => 'made_to_order',
                    'taxonomy_id' => 1,
                    'return_policy_id' => null,
                    'shop_section_id' => null,
                    'processing_min' => 1,
                    'processing_max' => 5,
                    'is_published' => false,
                    'state' => 'active',
                    'variants' => [
                        [
                            'title' => 'Small, Blue',
                            'price' => 100.00,
                            'sku' => 'SKU123-SB',
                            'quantity' => 5,
                        ],
                        [
                            'title' => 'Medium, Blue',
                            'price' => 100.00,
                            'sku' => 'SKU123-MB',
                            'quantity' => 5,
                        ],
                        [
                            'title' => 'Large, Blue',
                            'price' => 100.00,
                            'sku' => 'SKU123-LB',
                            'quantity' => 5,
                        ],
                    ],
                    'variantsInputs' => [
                        'size' => ['Small', 'Medium', 'Large'],
                        'color' => ['Blue'],
                    ],
                    'variantsVary' => true,
                    'images' => array_fill(0, 10, ['url' => null]),
                    'video' => ['src' => null],
                    'should_auto_renew' => false,
                    'is_personalizable' => false,
                    'personalization_is_required' => false,
                    'personalization_char_count_max' => null,
                    'personalization_instructions' => '',
                    'sku' => 'SKU123',
                    'shop_section_id' => null,
                    'renewal_option' => 'manual',
                    'type' => 'physical',
                    'production_partner_ids' => [],
                    'shipping_profile' => ['id' => 123456, 'processingDays' => '1-2 days', 'title' => 'Fixed pices', 'type' => 'calculated'],
                    'is_customizable' => false,
                    'is_taxable' => false,
                    'is_supply' => false,
                    'image_ids' => null,
                    'styles' => null,
                    'item_weight' => null,
                    'item_length' => null,
                    'item_width' => null,
                    'item_height' => null,
                    'item_weight_unit' => null,
                    'item_dimensions_unit' => null,
                    'shop_id' => $user->shops[1]->id,
                ],
            ],
        ],
    ];

    actingAs($user)
        ->post(route('listings.store'), $payload)
        ->assertStatus(302)
        ->assertSessionHasErrors([
            'shops.1.shopData.item_weight' => 'The shops.1.shopData.item_weight field is required when shops.1.shopData.shipping_profile is present.',
            'shops.1.shopData.item_length' => 'The shops.1.shopData.item_length field is required when shops.1.shopData.shipping_profile is present.',
            'shops.1.shopData.item_width' => 'The shops.1.shopData.item_width field is required when shops.1.shopData.shipping_profile is present.',
            'shops.1.shopData.item_height' => 'The shops.1.shopData.item_height field is required when shops.1.shopData.shipping_profile is present.',
            'shops.1.shopData.item_weight_unit' => 'The shops.1.shopData.item_weight_unit field is required when shops.1.shopData.shipping_profile is present.',
            'shops.1.shopData.item_dimensions_unit' => 'The shops.1.shopData.item_dimensions_unit field is required when shops.1.shopData.shipping_profile is present.',
        ]);
});

test('user can upload files', function () {
    Http::fake([
        // Mock the response for the createDraftListing method.
        'https://openapi.etsy.com/v3/application/shops/*/listings' => Http::response([
            'listing_id' => 123456789,
            'state' => 'draft',
        ], 201),
    ]);
});

test('user can delete multiple listings', function () {
})->markTestSkipped('Handle in the frontend.');

test('global images upload will uplodate to all listings', function () {
})->markTestSkipped('Handle in the frontend.');