Create CI testing

This commit is contained in:
Deon George 2021-06-15 22:19:14 +10:00
parent 4011b2a82d
commit 292040cef7
14 changed files with 356 additions and 44 deletions

41
.env.testing Normal file
View File

@ -0,0 +1,41 @@
APP_NAME="Clearing Houz"
APP_ENV=testing
APP_KEY=
APP_DEBUG=true
#APP_URL=http://localhost
LOG_CHANNEL=stderr
LOG_LEVEL=info
DB_CONNECTION=pgsql
DB_HOST=database
DB_PORT=5432
DB_DATABASE=postgres
DB_USERNAME=postgres
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=mail.leenooks.vpn
MAIL_PORT=25
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_AUTO_EMBED_METHOD=base64
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

View File

@ -10,4 +10,5 @@ cache:
- vendor/ - vendor/
include: include:
- .gitlab-test.yml
- .gitlab-docker-x86_64.yml - .gitlab-docker-x86_64.yml

40
.gitlab-test.yml Normal file
View File

@ -0,0 +1,40 @@
test:
image: ${CI_REGISTRY}/leenooks/php:8.0-fpm-ext-test
stage: test
# NOTE: This service is dependant on project file configuration, which is not there if the cache was deleted
# resulting in the testing to fail on the first run.
services:
- name: postgres:13-alpine
alias: database
variables:
POSTGRES_PASSWORD: secret
tags:
- php
only:
- master
before_script:
- mv .env.testing .env
# Install Composer and project dependencies.
- mkdir -p /root/.composer
- if [ -n "$GITHUB_TOKEN" ]; then cat $GITHUB_TOKEN |base64 -d > /root/.composer/auth.json ; fi
- composer install
# Generate an application key. Re-cache.
- php artisan key:generate
- php artisan migrate
script:
# run laravel tests
- XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text --colors=never
# run frontend tests
# if you have any task for testing frontend
# set it in your package.json script
# comment this out if you don't have a frontend test
# npm test

View File

@ -11,4 +11,14 @@ class HomeController extends Controller
return view('domain.view') return view('domain.view')
->with('o',$o); ->with('o',$o);
} }
/**
* System Setup
*
* @note: Protected by Route
*/
public function setup()
{
}
} }

View File

@ -2,13 +2,14 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use App\Traits\ScopeActive; use App\Traits\ScopeActive;
class Domain extends Model class Domain extends Model
{ {
use ScopeActive; use HasFactory,ScopeActive;
/* SCOPES */ /* SCOPES */

View File

@ -5,26 +5,30 @@ namespace App\Providers;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Models\User;
class AuthServiceProvider extends ServiceProvider class AuthServiceProvider extends ServiceProvider
{ {
/** /**
* The policy mappings for the application. * The policy mappings for the application.
* *
* @var array * @var array
*/ */
protected $policies = [ protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy', 'App\Model' => 'App\Policies\ModelPolicy',
]; ];
/** /**
* Register any authentication / authorization services. * Register any authentication / authorization services.
* *
* @return void * @return void
*/ */
public function boot() public function boot()
{ {
$this->registerPolicies(); $this->registerPolicies();
// Gate::define('admin',function (User $o) {
} return $o->admin == TRUE;
});
}
} }

View File

@ -37,7 +37,9 @@
"app/helpers.php" "app/helpers.php"
], ],
"psr-4": { "psr-4": {
"App\\": "app/" "App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
} }
}, },
"autoload-dev": { "autoload-dev": {

View File

@ -0,0 +1,52 @@
<?php
namespace Database\Factories;
use App\Models\Domain;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class DomainFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Domain::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->name(),
'dnsdomain' => $this->faker->unique()->safeEmail(),
'notes' => $this->faker->text(),
'homepage' => $this->faker->text(),
'active' => FALSE,
'public' => FALSE,
];
}
public function active()
{
return $this->state(function (array $attributes) {
return [
'active' => TRUE,
];
});
}
public function public()
{
return $this->state(function (array $attributes) {
return [
'public' => TRUE,
];
});
}
}

View File

@ -1,24 +1,42 @@
<?php <?php
use Faker\Generator as Faker; namespace Database\Factories;
/* use App\Models\User;
|-------------------------------------------------------------------------- use Illuminate\Database\Eloquent\Factories\Factory;
| Model Factories use Illuminate\Support\Str;
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/
$factory->define(App\User::class, function (Faker $faker) { class UserFactory extends Factory
return [ {
'name' => $faker->name, /**
'email' => $faker->unique()->safeEmail, * The name of the factory's corresponding model.
'email_verified_at' => now(), *
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret * @var string
'remember_token' => str_random(10), */
]; protected $model = User::class;
});
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
public function admin()
{
return $this->state(function (array $attributes) {
return [
'admin' => true,
];
});
}
}

View File

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddAdminToUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('admin')->nullable();
});
Schema::create('domain_user', function (Blueprint $table) {
$table->integer('domain_id');
$table->foreign('domain_id')->references('id')->on('domains');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('admin');
});
Schema::dropIfExists('domain_user');
}
}

View File

@ -0,0 +1,9 @@
@extends('layouts.app')
@section('htmlheader_title')
{{ $o->name }}
@endsection
@section('content')
<h1>{{ $o->name }} <small class="push-right">Last Update: {{ $o->updated_at }}</small></h1>
<p>{!! \Illuminate\Mail\Markdown::parse($o->homepage) !!}</p>
@endsection

View File

@ -42,8 +42,10 @@ Route::middleware(['verified'])->group(function () {
Route::get('ftn/zone',[ZoneController::class,'home']); Route::get('ftn/zone',[ZoneController::class,'home']);
Route::match(['get','post'],'ftn/zone/addedit/{o?}',[ZoneController::class,'add_edit']) Route::match(['get','post'],'ftn/zone/addedit/{o?}',[ZoneController::class,'add_edit'])
->where('o','[0-9]+'); ->where('o','[0-9]+');
Route::get('ftn/network/{name}',[HomeController::class,'network']);
}); });
Route::get('network/{o}',[HomeController::class,'network']); Route::get('network/{o}',[HomeController::class,'network']);
Route::middleware(['auth','can:admin'])->group(function () {
Route::get('setup',[HomeController::class,'setup']);
});

View File

@ -14,7 +14,7 @@ class ExampleTest extends TestCase
*/ */
public function testBasicTest() public function testBasicTest()
{ {
$response = $this->get('/'); $response = $this->get('/about');
$response->assertStatus(200); $response->assertStatus(200);
} }

View File

@ -0,0 +1,90 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Auth;
use Tests\TestCase;
use App\Models\User;
use App\Models\Domain;
class SiteAdminTest extends TestCase
{
use DatabaseTransactions;
/**
* Testing a unauthenticated visitor to the site.
*/
public function test_guestuser()
{
$this->get('about')
->assertOk();
$this->get('ftn/domain')
->assertRedirect('login');
$this->get('ftn/node')
->assertRedirect('login');
$this->get('ftn/zone')
->assertRedirect('login');
$this->get('network/1')
->assertNotFound();
Domain::factory()->create([
'id'=>1,
'name'=>'test',
]);
$this->get('network/1')
->assertOK();
}
/**
* Verify user who has registered by not verified their email
*/
public function test_unverified_user()
{
$user = User::factory()->make([
'name'=>'Site Visitor',
'email_verified_at'=>NULL,
]);
// Use model in tests...
$this->actingAs($user);
$this->get('ftn/domain')
->assertRedirect('email/verify');
$this->get('ftn/node')
->assertRedirect('email/verify');
$this->get('ftn/zone')
->assertRedirect('email/verify');
Auth::logout();
}
public function test_site_admin()
{
// Site Visitor
$this->get('setup')
->assertRedirect('login');
// Valid User
$user = User::factory()->make([
'name'=>'Site User',
]);
$this->actingAs($user);
$this->get('setup')
->assertForbidden();
// Admin User
$user = User::factory()->admin()->make([
'name'=>'Site User',
]);
$this->actingAs($user);
$this->get('setup')
->assertOK();
}
}