diff --git a/tests/src/Functional/MenuBlockTest.php b/tests/src/Functional/MenuBlockTest.php
new file mode 100644
index 0000000..6e80a8d
--- /dev/null
+++ b/tests/src/Functional/MenuBlockTest.php
@@ -0,0 +1,354 @@
+<?php
+
+namespace Drupal\Tests\menu_block\Functional;
+
+use Drupal\block\Entity\Block;
+use Drupal\menu_link_content\Entity\MenuLinkContent;
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Class MenuBlockTest.
+ *
+ * Tests for the menu_block module.
+ *
+ * @group menu_block
+ */
+class MenuBlockTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'block',
+    'menu_block',
+    'menu_test',
+  ];
+
+  /**
+   * An administrative user to configure the test environment.
+   */
+  protected $adminUser;
+
+  /**
+   * The menu link plugin manager.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkManagerInterface
+   */
+  protected $menuLinkManager;
+
+  protected $blockStorage;
+
+  protected $links;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $this->menuLinkManager = \Drupal::service('plugin.manager.menu.link');
+    $this->blockStorage = \Drupal::service('entity_type.manager')
+      ->getStorage('block')
+    ;
+
+    $this->links = $this->createLinkHierarchy();
+
+    // Create and log in an administrative user.
+    $this->adminUser = $this->drupalCreateUser([
+      'administer blocks',
+      'access administration pages',
+    ]);
+    $this->drupalLogin($this->adminUser);
+  }
+
+  /**
+   * Check if all menu block configuration options are available.
+   */
+  public function testMenuBlockFormDisplay() {
+    $this->drupalGet('admin/structure/block/add/menu_block:main');
+    $this->assertSession()->pageTextContains('Initial visibility level');
+    $this->assertSession()->pageTextContains('Number of levels to display');
+    $this->assertSession()->pageTextContains('Expand all menu links');
+    $this->assertSession()->pageTextContains('Fixed parent item');
+    $this->assertSession()
+      ->pageTextContains('Make the initial visibility level follow the active menu item.')
+    ;
+    $this->assertSession()->pageTextContains('Theme hook suggestion');
+  }
+
+  /**
+   * Check if all menu block settings are saved correctly.
+   */
+  public function testMenuBlockUi() {
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Main navigation',
+      'settings[label_display]' => FALSE,
+      'settings[level]' => 2,
+      'settings[depth]' => 6,
+      'settings[expand]' => TRUE,
+      'settings[parent]' => 'main:',
+      'settings[follow]' => TRUE,
+      'settings[follow_parent]' => 'active',
+      'settings[suggestion]' => 'main',
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+    $block = Block::load($block_id);
+    $block_settings = $block->get('settings');
+    self::assertSame(2, $block_settings['level']);
+    self::assertSame(6, $block_settings['depth']);
+    self::assertTrue($block_settings['expand']);
+    self::assertSame('main:', $block_settings['parent']);
+    self::assertTrue($block_settings['follow']);
+    self::assertSame('active', $block_settings['follow_parent']);
+    self::assertSame('main', $block_settings['suggestion']);
+  }
+
+  /**
+   * Test the menu_block level option.
+   */
+  public function testMenuBlockLevel() {
+    // Add new menu block.
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Main navigation',
+      'settings[label_display]' => FALSE,
+      'settings[level]' => 1,
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+    // Check if the parent menu item is visible, but the child menu items not.
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-2 menu item');
+
+    $this->drupalPostForm('admin/structure/block/manage/' . $block_id, [
+      'settings[level]' => 2,
+    ], 'Save block');
+
+    // Check if the menu items of level 2 are visible, but not the parent menu item.
+    $this->drupalGet('menu-test/hierarchy/parent');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextContains('child-2 menu item');
+    $this->assertSession()->pageTextNotContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+  }
+
+  /**
+   * Test the menu_block depth option.
+   */
+  public function testMenuBlockDepth() {
+    // Add new menu block.
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Main navigation',
+      'settings[label_display]' => FALSE,
+      'settings[level]' => 1,
+      'settings[depth]' => 1,
+      'settings[expand]' => TRUE,
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+    // Check if the parent menu item is visible, but the child menu items not.
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-2 menu item');
+
+    $this->drupalPostForm('admin/structure/block/manage/' . $block_id, [
+      'settings[depth]' => 2,
+    ], 'Save block');
+
+    // Check if the menu items of level 2 are visible, but not the parent menu item.
+    $this->drupalGet('menu-test/hierarchy/parent');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextContains('child-2 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+
+    $this->drupalPostForm('admin/structure/block/manage/' . $block_id, [
+      'settings[depth]' => 0,
+    ], 'Save block');
+
+    // Check if the menu items of level 2 are visible, but not the parent menu item.
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextContains('child-2 menu item');
+    $this->assertSession()->pageTextContains('child-1-1 menu item');
+  }
+
+  /**
+   * Test the menu_block expand option.
+   */
+  public function testMenuBlockExpand() {
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Main navigation',
+      'settings[label_display]' => FALSE,
+      'settings[level]' => 1,
+      'settings[expand]' => TRUE,
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+    // Check if the parent menu item is visible, but the child menu items not.
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextContains('child-1-1 menu item');
+    $this->assertSession()->pageTextContains('child-2 menu item');
+
+    $this->drupalPostForm('admin/structure/block/manage/' . $block_id, [
+      'settings[expand]' => FALSE,
+    ], 'Save block');
+
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-2 menu item');
+  }
+
+  public function testMenuBlockParent() {
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Main navigation',
+      'settings[label_display]' => FALSE,
+      'settings[parent]' => 'main:' . $this->links['parent'],
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextNotContains('parent menu item');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+
+    $this->drupalPostForm('admin/structure/block/manage/' . $block_id, [
+      'settings[parent]' => 'main:' . $this->links['child-1'],
+    ], 'Save block');
+
+    $this->assertSession()->pageTextNotContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextContains('child-1-1 menu item');
+    $this->assertSession()->pageTextContains('child-1-2 menu item');
+  }
+
+  public function testMenuBlockFollow() {
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Main navigation',
+      'settings[label_display]' => FALSE,
+      'settings[follow]' => TRUE,
+      'settings[follow_parent]' => 'child',
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+
+    $this->drupalGet('menu-test/hierarchy/parent');
+    $this->assertSession()->pageTextNotContains('parent menu item');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+
+    $this->drupalGet('menu-test/hierarchy/parent/child');
+    $this->assertSession()->pageTextNotContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextContains('child-1-1 menu item');
+    $this->assertSession()->pageTextContains('child-1-2 menu item');
+    $this->assertSession()->pageTextNotContains('child-2 menu item');
+
+    $this->drupalPostForm('admin/structure/block/manage/' . $block_id, [
+      'settings[follow_parent]' => 'active',
+    ], 'Save block');
+
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextNotContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+
+    $this->drupalGet('menu-test/hierarchy/parent');
+    $this->assertSession()->pageTextContains('parent menu item');
+    $this->assertSession()->pageTextContains('child-1 menu item');
+    $this->assertSession()->pageTextNotContains('child-1-1 menu item');
+  }
+
+  /**
+   * Create a simple hierarchy of links.
+   */
+  protected function createLinkHierarchy() {
+    // First remove all the menu links in the menu.
+    $this->menuLinkManager->deleteLinksInMenu('main');
+
+    // Then create a simple link hierarchy:
+    // - parent menu item
+    //   - child-1 menu item
+    //      - child-1-1 menu item
+    //      - child-1-2 menu item
+    //   - child-2 menu item
+    $base_options = [
+      'provider' => 'menu_block',
+      'menu_name' => 'main',
+    ];
+
+    $parent = $base_options + [
+        'title' => 'parent menu item',
+        'link' => ['uri' => 'internal:/menu-test/hierarchy/parent'],
+      ];
+    $link = MenuLinkContent::create($parent);
+    $link->save();
+    $links['parent'] = $link->getPluginId();
+
+    $child_1 = $base_options + [
+        'title' => 'child-1 menu item',
+        'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child'],
+        'parent' => $links['parent'],
+      ];
+    $link = MenuLinkContent::create($child_1);
+    $link->save();
+    $links['child-1'] = $link->getPluginId();
+
+    $child_1_1 = $base_options + [
+        'title' => 'child-1-1 menu item',
+        'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child2/child'],
+        'parent' => $links['child-1'],
+      ];
+    $link = MenuLinkContent::create($child_1_1);
+    $link->save();
+    $links['child-1-1'] = $link->getPluginId();
+
+    $child_1_2 = $base_options + [
+        'title' => 'child-1-2 menu item',
+        'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child2/child'],
+        'parent' => $links['child-1'],
+      ];
+    $link = MenuLinkContent::create($child_1_2);
+    $link->save();
+    $links['child-1-2'] = $link->getPluginId();
+
+    $child_2 = $base_options + [
+        'title' => 'child-2 menu item',
+        'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child'],
+        'parent' => $links['parent'],
+      ];
+    $link = MenuLinkContent::create($child_2);
+    $link->save();
+    $links['child-2'] = $link->getPluginId();
+
+    return $links;
+  }
+
+}
