Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5a5ac78
Refactor test method names for consistency and clarity across various…
DEberhardt Sep 7, 2025
0baa103
Refactor test method names for consistency and clarity
DEberhardt Sep 8, 2025
4c45ea1
Fix spacing in anonymous class instantiations for consistency (runnin…
DEberhardt Sep 8, 2025
995e1f5
Refactor test methods to directly invoke protected toStringName() and…
DEberhardt Sep 8, 2025
bcc246f
Add basic codecov file
mintopia Sep 8, 2025
b2ffb07
Set threshold for PRs
mintopia Sep 8, 2025
8735755
Update readme to include coverage
mintopia Sep 8, 2025
398092a
Allow workflow for PRs with just md changes
mintopia Sep 8, 2025
9cb94f8
Fix code coverage
mintopia Sep 8, 2025
d6198ff
Ignore md and docs from workflows
mintopia Sep 8, 2025
9c2dc3f
Refactor AbstractTransformerTest: replace DummyObject and DummyTransf…
DEberhardt Sep 8, 2025
dda2a0d
Refactor AbstractTicketProviderTest: replace DummyTicketProvider with…
DEberhardt Sep 8, 2025
c81cb63
Refactor tests: replace DummyTicketProvider and DummySocialProvider w…
DEberhardt Sep 8, 2025
0cc8142
Refactor tests: replace DummySocialProvider with inline class and sim…
DEberhardt Sep 8, 2025
2e9379e
Refactor tests: remove DummySocialProvider classes to simplify test s…
DEberhardt Sep 8, 2025
01db214
Refactor tests: replace DummyGenericTicketProvider with makeTicketPro…
DEberhardt Sep 8, 2025
ac28294
Refactor tests: replace DummyDiscordProvider with makeDummyDiscordPro…
DEberhardt Sep 8, 2025
d2a30f8
Refactor tests: replace DummyTicketTailorProvider with makeTicketTail…
DEberhardt Sep 8, 2025
5f39f65
Refactor tests: replace DummyWooCommerceProvider with makeWooCommerce…
DEberhardt Sep 8, 2025
cc89627
Refactor tests: replace direct method calls with callProtected helper…
DEberhardt Sep 8, 2025
cfe39fa
Refactor tests: replace Closure::bind with Closure::call for improved…
DEberhardt Sep 8, 2025
a06395a
Refactor tests: deprecate DummyTicketTailorProvider, DummyGenericTick…
DEberhardt Sep 8, 2025
dbd1a7c
Remove now unused Dummy Class files
DEberhardt Sep 8, 2025
467d4f9
Refactor tests: streamline constructor syntax for anonymous classes a…
DEberhardt Sep 8, 2025
e5dacfd
Refactor tests: add base URI to Guzzle client instantiation for consi…
DEberhardt Sep 8, 2025
c96b894
Add getTicketTypes method to ProviderTestHelpers for improved test co…
DEberhardt Sep 8, 2025
297975d
Refactor tests: update constructor syntax for anonymous classes and r…
DEberhardt Sep 8, 2025
5b05431
Refactor tests: remove DummyDiscordProvider and update SocialProvider…
DEberhardt Sep 8, 2025
4d567e1
Refactor tests: replace makeTicketProvider with basicProviderStub for…
DEberhardt Sep 8, 2025
593ac1e
Refactor tests: update constructor syntax for anonymous classes in Ti…
DEberhardt Sep 8, 2025
91053f5
Refactor tests: update provider service initialization in AbstractSoc…
DEberhardt Sep 8, 2025
dac95f7
Refactor tests: enhance admin property precedence logic in AbstractTr…
DEberhardt Sep 8, 2025
5581734
Refactor tests: remove unused dummy provider classes and stubs; repla…
DEberhardt Sep 8, 2025
b32f0eb
Refactor tests: replace ResolveDummyProvider with a closure-based fac…
DEberhardt Sep 8, 2025
4a948bf
Refactor tests: merge extra tests from GenericTicketProviderExtraTest…
DEberhardt Sep 8, 2025
f0249dd
Refactor testProcessWebhookCallsProcessTicketAndReturnsTrue to improv…
DEberhardt Sep 8, 2025
93a8f81
Remove rule from phpcs.xml
mintopia Sep 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ yarn-error.log
/html-coverage
clover.xml
coverage.txt
.github/copilot-instructions.md
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Control
[![codecov](https://codecov.io/github/mintopia/control/graph/badge.svg?token=UH1Y6FBHQW)](https://codecov.io/github/mintopia/control)

## Introduction

Expand Down Expand Up @@ -158,15 +159,16 @@ service:
It's an open source project and I'm happy to accept pull requests. I am terrible at UI and UX, which is why this is
entirely using server-side rendering. If someone wants to use Vue/Laravel Livewire - please go ahead!

We have 100% test coverage, and would like to remain that way.

## Roadmap

The following features are on the roadmap:

- Better UI/UX. I'm currently using [tabler.io](https://tabler.io) and entirely server-side rendering.
- Full-featured API. There's a basic one to support seating plan refreshes. I need to refactor it and improve it.
- UI Customisation from Admin Pages. Currently the UI colours, branding is all either in the `.env` or compiled into the CSS at build.
- Unit Tests. This was very rapidly developed, I'm sorry!
- PHPCS and PHPStan. Should be aiming for PSR-12 and level 8 PHPStan.
- Static Analysis - We should be aiming for level 8 in PHPStan.

## Thanks

Expand Down
10 changes: 10 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
coverage:
status:
project:
default:
target: 100%
threshold: 0%
base: auto
if_ci_failed: error
informational: false
only_pulls: false
3 changes: 0 additions & 3 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,4 @@

<arg value="np"/>
<rule ref="PSR12"/>
<rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
<exclude-pattern>tests/*</exclude-pattern>
</rule>
</ruleset>
2 changes: 1 addition & 1 deletion tests/Feature/ExampleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ExampleTest extends TestCase
/**
* A basic test example.
*/
public function test_the_application_returns_a_successful_response(): void
public function testTheApplicationReturnsASuccessfulResponse(): void
{
$user = User::factory()->create();

Expand Down
25 changes: 19 additions & 6 deletions tests/Feature/app/Services/AbstractSocialProviderInstallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,32 @@

use App\Models\ProviderSetting;
use App\Models\SocialProvider;
use Tests\Feature\app\Services\HelperClasses\InstallDummyProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AbstractSocialProviderInstallTest extends TestCase
{
use RefreshDatabase;

public function test_install_creates_provider_and_settings()
protected $providerSvc;

protected function setUp(): void
{
$providerSvc = new InstallDummyProvider();
parent::setUp();
// Inline dummy provider setup
$this->providerSvc = new class extends \App\Services\SocialProviders\AbstractSocialProvider {
protected string $name = 'Install Dummy';
protected string $code = 'install_dummy_test_fixed';
protected string $socialiteProviderCode = 'install_dummy_code';
protected function updateAccount(\App\Models\LinkedAccount $account, $remoteUser): void
{
}
};
}

$installed = $providerSvc->install();
public function testInstallCreatesProviderAndSettings()
{
$installed = $this->providerSvc->install();

$this->assertInstanceOf(SocialProvider::class, $installed);
$this->assertDatabaseHas('social_providers', ['code' => $installed->code]);
Expand All @@ -31,9 +44,9 @@ public function test_install_creates_provider_and_settings()
$this->assertTrue((bool)$secret->encrypted);
}

public function test_install_idempotent_on_existing_provider()
public function testInstallIdempotentOnExistingProvider()
{
$svc = new InstallDummyProvider();
$svc = $this->providerSvc;
$code = 'install_dummy_test_fixed';

// Create an existing provider
Expand Down
44 changes: 37 additions & 7 deletions tests/Feature/app/Services/AbstractSocialProviderResolveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Tests\Feature\app\Services;

use App\Models\SocialProvider;
use Tests\Feature\app\Services\HelperClasses\ResolveDummyProvider;
use App\Services\SocialProviders\AbstractSocialProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Auth;
use ReflectionClass;
Expand All @@ -13,22 +13,52 @@ class AbstractSocialProviderResolveTest extends TestCase
{
use RefreshDatabase;

public function test_constructor_keeps_explicit_redirect_url()
protected \Closure $makeResolveProvider;

protected function setUp(): void
{
parent::setUp();

$this->makeResolveProvider = function (\App\Models\SocialProvider $prov, ?string $redirectUrl = null) {
return new class ($prov, $redirectUrl) extends AbstractSocialProvider {
protected string $name = 'Resolve Dummy';
protected string $code = 'resolve_dummy_test';
protected string $socialiteProviderCode = 'resolve_dummy_code';

protected function updateAccount(\App\Models\LinkedAccount $account, $remoteUser): void
{
// no-op
}
};
};
}

protected function makeResolveProvider(\App\Models\SocialProvider $prov, ?string $redirectUrl = null)
{
$factory = $this->makeResolveProvider;
if (!is_callable($factory)) {
throw new \RuntimeException('makeResolveProvider closure not initialized');
}

return $factory($prov, $redirectUrl);
}

public function testConstructorKeepsExplicitRedirectUrl()
{
$prov = SocialProvider::factory()->create(['auth_enabled' => true, 'code' => 'rd_x']);
$svc = new ResolveDummyProvider($prov, 'https://example.test/custom');
$svc = $this->makeResolveProvider($prov, 'https://example.test/custom');

$ref = new ReflectionClass($svc);
$p = $ref->getProperty('redirectUrl');
$p->setAccessible(true);
$this->assertEquals('https://example.test/custom', $p->getValue($svc));
}

public function test_resolve_sets_login_return_when_guest_and_auth_enabled()
public function testResolveSetsLoginReturnWhenGuestAndAuthEnabled()
{
Auth::shouldReceive('guest')->andReturn(true);
$prov = SocialProvider::factory()->create(['auth_enabled' => true, 'code' => 'rd_guest']);
$svc = new ResolveDummyProvider($prov);
$svc = $this->makeResolveProvider($prov);

$ref = new ReflectionClass($svc);
$p = $ref->getProperty('redirectUrl');
Expand All @@ -39,11 +69,11 @@ public function test_resolve_sets_login_return_when_guest_and_auth_enabled()
$this->assertStringContainsString('resolve_dummy_test', $val);
}

public function test_resolve_sets_linkedaccounts_when_not_guest()
public function testResolveSetsLinkedaccountsWhenNotGuest()
{
Auth::shouldReceive('guest')->andReturn(false);
$prov = SocialProvider::factory()->create(['auth_enabled' => true, 'code' => 'rd_not_guest']);
$svc = new ResolveDummyProvider($prov);
$svc = $this->makeResolveProvider($prov);

$ref = new ReflectionClass($svc);
$p = $ref->getProperty('redirectUrl');
Expand Down
19 changes: 0 additions & 19 deletions tests/Feature/app/Services/HelperClasses/InstallDummyProvider.php

This file was deleted.

18 changes: 0 additions & 18 deletions tests/Feature/app/Services/HelperClasses/ResolveDummyProvider.php

This file was deleted.

53 changes: 49 additions & 4 deletions tests/Feature/app/Transformers/V1/AbstractTransformerExtraTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,65 @@
namespace Tests\Feature\app\Transformers\V1;

use App\Models\User;
use Tests\Feature\app\Transformers\V1\HelperClasses\NoopTransformer;
use Tests\Feature\app\Transformers\V1\HelperClasses\PrecedenceTransformer;
use Illuminate\Support\Carbon;
use ReflectionClass;
use Tests\TestCase;

class AbstractTransformerExtraTest extends TestCase
{
protected $noopTransformer;
protected $precedenceTransformer;

protected function setUp(): void
{
parent::setUp();
$this->noopTransformer = new class (null) {
protected $user;
public function __construct($user)
{
$this->user = $user;
}
protected function modifyForUser($data, $object)
{
return $data;
}
};
$this->precedenceTransformer = new class ($this->createMock(\App\Models\User::class)) {
protected $user;
public function __construct($user)
{
$this->user = $user;
}
protected function modifyForUser($data, $object)
{
// Simulate admin precedence logic
if ($this->user && method_exists($this->user, 'hasRole') && $this->user->hasRole('admin')) {
// Merge admin-provided properties into the original data so admin values overwrite originals
return array_merge($data, [
'foo' => 'baz',
'extra' => 'value_from_admin',
'id' => $object->id,
'created_at' => $object->created_at->toIso8601String(),
'updated_at' => $object->updated_at->toIso8601String(),
]);
}
return $data;
}
};
}

public function testModifyForUserAdminPropertyPrecedence()
{
$user = $this->createMock(User::class);
$user->method('hasRole')->with('admin')->willReturn(true);

$transformer = new PrecedenceTransformer($user);
$transformer = $this->precedenceTransformer;

// Inject the configured user mock into the transformer so modifyForUser sees admin role.
$reflectionTransformer = new ReflectionClass($transformer);
$prop = $reflectionTransformer->getProperty('user');
$prop->setAccessible(true);
$prop->setValue($transformer, $user);

$object = new class {
public $id = 2;
Expand Down Expand Up @@ -50,7 +95,7 @@ public function __construct()
public function testModifyForUserWithNullUserReturnsOriginalData()
{
// When no user is provided, modifyForUser should return the original data
$transformer = new NoopTransformer(null);
$transformer = $this->noopTransformer;

$object = new class {
public $id = 5;
Expand Down

This file was deleted.

This file was deleted.

Loading