| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- <?php
- namespace Webkul\BagistoApi\Tests\Feature\GraphQL;
- use Webkul\BagistoApi\Tests\GraphQLTestCase;
- use Webkul\Core\Models\Channel;
- use Webkul\Customer\Models\Customer;
- use Webkul\Product\Models\Product;
- use Webkul\Product\Models\ProductReview;
- class CustomerReviewTest extends GraphQLTestCase
- {
- /**
- * Create test data — customer with reviews on multiple products
- */
- private function createTestData(): array
- {
- $this->seedRequiredData();
- $customer = $this->createCustomer();
- $product1 = Product::factory()->create();
- $product2 = Product::factory()->create();
- $review1 = ProductReview::factory()->create([
- 'customer_id' => $customer->id,
- 'product_id' => $product1->id,
- 'title' => 'Great product',
- 'comment' => 'Really enjoyed using this product.',
- 'rating' => 5,
- 'status' => 'approved',
- 'name' => $customer->first_name,
- ]);
- $review2 = ProductReview::factory()->create([
- 'customer_id' => $customer->id,
- 'product_id' => $product2->id,
- 'title' => 'Average product',
- 'comment' => 'It was okay, nothing special.',
- 'rating' => 3,
- 'status' => 'pending',
- 'name' => $customer->first_name,
- ]);
- return compact('customer', 'product1', 'product2', 'review1', 'review2');
- }
- // ── Collection Queries ────────────────────────────────────
- /**
- * Test: Query all customer reviews collection
- */
- public function test_get_customer_reviews_collection(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews {
- edges {
- cursor
- node {
- id
- _id
- title
- comment
- rating
- status
- name
- product {
- id
- }
- customer {
- id
- }
- createdAt
- updatedAt
- }
- }
- pageInfo {
- endCursor
- startCursor
- hasNextPage
- hasPreviousPage
- }
- totalCount
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- expect($data['totalCount'])->toBeGreaterThanOrEqual(2);
- expect($data['edges'])->not()->toBeEmpty();
- }
- /**
- * Test: Unauthenticated request returns error
- */
- public function test_get_customer_reviews_requires_authentication(): void
- {
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 5) {
- edges {
- node {
- _id
- }
- }
- }
- }
- GQL;
- $response = $this->graphQL($query);
- $response->assertOk();
- $errors = $response->json('errors');
- expect($errors)->not()->toBeEmpty();
- }
- /**
- * Test: Customer only sees their own reviews
- */
- public function test_customer_only_sees_own_reviews(): void
- {
- $testData = $this->createTestData();
- /** Create another customer with their own review */
- $otherCustomer = $this->createCustomer();
- $product = Product::factory()->create();
- ProductReview::factory()->create([
- 'customer_id' => $otherCustomer->id,
- 'product_id' => $product->id,
- 'status' => 'approved',
- ]);
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 50) {
- edges {
- node {
- _id
- }
- }
- totalCount
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- /** Should only see the 2 reviews belonging to testData customer */
- expect($data['totalCount'])->toBe(2);
- }
- // ── Single Item Query ─────────────────────────────────────
- /**
- * Test: Query single customer review by ID
- */
- public function test_get_customer_review_by_id(): void
- {
- $testData = $this->createTestData();
- $reviewId = "/api/shop/customer-reviews/{$testData['review1']->id}";
- $query = <<<GQL
- query getCustomerReview {
- customerReview(id: "{$reviewId}") {
- id
- _id
- title
- comment
- rating
- status
- name
- product {
- id
- }
- customer {
- id
- }
- createdAt
- updatedAt
- }
- }
- GQL;
- $response = $this->graphQL($query);
- $response->assertOk();
- $data = $response->json('data.customerReview');
- expect($data['_id'])->toBe($testData['review1']->id);
- expect($data['title'])->toBe('Great product');
- expect($data['rating'])->toBe(5);
- expect($data['product'])->toHaveKey('id');
- expect($data['customer'])->toHaveKey('id');
- }
- /**
- * Test: Query with invalid ID returns null/error
- */
- public function test_invalid_customer_review_id_returns_error(): void
- {
- $query = <<<'GQL'
- query getCustomerReview {
- customerReview(id: "/api/shop/customer-reviews/99999") {
- id
- }
- }
- GQL;
- $response = $this->graphQL($query);
- $response->assertOk();
- expect($response->json('data.customerReview'))->toBeNull();
- }
- // ── Filtering ─────────────────────────────────────────────
- /**
- * Test: Filter reviews by status
- */
- public function test_filter_reviews_by_status(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 10, status: "approved") {
- edges {
- node {
- _id
- status
- }
- }
- totalCount
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- expect($data['totalCount'])->toBe(1);
- $statuses = collect($data['edges'])->pluck('node.status')->unique()->toArray();
- expect($statuses)->toBe(['approved']);
- }
- /**
- * Test: Filter reviews by rating
- */
- public function test_filter_reviews_by_rating(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 10, rating: 5) {
- edges {
- node {
- _id
- rating
- }
- }
- totalCount
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- expect($data['totalCount'])->toBe(1);
- $ratings = collect($data['edges'])->pluck('node.rating')->unique()->toArray();
- expect($ratings)->toBe([5]);
- }
- /**
- * Test: Filter with no matching results returns empty collection
- */
- public function test_filter_with_no_matches_returns_empty(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 10, status: "rejected") {
- edges {
- node {
- _id
- }
- }
- totalCount
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- expect($data['totalCount'])->toBe(0);
- expect($data['edges'])->toBeEmpty();
- }
- // ── Pagination ────────────────────────────────────────────
- /**
- * Test: Pagination with first parameter
- */
- public function test_pagination_first(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 1) {
- edges {
- node {
- _id
- }
- }
- pageInfo {
- hasNextPage
- }
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- expect($data['edges'])->toHaveCount(1);
- }
- /**
- * Test: Cursor-based pagination with after parameter
- */
- public function test_pagination_with_cursor(): void
- {
- $testData = $this->createTestData();
- /** Fetch first page to get cursor */
- $firstQuery = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 1) {
- edges {
- cursor
- node {
- _id
- }
- }
- }
- }
- GQL;
- $firstResponse = $this->authenticatedGraphQL($testData['customer'], $firstQuery);
- $cursor = $firstResponse->json('data.customerReviews.edges.0.cursor');
- /** Fetch second page using cursor */
- $secondQuery = <<<GQL
- query getCustomerReviews {
- customerReviews(first: 1, after: "{$cursor}") {
- edges {
- node {
- _id
- }
- }
- }
- }
- GQL;
- $secondResponse = $this->authenticatedGraphQL($testData['customer'], $secondQuery);
- $secondResponse->assertOk();
- }
- // ── Field & Format Assertions ─────────────────────────────
- /**
- * Test: All expected fields are present on the review node
- */
- public function test_query_all_fields(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 1) {
- edges {
- node {
- id
- _id
- title
- comment
- rating
- status
- name
- product {
- id
- }
- customer {
- id
- }
- createdAt
- updatedAt
- }
- }
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $node = $response->json('data.customerReviews.edges.0.node');
- expect($node)->toHaveKeys([
- 'id', '_id', 'title', 'comment', 'rating',
- 'status', 'name', 'product', 'customer',
- 'createdAt', 'updatedAt',
- ]);
- }
- /**
- * Test: Timestamps are returned in ISO8601 format
- */
- public function test_timestamps_are_iso8601_format(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 1) {
- edges {
- node {
- _id
- createdAt
- updatedAt
- }
- }
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $node = $response->json('data.customerReviews.edges.0.node');
- expect($node['createdAt'])->toMatch('/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/');
- expect($node['updatedAt'])->toMatch('/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/');
- }
- /**
- * Test: Numeric ID (_id) is an integer
- */
- public function test_numeric_id_is_integer(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 1) {
- edges {
- node {
- _id
- }
- }
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $node = $response->json('data.customerReviews.edges.0.node');
- expect($node['_id'])->toBeInt();
- }
- // ── Schema Introspection ──────────────────────────────────
- /**
- * Test: CustomerReview type exists in GraphQL schema
- */
- public function test_introspection_query(): void
- {
- $query = <<<'GQL'
- {
- __type(name: "CustomerReview") {
- name
- kind
- fields {
- name
- }
- }
- }
- GQL;
- $response = $this->graphQL($query);
- $response->assertOk();
- $type = $response->json('data.__type');
- expect($type['name'])->toBe('CustomerReview');
- expect($type['kind'])->toBe('OBJECT');
- $fieldNames = collect($type['fields'])->pluck('name')->toArray();
- expect($fieldNames)->toContain('id', '_id', 'title', 'comment', 'rating', 'status', 'name');
- }
- // ── Edge Cases ────────────────────────────────────────────
- /**
- * Test: Customer with no reviews returns empty collection
- */
- public function test_customer_with_no_reviews_returns_empty(): void
- {
- $this->seedRequiredData();
- $customer = $this->createCustomer();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 10) {
- edges {
- node {
- _id
- }
- }
- totalCount
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($customer, $query);
- $response->assertOk();
- $data = $response->json('data.customerReviews');
- expect($data['totalCount'])->toBe(0);
- expect($data['edges'])->toBeEmpty();
- }
- /**
- * Test: Reviews include product relationship data
- */
- public function test_reviews_include_product_relationship(): void
- {
- $testData = $this->createTestData();
- $query = <<<'GQL'
- query getCustomerReviews {
- customerReviews(first: 1) {
- edges {
- node {
- _id
- product {
- id
- }
- }
- }
- }
- }
- GQL;
- $response = $this->authenticatedGraphQL($testData['customer'], $query);
- $response->assertOk();
- $node = $response->json('data.customerReviews.edges.0.node');
- expect($node)->toHaveKey('product');
- expect($node['product'])->toHaveKey('id');
- }
- }
|