Skip to content

Commit a0d3844

Browse files
committed
Merge branch 'pr/40' into dev-main
2 parents 3ebf31e + 4173dc3 commit a0d3844

33 files changed

+1103
-74
lines changed

flake.nix

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
./vendor/bin/pest --coverage
4545
unset XDEBUG_MODE
4646
'';
47+
coverage-xml.exec = ''
48+
export XDEBUG_MODE=coverage
49+
./vendor/bin/pest --coverage --coverage-clover clover.xml
50+
unset XDEBUG_MODE
51+
'';
4752

4853
# swap a and artisan commands for testbench
4954
a.exec = ''
@@ -65,6 +70,10 @@
6570
ini = ''
6671
memory_limit = 5G
6772
max_execution_time = 90
73+
74+
[xdebug]
75+
xdebug.start_with_request=yes
76+
xdebug.start_upon_error=yes
6877
'';
6978
};
7079
};

phpunit.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
2+
<phpunit
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
5+
beStrictAboutOutputDuringTests="true"
6+
bootstrap="vendor/autoload.php"
7+
colors="true"
8+
failOnRisky="true"
9+
>
310
<testsuites>
411
<testsuite name="Tests">
512
<directory suffix="Test.php">./tests</directory>
@@ -18,7 +25,7 @@
1825
</php>
1926
<source>
2027
<include>
21-
<directory suffix=".php">src/</directory>
28+
<directory suffix=".php">./src</directory>
2229
</include>
2330
</source>
2431
</phpunit>

src/Eloquent/Model.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,16 +276,6 @@ public function getForeignKey(): string
276276
return Str::snake(class_basename($this)).'_'.ltrim($this->primaryKey, '_');
277277
}
278278

279-
/**
280-
* {@inheritdoc}
281-
*/
282-
public function newEloquentBuilder($query): Builder
283-
{
284-
$builder = new Builder($query);
285-
286-
return $builder;
287-
}
288-
289279
public function saveWithoutRefresh(array $options = []): bool
290280
{
291281
$this->mergeAttributesFromCachedCasts();

src/Exceptions/MissingOrderException.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,4 @@ public function __construct($message = 'Order parameter is required for paginati
1414
{
1515
parent::__construct($message, $code, $previous);
1616
}
17-
18-
public function render($request): \Illuminate\Http\JsonResponse
19-
{
20-
return response()->json([
21-
'error' => $this->getMessage(),
22-
], 400);
23-
}
2417
}

src/Meta/ModelMetaData.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public function parseHighlights($data = []): ?object
9898
return null;
9999
}
100100

101-
public function asArray()
101+
public function asArray() : array
102102
{
103103
return [
104104
'score' => $this->score,

tests/ConnectionTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Support\Facades\DB;
6+
use PDPhilip\Elasticsearch\Connection;
7+
use PDPhilip\Elasticsearch\Schema\Builder as SchemaBuilder;
8+
9+
test('Connection', function () {
10+
$connection = DB::connection('elasticsearch');
11+
12+
expect($connection)->toBeInstanceOf(Connection::class)
13+
->and($connection->getDriverName())->toEqual('elasticsearch')
14+
->and($connection->getDriverTitle())->toEqual('elasticsearch');
15+
});
16+
17+
test('Reconnect', function () {
18+
$c1 = DB::connection('elasticsearch');
19+
$c2 = DB::connection('elasticsearch');
20+
expect(spl_object_hash($c1) === spl_object_hash($c2))->toBeTrue();
21+
22+
$c1 = DB::connection('elasticsearch');
23+
DB::purge('elasticsearch');
24+
$c2 = DB::connection('elasticsearch');
25+
expect(spl_object_hash($c1) !== spl_object_hash($c2))->toBeTrue();
26+
});
27+
28+
test('Schema Builder', function () {
29+
$schema = DB::connection('elasticsearch')->getSchemaBuilder();
30+
expect($schema)->toBeInstanceOf(SchemaBuilder::class);
31+
});
32+
33+
test('Driver Name', function () {
34+
$driver = DB::connection('elasticsearch')->getDriverName();
35+
expect($driver === 'elasticsearch')->toBeTrue();
36+
});

tests/Eloquent/AggregationTest.php

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
declare(strict_types=1);
44

5+
use Illuminate\Database\Eloquent\Factories\Sequence;
56
use Workbench\App\Models\Product;
7+
use Workbench\App\Models\UserLog;
68

79
test('retrieve distinct product statuses', function () {
810
Product::factory()->state(['status' => 1])->count(3)->create();
@@ -40,3 +42,138 @@
4042

4143
expect($statuses->first()->status_count)->toEqual(5);
4244
});
45+
46+
it('should perform aggregate sum on distinct and groupBy queries', function () {
47+
createCompanyData(
48+
logsPerUser: 50
49+
);
50+
51+
$dist = UserLog::where('status', 9)->distinct()->sum('code');
52+
$grp = UserLog::where('status', 9)->groupBy(['code'])->sum('code');
53+
54+
expect($dist)->toEqual($grp);
55+
});
56+
57+
it('should perform aggregate max on distinct and groupBy queries', function () {
58+
createCompanyData(
59+
logsPerUser: 50
60+
);
61+
62+
$dist = UserLog::where('status', 9)->distinct()->max('code');
63+
$grp = UserLog::where('status', 9)->groupBy(['code'])->max('code');
64+
65+
expect($dist)->toEqual($grp);
66+
67+
});
68+
69+
it('should perform aggregate min on distinct and groupBy queries', function () {
70+
createCompanyData(
71+
logsPerUser: 50
72+
);
73+
74+
$dist = UserLog::where('status', 9)->distinct()->min('code');
75+
$grp = UserLog::where('status', 9)->groupBy(['code'])->min('code');
76+
77+
expect($dist)->toEqual($grp);
78+
79+
});
80+
81+
it('should perform aggregate avg on distinct and groupBy queries', function () {
82+
createCompanyData(
83+
logsPerUser: 50
84+
);
85+
86+
$dist = UserLog::where('status', 9)->distinct()->avg('code');
87+
$grp = UserLog::where('status', 9)->groupBy(['code'])->avg('code');
88+
89+
expect($dist)->toEqual($grp);
90+
91+
});
92+
93+
test('Count', function () {
94+
$products = Product::factory(10)->make();
95+
Product::insert($products->toArray());
96+
expect(Product::count())->toBe(10);
97+
});
98+
99+
test('Max', function () {
100+
$products = Product::factory(10)
101+
->state(new Sequence(
102+
['price' => 10.0],
103+
['price' => 120.0],
104+
))->make();
105+
Product::insert($products->toArray());
106+
expect(Product::max('price'))->toBe(120.0);
107+
});
108+
109+
test('Min', function () {
110+
$products = Product::factory(10)
111+
->state(new Sequence(
112+
['price' => 10.0],
113+
['price' => 120.0],
114+
))->make();
115+
Product::insert($products->toArray());
116+
expect(Product::min('price'))->toBe(10.0);
117+
});
118+
119+
test('Avg', function () {
120+
$products = Product::factory(10)
121+
->state(new Sequence(
122+
['price' => 10.0],
123+
['price' => 120.0],
124+
))->make();
125+
Product::insert($products->toArray());
126+
expect(Product::avg('price'))->toBe(65.0);
127+
});
128+
129+
test('Sum', function () {
130+
$products = Product::factory(10)
131+
->state(['price' => 10.0])->make();
132+
Product::insert($products->toArray());
133+
expect(Product::sum('price'))->toBe(100.0);
134+
});
135+
136+
test('Multiple fields at once', function () {
137+
$products = Product::factory(10)
138+
->state(new Sequence(
139+
['price' => 10.0, 'discount_amount' => 5.0],
140+
['price' => 120.0, 'discount_amount' => 7.0],
141+
))->make();
142+
Product::insert($products->toArray());
143+
144+
$max = Product::max(['price', 'discount_amount']);
145+
146+
expect($max)->toBeArray()
147+
->and($max['max_price'])->toBe(120.0)
148+
->and($max['max_discount_amount'])->toBe(7.0);
149+
});
150+
151+
test('Multiple aggs', function () {
152+
$products = Product::factory(10)
153+
->state(new Sequence(
154+
['price' => 10.0, 'discount_amount' => 5.0],
155+
['price' => 120.0, 'discount_amount' => 7.0],
156+
))->make();
157+
Product::insert($products->toArray());
158+
159+
$max = Product::agg(['count', 'avg', 'min', 'max', 'sum'], 'price');
160+
161+
expect($max)->toBeArray()
162+
->and($max)->toHaveKeys(['max_price', 'min_price', 'count_price', 'avg_price', 'sum_price']);
163+
});
164+
165+
test('Matrix', function () {
166+
$products = Product::factory(100)
167+
->state(new Sequence(
168+
['color' => 'red'],
169+
['color' => 'green'],
170+
['color' => 'blue'],
171+
['color' => 'yellow'],
172+
))->make();
173+
Product::insert($products->toArray());
174+
175+
$matrix = Product::whereNotIn('color', ['red', 'green'])->matrix('price');
176+
177+
expect($matrix)->toBeArray()
178+
->and($matrix['fields'])->toBeArray();
179+
});

tests/Eloquent/ElasticsearchSpecificTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@
9595
expect($regexProducts)->toHaveCount(2);
9696
});
9797

98+
test('search for products using or regex on color', function () {
99+
Product::factory()->state(['color' => 'blue'])->create();
100+
Product::factory()->state(['color' => 'black'])->create();
101+
Product::factory()->state(['color' => 'red'])->create();
102+
103+
$regexProducts = Product::where('color', 'red')->orWhereRegex('color', 'bl(ue)?(ack)?')->get();
104+
expect($regexProducts)->toHaveCount(3);
105+
});
106+
98107
test('execute raw DSL query on products', function () {
99108
Product::factory()->state(['color' => 'silver'])->create();
100109
Product::factory(2)->state(['color' => 'silver'])->create();
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Eloquent\Factories\Sequence;
6+
use Workbench\App\Models\Product;
7+
8+
beforeEach(function () {
9+
Product::truncate();
10+
});
11+
12+
it('should find active or stock greater than 50', function () {
13+
$products = Product::factory(99)
14+
->state(new Sequence(
15+
['in_stock' => 51],
16+
['in_stock' => 3],
17+
['is_active' => true, 'in_stock' => 10],
18+
))->make();
19+
Product::insert($products->toArray());
20+
21+
$prods = Product::whereNested(function ($query) {
22+
$query->where('is_active', true)->orWhere('in_stock', '>', 50);
23+
})->get();
24+
25+
$prodsAlt = Product::where(function ($query) {
26+
$query->where('is_active', true)->orWhere('in_stock', '>', 50);
27+
})->get();
28+
29+
expect(count($prods))->toBeLessThanOrEqual(90)
30+
->and(count($prodsAlt))->toBeLessThanOrEqual(90);
31+
32+
});
33+
34+
it('should find black and active or blue and inactive', function () {
35+
$products = Product::factory(100)
36+
->state(new Sequence(
37+
['is_active' => true, 'color' => 'black'],
38+
['is_active' => true, 'color' => 'blue'],
39+
['is_active' => false, 'color' => 'black'],
40+
['is_active' => false, 'color' => 'blue'],
41+
))->make();
42+
Product::insert($products->toArray());
43+
44+
$prodsAlt = Product::where(function ($query) {
45+
$query->where('color', 'black')->where('is_active', true);
46+
})->orWhere(
47+
function ($query) {
48+
$query->where('color', 'blue')->where('is_active', false);
49+
}
50+
)->get();
51+
52+
expect(count($prodsAlt))->toBeLessThanOrEqual(50);
53+
});
54+
55+
it('should find (Black Or Blue) And (Status1 Or NotActive)', function () {
56+
$products = Product::factory(100)
57+
->state(new Sequence(
58+
['is_active' => true, 'color' => 'black', 'status' => 2],
59+
['is_active' => true, 'color' => 'blue', 'status' => 2],
60+
['is_active' => false, 'color' => 'black', 'status' => 2],
61+
['is_active' => false, 'color' => 'blue', 'status' => 2],
62+
['is_active' => true, 'color' => 'black', 'status' => 1],
63+
['is_active' => true, 'color' => 'blue', 'status' => 1],
64+
['is_active' => false, 'color' => 'black', 'status' => 1],
65+
['is_active' => false, 'color' => 'blue', 'status' => 1],
66+
))->make();
67+
Product::insert($products->toArray());
68+
69+
$prods = Product::whereNested(function ($query) {
70+
$query->where('color', 'black')->orWhere('color', 'blue');
71+
})->whereNested(function ($query) {
72+
$query->where('status', 1)->orWhere('is_active', false);
73+
}
74+
)->get();
75+
76+
expect(count($prods))->toBeLessThanOrEqual(74);
77+
78+
$prodsAlt = Product::where(function ($query) {
79+
$query->where('color', 'black')->orWhere('color', 'blue');
80+
})->where(function ($query) {
81+
$query->where('status', 1)->orWhere('is_active', false);
82+
}
83+
)->get();
84+
85+
expect(count($prodsAlt))->toBeLessThanOrEqual(74);
86+
});

tests/Eloquent/InsertTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare(strict_types=1);
44

55
use PDPhilip\Elasticsearch\Collection\ElasticCollection;
6+
use PDPhilip\Elasticsearch\Meta\QueryMetaData;
67
use Workbench\App\Models\Product;
78

89
test('bulk insert returns a Elastic Collection', function () {
@@ -17,7 +18,14 @@
1718
$products = Product::factory(1000)->make();
1819
$result = Product::insertWithoutRefresh($products->toArray());
1920
expect($result)->toBeInstanceOf(ElasticCollection::class)
20-
->and($result->getQueryMetaAsArray())->toBeArray();
21+
->and($result->getDsl())->toBeArray()
22+
->and($result->getDsl())->toHaveKeys(['query', 'dsl'])
23+
->and($result->getTook())->toBeInt()
24+
->and($result->getTotal())->toBeInt()
25+
->and($result->getMaxScore())->toBeString()
26+
->and($result->getResults())->toBeArray()
27+
->and($result->getQueryMetaAsArray())->toBeArray()
28+
->and($result->getQueryMeta())->toBeInstanceOf(QueryMetaData::class);
2129
sleep(2);
2230
expect(Product::count())->toBe(1000);
2331
});

0 commit comments

Comments
 (0)