Skip to content

Commit e22e114

Browse files
committed
wip
1 parent 369e457 commit e22e114

File tree

3 files changed

+124
-55
lines changed

3 files changed

+124
-55
lines changed

config/laravel-playwright.php

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,25 @@
5959
'user' => 'App\\Models\\User',
6060

6161
/**
62-
* When passing state values to the factory, you can include a class or class alias (see
63-
* below) along with a value and column. This is handy for when the state method on the
64-
* factory expects an object as the parameter(s). These config values will be used as the
65-
* separators to split the class/alias from the id and column.
62+
* When passing state values to the factory, you can include a FQCN or class alias (see
63+
* below) along with a value and column, or params (if param_alias). This is handy for
64+
* when the state method on the factory expects an object as the parameter(s). The
65+
* separator config values defined below will be used as the detectors and
66+
* separators to split the class/alias from the passed options/params.
67+
*
68+
* When passing a model or model alias, you should prefix the model definition with
69+
* 'model.' (can be changed as desired below) so that we can differentiate it from
70+
* a param alias.
71+
*
72+
* ** To fetch a model and pass to the state method: **
6673
*
67-
* eg:
6874
* This will trigger the "first" eloquent method to execute with a "where" clause for
69-
* the user with an id of 100. This User will then be passed to the "createdBy"
70-
* method on the factory.
75+
* the user with an `id` of 100. This fetched and hydrated `User` will then be passed
76+
* to your "createdBy" method on the defined factory.
7177
*
7278
* $state = [
7379
* 'createdBy' => [
74-
* ['user@100:id'],
80+
* ['model.user:100,id'],
7581
* ],
7682
* ]
7783
*
@@ -80,47 +86,61 @@
8086
*
8187
* $state = [
8288
* 'createdBy' => [
83-
* ['\\App\\Models\\User@100'],
89+
* ['model.\\App\\Models\\User:100'],
8490
* ],
8591
* ]
8692
*
87-
* eg:
88-
* This will use the `param_alias` commented out below to resolve the param for the endsAt
93+
* ** To construct an object with params to be passed to the state method: **
94+
*
95+
* This will use a `param_alias` (defined below) to resolve the param for the `endsAt`
8996
* state method on the factory as a Carbon instance with the value to the right of the
9097
* separator. You can also pass multiple parameters to the state method that resolve using
91-
* aliases as defined below. Parameters for the param_alias should be wrapped in square
92-
* brackets as shown below.
98+
* aliases as defined below. Parameters for the param_alias should be wrapped in
99+
* parentheses as shown below.
93100
*
101+
* This example will use the `carbon` alias (defined below - commented out) to make a
102+
* `Carbon` instance with the value `2023-12-25 23:59:59`, and will be passed to the
103+
* `endsAt` method on the factory:
94104
* $state = [
95105
* 'endsAt' => [
96-
* ['carbon@[2023-12-25 23:59:59]'],
106+
* ['carbon(2023-12-25 23:59:59)'],
97107
* ],
108+
* ]
109+
*
110+
* This example will use the carbon alias to make 2 instances, each with the date values
111+
* as shown, and both instances will then be passed, in the order they are defined, to the `liveBetween` method on the factory class:
112+
* $state = [
98113
* 'liveBetween' => [
99-
* ['carbon@[2023-01-01 00:00:00]', 'carbon@[2023-12-25 23:59:59]'],
114+
* ['carbon(2023-01-01 00:00:00)', 'carbon(2023-12-25 23:59:59)'],
100115
* ],
116+
* ]
117+
*
118+
* This example will use the collect alias to make a Collection with 2 items as defined.
119+
* The Collection instance will then be passed to the comments method on the factory:
120+
* $state = [
101121
* 'comments' => [
102-
* ['collect@[hello,goodbye]'],
122+
* ['collect(hello,goodbye)'],
103123
* ],
104124
* ]
105125
*/
106126

107127
/**
108-
* Used to separate the alias from any other passed options. Should be used first.
128+
* Used to separate the model from any other passed options.
109129
*/
110-
'alias_separator' => '@',
111-
112-
/**
113-
* If passing multiple params to be passed into an aliases callable, you can separate
114-
* them using this option.
115-
*/
116-
'param_separator' => ',',
130+
'model_separator' => ':',
117131

118132
/**
119133
* If you wish to resolve a model from the DB, you can optionally pass the column to compare
120134
* the value to in a where clause. The default column used is `id`. Use this separator to
121135
* separate the desired column from the rest of the passed options.
122136
*/
123-
'column_separator' => ':',
137+
'column_separator' => ',',
138+
139+
/**
140+
* If passing multiple params to be passed into an alias' callable, you can separate
141+
* them using this option.
142+
*/
143+
'param_separator' => ',',
124144

125145
/**
126146
* You can optionally register aliases for models or other objects, rather than having
@@ -136,7 +156,7 @@
136156

137157
'param_aliases' => [
138158
// 'carbon' => fn($date) => \Carbon\Carbon::create($date),
139-
// 'collect' => fn($items) => \Illuminate\Support\Collection::make($items),
159+
// 'collect' => fn($items) => \Illuminate\Support\Collection::make(...$items),
140160
],
141161

142162
],
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Leeovery\LaravelPlaywright\Exceptions;
4+
5+
use Exception;
6+
7+
class LaravelPlaywrightException extends Exception
8+
{
9+
public static function resolvedModelDoesNotExist($model): LaravelPlaywrightException
10+
{
11+
return new self("Passed model does not exist ({$model}).", 404);
12+
}
13+
14+
public static function resolvedParamAliasDoesNotExist($alias): LaravelPlaywrightException
15+
{
16+
return new self("Passed param alias does not exist ({$alias}).", 404);
17+
}
18+
}

src/Http/Controllers/LaravelPlaywrightController.php

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
namespace Leeovery\LaravelPlaywright\Http\Controllers;
44

5-
use Illuminate\Support\Arr;
6-
use Illuminate\Support\Str;
5+
use Illuminate\Database\Eloquent\Factories\Factory;
76
use Illuminate\Http\Request;
7+
use Illuminate\Routing\Route as RoutingRoute;
8+
use Illuminate\Support\Arr;
9+
use Illuminate\Support\Facades\Artisan;
810
use Illuminate\Support\Facades\DB;
911
use Illuminate\Support\Facades\Route;
10-
use Illuminate\Support\Facades\Artisan;
11-
use Illuminate\Routing\Route as RoutingRoute;
12-
use Illuminate\Database\Eloquent\Factories\Factory;
12+
use Illuminate\Support\Str;
13+
use Leeovery\LaravelPlaywright\Exceptions\LaravelPlaywrightException;
14+
use Throwable;
1315

1416
class LaravelPlaywrightController
1517
{
@@ -119,11 +121,11 @@ public function tearDownEnv()
119121
public function routes()
120122
{
121123
return collect(Route::getRoutes()->getRoutes())
122-
->reject(fn(RoutingRoute $route) => Str::of($route->getName())
124+
->reject(fn (RoutingRoute $route) => Str::of($route->getName())
123125
->contains(config('laravel-playwright.route.ignore_names'))
124126
)
125-
->reject(fn(RoutingRoute $route) => is_null($route->getName()))
126-
->mapWithKeys(fn(RoutingRoute $route) => [
127+
->reject(fn (RoutingRoute $route) => is_null($route->getName()))
128+
->mapWithKeys(fn (RoutingRoute $route) => [
127129
$route->getName() => [
128130
'name' => $route->getName(),
129131
'uri' => $route->uri(),
@@ -150,7 +152,7 @@ public function login(Request $request)
150152
->first();
151153
}
152154

153-
if (!$user) {
155+
if (! $user) {
154156
$user = DB::transaction(function () use ($request) {
155157
return $this
156158
->factoryBuilder($this->userClassName($request), $request->input('state', []))
@@ -176,19 +178,31 @@ protected function userClassName(Request $request)
176178
return config('laravel-playwright.factory.user');
177179
}
178180

181+
/**
182+
* @throws Throwable
183+
*/
179184
protected function resolveModelAlias(string $alias)
180185
{
181-
return data_get(config('laravel-playwright.factory.model_aliases'), $alias, $alias);
186+
$model = data_get(config('laravel-playwright.factory.model_aliases'), $alias, $alias);
187+
188+
throw_unless(class_exists($model),
189+
LaravelPlaywrightException::resolvedModelDoesNotExist($model)
190+
);
191+
192+
return $model;
182193
}
183194

195+
/**
196+
* @throws Throwable
197+
*/
184198
protected function factoryBuilder($model, $states = []): Factory
185199
{
186200
$factory = $this->resolveModelAlias($model)::factory();
187201

188202
foreach (Arr::wrap($states) as $state) {
189203
$attributes = [];
190204
if (is_array($state)) {
191-
$attributes = $this->buildUpStateAttributes($state);
205+
$attributes = $this->resolveStateAttributes($state);
192206
$state = array_key_first($state);
193207
}
194208
$factory = $factory->{$state}(...$attributes);
@@ -234,54 +248,71 @@ public function factory(Request $request)
234248
)
235249
->count($request->integer('count', 1))
236250
->create($request->input('attributes'))
237-
->each(fn($model) => $model->setHidden([])->setVisible([]))
251+
->each(fn ($model) => $model->setHidden([])->setVisible([]))
238252
->load($request->input('load') ?? [])
239-
->pipe(fn($collection) => $collection->count() > 1
253+
->pipe(fn ($collection) => $collection->count() > 1
240254
? $collection
241255
: $collection->first());
242256
});
243257
}
244258

245-
protected function buildUpStateAttributes($state): array
259+
protected function resolveStateAttributes($state): array
246260
{
247-
if (!is_array($state)) {
261+
if (! is_array($state)) {
248262
return [];
249263
}
250264

251-
$aliasSeparator = config('laravel-playwright.factory.alias_separator');
252-
$paramSeparator = config('laravel-playwright.factory.param_separator');
265+
$modelDesignator = config('laravel-playwright.factory.model_designator');
266+
$modelSeparator = config('laravel-playwright.factory.model_separator');
253267
$columnSeparator = config('laravel-playwright.factory.column_separator');
268+
$paramSeparator = config('laravel-playwright.factory.param_separator');
254269

255270
return collect(...array_values($state))->map(function ($attribute) use (
271+
$modelDesignator,
272+
$modelSeparator,
256273
$columnSeparator,
257274
$paramSeparator,
258-
$aliasSeparator
259275
) {
260-
if (!is_string($attribute) || !str_contains($attribute, $aliasSeparator)) {
276+
if (
277+
! is_string($attribute)
278+
|| ! str_contains($attribute, $modelDesignator)
279+
|| (! str_contains($attribute, '(') && ! str_contains($attribute, ')'))
280+
) {
261281
return $attribute;
262282
}
263283

264-
if (str_contains($attribute, '[') && str_contains($attribute, ']')) {
265-
[$alias, $options] = explode($aliasSeparator, $attribute);
266-
$options = str($options)
267-
->remove('[')
268-
->remove(']')
284+
if (str_contains($attribute, '(') && str_contains($attribute, ')')) {
285+
$paramAlias = Str::before($attribute, '(');
286+
$params = str($attribute)
287+
->between('(', ')')
269288
->explode($paramSeparator)
270-
->map(fn($option) => trim($option));
271-
return value($this->resolveParamAlias($alias), ...$options);
289+
->map(fn ($option) => trim($option));
290+
291+
return value($this->resolveParamAlias($paramAlias), ...$params);
272292
}
273293

274-
[$modelAlias, $options] = explode($aliasSeparator, $attribute);
294+
$attribute = Str::after($attribute, $modelDesignator);
295+
296+
[$model, $options] = explode($modelSeparator, $attribute);
275297
[$value, $column] = array_pad(explode($columnSeparator, $options), 2, null);
276298
$column ??= 'id';
277299

278-
return $this->resolveModelAlias($modelAlias)::where($column, $value)->first();
300+
return $this->resolveModelAlias($model)::where($column, $value)->first();
279301
})->filter()->all();
280302
}
281303

304+
/**
305+
* @throws Throwable
306+
*/
282307
protected function resolveParamAlias(string $alias): callable
283308
{
284-
return data_get(config('laravel-playwright.factory.param_aliases'), $alias, $alias);
309+
$paramAlias = data_get(config('laravel-playwright.factory.param_aliases'), $alias);
310+
311+
throw_if(is_null($paramAlias),
312+
LaravelPlaywrightException::resolvedParamAliasDoesNotExist($alias)
313+
);
314+
315+
return $paramAlias;
285316
}
286317

287318
public function logout()

0 commit comments

Comments
 (0)