Skip to content

Commit 7f9fe3f

Browse files
committed
fix: resolve ChildProcess dynamic property warnings
- Implement __get magic method for settings access - Add test verification for property hydration - Remove direct dynamic property assignments
1 parent afe7316 commit 7f9fe3f

File tree

2 files changed

+117
-90
lines changed

2 files changed

+117
-90
lines changed

src/ChildProcess.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class ChildProcess implements ChildProcessContract
1919

2020
public readonly bool $persistent;
2121

22+
protected array $settings = [];
23+
2224
final public function __construct(protected Client $client) {}
2325

2426
public function get(?string $alias = null): ?self
@@ -146,10 +148,13 @@ protected function fromRuntimeProcess($process)
146148
$this->pid = $process['pid'];
147149
}
148150

149-
foreach ($process['settings'] as $key => $value) {
150-
$this->{$key} = $value;
151-
}
151+
$this->settings = $process['settings'] ?? [];
152152

153153
return $this;
154154
}
155+
156+
public function __get($name)
157+
{
158+
return $this->settings[$name] ?? null;
159+
}
155160
}

tests/ChildProcess/ChildProcessTest.php

Lines changed: 109 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,121 +6,143 @@
66
use Native\Laravel\Client\Client;
77
use Native\Laravel\Facades\ChildProcess;
88

9-
beforeEach(function () {
10-
Http::fake();
9+
describe('API', function () {
10+
beforeEach(function () {
11+
Http::fake();
1112

12-
$mock = Mockery::mock(ChildProcessImplement::class, [resolve(Client::class)])
13-
->makePartial()
14-
->shouldAllowMockingProtectedMethods();
13+
$mock = Mockery::mock(ChildProcessImplement::class, [resolve(Client::class)])
14+
->makePartial()
15+
->shouldAllowMockingProtectedMethods();
1516

16-
$this->instance(ChildProcessImplement::class, $mock->allows([
17-
'fromRuntimeProcess' => $mock,
18-
]));
19-
});
17+
$this->instance(ChildProcessImplement::class, $mock->allows([
18+
'fromRuntimeProcess' => $mock,
19+
]));
20+
});
2021

21-
it('can start a child process', function () {
22-
ChildProcess::start('foo bar', 'some-alias', 'path/to/dir', ['baz' => 'zah']);
22+
it('can start a child process', function () {
23+
ChildProcess::start('foo bar', 'some-alias', 'path/to/dir', ['baz' => 'zah']);
2324

24-
Http::assertSent(function (Request $request) {
25-
return $request->url() === 'http://localhost:4000/api/child-process/start' &&
26-
$request['alias'] === 'some-alias' &&
27-
$request['cmd'] === ['foo bar'] &&
28-
$request['cwd'] === 'path/to/dir' &&
29-
$request['env'] === ['baz' => 'zah'];
25+
Http::assertSent(function (Request $request) {
26+
return $request->url() === 'http://localhost:4000/api/child-process/start' &&
27+
$request['alias'] === 'some-alias' &&
28+
$request['cmd'] === ['foo bar'] &&
29+
$request['cwd'] === 'path/to/dir' &&
30+
$request['env'] === ['baz' => 'zah'];
31+
});
3032
});
31-
});
3233

33-
it('can start a php command', function () {
34-
ChildProcess::php("-r 'sleep(5);'", 'some-alias', ['baz' => 'zah']);
34+
it('can start a php command', function () {
35+
ChildProcess::php("-r 'sleep(5);'", 'some-alias', ['baz' => 'zah']);
3536

36-
Http::assertSent(function (Request $request) {
37-
return $request->url() === 'http://localhost:4000/api/child-process/start-php' &&
38-
$request['alias'] === 'some-alias' &&
39-
$request['cmd'] === ["-r 'sleep(5);'"] &&
40-
$request['cwd'] === base_path() &&
41-
$request['env'] === ['baz' => 'zah'];
37+
Http::assertSent(function (Request $request) {
38+
return $request->url() === 'http://localhost:4000/api/child-process/start-php' &&
39+
$request['alias'] === 'some-alias' &&
40+
$request['cmd'] === ["-r 'sleep(5);'"] &&
41+
$request['cwd'] === base_path() &&
42+
$request['env'] === ['baz' => 'zah'];
43+
});
4244
});
43-
});
4445

45-
it('can start a artisan command', function () {
46-
ChildProcess::artisan('foo:bar --verbose', 'some-alias', ['baz' => 'zah']);
46+
it('can start a artisan command', function () {
47+
ChildProcess::artisan('foo:bar --verbose', 'some-alias', ['baz' => 'zah']);
4748

48-
Http::assertSent(function (Request $request) {
49-
return $request->url() === 'http://localhost:4000/api/child-process/start-php' &&
50-
$request['alias'] === 'some-alias' &&
51-
$request['cmd'] === ['artisan', 'foo:bar --verbose'] &&
52-
$request['cwd'] === base_path() &&
53-
$request['env'] === ['baz' => 'zah'];
49+
Http::assertSent(function (Request $request) {
50+
return $request->url() === 'http://localhost:4000/api/child-process/start-php' &&
51+
$request['alias'] === 'some-alias' &&
52+
$request['cmd'] === ['artisan', 'foo:bar --verbose'] &&
53+
$request['cwd'] === base_path() &&
54+
$request['env'] === ['baz' => 'zah'];
55+
});
5456
});
55-
});
5657

57-
it('accepts either a string or a array as start command argument', function () {
58-
ChildProcess::start('foo bar', 'some-alias');
59-
Http::assertSent(fn (Request $request) => $request['cmd'] === ['foo bar']);
58+
it('accepts either a string or a array as start command argument', function () {
59+
ChildProcess::start('foo bar', 'some-alias');
60+
Http::assertSent(fn(Request $request) => $request['cmd'] === ['foo bar']);
6061

61-
ChildProcess::start(['foo', 'baz'], 'some-alias');
62-
Http::assertSent(fn (Request $request) => $request['cmd'] === ['foo', 'baz']);
63-
});
62+
ChildProcess::start(['foo', 'baz'], 'some-alias');
63+
Http::assertSent(fn(Request $request) => $request['cmd'] === ['foo', 'baz']);
64+
});
6465

65-
it('accepts either a string or a array as php command argument', function () {
66-
ChildProcess::php("-r 'sleep(5);'", 'some-alias');
67-
Http::assertSent(fn (Request $request) => $request['cmd'] === ["-r 'sleep(5);'"]);
66+
it('accepts either a string or a array as php command argument', function () {
67+
ChildProcess::php("-r 'sleep(5);'", 'some-alias');
68+
Http::assertSent(fn(Request $request) => $request['cmd'] === ["-r 'sleep(5);'"]);
6869

69-
ChildProcess::php(['-r', "'sleep(5);'"], 'some-alias');
70-
Http::assertSent(fn (Request $request) => $request['cmd'] === ['-r', "'sleep(5);'"]);
71-
});
70+
ChildProcess::php(['-r', "'sleep(5);'"], 'some-alias');
71+
Http::assertSent(fn(Request $request) => $request['cmd'] === ['-r', "'sleep(5);'"]);
72+
});
7273

73-
it('accepts either a string or a array as artisan command argument', function () {
74-
ChildProcess::artisan('foo:bar', 'some-alias');
75-
Http::assertSent(fn (Request $request) => $request['cmd'] === ['artisan', 'foo:bar']);
74+
it('accepts either a string or a array as artisan command argument', function () {
75+
ChildProcess::artisan('foo:bar', 'some-alias');
76+
Http::assertSent(fn(Request $request) => $request['cmd'] === ['artisan', 'foo:bar']);
7677

77-
ChildProcess::artisan(['foo:baz'], 'some-alias');
78-
Http::assertSent(fn (Request $request) => $request['cmd'] === ['artisan', 'foo:baz']);
79-
});
78+
ChildProcess::artisan(['foo:baz'], 'some-alias');
79+
Http::assertSent(fn(Request $request) => $request['cmd'] === ['artisan', 'foo:baz']);
80+
});
8081

81-
it('sets the cwd to the base path if none was given', function () {
82-
ChildProcess::start(['foo', 'bar'], 'some-alias', cwd: 'path/to/dir');
83-
Http::assertSent(fn (Request $request) => $request['cwd'] === 'path/to/dir');
82+
it('sets the cwd to the base path if none was given', function () {
83+
ChildProcess::start(['foo', 'bar'], 'some-alias', cwd: 'path/to/dir');
84+
Http::assertSent(fn(Request $request) => $request['cwd'] === 'path/to/dir');
8485

85-
ChildProcess::start(['foo', 'bar'], 'some-alias');
86-
Http::assertSent(fn (Request $request) => $request['cwd'] === base_path());
87-
});
86+
ChildProcess::start(['foo', 'bar'], 'some-alias');
87+
Http::assertSent(fn(Request $request) => $request['cwd'] === base_path());
88+
});
8889

89-
it('can stop a child process', function () {
90-
ChildProcess::stop('some-alias');
90+
it('can stop a child process', function () {
91+
ChildProcess::stop('some-alias');
9192

92-
Http::assertSent(function (Request $request) {
93-
return $request->url() === 'http://localhost:4000/api/child-process/stop' &&
94-
$request['alias'] === 'some-alias';
93+
Http::assertSent(function (Request $request) {
94+
return $request->url() === 'http://localhost:4000/api/child-process/stop' &&
95+
$request['alias'] === 'some-alias';
96+
});
9597
});
96-
});
9798

98-
it('can send messages to a child process', function () {
99-
ChildProcess::message('some-message', 'some-alias');
99+
it('can send messages to a child process', function () {
100+
ChildProcess::message('some-message', 'some-alias');
100101

101-
Http::assertSent(function (Request $request) {
102-
return $request->url() === 'http://localhost:4000/api/child-process/message' &&
103-
$request['alias'] === 'some-alias' &&
104-
$request['message'] === 'some-message';
102+
Http::assertSent(function (Request $request) {
103+
return $request->url() === 'http://localhost:4000/api/child-process/message' &&
104+
$request['alias'] === 'some-alias' &&
105+
$request['message'] === 'some-message';
106+
});
105107
});
106-
});
107108

108-
it('can mark a process as persistent', function () {
109-
ChildProcess::start('foo bar', 'some-alias', persistent: true);
110-
Http::assertSent(fn (Request $request) => $request['persistent'] === true);
111-
});
109+
it('can mark a process as persistent', function () {
110+
ChildProcess::start('foo bar', 'some-alias', persistent: true);
111+
Http::assertSent(fn(Request $request) => $request['persistent'] === true);
112+
});
112113

113-
it('can mark a php command as persistent', function () {
114-
ChildProcess::php("-r 'sleep(5);'", 'some-alias', persistent: true);
115-
Http::assertSent(fn (Request $request) => $request['persistent'] === true);
116-
});
114+
it('can mark a php command as persistent', function () {
115+
ChildProcess::php("-r 'sleep(5);'", 'some-alias', persistent: true);
116+
Http::assertSent(fn(Request $request) => $request['persistent'] === true);
117+
});
118+
119+
it('can mark a artisan command as persistent', function () {
120+
ChildProcess::artisan('foo:bar', 'some-alias', persistent: true);
121+
Http::assertSent(fn(Request $request) => $request['persistent'] === true);
122+
});
117123

118-
it('can mark a artisan command as persistent', function () {
119-
ChildProcess::artisan('foo:bar', 'some-alias', persistent: true);
120-
Http::assertSent(fn (Request $request) => $request['persistent'] === true);
124+
it('marks the process as non-persistent by default', function () {
125+
ChildProcess::start('foo bar', 'some-alias');
126+
Http::assertSent(fn(Request $request) => $request['persistent'] === false);
127+
});
121128
});
122129

123-
it('marks the process as non-persistent by default', function () {
124-
ChildProcess::start('foo bar', 'some-alias');
125-
Http::assertSent(fn (Request $request) => $request['persistent'] === false);
130+
describe('Hydration', function () {
131+
it('hydrates runtime properties from API responses', function () {
132+
$processData = [
133+
'pid' => 1234,
134+
'settings' => [
135+
'iniSettings' => ['memory_limit' => '256M'],
136+
],
137+
];
138+
Http::fake([
139+
'http://localhost:4000/api/child-process/start-php' => Http::response($processData, 200),
140+
]);
141+
142+
$childProcess = new ChildProcessImplement(resolve(Client::class));
143+
144+
$result = $childProcess->php("-r 'sleep(5);'", 'some-alias');
145+
expect($result->pid)->toBe(1234);
146+
expect($result->iniSettings)->toBe(['memory_limit' => '256M']);
147+
});
126148
});

0 commit comments

Comments
 (0)