Skip to content

Commit 3572c7b

Browse files
laylatichygitbutler-client
authored andcommitted
test(database): add failing tests for whereHas in WhereGroupBuilder
1 parent f527f4c commit 3572c7b

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Database\Builder;
6+
7+
use PHPUnit\Framework\Attributes\Test;
8+
use Tempest\Database\Builder\QueryBuilders\WhereGroupBuilder;
9+
use Tempest\Database\Migrations\CreateMigrationsTable;
10+
use Tests\Tempest\Fixtures\Migrations\CreateAuthorTable;
11+
use Tests\Tempest\Fixtures\Migrations\CreateBookTable;
12+
use Tests\Tempest\Fixtures\Migrations\CreateChapterTable;
13+
use Tests\Tempest\Fixtures\Migrations\CreateIsbnTable;
14+
use Tests\Tempest\Fixtures\Migrations\CreatePublishersTable;
15+
use Tests\Tempest\Fixtures\Modules\Books\Models\Author;
16+
use Tests\Tempest\Fixtures\Modules\Books\Models\Book;
17+
use Tests\Tempest\Fixtures\Modules\Books\Models\Chapter;
18+
use Tests\Tempest\Fixtures\Modules\Books\Models\Isbn;
19+
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
20+
21+
/**
22+
* @internal
23+
*/
24+
final class WhereHasInWhereGroupTest extends FrameworkIntegrationTestCase
25+
{
26+
#[Test]
27+
public function where_has_in_where_group_compiles_exists_subquery(): void
28+
{
29+
$sql = Book::select()
30+
->whereGroup(callback: function (WhereGroupBuilder $group): void {
31+
$group->whereHas(relation: 'chapters');
32+
})
33+
->compile();
34+
35+
$this->assertSameWithoutBackticks(
36+
'SELECT books.id AS books.id, books.title AS books.title, books.author_id AS books.author_id FROM books WHERE EXISTS (SELECT 1 FROM chapters WHERE chapters.book_id = books.id)',
37+
$sql,
38+
);
39+
}
40+
41+
#[Test]
42+
public function or_where_has_in_where_group_compiles_or_exists_wrapped_in_parentheses(): void
43+
{
44+
$sql = Book::select()
45+
->whereGroup(callback: function (WhereGroupBuilder $group): void {
46+
$group
47+
->whereHas(relation: 'chapters')
48+
->orWhereHas(relation: 'isbn');
49+
})
50+
->compile();
51+
52+
$this->assertSameWithoutBackticks(
53+
'SELECT books.id AS books.id, books.title AS books.title, books.author_id AS books.author_id FROM books WHERE (EXISTS (SELECT 1 FROM chapters WHERE chapters.book_id = books.id) OR EXISTS (SELECT 1 FROM isbns WHERE isbns.book_id = books.id))',
54+
$sql,
55+
);
56+
}
57+
58+
#[Test]
59+
public function or_where_doesnt_have_in_where_group_compiles_or_not_exists(): void
60+
{
61+
$sql = Book::select()
62+
->whereGroup(callback: function (WhereGroupBuilder $group): void {
63+
$group
64+
->whereHas(relation: 'chapters')
65+
->orWhereDoesntHave(relation: 'isbn');
66+
})
67+
->compile();
68+
69+
$this->assertSameWithoutBackticks(
70+
'SELECT books.id AS books.id, books.title AS books.title, books.author_id AS books.author_id FROM books WHERE (EXISTS (SELECT 1 FROM chapters WHERE chapters.book_id = books.id) OR NOT EXISTS (SELECT 1 FROM isbns WHERE isbns.book_id = books.id))',
71+
$sql,
72+
);
73+
}
74+
75+
#[Test]
76+
public function where_has_in_where_group_with_callback_compiles_constrained_subquery(): void
77+
{
78+
$sql = Book::select()
79+
->whereGroup(callback: function (WhereGroupBuilder $group): void {
80+
$group->whereHas(
81+
relation: 'chapters',
82+
callback: function ($query): void {
83+
$query->whereField(field: 'title', value: 'Chapter 1');
84+
},
85+
);
86+
})
87+
->compile();
88+
89+
$this->assertSameWithoutBackticks(
90+
'SELECT books.id AS books.id, books.title AS books.title, books.author_id AS books.author_id FROM books WHERE EXISTS (SELECT 1 FROM chapters WHERE chapters.book_id = books.id AND chapters.title = ?)',
91+
$sql,
92+
);
93+
}
94+
95+
#[Test]
96+
public function where_has_in_or_where_group_combines_with_outer_where(): void
97+
{
98+
$sql = Book::select()
99+
->whereField(field: 'title', value: 'LOTR 1')
100+
->orWhereGroup(callback: function (WhereGroupBuilder $group): void {
101+
$group
102+
->whereHas(relation: 'chapters')
103+
->orWhereHas(relation: 'isbn');
104+
})
105+
->compile();
106+
107+
$this->assertSameWithoutBackticks(
108+
'SELECT books.id AS books.id, books.title AS books.title, books.author_id AS books.author_id FROM books WHERE books.title = ? OR (EXISTS (SELECT 1 FROM chapters WHERE chapters.book_id = books.id) OR EXISTS (SELECT 1 FROM isbns WHERE isbns.book_id = books.id))',
109+
$sql,
110+
);
111+
}
112+
113+
#[Test]
114+
public function or_where_has_in_where_group_returns_matching_books(): void
115+
{
116+
$this->seed();
117+
118+
$books = Book::select()
119+
->whereGroup(callback: function (WhereGroupBuilder $group): void {
120+
$group
121+
->whereHas(relation: 'chapters')
122+
->orWhereHas(relation: 'isbn');
123+
})
124+
->orderBy(field: 'id')
125+
->all();
126+
127+
$this->assertCount(2, $books);
128+
$this->assertSame('LOTR 1', $books[0]->title);
129+
$this->assertSame('Timeline Taxi', $books[1]->title);
130+
}
131+
132+
private function seed(): void
133+
{
134+
$this->database->migrate(
135+
CreateMigrationsTable::class,
136+
CreatePublishersTable::class,
137+
CreateAuthorTable::class,
138+
CreateBookTable::class,
139+
CreateChapterTable::class,
140+
CreateIsbnTable::class,
141+
);
142+
143+
$brent = Author::create(name: 'Brent');
144+
$tolkien = Author::create(name: 'Tolkien');
145+
146+
$lotr1 = Book::create(title: 'LOTR 1', author: $tolkien);
147+
Book::create(title: 'LOTR 2', author: $tolkien);
148+
Book::create(title: 'LOTR 3', author: $tolkien);
149+
$timelineTaxi = Book::create(title: 'Timeline Taxi', author: $brent);
150+
151+
Chapter::create(title: 'Chapter 1', book: $lotr1);
152+
153+
Isbn::create(value: 'isbn-lotr-1', book: $lotr1);
154+
Isbn::create(value: 'isbn-tt', book: $timelineTaxi);
155+
}
156+
}

0 commit comments

Comments
 (0)