PHP Classes

File: tests/Feature/Introspection/SnapshotBuilderTest.php

Recommend this page to a friend!
  Packages of Alberto Arena   Laravel Truss   tests/Feature/Introspection/SnapshotBuilderTest.php   Download  
File: tests/Feature/Introspection/SnapshotBuilderTest.php
Role: Example script
Content type: text/plain
Description: Example script
Class: Laravel Truss
View a diagram of a Laravel application models
Author: By
Last change:
Date: 9 days ago
Size: 4,408 bytes
 

Contents

Class file image Download
<?php

declare(strict_types=1);

use
AlbertoArena\Truss\Introspection\Data\Table;
use
AlbertoArena\Truss\Introspection\SnapshotBuilder;
use
Illuminate\Support\Facades\DB;

/**
 * @return array<string, Table>
 */
function introspectFixtures(): array
{
   
$tables = (new SnapshotBuilder)->introspect('testing');

    return
collect($tables)->keyBy('name')->all();
}

beforeEach(function () {
    (require
__DIR__.'/../../Fixtures/migrations/0001_01_01_000000_create_fixture_tables.php')->up();
});

it('introspects every fixture table from the live connection', function () {
   
expect(array_keys(introspectFixtures()))
        ->
toContain('users', 'posts', 'tags', 'post_tag', 'categories', 'regions', 'region_stats', 'logs');
});

it('scopes introspection to the connection schema and ignores other databases on the server', function () {
   
// Reproduces issue #3: on a server hosting several databases (a shared local
    // MySQL, or here a second attached SQLite schema), an unscoped getTables() lists
    // every schema's tables, so foreign tables leak into the snapshot. Truss must
    // only introspect the tables that belong to the target connection's own schema.
   
$connection = DB::connection('testing');
   
$connection->statement("ATTACH DATABASE ':memory:' AS other_app");
   
$connection->statement('CREATE TABLE other_app.ghost (id integer primary key)');

   
$names = array_keys(introspectFixtures());

   
expect($names)->toContain('users') // our own schema is still fully introspected
       
->and($names)->not->toContain('ghost'); // a table from another database must not leak in
});

it('reports the primary key, hoisted out of the index list', function () {
   
$users = introspectFixtures()['users'];

   
expect($users->primaryKey)->toBe(['id'])
        ->
and(collect($users->indexes)->pluck('columns')->flatten())->not->toContain('id');
});

it('reports a composite primary key on a pivot table', function () {
   
expect(introspectFixtures()['post_tag']->primaryKey)->toBe(['post_id', 'tag_id']);
});

it('reports an empty primary key for a key-less table', function () {
   
expect(introspectFixtures()['logs']->primaryKey)->toBe([]);
});

it('reports native column types, nullability and defaults', function () {
   
$posts = collect(introspectFixtures()['posts']->columns)->keyBy('name');

   
expect($posts['title']->type)->toBeString()->not->toBeEmpty()
        ->
and($posts['body']->nullable)->toBeTrue()
        ->
and($posts['body']->default)->toBeNull()
        ->
and($posts['status']->default)->not->toBeNull()
        ->
and($posts['title']->nullable)->toBeFalse();
});

it('reports a single-column foreign key with its referential action', function () {
   
$fks = introspectFixtures()['posts']->foreignKeys;

   
$userFk = collect($fks)->firstWhere('referencesTable', 'users');

   
expect($userFk->columns)->toBe(['user_id'])
        ->
and($userFk->referencesColumns)->toBe(['id'])
        ->
and(strtolower((string) $userFk->onDelete))->toBe('cascade');
});

it('reports a self-referential foreign key', function () {
   
$fk = collect(introspectFixtures()['categories']->foreignKeys)->first();

   
expect($fk->columns)->toBe(['parent_id'])
        ->
and($fk->referencesTable)->toBe('categories');
});

it('reports a composite foreign key', function () {
   
$fk = collect(introspectFixtures()['region_stats']->foreignKeys)
        ->
firstWhere('referencesTable', 'regions');

   
expect($fk->columns)->toBe(['country_code', 'region_code'])
        ->
and($fk->referencesColumns)->toBe(['country_code', 'region_code']);
});

it('reports single and composite indexes', function () {
   
$userIndexes = introspectFixtures()['users']->indexes;
   
$emailIndex = collect($userIndexes)->firstWhere('columns', ['email']);

   
expect($emailIndex->unique)->toBeTrue();

   
$postIndexes = introspectFixtures()['posts']->indexes;
   
$composite = collect($postIndexes)->firstWhere('columns', ['user_id', 'published']);

   
expect($composite)->not->toBeNull()
        ->
and($composite->unique)->toBeFalse();
});

it('builds a serialized snapshot without an envelope timestamp', function () {
   
$snapshot = (new SnapshotBuilder)->build('testing');

   
expect($snapshot['connection'])->toBe('testing')
        ->
and($snapshot['fallback'])->toBeFalse()
        ->
and($snapshot['tables'])->toBeArray()
        ->
and($snapshot)->not->toHaveKey('generated_at');
});