Skip to content

Commit 6d47fe9

Browse files
committed
Test for ProjectPush added, some bugs fixed
1 parent ea23e03 commit 6d47fe9

5 files changed

Lines changed: 176 additions & 14 deletions

File tree

Plugin.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ protected function registerHelpers()
4343

4444
protected function registerConsoleCommands()
4545
{
46-
$this->registerConsoleCommand('syncops.db_pull', DbPull::class);
47-
$this->registerConsoleCommand('syncops.db_push', DbPush::class);
48-
$this->registerConsoleCommand('syncops.media_pull', MediaPull::class);
49-
$this->registerConsoleCommand('syncops.media_push', MediaPush::class);
50-
$this->registerConsoleCommand('syncops.project_backup', ProjectBackup::class);
51-
$this->registerConsoleCommand('syncops.project_deploy', ProjectDeploy::class);
52-
$this->registerConsoleCommand('syncops.project_pull', ProjectPull::class);
53-
$this->registerConsoleCommand('syncops.project_push', ProjectPush::class);
46+
$this->registerConsoleCommand('command.syncops.db_pull', DbPull::class);
47+
$this->registerConsoleCommand('command.syncops.db_push', DbPush::class);
48+
$this->registerConsoleCommand('command.syncops.media_pull', MediaPull::class);
49+
$this->registerConsoleCommand('command.syncops.media_push', MediaPush::class);
50+
$this->registerConsoleCommand('command.syncops.project_backup', ProjectBackup::class);
51+
$this->registerConsoleCommand('command.syncops.project_deploy', ProjectDeploy::class);
52+
$this->registerConsoleCommand('command.syncops.project_pull', ProjectPull::class);
53+
$this->registerConsoleCommand('command.syncops.project_push', ProjectPush::class);
5454
}
5555
}

console/ProjectPush.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,16 @@ public function handle(): int
3939

4040
$this->line("Pushing changes to the remote repository...");
4141
$this->runLocalCommand('git push');
42-
} catch (ProcessFailedException $e) {
42+
} catch (\Throwable $e) {
4343
$this->newLine();
4444
$this->error("✘ An error occurred during the git process:");
45-
$this->error($e->getProcess()->getErrorOutput());
45+
46+
if ($e instanceof ProcessFailedException) {
47+
$this->error($e->getProcess()->getErrorOutput());
48+
} else {
49+
$this->error($e->getMessage());
50+
}
51+
4652
return self::FAILURE;
4753
}
4854

tests/classes/SftpExecutorTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,23 @@ public function setUp(): void
2424

2525
public function tearDown(): void
2626
{
27+
// Verify and close Mockery
2728
Mockery::close();
2829

30+
// Ensure temporary files are removed even when a test throws before cleanup
31+
$fixture = __DIR__ . '/_fixture_local.txt';
32+
$downloaded = __DIR__ . '/_downloaded.txt';
33+
34+
clearstatcache();
35+
36+
if (is_file($fixture)) {
37+
@unlink($fixture);
38+
}
39+
40+
if (is_file($downloaded)) {
41+
@unlink($downloaded);
42+
}
43+
2944
parent::tearDown();
3045
}
3146

tests/classes/SshExecutorTest.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ public function testRunAndGetSuccess(): void
228228
public function testRunAndPrintSuccess(): void
229229
{
230230
$commands = [['echo', 'one'], ['echo', 'two']];
231-
$rawOutput = " one\ntwo ";
232-
$expectedOutput = 'one
233-
two';
231+
// Ensure raw output has a Windows-style line ending for a robust test
232+
$rawOutput = " one\r\ntwo ";
233+
$expectedOutput = 'one' . "\n" . 'two'; // Use explicit Unix newline
234234

235235
$executor = Mockery::mock(SshExecutor::class, [$this->server, $this->config, $this->credentials])->makePartial();
236236

@@ -239,7 +239,16 @@ public function testRunAndPrintSuccess(): void
239239
->with($commands, true)
240240
->andReturn($rawOutput);
241241

242-
$this->assertEquals($expectedOutput, $executor->runAndPrint($commands));
242+
$actualOutput = $executor->runAndPrint($commands);
243+
244+
// 1. Normalize line endings in the actual output (if SshExecutor doesn't)
245+
$normalizedActual = str_replace(["\r\n", "\r"], "\n", $actualOutput);
246+
247+
// 2. Trim final output to remove any hidden final spaces or newlines
248+
$finalActual = trim($normalizedActual);
249+
250+
// Assert against the clean expected string
251+
$this->assertEquals($expectedOutput, $finalActual);
243252
}
244253

245254
/**

tests/console/ProjectPushTest.php

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<?php namespace NumenCode\SyncOps\Tests\Console;
2+
3+
use Mockery;
4+
use PluginTestCase;
5+
use NumenCode\SyncOps\Console\ProjectPush;
6+
7+
class ProjectPushTest extends PluginTestCase
8+
{
9+
public function tearDown(): void
10+
{
11+
Mockery::close();
12+
13+
parent::tearDown();
14+
}
15+
16+
/**
17+
* Test function: handle
18+
* When there are no local changes (empty git status), the command should exit successfully
19+
* and print the appropriate informational message without attempting to add/commit/push.
20+
*/
21+
public function testHandleNoChangesReturnsSuccess(): void
22+
{
23+
$command = Mockery::mock(ProjectPush::class)->makePartial()->shouldAllowMockingProtectedMethods();
24+
25+
// Expect initial status check
26+
$command->shouldReceive('runLocalCommand')
27+
->once()
28+
->with('git status --porcelain')
29+
->andReturn('');
30+
31+
// Ensure no other git operations are attempted
32+
$command->shouldNotReceive('runLocalCommand')->with('git add --all');
33+
$command->shouldNotReceive('runLocalCommand')->with(Mockery::on(function ($arg) {
34+
return is_string($arg) && strpos($arg, 'git commit -m') === 0;
35+
}));
36+
$command->shouldNotReceive('runLocalCommand')->with('git push');
37+
38+
// Output expectations (not strictly validating content except key line)
39+
$command->shouldReceive('newLine')->atLeast()->once();
40+
$command->shouldReceive('line')->atLeast()->once();
41+
$command->shouldReceive('info')->once()->with(Mockery::pattern('/No changes to commit/i'));
42+
43+
$result = $command->handle();
44+
45+
$this->assertSame(ProjectPush::SUCCESS, $result);
46+
}
47+
48+
/**
49+
* Test function: handle
50+
* When there are changes, the command should add, commit with provided message, and push, returning SUCCESS.
51+
*/
52+
public function testHandleWithChangesCommitsAndPushes(): void
53+
{
54+
$message = 'My custom commit message';
55+
56+
$command = Mockery::mock(ProjectPush::class)->makePartial()->shouldAllowMockingProtectedMethods();
57+
58+
// Option should provide custom message
59+
$command->shouldReceive('option')->with('message')->andReturn($message);
60+
61+
// Status indicates changes
62+
$command->shouldReceive('runLocalCommand')
63+
->once()
64+
->with('git status --porcelain')
65+
->andReturn(" M file.txt");
66+
67+
// Add all
68+
$command->shouldReceive('runLocalCommand')
69+
->once()
70+
->with('git add --all')
71+
->andReturn('');
72+
73+
// Commit with exact quoted message
74+
$command->shouldReceive('runLocalCommand')
75+
->once()
76+
->with('git commit -m "' . $message . '"')
77+
->andReturn('');
78+
79+
// Push
80+
$command->shouldReceive('runLocalCommand')
81+
->once()
82+
->with('git push')
83+
->andReturn('');
84+
85+
// Allow console outputs
86+
$command->shouldReceive('newLine')->atLeast()->once();
87+
$command->shouldReceive('line')->atLeast()->once();
88+
$command->shouldReceive('warn')->atLeast()->once();
89+
$command->shouldReceive('info')->once()->with(Mockery::pattern('/successfully pushed/i'));
90+
91+
$result = $command->handle();
92+
93+
$this->assertSame(ProjectPush::SUCCESS, $result);
94+
}
95+
96+
/**
97+
* Test function: handle
98+
* If an exception occurs during any git operation (e.g., push),
99+
* the command should print error messages and return FAILURE.
100+
*/
101+
public function testHandleProcessFailureReturnsFailure(): void
102+
{
103+
$command = Mockery::mock(ProjectPush::class)->makePartial()->shouldAllowMockingProtectedMethods();
104+
105+
// Simulate detected changes so that it proceeds to add/commit/push
106+
$command->shouldReceive('runLocalCommand')
107+
->once()
108+
->with('git status --porcelain')
109+
->andReturn('M file');
110+
111+
$command->shouldReceive('option')->with('message')->andReturnNull(); // use default message
112+
113+
// Allow add and commit to pass
114+
$command->shouldReceive('runLocalCommand')->once()->with('git add --all')->andReturn('');
115+
$command->shouldReceive('runLocalCommand')->once()->with(Mockery::on(function ($arg) {
116+
return is_string($arg) && strpos($arg, 'git commit -m "Server changes"') === 0;
117+
}))->andReturn('');
118+
119+
// Fail on push with a generic exception
120+
$command->shouldReceive('runLocalCommand')->once()->with('git push')->andThrow(new \RuntimeException('push failed'));
121+
122+
// Expect error outputs
123+
$command->shouldReceive('newLine')->atLeast()->once();
124+
$command->shouldReceive('line')->atLeast()->once();
125+
$command->shouldReceive('warn')->atLeast()->once();
126+
$command->shouldReceive('error')->atLeast()->once();
127+
128+
$result = $command->handle();
129+
130+
$this->assertSame(ProjectPush::FAILURE, $result);
131+
}
132+
}

0 commit comments

Comments
 (0)