Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Twill Laravel Package

area17/twill

Twill is an open-source Laravel package for building a custom CMS fast. It provides a polished admin UI with prebuilt features and Vue components, stays flexible and extensible, works headless or integrated, and lets you use your own models with no lock-in.

View on GitHub
Deep Wiki
Context7

Testing Twill

Twill provides some dusk testing helpers to make it easy to get basic coverage of your cms's functionality.

Setup Laravel dusk

Installation

Depending on your setup, you can add Laravel dusk using composer require --dev laravel/dusk

Then you need to install the base files: php artisan dusk:install

You will also need to install Google Chrome and then install the correct browser driver:

php artisan dusk:chrome-driver --detect

Finally you can generate a first test using:

Generating a test file

php artisan dusk:make MyModuleTest

More

See Laravel documentation for more details

Authenticating

In order to login into the cms you need a user and login.

$this->artisan('twill:superadmin user@example.org password');

$this->browse(function(Browser $browser) {
    $browser->loginAs(\App\Models\User::firstWhere('email', 'user@example.org'), 'twill_users');
});

Dusk helpers

From within a dusk test you can run the following macro's:

visitTwill: Visit the admin panel.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();// [tl! focus]
});

createModuleEntryWithTitle: Create a specific module edit page.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->createModuleEntryWithTitle('Partners', 'Twill');// [tl! focus]
});

visitModuleEntryWithTitle: Visit a specific module edit page.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');// [tl! focus]
});

assertVselectHasOptions: Check if a select field has given options.

The first parameter is the selector by which the field identifies.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');
    $browser->assertVselectHasOptions('.input-wrapper-option', ['option1', 'option2']);// [tl! focus]
});

selectVselectOption: Select a given option.

The first parameter is the selector by which the field identifies.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');
    $browser->selectVselectOption('.input-wrapper-option', 'option1');// [tl! focus]
});

assertVselectHasOptionSelected: Check if a given option is selected.

The first parameter is the selector by which the field identifies.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');
    $browser->selectVselectOption('.input-wrapper-option', 'option1');
    $browser->assertVselectHasOptionSelected('.input-wrapper-option', 'option1');// [tl! focus]
});

pressSaveAndCheckSaved: Save and check that the save was successfully.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');
    $browser->pressSaveAndCheckSaved();// [tl! focus]
});

addBlockWithContent: Add a new block and set the content.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');

    $browser->addBlockWithContent('Text', [ // [tl! focus:start]
        'Title' => 'This is the title',
        'Text' => 'This is the wysiwyg'
    ]); // [tl! focus:end]

    $browser->pressSaveAndCheckSaved('Save as draft');
});

withinNewBlock: Same ass add block with content but for more manual control.

$prefix is the block identifier which is prefixed for block fields.

$this->browse(function(Browser $browser) {
    $browser->visitTwill();
    $browser->visitModuleEntryWithTitle('Partners', 'Twill');

    $browser->withinNewBlock('Text', function(Browser $browser, string $prefix) { // [tl! focus:start]
        $browser->type($prefix . '[title][en]', 'Hello world');
    });// [tl! focus:end]

    $browser->pressSaveAndCheckSaved('Save as draft');
});

withinEditor: Opens the editor for the current page, allows you to interact and then closes it.

dragBlock: Allows you to drag a block in the editor. (When running in headed mode, this may not work as it uses your cursor)

$this->browse(function(Browser $browser) {
    $browser->visitTwill();

    $browser->createModuleEntryWithTitle('Page', 'Example page');

    $browser->withinEditor(function (Browser $editor) { // [tl! focus:start]
        $editor->dragBlock('Text', function (Browser $block, string $prefix) {
            $block->type($prefix . '[title][en]', 'Hello world');
        });
    }); // [tl! focus:end]

    $browser->pressSaveAndCheckSaved('Save as draft');
});
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport