1
0

提交代码

This commit is contained in:
2020-08-06 14:50:07 +08:00
parent 9d0d5f4be9
commit d7a848c824
11299 changed files with 1321854 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
<?php
class AuthTest extends TestCase
{
public function testLoginPage()
{
$this->visit('admin/auth/login')
->see('login');
}
public function testVisitWithoutLogin()
{
$this->visit('admin')
->dontSeeIsAuthenticated('admin')
->seePageIs('admin/auth/login');
}
public function testLogin()
{
$credentials = ['username' => 'admin', 'password' => 'admin'];
$this->visit('admin/auth/login')
->see('login')
->submitForm('Login', $credentials)
->see('dashboard')
->seeCredentials($credentials, 'admin')
->seeIsAuthenticated('admin')
->seePageIs('admin')
->see('Dashboard')
->see('Description...')
->see('Environment')
->see('PHP version')
->see('Laravel version')
->see('Available extensions')
->seeLink('laravel-admin-ext/helpers', 'https://github.com/laravel-admin-extensions/helpers')
->seeLink('laravel-admin-ext/backup', 'https://github.com/laravel-admin-extensions/backup')
->seeLink('laravel-admin-ext/media-manager', 'https://github.com/laravel-admin-extensions/media-manager')
->see('Dependencies')
->see('php')
// ->see('>=7.0.0')
->see('laravel/framework');
$this
->see('<span>Admin</span>')
->see('<span>Users</span>')
->see('<span>Roles</span>')
->see('<span>Permission</span>')
->see('<span>Operation log</span>')
->see('<span>Menu</span>');
}
public function testLogout()
{
$this->visit('admin/auth/logout')
->seePageIs('admin/auth/login')
->dontSeeIsAuthenticated('admin');
}
}

View File

@@ -0,0 +1,164 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Illuminate\Support\Facades\File;
use Tests\Models\File as FileModel;
class FileUploadTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testFileUploadPage()
{
$this->visit('admin/files/create')
->see('Upload file')
->seeInElement('h3[class=box-title]', 'Create')
->seeElement('input[name=file1]')
->seeElement('input[name=file2]')
->seeElement('input[name=file3]')
->seeElement('input[name=file4]')
->seeElement('input[name=file5]')
->seeElement('input[name=file6]')
// ->seeInElement('a[href="/admin/files"]', 'List')
->seeInElement('button[type=reset]', 'Reset')
->seeInElement('button[type=submit]', 'Submit');
}
protected function uploadFiles()
{
return $this->visit('admin/files/create')
->attach(__DIR__.'/AuthTest.php', 'file1')
->attach(__DIR__.'/InstallTest.php', 'file2')
->attach(__DIR__.'/IndexTest.php', 'file3')
->attach(__DIR__.'/LaravelTest.php', 'file4')
->attach(__DIR__.'/routes.php', 'file5')
->attach(__DIR__.'/migrations/2016_11_22_093148_create_test_tables.php', 'file6')
->press('Submit');
}
public function testUploadFile()
{
File::cleanDirectory(public_path('uploads/files'));
$this->uploadFiles()
->seePageIs('admin/files');
$this->assertEquals(FileModel::count(), 1);
$where = [
'file1' => 'files/AuthTest.php',
'file2' => 'files/InstallTest.php',
'file3' => 'files/IndexTest.php',
'file4' => 'files/LaravelTest.php',
'file5' => 'files/routes.php',
'file6' => 'files/2016_11_22_093148_create_test_tables.php',
];
$this->seeInDatabase('test_files', $where);
$files = FileModel::first()->toArray();
foreach (range(1, 6) as $index) {
$this->assertFileExists(public_path('uploads/'.$files['file'.$index]));
}
File::cleanDirectory(public_path('uploads/files'));
}
public function testUpdateFile()
{
File::cleanDirectory(public_path('uploads/files'));
$this->uploadFiles();
$old = FileModel::first();
$this->visit('admin/files/1/edit')
->see('ID')
->see('Created At')
->see('Updated At')
->seeElement('input[name=file1]')
->seeElement('input[name=file2]')
->seeElement('input[name=file3]')
->seeElement('input[name=file4]')
->seeElement('input[name=file5]')
->seeElement('input[name=file6]')
// ->seeInElement('a[href="/admin/files"]', 'List')
->seeInElement('button[type=reset]', 'Reset')
->seeInElement('button[type=submit]', 'Submit');
$this->attach(__DIR__.'/RolesTest.php', 'file3')
->attach(__DIR__.'/MenuTest.php', 'file4')
->attach(__DIR__.'/TestCase.php', 'file5')
->press('Submit');
$new = FileModel::first();
$this->assertEquals($old->id, $new->id);
$this->assertEquals($old->file1, $new->file1);
$this->assertEquals($old->file2, $new->file2);
$this->assertEquals($old->file6, $new->file6);
$this->assertNotEquals($old->file3, $new->file3);
$this->assertNotEquals($old->file4, $new->file4);
$this->assertNotEquals($old->file5, $new->file5);
File::cleanDirectory(public_path('uploads/files'));
}
public function testDeleteFiles()
{
File::cleanDirectory(public_path('uploads/files'));
$this->uploadFiles();
$this->visit('admin/files')
->seeInElement('td', 1);
$files = FileModel::first()->toArray();
$this->delete('admin/files/1')
->dontSeeInDatabase('test_files', ['id' => 1]);
foreach (range(1, 6) as $index) {
$this->assertFileNotExists(public_path('uploads/'.$files['file'.$index]));
}
$this->visit('admin/files')
->seeInElement('td', 'svg');
}
public function testBatchDelete()
{
File::cleanDirectory(public_path('uploads/files'));
$this->uploadFiles();
$this->uploadFiles();
$this->uploadFiles();
$this->visit('admin/files')
->seeInElement('td', 1)
->seeInElement('td', 2)
->seeInElement('td', 3);
$fi = new FilesystemIterator(public_path('uploads/files'), FilesystemIterator::SKIP_DOTS);
$this->assertEquals(iterator_count($fi), 18);
$this->assertEquals(FileModel::count(), 3);
$this->delete('admin/files/1,2,3');
$this->assertEquals(FileModel::count(), 0);
$this->visit('admin/files')
->seeInElement('td', 'svg');
$this->assertEquals(iterator_count($fi), 0);
}
}

View File

@@ -0,0 +1,239 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Illuminate\Support\Facades\File;
use Tests\Models\Image;
use Tests\Models\MultipleImage;
class ImageUploadTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testDisableFilter()
{
$this->visit('admin/images')
->dontSeeElement('input[name=id]');
}
public function testImageUploadPage()
{
$this->visit('admin/images/create')
->see('Upload image')
->seeInElement('h3[class=box-title]', 'Create')
->seeElement('input[name=image1]')
->seeElement('input[name=image2]')
->seeElement('input[name=image3]')
->seeElement('input[name=image4]')
->seeElement('input[name=image5]')
->seeElement('input[name=image6]')
->seeInElement('button[type=reset]', 'Reset')
->seeInElement('button[type=submit]', 'Submit');
}
protected function uploadImages()
{
return $this->visit('admin/images/create')
->attach(__DIR__.'/assets/test.jpg', 'image1')
->attach(__DIR__.'/assets/test.jpg', 'image2')
->attach(__DIR__.'/assets/test.jpg', 'image3')
->attach(__DIR__.'/assets/test.jpg', 'image4')
->attach(__DIR__.'/assets/test.jpg', 'image5')
->attach(__DIR__.'/assets/test.jpg', 'image6')
->press('Submit');
}
public function testUploadImage()
{
File::cleanDirectory(public_path('uploads/images'));
$this->uploadImages()
->seePageIs('admin/images');
$this->assertEquals(Image::count(), 1);
$this->seeInDatabase('test_images', ['image4' => 'images/renamed.jpeg']);
$images = Image::first()->toArray();
foreach (range(1, 6) as $index) {
$this->assertFileExists(public_path('uploads/'.$images['image'.$index]));
}
$this->assertFileExists(public_path('uploads/images/asdasdasdasdasd.jpeg'));
File::cleanDirectory(public_path('uploads/images'));
}
public function testRemoveImage()
{
File::cleanDirectory(public_path('uploads/images'));
$this->uploadImages();
$this->assertEquals($this->fileCountInImageDir(), 6);
}
public function testUpdateImage()
{
File::cleanDirectory(public_path('uploads/images'));
$this->uploadImages();
$old = Image::first();
$this->visit('admin/images/1/edit')
->see('ID')
->see('Created At')
->see('Updated At')
->seeElement('input[name=image1]')
->seeElement('input[name=image2]')
->seeElement('input[name=image3]')
->seeElement('input[name=image4]')
->seeElement('input[name=image5]')
->seeElement('input[name=image6]')
->seeInElement('button[type=reset]', 'Reset')
->seeInElement('button[type=submit]', 'Submit');
$this->attach(__DIR__.'/assets/test.jpg', 'image3')
->attach(__DIR__.'/assets/test.jpg', 'image4')
->attach(__DIR__.'/assets/test.jpg', 'image5')
->press('Submit');
$new = Image::first();
$this->assertEquals($old->id, $new->id);
$this->assertEquals($old->image1, $new->image1);
$this->assertEquals($old->image2, $new->image2);
$this->assertEquals($old->image6, $new->image6);
$this->assertNotEquals($old->image3, $new->image3);
$this->assertNotEquals($old->image4, $new->image4);
$this->assertNotEquals($old->image5, $new->image5);
File::cleanDirectory(public_path('uploads/images'));
}
public function testDeleteImages()
{
File::cleanDirectory(public_path('uploads/images'));
$this->uploadImages();
$this->visit('admin/images')
->seeInElement('td', 1);
$images = Image::first()->toArray();
$this->delete('admin/images/1')
->dontSeeInDatabase('test_images', ['id' => 1]);
foreach (range(1, 6) as $index) {
$this->assertFileNotExists(public_path('uploads/'.$images['image'.$index]));
}
$this->visit('admin/images')
->seeInElement('td', 'svg');
}
public function testBatchDelete()
{
File::cleanDirectory(public_path('uploads/images'));
$this->uploadImages();
$this->uploadImages();
$this->uploadImages();
$this->visit('admin/images')
->seeInElement('td', 1)
->seeInElement('td', 2)
->seeInElement('td', 3);
$this->assertEquals($this->fileCountInImageDir(), 18);
$this->assertEquals(Image::count(), 3);
$this->delete('admin/images/1,2,3');
$this->assertEquals(Image::count(), 0);
$this->visit('admin/images')
->seeInElement('td', 'svg');
$this->assertEquals($this->fileCountInImageDir(), 0);
}
public function testUploadMultipleImage()
{
File::cleanDirectory(public_path('uploads/images'));
$this->visit('admin/multiple-images/create')
->seeElement('input[type=file][name="pictures[]"][multiple=1]');
$path = __DIR__.'/assets/test.jpg';
$file = new \Illuminate\Http\UploadedFile(
$path, 'test.jpg', 'image/jpeg', filesize($path), null, true
);
$size = rand(10, 20);
$files = ['pictures' => array_pad([], $size, $file)];
$this->call(
'POST', // $method
'/admin/multiple-images', // $action
[], // $parameters
[],
$files
);
$this->assertResponseStatus(302);
$this->assertRedirectedTo('/admin/multiple-images');
$this->assertEquals($this->fileCountInImageDir(), $size);
$pictures = MultipleImage::first()->pictures;
$this->assertCount($size, $pictures);
foreach ($pictures as $picture) {
$this->assertFileExists(public_path('uploads/'.$picture));
}
}
public function testRemoveMultipleFiles()
{
File::cleanDirectory(public_path('uploads/images'));
// upload files
$path = __DIR__.'/assets/test.jpg';
$file = new \Illuminate\Http\UploadedFile(
$path, 'test.jpg', 'image/jpeg', filesize($path), null, true
);
$size = rand(10, 20);
$files = ['pictures' => array_pad([], $size, $file)];
$this->call(
'POST', // $method
'/admin/multiple-images', // $action
[], // $parameters
[],
$files
);
$this->assertEquals($this->fileCountInImageDir(), $size);
}
protected function fileCountInImageDir($dir = 'uploads/images')
{
$file = new FilesystemIterator(public_path($dir), FilesystemIterator::SKIP_DOTS);
return iterator_count($file);
}
}

View File

@@ -0,0 +1,49 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
class IndexTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testIndex()
{
$this->visit('admin/')
->see('Dashboard')
->see('Description...')
->see('Environment')
->see('PHP version')
->see('Laravel version')
->see('Available extensions')
->seeLink('laravel-admin-ext/helpers', 'https://github.com/laravel-admin-extensions/helpers')
->seeLink('laravel-admin-ext/backup', 'https://github.com/laravel-admin-extensions/backup')
->seeLink('laravel-admin-ext/media-manager', 'https://github.com/laravel-admin-extensions/media-manager')
->see('Dependencies')
->see('php')
// ->see('>=7.0.0')
->see('laravel/framework');
}
public function testClickMenu()
{
$this->visit('admin/')
->click('Users')
->seePageis('admin/auth/users')
->click('Roles')
->seePageis('admin/auth/roles')
->click('Permission')
->seePageis('admin/auth/permissions')
->click('Menu')
->seePageis('admin/auth/menu')
->click('Operation log')
->seePageis('admin/auth/logs');
}
}

View File

@@ -0,0 +1,25 @@
<?php
class InstallTest extends TestCase
{
public function testInstalledDirectories()
{
$this->assertFileExists(admin_path());
$this->assertFileExists(admin_path('Controllers'));
$this->assertFileExists(admin_path('routes.php'));
$this->assertFileExists(admin_path('bootstrap.php'));
$this->assertFileExists(admin_path('Controllers/HomeController.php'));
$this->assertFileExists(admin_path('Controllers/AuthController.php'));
$this->assertFileExists(admin_path('Controllers/ExampleController.php'));
$this->assertFileExists(config_path('admin.php'));
$this->assertFileExists(public_path('vendor/laravel-admin'));
}
}

View File

@@ -0,0 +1,11 @@
<?php
class LaravelTest extends TestCase
{
public function testLaravel()
{
$this->visit('/')
->assertResponseStatus(200)
->see('Laravel');
}
}

View File

@@ -0,0 +1,76 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Auth\Database\Menu;
class MenuTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testMenuIndex()
{
$this->visit('admin/auth/menu')
->see('Menu')
->see('Index')
->see('Auth')
->see('Users')
->see('Roles')
->see('Permission')
->see('Menu');
}
public function testAddMenu()
{
$item = ['parent_id' => '0', 'title' => 'Test', 'uri' => 'test'];
$this->visit('admin/auth/menu')
->seePageIs('admin/auth/menu')
->see('Menu')
->submitForm('Submit', $item)
->seePageIs('admin/auth/menu')
->seeInDatabase(config('admin.database.menu_table'), $item)
->assertEquals(8, Menu::count());
// $this->expectException(\Laravel\BrowserKitTesting\HttpException::class);
//
// $this->visit('admin')
// ->see('Test')
// ->click('Test');
}
public function testDeleteMenu()
{
$this->delete('admin/auth/menu/8')
->assertEquals(7, Menu::count());
}
public function testEditMenu()
{
$this->visit('admin/auth/menu/1/edit')
->see('Menu')
->submitForm('Submit', ['title' => 'blablabla'])
->seePageIs('admin/auth/menu')
->seeInDatabase(config('admin.database.menu_table'), ['title' => 'blablabla'])
->assertEquals(7, Menu::count());
}
public function testShowPage()
{
$this->visit('admin/auth/menu/1')
->seePageIs('admin/auth/menu/1/edit');
}
public function testEditMenuParent()
{
$this->expectException(\Laravel\BrowserKitTesting\HttpException::class);
$this->visit('admin/auth/menu/5/edit')
->see('Menu')
->submitForm('Submit', ['parent_id' => 5]);
}
}

View File

@@ -0,0 +1,25 @@
<?php
use Tests\Models\Tree;
class ModelTreeTest extends TestCase
{
public function setUp()
{
parent::setUp();
}
public function testSelectOptions()
{
$rootText = 'Root Text';
$options = Tree::selectOptions(function ($query) {
return $query->where('uri', '');
}, $rootText);
$count = Tree::query()->where('uri', '')->count();
$this->assertEquals(array_shift($options), $rootText);
$this->assertEquals(count($options), $count);
}
}

View File

@@ -0,0 +1,84 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Auth\Database\OperationLog;
class OperationLogTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testOperationLogIndex()
{
$this->visit('admin/auth/logs')
->see('Operation log')
->see('List')
->see('GET')
->see('admin/auth/logs');
}
public function testGenerateLogs()
{
$table = config('admin.database.operation_log_table');
$this->visit('admin/auth/menu')
->seePageIs('admin/auth/menu')
->visit('admin/auth/users')
->seePageIs('admin/auth/users')
->visit('admin/auth/permissions')
->seePageIs('admin/auth/permissions')
->visit('admin/auth/roles')
->seePageIs('admin/auth/roles')
->visit('admin/auth/logs')
->seePageIs('admin/auth/logs')
->seeInDatabase($table, ['path' => 'admin/auth/menu', 'method' => 'GET'])
->seeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET'])
->seeInDatabase($table, ['path' => 'admin/auth/permissions', 'method' => 'GET'])
->seeInDatabase($table, ['path' => 'admin/auth/roles', 'method' => 'GET']);
$this->assertEquals(4, OperationLog::count());
}
public function testDeleteLogs()
{
$table = config('admin.database.operation_log_table');
$this->visit('admin/auth/logs')
->seePageIs('admin/auth/logs')
->assertEquals(0, OperationLog::count());
$this->visit('admin/auth/users');
$this->seeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET']);
$this->delete('admin/auth/logs/1')
->assertEquals(0, OperationLog::count());
}
public function testDeleteMultipleLogs()
{
$table = config('admin.database.operation_log_table');
$this->visit('admin/auth/menu')
->visit('admin/auth/users')
->visit('admin/auth/permissions')
->visit('admin/auth/roles')
->seeInDatabase($table, ['path' => 'admin/auth/menu', 'method' => 'GET'])
->seeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET'])
->seeInDatabase($table, ['path' => 'admin/auth/permissions', 'method' => 'GET'])
->seeInDatabase($table, ['path' => 'admin/auth/roles', 'method' => 'GET'])
->assertEquals(4, OperationLog::count());
$this->delete('admin/auth/logs/1,2,3,4')
->notSeeInDatabase($table, ['path' => 'admin/auth/menu', 'method' => 'GET'])
->notSeeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET'])
->notSeeInDatabase($table, ['path' => 'admin/auth/permissions', 'method' => 'GET'])
->notSeeInDatabase($table, ['path' => 'admin/auth/roles', 'method' => 'GET'])
->assertEquals(0, OperationLog::count());
}
}

View File

@@ -0,0 +1,214 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Auth\Database\Permission;
use Encore\Admin\Auth\Database\Role;
class PermissionsTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testPermissionsIndex()
{
$this->assertTrue(Administrator::first()->isAdministrator());
$this->visit('admin/auth/permissions')
->see('Permissions');
}
public function testAddAndDeletePermissions()
{
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-edit', 'name' => 'Can edit', 'http_path' => 'users/1/edit', 'http_method' => ['GET']])
->seePageIs('admin/auth/permissions')
->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-delete', 'name' => 'Can delete', 'http_path' => 'users/1', 'http_method' => ['DELETE']])
->seePageIs('admin/auth/permissions')
->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-edit', 'name' => 'Can edit', 'http_path' => 'users/1/edit', 'http_method' => 'GET'])
->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-delete', 'name' => 'Can delete', 'http_path' => 'users/1', 'http_method' => 'DELETE'])
->assertEquals(7, Permission::count());
$this->assertTrue(Administrator::first()->can('can-edit'));
$this->assertTrue(Administrator::first()->can('can-delete'));
$this->delete('admin/auth/permissions/6')
->assertEquals(6, Permission::count());
$this->delete('admin/auth/permissions/7')
->assertEquals(5, Permission::count());
}
public function testAddPermissionToRole()
{
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-create', 'name' => 'Can Create', 'http_path' => 'users/create', 'http_method' => ['GET']])
->seePageIs('admin/auth/permissions');
$this->assertEquals(6, Permission::count());
$this->visit('admin/auth/roles/1/edit')
->see('Edit')
->submitForm('Submit', ['permissions' => [1]])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.role_permissions_table'), ['role_id' => 1, 'permission_id' => 1]);
}
public function testAddPermissionToUser()
{
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-create', 'name' => 'Can Create', 'http_path' => 'users/create', 'http_method' => ['GET']])
->seePageIs('admin/auth/permissions');
$this->assertEquals(6, Permission::count());
$this->visit('admin/auth/users/1/edit')
->see('Edit')
->submitForm('Submit', ['permissions' => [1], 'roles' => [1]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.user_permissions_table'), ['user_id' => 1, 'permission_id' => 1])
->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 1, 'role_id' => 1]);
}
public function testAddUserAndAssignPermission()
{
$user = [
'username' => 'Test',
'name' => 'Name',
'password' => '123456',
'password_confirmation' => '123456',
];
$this->visit('admin/auth/users/create')
->see('Create')
->submitForm('Submit', $user)
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);
$this->assertFalse(Administrator::find(2)->isAdministrator());
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-update', 'name' => 'Can Update', 'http_path' => 'users/*/edit', 'http_method' => ['GET']])
->seePageIs('admin/auth/permissions');
$this->assertEquals(6, Permission::count());
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-remove', 'name' => 'Can Remove', 'http_path' => 'users/*', 'http_method' => ['DELETE']])
->seePageIs('admin/auth/permissions');
$this->assertEquals(7, Permission::count());
$this->visit('admin/auth/users/2/edit')
->see('Edit')
->submitForm('Submit', ['permissions' => [6]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 6]);
$this->assertTrue(Administrator::find(2)->can('can-update'));
$this->assertTrue(Administrator::find(2)->cannot('can-remove'));
$this->visit('admin/auth/users/2/edit')
->see('Edit')
->submitForm('Submit', ['permissions' => [7]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 7]);
$this->assertTrue(Administrator::find(2)->can('can-remove'));
$this->visit('admin/auth/users/2/edit')
->see('Edit')
->submitForm('Submit', ['permissions' => []])
->seePageIs('admin/auth/users')
->missingFromDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 6])
->missingFromDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 7]);
$this->assertTrue(Administrator::find(2)->cannot('can-update'));
$this->assertTrue(Administrator::find(2)->cannot('can-remove'));
}
public function testPermissionThroughRole()
{
$user = [
'username' => 'Test',
'name' => 'Name',
'password' => '123456',
'password_confirmation' => '123456',
];
// 1.add a user
$this->visit('admin/auth/users/create')
->see('Create')
->submitForm('Submit', $user)
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);
$this->assertFalse(Administrator::find(2)->isAdministrator());
// 2.add a role
$this->visit('admin/auth/roles/create')
->see('Roles')
->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])
->assertEquals(2, Role::count());
$this->assertFalse(Administrator::find(2)->isRole('developer'));
// 3.assign role to user
$this->visit('admin/auth/users/2/edit')
->see('Edit')
->submitForm('Submit', ['roles' => [2]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 2, 'role_id' => 2]);
$this->assertTrue(Administrator::find(2)->isRole('developer'));
// 4.add a permission
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-remove', 'name' => 'Can Remove', 'http_path' => 'users/*', 'http_method' => ['DELETE']])
->seePageIs('admin/auth/permissions');
$this->assertEquals(6, Permission::count());
$this->assertTrue(Administrator::find(2)->cannot('can-remove'));
// 5.assign permission to role
$this->visit('admin/auth/roles/2/edit')
->see('Edit')
->submitForm('Submit', ['permissions' => [6]])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.role_permissions_table'), ['role_id' => 2, 'permission_id' => 6]);
$this->assertTrue(Administrator::find(2)->can('can-remove'));
}
public function testEditPermission()
{
$this->visit('admin/auth/permissions/create')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-edit', 'name' => 'Can edit', 'http_path' => 'users/1/edit', 'http_method' => ['GET']])
->seePageIs('admin/auth/permissions')
->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-edit'])
->seeInDatabase(config('admin.database.permissions_table'), ['name' => 'Can edit'])
->assertEquals(6, Permission::count());
$this->visit('admin/auth/permissions/1/edit')
->see('Permissions')
->submitForm('Submit', ['slug' => 'can-delete'])
->seePageIs('admin/auth/permissions')
->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-delete'])
->assertEquals(6, Permission::count());
}
}

View File

@@ -0,0 +1,105 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Encore\Admin\Auth\Database\Role;
class RolesTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testRolesIndex()
{
$this->visit('admin/auth/roles')
->see('Roles')
->see('administrator');
}
public function testAddRole()
{
$this->visit('admin/auth/roles/create')
->see('Roles')
->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])
->assertEquals(2, Role::count());
}
public function testAddRoleToUser()
{
$user = [
'username' => 'Test',
'name' => 'Name',
'password' => '123456',
'password_confirmation' => '123456',
];
$this->visit('admin/auth/users/create')
->see('Create')
->submitForm('Submit', $user)
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);
$this->assertEquals(1, Role::count());
$this->visit('admin/auth/roles/create')
->see('Roles')
->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])
->assertEquals(2, Role::count());
$this->assertFalse(Administrator::find(2)->isRole('developer'));
$this->visit('admin/auth/users/2/edit')
->see('Edit')
->submitForm('Submit', ['roles' => [2]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 2, 'role_id' => 2]);
$this->assertTrue(Administrator::find(2)->isRole('developer'));
$this->assertFalse(Administrator::find(2)->inRoles(['editor', 'operator']));
$this->assertTrue(Administrator::find(2)->inRoles(['developer', 'operator', 'editor']));
}
public function testDeleteRole()
{
$this->assertEquals(1, Role::count());
$this->visit('admin/auth/roles/create')
->see('Roles')
->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])
->assertEquals(2, Role::count());
$this->delete('admin/auth/roles/2')
->assertEquals(1, Role::count());
$this->delete('admin/auth/roles/1')
->assertEquals(0, Role::count());
}
public function testEditRole()
{
$this->visit('admin/auth/roles/create')
->see('Roles')
->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])
->assertEquals(2, Role::count());
$this->visit('admin/auth/roles/2/edit')
->see('Roles')
->submitForm('Submit', ['name' => 'blablabla'])
->seePageIs('admin/auth/roles')
->seeInDatabase(config('admin.database.roles_table'), ['name' => 'blablabla'])
->assertEquals(2, Role::count());
}
}

View File

@@ -0,0 +1,94 @@
<?php
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Laravel\BrowserKitTesting\TestCase as BaseTestCase;
class TestCase extends BaseTestCase
{
protected $baseUrl = 'http://localhost:8000';
/**
* Boots the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../vendor/laravel/laravel/bootstrap/app.php';
$app->booting(function () {
$loader = \Illuminate\Foundation\AliasLoader::getInstance();
$loader->alias('Admin', \Encore\Admin\Facades\Admin::class);
});
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
$app->register('Encore\Admin\AdminServiceProvider');
return $app;
}
public function setUp()
{
parent::setUp();
$adminConfig = require __DIR__.'/config/admin.php';
$this->app['config']->set('database.default', 'mysql');
$this->app['config']->set('database.connections.mysql.host', env('MYSQL_HOST', 'localhost'));
$this->app['config']->set('database.connections.mysql.database', 'laravel_admin_test');
$this->app['config']->set('database.connections.mysql.username', 'root');
$this->app['config']->set('database.connections.mysql.password', '');
$this->app['config']->set('app.key', 'AckfSECXIvnK5r28GVIWUAxmbBSjTsmF');
$this->app['config']->set('filesystems', require __DIR__.'/config/filesystems.php');
$this->app['config']->set('admin', $adminConfig);
foreach (Arr::dot(Arr::get($adminConfig, 'auth'), 'auth.') as $key => $value) {
$this->app['config']->set($key, $value);
}
$this->artisan('vendor:publish', ['--provider' => 'Encore\Admin\AdminServiceProvider']);
Schema::defaultStringLength(191);
$this->artisan('admin:install');
$this->migrateTestTables();
if (file_exists($routes = admin_path('routes.php'))) {
require $routes;
}
require __DIR__.'/routes.php';
require __DIR__.'/seeds/factory.php';
}
public function tearDown()
{
(new CreateAdminTables())->down();
(new CreateTestTables())->down();
DB::select("delete from `migrations` where `migration` = '2016_01_04_173148_create_admin_tables'");
parent::tearDown();
}
/**
* run package database migrations.
*
* @return void
*/
public function migrateTestTables()
{
$fileSystem = new Filesystem();
$fileSystem->requireOnce(__DIR__.'/migrations/2016_11_22_093148_create_test_tables.php');
(new CreateTestTables())->up();
}
}

View File

@@ -0,0 +1,209 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Tests\Models\User as UserModel;
class UserFormTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testCreatePage()
{
$this->visit('admin/users/create')
->seeElement('input[type=text][name=username]')
->seeElement('input[type=email][name=email]')
->seeElement('input[type=text][name=mobile]')
->seeElement('input[type=file][name=avatar]')
->seeElement('hr')
->seeElement("input[type=text][name='profile[first_name]']")
->seeElement("input[type=text][name='profile[last_name]']")
->seeElement("input[type=text][name='profile[postcode]']")
->seeElement("textarea[name='profile[address]'][rows=15]")
->seeElement("input[type=hidden][name='profile[latitude]']")
->seeElement("input[type=hidden][name='profile[longitude]']")
->seeElement("input[type=text][name='profile[color]']")
->seeElement("input[type=text][name='profile[start_at]']")
->seeElement("input[type=text][name='profile[end_at]']")
->seeElement('span[class=help-block] i[class*=fa-info-circle]')
->seeInElement('span[class=help-block]', 'Please input your postcode')
->seeElement('span[class=help-block] i[class*=fa-image]')
->seeInElement('span[class=help-block]', '上传头像')
->seeElement("select[name='tags[]'][multiple=multiple]")
->seeInElement('a[html-field]', 'html...');
}
public function testSubmitForm()
{
$data = [
'username' => 'John Doe',
'email' => 'hello@world.com',
'mobile' => '13421234123',
'password' => '123456',
'password_confirmation' => '123456',
//"avatar" => "test.jpg",
'profile' => [
'first_name' => 'John',
'last_name' => 'Doe',
'postcode' => '123456',
'address' => 'Jinshajiang RD',
'latitude' => '131.2123123456',
'longitude' => '21.342123456',
'color' => '#ffffff',
'start_at' => date('Y-m-d H:i:s', time()),
'end_at' => date('Y-m-d H:i:s', time()),
],
];
$this->visit('admin/users/create')
->attach(__DIR__.'/assets/test.jpg', 'avatar')
->submitForm('Submit', $data)
->seePageIs('admin/users')
->seeInElement('td', 1)
->seeInElement('td', $data['username'])
->seeInElement('td', $data['email'])
->seeInElement('td', $data['mobile'])
->seeInElement('td', "{$data['profile']['first_name']} {$data['profile']['last_name']}")
->seeElement('td img')
->seeInElement('td', $data['profile']['postcode'])
->seeInElement('td', $data['profile']['address'])
->seeInElement('td', "{$data['profile']['latitude']} {$data['profile']['longitude']}")
->seeInElement('td', $data['profile']['color'])
->seeInElement('td', $data['profile']['start_at'])
->seeInElement('td', $data['profile']['end_at']);
$this->assertCount(1, UserModel::all());
$this->seeInDatabase('test_users', ['username' => $data['username']]);
$this->seeInDatabase('test_users', ['email' => $data['email']]);
$this->seeInDatabase('test_users', ['mobile' => $data['mobile']]);
$this->seeInDatabase('test_users', ['password' => $data['password']]);
$this->seeInDatabase('test_user_profiles', ['first_name' => $data['profile']['first_name']]);
$this->seeInDatabase('test_user_profiles', ['last_name' => $data['profile']['last_name']]);
$this->seeInDatabase('test_user_profiles', ['postcode' => $data['profile']['postcode']]);
$this->seeInDatabase('test_user_profiles', ['address' => $data['profile']['address']]);
$this->seeInDatabase('test_user_profiles', ['latitude' => $data['profile']['latitude']]);
$this->seeInDatabase('test_user_profiles', ['longitude' => $data['profile']['longitude']]);
$this->seeInDatabase('test_user_profiles', ['color' => $data['profile']['color']]);
$this->seeInDatabase('test_user_profiles', ['start_at' => $data['profile']['start_at']]);
$this->seeInDatabase('test_user_profiles', ['end_at' => $data['profile']['end_at']]);
$avatar = UserModel::first()->avatar;
$this->assertFileExists(public_path('uploads/'.$avatar));
}
protected function seedsTable($count = 100)
{
factory(\Tests\Models\User::class, $count)
->create()
->each(function ($u) {
$u->profile()->save(factory(\Tests\Models\Profile::class)->make());
$u->tags()->saveMany(factory(\Tests\Models\Tag::class, 5)->make());
});
}
public function testEditForm()
{
$this->seedsTable(10);
$id = rand(1, 10);
$user = UserModel::with('profile')->find($id);
$this->visit("admin/users/$id/edit")
->seeElement("input[type=text][name=username][value='{$user->username}']")
->seeElement("input[type=email][name=email][value='{$user->email}']")
->seeElement("input[type=text][name=mobile][value='{$user->mobile}']")
->seeElement('hr')
->seeElement("input[type=text][name='profile[first_name]'][value='{$user->profile->first_name}']")
->seeElement("input[type=text][name='profile[last_name]'][value='{$user->profile->last_name}']")
->seeElement("input[type=text][name='profile[postcode]'][value='{$user->profile->postcode}']")
->seeInElement("textarea[name='profile[address]']", $user->profile->address)
->seeElement("input[type=hidden][name='profile[latitude]'][value='{$user->profile->latitude}']")
->seeElement("input[type=hidden][name='profile[longitude]'][value='{$user->profile->longitude}']")
->seeElement("input[type=text][name='profile[color]'][value='{$user->profile->color}']")
->seeElement("input[type=text][name='profile[start_at]'][value='{$user->profile->start_at}']")
->seeElement("input[type=text][name='profile[end_at]'][value='{$user->profile->end_at}']")
->seeElement("select[name='tags[]'][multiple=multiple]");
$this->assertCount(50, $this->crawler()->filter("select[name='tags[]'] option"));
$this->assertCount(5, $this->crawler()->filter("select[name='tags[]'] option[selected]"));
}
public function testUpdateForm()
{
$this->seedsTable(10);
$id = rand(1, 10);
$this->visit("admin/users/$id/edit")
->type('hello world', 'username')
->type('123', 'password')
->type('123', 'password_confirmation')
->press('Submit')
->seePageIs('admin/users')
->seeInDatabase('test_users', ['username' => 'hello world']);
$user = UserModel::with('profile')->find($id);
$this->assertEquals($user->username, 'hello world');
}
public function testUpdateFormWithRule()
{
$this->seedsTable(10);
$id = rand(1, 10);
$this->visit("admin/users/$id/edit")
->type('', 'email')
->press('Submit')
->seePageIs("admin/users/$id/edit")
->see('The email field is required');
$this->type('xxaxx', 'email')
->press('Submit')
->seePageIs("admin/users/$id/edit")
->see('The email must be a valid email address.');
$this->visit("admin/users/$id/edit")
->type('123', 'password')
->type('1234', 'password_confirmation')
->press('Submit')
->seePageIs("admin/users/$id/edit")
->see('The Password confirmation does not match.');
$this->type('xx@xx.xx', 'email')
->type('123', 'password')
->type('123', 'password_confirmation')
->press('Submit')
->seePageIs('admin/users')
->seeInDatabase('test_users', ['email' => 'xx@xx.xx']);
}
public function testFormHeader()
{
$this->seedsTable(1);
$this->visit('admin/users/1/edit')
->seeInElement('a[class*=btn-danger]', 'Delete')
->seeInElement('a[class*=btn-default]', 'List')
->seeInElement('a[class*=btn-primary]', 'View');
}
public function testFormFooter()
{
$this->seedsTable(1);
$this->visit('admin/users/1/edit')
->seeElement('input[type=checkbox][value=1]')
->seeElement('input[type=checkbox][value=2]');
}
}

View File

@@ -0,0 +1,230 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Tests\Models\Profile as ProfileModel;
use Tests\Models\User as UserModel;
class UserGridTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testIndexPage()
{
$this->visit('admin/users')
->see('All users')
->seeInElement('tr th', 'Username')
->seeInElement('tr th', 'Email')
->seeInElement('tr th', 'Mobile')
->seeInElement('tr th', 'Full name')
->seeInElement('tr th', 'Avatar')
->seeInElement('tr th', 'Post code')
->seeInElement('tr th', 'Address')
->seeInElement('tr th', 'Position')
->seeInElement('tr th', 'Color')
->seeInElement('tr th', '开始时间')
->seeInElement('tr th', '结束时间')
->seeInElement('tr th', 'Color')
->seeInElement('tr th', 'Created at')
->seeInElement('tr th', 'Updated at');
$action = url('/admin/users');
$this->seeElement("form[action='$action'][method=get]")
->seeElement("form[action='$action'][method=get] input[name=id]")
->seeElement("form[action='$action'][method=get] input[name=username]")
->seeElement("form[action='$action'][method=get] input[name=email]")
->seeElement("form[action='$action'][method=get] input[name='profile[start_at][start]']")
->seeElement("form[action='$action'][method=get] input[name='profile[start_at][end]']")
->seeElement("form[action='$action'][method=get] input[name='profile[end_at][start]']")
->seeElement("form[action='$action'][method=get] input[name='profile[end_at][end]']");
$urlAll = url('/admin/users?_export_=all');
$urlNew = url('/admin/users/create');
$this->seeInElement("a[href=\"{$urlAll}\"]", 'All')
->seeInElement("a[href=\"{$urlNew}\"]", 'New');
}
protected function seedsTable($count = 100)
{
factory(\Tests\Models\User::class, $count)
->create()
->each(function ($u) {
$u->profile()->save(factory(\Tests\Models\Profile::class)->make());
$u->tags()->saveMany(factory(\Tests\Models\Tag::class, 5)->make());
});
}
public function testGridWithData()
{
$this->seedsTable();
$this->visit('admin/users')
->see('All users');
$this->assertCount(100, UserModel::all());
$this->assertCount(100, ProfileModel::all());
}
public function testGridPagination()
{
$this->seedsTable(65);
$this->visit('admin/users')
->see('All users');
$this->visit('admin/users?page=2');
$this->assertCount(20, $this->crawler()->filter('td a i[class*=fa-edit]'));
$this->visit('admin/users?page=3');
$this->assertCount(20, $this->crawler()->filter('td a i[class*=fa-edit]'));
$this->visit('admin/users?page=4');
$this->assertCount(5, $this->crawler()->filter('td a i[class*=fa-edit]'));
$this->click(1)->seePageIs('admin/users?page=1');
$this->assertCount(20, $this->crawler()->filter('td a i[class*=fa-edit]'));
}
public function testEqualFilter()
{
$this->seedsTable(50);
$this->visit('admin/users')
->see('All users');
$this->assertCount(50, UserModel::all());
$this->assertCount(50, ProfileModel::all());
$id = rand(1, 50);
$user = UserModel::find($id);
$this->visit('admin/users?id='.$id)
->seeInElement('td', $user->username)
->seeInElement('td', $user->email)
->seeInElement('td', $user->mobile)
->seeElement("img[src='{$user->avatar}']")
->seeInElement('td', "{$user->profile->first_name} {$user->profile->last_name}")
->seeInElement('td', $user->postcode)
->seeInElement('td', $user->address)
->seeInElement('td', "{$user->profile->latitude} {$user->profile->longitude}")
->seeInElement('td', $user->color)
->seeInElement('td', $user->start_at)
->seeInElement('td', $user->end_at);
}
public function testLikeFilter()
{
$this->seedsTable(50);
$this->visit('admin/users')
->see('All users');
$this->assertCount(50, UserModel::all());
$this->assertCount(50, ProfileModel::all());
$users = UserModel::where('username', 'like', '%mi%')->get();
$this->visit('admin/users?username=mi');
$this->assertCount($this->crawler()->filter('table tr')->count() - 1, $users);
foreach ($users as $user) {
$this->seeInElement('td', $user->username);
}
}
public function testFilterRelation()
{
$this->seedsTable(50);
$user = UserModel::with('profile')->find(rand(1, 50));
$this->visit('admin/users?email='.$user->email)
->seeInElement('td', $user->username)
->seeInElement('td', $user->email)
->seeInElement('td', $user->mobile)
->seeElement("img[src='{$user->avatar}']")
->seeInElement('td', "{$user->profile->first_name} {$user->profile->last_name}")
->seeInElement('td', $user->postcode)
->seeInElement('td', $user->address)
->seeInElement('td', "{$user->profile->latitude} {$user->profile->longitude}")
->seeInElement('td', $user->color)
->seeInElement('td', $user->start_at)
->seeInElement('td', $user->end_at);
}
public function testDisplayCallback()
{
$this->seedsTable(1);
$user = UserModel::with('profile')->find(1);
$this->visit('admin/users')
->seeInElement('th', 'Column1 not in table')
->seeInElement('th', 'Column2 not in table')
->seeInElement('td', "full name:{$user->profile->first_name} {$user->profile->last_name}")
->seeInElement('td', "{$user->email}#{$user->profile->color}");
}
public function testHasManyRelation()
{
factory(\Tests\Models\User::class, 10)
->create()
->each(function ($u) {
$u->profile()->save(factory(\Tests\Models\Profile::class)->make());
$u->tags()->saveMany(factory(\Tests\Models\Tag::class, 5)->make());
});
$this->visit('admin/users')
->seeElement('td code');
$this->assertCount(50, $this->crawler()->filter('td code'));
}
public function testGridActions()
{
$this->seedsTable(15);
$this->visit('admin/users');
$this->assertCount(15, $this->crawler()->filter('td a i[class*=fa-edit]'));
$this->assertCount(15, $this->crawler()->filter('td a i[class*=fa-trash]'));
}
public function testGridRows()
{
$this->seedsTable(10);
$this->visit('admin/users')
->seeInElement('td a[class*=btn]', 'detail');
$this->assertCount(5, $this->crawler()->filter('td a[class*=btn]'));
}
public function testGridPerPage()
{
$this->seedsTable(98);
$this->visit('admin/users')
->seeElement('select[class*=per-page][name=per-page]')
->seeInElement('select option', 10)
->seeInElement('select option[selected]', 20)
->seeInElement('select option', 30)
->seeInElement('select option', 50)
->seeInElement('select option', 100);
$this->assertEquals('http://localhost:8000/admin/users?per_page=20', $this->crawler()->filter('select option[selected]')->attr('value'));
$perPage = rand(1, 98);
$this->visit('admin/users?per_page='.$perPage)
->seeInElement('select option[selected]', $perPage)
->assertCount($perPage + 1, $this->crawler()->filter('tr'));
}
}

View File

@@ -0,0 +1,96 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
use Illuminate\Support\Facades\File;
class UserSettingTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->be(Administrator::first(), 'admin');
}
public function testVisitSettingPage()
{
$this->visit('admin/auth/setting')
->see('User setting')
->see('Username')
->see('Name')
->see('Avatar')
->see('Password')
->see('Password confirmation');
$this->seeElement('input[value=Administrator]')
->seeInElement('.box-body', 'administrator');
}
public function testUpdateName()
{
$data = [
'name' => 'tester',
];
$this->visit('admin/auth/setting')
->submitForm('Submit', $data)
->seePageIs('admin/auth/setting');
$this->seeInDatabase('admin_users', ['name' => $data['name']]);
}
public function testUpdateAvatar()
{
File::cleanDirectory(public_path('uploads/images'));
$this->visit('admin/auth/setting')
->attach(__DIR__.'/assets/test.jpg', 'avatar')
->press('Submit')
->seePageIs('admin/auth/setting');
$avatar = Administrator::first()->avatar;
$this->assertEquals('http://localhost:8000/uploads/images/test.jpg', $avatar);
}
public function testUpdatePasswordConfirmation()
{
$data = [
'password' => '123456',
'password_confirmation' => '123',
];
$this->visit('admin/auth/setting')
->submitForm('Submit', $data)
->seePageIs('admin/auth/setting')
->see('The Password confirmation does not match.');
}
public function testUpdatePassword()
{
$data = [
'password' => '123456',
'password_confirmation' => '123456',
];
$this->visit('admin/auth/setting')
->submitForm('Submit', $data)
->seePageIs('admin/auth/setting');
$this->assertTrue(app('hash')->check($data['password'], Administrator::first()->makeVisible('password')->password));
$this->visit('admin/auth/logout')
->seePageIs('admin/auth/login')
->dontSeeIsAuthenticated('admin');
$credentials = ['username' => 'admin', 'password' => '123456'];
$this->visit('admin/auth/login')
->see('login')
->submitForm('Login', $credentials)
->see('dashboard')
->seeCredentials($credentials, 'admin')
->seeIsAuthenticated('admin')
->seePageIs('admin');
}
}

View File

@@ -0,0 +1,95 @@
<?php
use Encore\Admin\Auth\Database\Administrator;
class UsersTest extends TestCase
{
protected $user;
public function setUp()
{
parent::setUp();
$this->user = Administrator::first();
$this->be($this->user, 'admin');
}
public function testUsersIndexPage()
{
$this->visit('admin/auth/users')
->see('Administrator');
}
public function testCreateUser()
{
$user = [
'username' => 'Test',
'name' => 'Name',
'password' => '123456',
'password_confirmation' => '123456',
];
// create user
$this->visit('admin/auth/users/create')
->see('Create')
->submitForm('Submit', $user)
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);
// assign role to user
$this->visit('admin/auth/users/2/edit')
->see('Edit')
->submitForm('Submit', ['roles' => [1]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 2, 'role_id' => 1]);
$this->visit('admin/auth/logout')
->dontSeeIsAuthenticated('admin')
->seePageIs('admin/auth/login')
->submitForm('Login', ['username' => $user['username'], 'password' => $user['password']])
->see('dashboard')
->seeIsAuthenticated('admin')
->seePageIs('admin');
$this->assertTrue($this->app['auth']->guard('admin')->getUser()->isAdministrator());
$this->see('<span>Users</span>')
->see('<span>Roles</span>')
->see('<span>Permission</span>')
->see('<span>Operation log</span>')
->see('<span>Menu</span>');
}
public function testUpdateUser()
{
$this->visit('admin/auth/users/'.$this->user->id.'/edit')
->see('Create')
->submitForm('Submit', ['name' => 'test', 'roles' => [1]])
->seePageIs('admin/auth/users')
->seeInDatabase(config('admin.database.users_table'), ['name' => 'test']);
}
public function testResetPassword()
{
$password = 'odjwyufkglte';
$data = [
'password' => $password,
'password_confirmation' => $password,
'roles' => [1],
];
$this->visit('admin/auth/users/'.$this->user->id.'/edit')
->see('Create')
->submitForm('Submit', $data)
->seePageIs('admin/auth/users')
->visit('admin/auth/logout')
->dontSeeIsAuthenticated('admin')
->seePageIs('admin/auth/login')
->submitForm('Login', ['username' => $this->user->username, 'password' => $password])
->see('dashboard')
->seeIsAuthenticated('admin')
->seePageIs('admin');
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,156 @@
<?php
return [
/*
* Laravel-admin name.
*/
'name' => 'Laravel-admin',
/*
* Logo in admin panel header.
*/
'logo' => '<b>Laravel</b> admin',
/*
* Mini-logo in admin panel header.
*/
'logo-mini' => '<b>La</b>',
/*
* Route configuration.
*/
'route' => [
'prefix' => 'admin',
'namespace' => 'App\\Admin\\Controllers',
'middleware' => ['web', 'admin'],
],
/*
* Laravel-admin install directory.
*/
'directory' => app_path('Admin'),
/*
* Laravel-admin html title.
*/
'title' => 'Admin',
/*
* Use `https`.
*/
'secure' => false,
/*
* Laravel-admin auth setting.
*/
'auth' => [
'guards' => [
'admin' => [
'driver' => 'session',
'provider' => 'admin',
],
],
'providers' => [
'admin' => [
'driver' => 'eloquent',
'model' => Encore\Admin\Auth\Database\Administrator::class,
],
],
],
/*
* Laravel-admin upload setting.
*/
'upload' => [
'disk' => 'admin',
'directory' => [
'image' => 'images',
'file' => 'files',
],
],
/*
* Laravel-admin database setting.
*/
'database' => [
// Database connection for following tables.
'connection' => '',
// User tables and model.
'users_table' => 'admin_users',
'users_model' => Encore\Admin\Auth\Database\Administrator::class,
// Role table and model.
'roles_table' => 'admin_roles',
'roles_model' => Encore\Admin\Auth\Database\Role::class,
// Permission table and model.
'permissions_table' => 'admin_permissions',
'permissions_model' => Encore\Admin\Auth\Database\Permission::class,
// Menu table and model.
'menu_table' => 'admin_menu',
'menu_model' => Encore\Admin\Auth\Database\Menu::class,
// Pivot table for table above.
'operation_log_table' => 'admin_operation_log',
'user_permissions_table' => 'admin_user_permissions',
'role_users_table' => 'admin_role_users',
'role_permissions_table' => 'admin_role_permissions',
'role_menu_table' => 'admin_role_menu',
],
/*
* By setting this option to open or close operation log in laravel-admin.
*/
'operation_log' => [
'enable' => true,
/*
* Routes that will not log to database.
*
* All method to path like: admin/auth/logs
* or specific method to path like: get:admin/auth/logs
*/
'except' => [
'admin/auth/logs*',
],
],
/*
* @see https://adminlte.io/docs/2.4/layout
*/
'skin' => 'skin-blue-light',
/*
|---------------------------------------------------------|
|LAYOUT OPTIONS | fixed |
| | layout-boxed |
| | layout-top-nav |
| | sidebar-collapse |
| | sidebar-mini |
|---------------------------------------------------------|
*/
'layout' => ['sidebar-mini', 'sidebar-collapse'],
/*
* Version displayed in footer.
*/
'version' => '1.5.x-dev',
/*
* Settings for extensions.
*/
'extensions' => [
],
];

View File

@@ -0,0 +1,95 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. A "local" driver, as well as a variety of cloud
| based drivers are available for your choosing. Just store away!
|
| Supported: "local", "ftp", "s3", "rackspace"
|
*/
'default' => 'public',
/*
|--------------------------------------------------------------------------
| Default Cloud Filesystem Disk
|--------------------------------------------------------------------------
|
| Many applications store files both locally and in the cloud. For this
| reason, you may specify a default "cloud" driver here. This driver
| will be bound as the Cloud disk implementation in the container.
|
*/
'cloud' => 's3',
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options.
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => 'your-key',
'secret' => 'your-secret',
'region' => 'your-region',
'bucket' => 'your-bucket',
],
'admin' => [
'driver' => 'local',
'root' => public_path('uploads'),
'visibility' => 'public',
'url' => 'http://localhost:8000/uploads/',
],
'qiniu' => [
'driver' => 'qiniu',
'domains' => [
'default' => 'of8kfibjo.bkt.clouddn.com', //你的七牛域名
'https' => 'dn-yourdomain.qbox.me', //你的HTTPS域名
'custom' => 'static.abc.com', //你的自定义域名
],
'access_key' => 'tIyz5h5IDT1-PQS22iRrI4dCBEktWj76O-ls856K', //AccessKey
'secret_key' => 'TCU2GuSlbzxKgnixYO_-pdo4odbXttm1RNNvEwSD', //SecretKey
'bucket' => 'laravel', //Bucket名字
'notify_url' => '', //持久化处理回调地址
],
'aliyun' => [
'driver' => 'oss',
'access_id' => 'LTAIsOQNIDQN78Jr',
'access_key' => 'ChsYewaCxm1mi7AIBPRniuncEbFHNO',
'bucket' => 'laravel-admin',
'endpoint' => 'oss-cn-shanghai.aliyuncs.com',
],
],
];

View File

@@ -0,0 +1,99 @@
<?php
namespace Tests\Controllers;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\ModelForm;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Tests\Models\File;
class FileController extends Controller
{
use ModelForm;
/**
* Index interface.
*
* @return Content
*/
public function index()
{
return Admin::content(function (Content $content) {
$content->header('header');
$content->description('description');
$content->body($this->grid());
});
}
/**
* Edit interface.
*
* @param $id
*
* @return Content
*/
public function edit($id)
{
return Admin::content(function (Content $content) use ($id) {
$content->header('header');
$content->description('description');
$content->body($this->form()->edit($id));
});
}
/**
* Create interface.
*
* @return Content
*/
public function create()
{
return Admin::content(function (Content $content) {
$content->header('Upload file');
$content->body($this->form());
});
}
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Admin::grid(File::class, function (Grid $grid) {
$grid->id('ID')->sortable();
$grid->created_at();
$grid->updated_at();
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Admin::form(File::class, function (Form $form) {
$form->display('id', 'ID');
$form->file('file1');
$form->file('file2');
$form->file('file3');
$form->file('file4');
$form->file('file5');
$form->file('file6');
$form->display('created_at', 'Created At');
$form->display('updated_at', 'Updated At');
});
}
}

View File

@@ -0,0 +1,103 @@
<?php
namespace Tests\Controllers;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\ModelForm;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Tests\Models\Image;
class ImageController extends Controller
{
use ModelForm;
/**
* Index interface.
*
* @return Content
*/
public function index()
{
return Admin::content(function (Content $content) {
$content->header('header');
$content->description('description');
$content->body($this->grid());
});
}
/**
* Edit interface.
*
* @param $id
*
* @return Content
*/
public function edit($id)
{
return Admin::content(function (Content $content) use ($id) {
$content->header('header');
$content->description('description');
$content->body($this->form()->edit($id));
});
}
/**
* Create interface.
*
* @return Content
*/
public function create()
{
return Admin::content(function (Content $content) {
$content->header('Upload image');
$content->body($this->form());
});
}
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Admin::grid(Image::class, function (Grid $grid) {
$grid->id('ID')->sortable();
$grid->created_at();
$grid->updated_at();
$grid->disableFilter();
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Admin::form(Image::class, function (Form $form) {
$form->display('id', 'ID');
$form->image('image1');
$form->image('image2')->rotate(90);
$form->image('image3')->flip('v');
$form->image('image4')->move(null, 'renamed.jpeg');
$form->image('image5')->name(function ($file) {
return 'asdasdasdasdasd.'.$file->guessExtension();
});
$form->image('image6')->uniqueName();
$form->display('created_at', 'Created At');
$form->display('updated_at', 'Updated At');
});
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace Tests\Controllers;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\ModelForm;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Tests\Models\MultipleImage;
class MultipleImageController extends Controller
{
use ModelForm;
/**
* Index interface.
*
* @return Content
*/
public function index()
{
return Admin::content(function (Content $content) {
$content->header('header');
$content->description('description');
$content->body($this->grid());
});
}
/**
* Edit interface.
*
* @param $id
*
* @return Content
*/
public function edit($id)
{
return Admin::content(function (Content $content) use ($id) {
$content->header('header');
$content->description('description');
$content->body($this->form()->edit($id));
});
}
/**
* Create interface.
*
* @return Content
*/
public function create()
{
return Admin::content(function (Content $content) {
$content->header('Upload image');
$content->body($this->form());
});
}
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Admin::grid(Image::class, function (Grid $grid) {
$grid->id('ID')->sortable();
$grid->created_at();
$grid->updated_at();
$grid->disableFilter();
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Admin::form(MultipleImage::class, function (Form $form) {
$form->display('id', 'ID');
$form->multipleImage('pictures');
$form->display('created_at', 'Created At');
$form->display('updated_at', 'Updated At');
});
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace Tests\Controllers;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\ModelForm;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Tests\Models\Tag;
use Tests\Models\User;
class UserController extends Controller
{
use ModelForm;
/**
* Index interface.
*
* @return Content
*/
public function index()
{
return Admin::content(function (Content $content) {
$content->header('All users');
$content->description('description');
$content->body($this->grid());
});
}
/**
* Edit interface.
*
* @param $id
*
* @return Content
*/
public function edit($id)
{
return Admin::content(function (Content $content) use ($id) {
$content->header('Edit user');
$content->description('description');
$content->body($this->form()->edit($id));
});
}
/**
* Create interface.
*
* @return Content
*/
public function create()
{
return Admin::content(function (Content $content) {
$content->header('Create user');
$content->body($this->form());
});
}
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Admin::grid(User::class, function (Grid $grid) {
$grid->id('ID')->sortable();
$grid->username();
$grid->email();
$grid->mobile();
$grid->full_name();
$grid->avatar()->display(function ($avatar) {
return "<img src='{$avatar}' />";
});
$grid->profile()->postcode('Post code');
$grid->profile()->address();
$grid->position('Position');
$grid->column('profile.color');
$grid->profile()->start_at('开始时间');
$grid->profile()->end_at('结束时间');
$grid->column('column1_not_in_table')->display(function () {
return 'full name:'.$this->full_name;
});
$grid->column('column2_not_in_table')->display(function () {
return $this->email.'#'.$this->profile['color'];
});
$grid->tags()->display(function ($tags) {
$tags = collect($tags)->map(function ($tag) {
return "<code>{$tag['name']}</code>";
})->toArray();
return implode('', $tags);
});
$grid->created_at();
$grid->updated_at();
$grid->filter(function ($filter) {
$filter->like('username');
$filter->like('email');
$filter->like('profile.postcode');
$filter->between('profile.start_at')->datetime();
$filter->between('profile.end_at')->datetime();
});
$grid->actions(function ($actions) {
if ($actions->getKey() % 2 == 0) {
$actions->append('<a href="/" class="btn btn-xs btn-danger">detail</a>');
}
});
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
Form::extend('map', Form\Field\Map::class);
Form::extend('editor', Form\Field\Editor::class);
return Admin::form(User::class, function (Form $form) {
$form->disableDeletion();
$form->display('id', 'ID');
$form->text('username');
$form->email('email')->rules('required');
$form->mobile('mobile');
$form->image('avatar')->help('上传头像', 'fa-image');
$form->ignore(['password_confirmation']);
$form->password('password')->rules('confirmed');
$form->password('password_confirmation');
$form->divider();
$form->text('profile.first_name');
$form->text('profile.last_name');
$form->text('profile.postcode')->help('Please input your postcode');
$form->textarea('profile.address')->rows(15);
$form->map('profile.latitude', 'profile.longitude', 'Position');
$form->color('profile.color');
$form->datetime('profile.start_at');
$form->datetime('profile.end_at');
$form->multipleSelect('tags', 'Tags')->options(Tag::all()->pluck('name', 'id')); //->rules('max:10|min:3');
$form->display('created_at', 'Created At');
$form->display('updated_at', 'Updated At');
$form->html('<a html-field>html...</a>');
});
}
}

View File

@@ -0,0 +1,98 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateTestTables extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('test_images', function (Blueprint $table) {
$table->increments('id');
$table->string('image1');
$table->string('image2');
$table->string('image3');
$table->string('image4');
$table->string('image5');
$table->string('image6');
$table->timestamps();
});
Schema::create('test_multiple_images', function (Blueprint $table) {
$table->increments('id');
$table->text('pictures');
$table->timestamps();
});
Schema::create('test_files', function (Blueprint $table) {
$table->increments('id');
$table->string('file1');
$table->string('file2');
$table->string('file3');
$table->string('file4');
$table->string('file5');
$table->string('file6');
$table->timestamps();
});
Schema::create('test_users', function (Blueprint $table) {
$table->increments('id');
$table->string('username');
$table->string('email');
$table->string('mobile')->nullable();
$table->string('avatar')->nullable();
$table->string('password');
$table->timestamps();
});
Schema::create('test_user_profiles', function (Blueprint $table) {
$table->increments('id');
$table->string('user_id');
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('postcode')->nullable();
$table->string('address')->nullable();
$table->string('latitude')->nullable();
$table->string('longitude')->nullable();
$table->string('color')->nullable();
$table->timestamp('start_at')->nullable();
$table->timestamp('end_at')->nullable();
$table->timestamps();
});
Schema::create('test_tags', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('test_user_tags', function (Blueprint $table) {
$table->integer('user_id');
$table->integer('tag_id');
$table->index(['user_id', 'tag_id']);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('test_images');
Schema::dropIfExists('test_multiple_images');
Schema::dropIfExists('test_files');
Schema::dropIfExists('test_users');
Schema::dropIfExists('test_user_profiles');
Schema::dropIfExists('test_tags');
Schema::dropIfExists('test_user_tags');
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Tests\Models;
use Illuminate\Database\Eloquent\Model;
class File extends Model
{
protected $table = 'test_files';
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Tests\Models;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
protected $table = 'test_images';
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Tests\Models;
use Illuminate\Database\Eloquent\Model;
class MultipleImage extends Model
{
protected $table = 'test_multiple_images';
public function setPicturesAttribute($pictures)
{
if (is_array($pictures)) {
$this->attributes['pictures'] = json_encode($pictures);
}
}
public function getPicturesAttribute($pictures)
{
return json_decode($pictures, true) ?: [];
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Tests\Models;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $table = 'test_user_profiles';
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Tests\Models;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
protected $table = 'test_tags';
public function users()
{
return $this->belongsToMany(User::class, 'test_user_tags', 'tag_id', 'user_id');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Tests\Models;
use Encore\Admin\Traits\AdminBuilder;
use Encore\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;
class Tree extends Model
{
use AdminBuilder, ModelTree;
/**
* Create a new Eloquent model instance.
*
* @param array $attributes
*/
public function __construct(array $attributes = [])
{
$connection = config('admin.database.connection') ?: config('database.default');
$this->setConnection($connection);
$this->setTable(config('admin.database.menu_table'));
parent::__construct($attributes);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Tests\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'test_users';
protected $appends = ['full_name', 'position'];
public function profile()
{
return $this->hasOne(Profile::class, 'user_id');
}
public function getFullNameAttribute()
{
return "{$this->profile['first_name']} {$this->profile['last_name']}";
}
public function getPositionAttribute()
{
return "{$this->profile->latitude} {$this->profile->longitude}";
}
public function tags()
{
return $this->belongsToMany(Tag::class, 'test_user_tags', 'user_id', 'tag_id');
}
}

View File

@@ -0,0 +1,12 @@
<?php
Route::group([
'prefix' => config('admin.route.prefix'),
'namespace' => 'Tests\Controllers',
'middleware' => ['web', 'admin'],
], function ($router) {
$router->resource('images', ImageController::class);
$router->resource('multiple-images', MultipleImageController::class);
$router->resource('files', FileController::class);
$router->resource('users', UserController::class);
});

View File

@@ -0,0 +1,18 @@
<?php
namespace Tests\Seeds;
use Illuminate\Database\Seeder;
class UserTableSeeder extends Seeder
{
public function run()
{
factory(\Tests\Models\User::class, 50)
->create()
->each(function ($u) {
$u->profile()->save(factory(\Tests\Models\Profile::class)->make());
$u->tags()->saveMany(factory(\Tests\Models\Tag::class, 5)->make());
});
}
}

View File

@@ -0,0 +1,36 @@
<?php
use Faker\Generator as Faker;
use Illuminate\Database\Eloquent\Factory;
$factory = app(Factory::class);
$factory->define(Tests\Models\User::class, function (Faker $faker) {
return [
'username' => $faker->userName,
'email' => $faker->email,
'mobile' => $faker->phoneNumber,
'avatar' => $faker->imageUrl(),
'password' => bcrypt('123456'),
];
});
$factory->define(Tests\Models\Profile::class, function (Faker $faker) {
return [
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'postcode' => $faker->postcode,
'address' => $faker->address,
'latitude' => $faker->latitude,
'longitude' => $faker->longitude,
'color' => $faker->hexColor,
'start_at' => $faker->dateTime,
'end_at' => $faker->dateTime,
];
});
$factory->define(Tests\Models\Tag::class, function (Faker $faker) {
return [
'name' => $faker->word,
];
});