diff --git a/tests/View/ParserTest.php b/tests/View/ParserTest.php
new file mode 100644
index 0000000..114ba29
--- /dev/null
+++ b/tests/View/ParserTest.php
@@ -0,0 +1,144 @@
+parse();
+
+ $expected = new ParsedFragment(
+ null,
+ [],
+ [],
+ [],
+ ['', '']
+ );
+
+ $this->assertEquals($expected, $fragment);
+ }
+
+ public function testCanParseViewWithAssets(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_with_assets.php');
+
+ $parser = new Parser($file);
+ $fragment = $parser->parse();
+
+ $expected = new ParsedFragment(
+ null,
+ [
+ 'test.css'
+ ],
+ [
+ 'test.js',
+ 'test_= $some[\'expression\'] ?>'
+ ],
+ [],
+ ['', '']
+ );
+
+ $this->assertEquals($expected, $fragment);
+ }
+
+ public function testCanParseViewWithExtends(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_with_extends.php');
+
+ $parser = new Parser($file);
+ $fragment = $parser->parse();
+
+ $expected = new ParsedFragment(
+ 'parent',
+ [],
+ [],
+ [
+ 'section1' => '
Test HTML with @extends
' . "\n"
+ ],
+ ['', '']
+ );
+
+ $this->assertEquals($expected, $fragment);
+ }
+
+ public function testCanParseComplexView(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_complex.php');
+
+ $parser = new Parser($file);
+ $fragment = $parser->parse();
+
+ $expected = new ParsedFragment(
+ 'parent',
+ [
+ 'test1.css'
+ ],
+ [
+ 'test1.js',
+ 'test2_= $some[\'expression\'] ?>'
+ ],
+ [
+ 'section1' => 'Test HTML with @extends - section 1
' . "\n",
+ 'section2' => 'Test HTML with @extends - section 2
' . "\n"
+ ],
+ [
+ '' . "\n",
+ '' . "\n" . 'EXTRA' . "\n",
+ ]
+ );
+
+ $this->assertEquals($expected, $fragment);
+ }
+
+ public function testFailsIfMultipleExtendsGiven(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_multiple_extends.php');
+
+ $parser = new Parser($file);
+
+ $this->expectExceptionMessage('Error in file ' . $file . ' in line 3 - There is already an \'@extends\' declared.');
+
+ $parser->parse();
+ }
+
+ public function testFailsIfSectionWithoutExtendsGiven(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_section_without_extends.php');
+
+ $parser = new Parser($file);
+
+ $this->expectExceptionMessage('Error in file ' . $file . ' in line 1 - \'@section\' has no meaning if view extends nothing.');
+
+ $parser->parse();
+ }
+
+ public function testFailsIfOpeningSectionBeforePreviousClosed(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_multiple_sections_open.php');
+
+ $parser = new Parser($file);
+
+ $this->expectExceptionMessage('Parse error in file ' . $file . ' in line 4 - A \'@section\' is already open (no \'@endsection\' found).');
+
+ $parser->parse();
+ }
+
+ public function testFailsIfClosingSectionWhenNoSectionIsOpen(): void
+ {
+ $file = realpath(self::TEST_VIEWS_PATH . '/view_invalid_section_not_open.php');
+
+ $parser = new Parser($file);
+
+ $this->expectExceptionMessage('Parse error in file ' . $file . ' in line 4 - Cannot end section until no \'@section\' is open.');
+
+ $parser->parse();
+ }
+}
diff --git a/tests/assets/views/view_complex.php b/tests/assets/views/view_complex.php
new file mode 100644
index 0000000..e9255eb
--- /dev/null
+++ b/tests/assets/views/view_complex.php
@@ -0,0 +1,22 @@
+@css(test1.css)
+@js(test1.js)
+@js(test2_= $some['expression'] ?>)
+
+@extra
+
+@endextra
+
+@extends(parent)
+
+@section(section1)
+Test HTML with @extends - section 1
+@endsection
+
+@section(section2)
+Test HTML with @extends - section 2
+@endsection
+
+@extra
+
+EXTRA
+@endextra
diff --git a/tests/assets/views/view_invalid_multiple_extends.php b/tests/assets/views/view_invalid_multiple_extends.php
new file mode 100644
index 0000000..f9fea38
--- /dev/null
+++ b/tests/assets/views/view_invalid_multiple_extends.php
@@ -0,0 +1,5 @@
+@extends(parent1)
+
+@extends(parent2)
+
+Test HTML with multiple @extends
diff --git a/tests/assets/views/view_invalid_multiple_sections_open.php b/tests/assets/views/view_invalid_multiple_sections_open.php
new file mode 100644
index 0000000..7832e04
--- /dev/null
+++ b/tests/assets/views/view_invalid_multiple_sections_open.php
@@ -0,0 +1,6 @@
+@extends(parent)
+
+@section(section1)
+@section(section2)
+
+Test HTML with opening @section before previous closed
diff --git a/tests/assets/views/view_invalid_section_not_open.php b/tests/assets/views/view_invalid_section_not_open.php
new file mode 100644
index 0000000..855a336
--- /dev/null
+++ b/tests/assets/views/view_invalid_section_not_open.php
@@ -0,0 +1,4 @@
+@extends(parent)
+
+Test HTML with @endsection when no section is open
+@endsection
diff --git a/tests/assets/views/view_invalid_section_without_extends.php b/tests/assets/views/view_invalid_section_without_extends.php
new file mode 100644
index 0000000..ec143a6
--- /dev/null
+++ b/tests/assets/views/view_invalid_section_without_extends.php
@@ -0,0 +1,3 @@
+@section(section1)
+
+Test HTML with @section but without @extends
diff --git a/tests/assets/views/view_with_assets.php b/tests/assets/views/view_with_assets.php
new file mode 100644
index 0000000..d5076a7
--- /dev/null
+++ b/tests/assets/views/view_with_assets.php
@@ -0,0 +1,4 @@
+@css(test.css)
+@js(test.js)
+@js(test_= $some['expression'] ?>)
+Test HTML with @css and @js
diff --git a/tests/assets/views/view_with_extends.php b/tests/assets/views/view_with_extends.php
new file mode 100644
index 0000000..0c3f301
--- /dev/null
+++ b/tests/assets/views/view_with_extends.php
@@ -0,0 +1,5 @@
+@extends(parent)
+
+@section(section1)
+Test HTML with @extends
+@endsection
diff --git a/tests/assets/views/view_without_extends.php b/tests/assets/views/view_without_extends.php
new file mode 100644
index 0000000..29864cd
--- /dev/null
+++ b/tests/assets/views/view_without_extends.php
@@ -0,0 +1 @@
+Test HTML without @extends
\ No newline at end of file