aboutsummaryrefslogtreecommitdiffstats
path: root/tests/unit/Module/HelpTest.php
blob: 0f1610db591d5bb9c469df0cdae66e382248556c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php
/**
 * SPDX-FileCopyrightText: 2024 Harald Eilertsen
 * SPDX-FileCopyrightText: 2024 Hubzilla Community
 *
 * SPDX-License-Identifier: MIT
 */

class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase {

	use \phpmock\phpunit\PHPMock;

	/**
	 * Define the stubs to make sure they work later in the test.
	 *
	 * @see https://php-mock.github.io/php-mock-phpunit/api/class-phpmock.phpunit.PHPMock.html#_defineFunctionMock
	 *
	 * @beforeClass
	 */
	public static function define_stubs(): void {
		self::defineFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
		self::defineFunctionMock('Zotlabs\Module', 'file_get_contents');
	}

	/**
	 * Test getting a help page when the underlying file exists.
	 *
	 * @testWith
	 *	["md"]
	 *	["bb"]
	 *	["html"]
	 */
	public function test_get_request_when_help_file_exists(string $ext): void {
		// Stub file exists, to only retur true for the file with the current
		// extension
		$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
		$fe_stub
			->expects($this->any())
			->willReturnCallback(
				fn (string $path) => $path === "doc/en/about/help_topic.{$ext}"
			);

		// Use a value map to make the `file_get_contents` stub return the
		// correct content for the file types.
		$file_content_map = [
			[ 'doc/en/about/help_topic.md', "### Help heading\n\$Projectname help content" ],
			[ 'doc/en/about/help_topic.bb', "[h3]Help heading[/h3]\n\n\$Projectname help content" ],
			[ 'doc/en/about/help_topic.html', "<h3>Help heading</h3><p>\$Projectname help content</p>" ],
		];

		// Stub `file_get_contents` to plant our own content.
		$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
		$fgc_stub
			->expects($this->once())
			->willReturn($this->returnValueMap($file_content_map));


		$this->get("help/about/help_topic");

		// Check that markdown content was correctly rendered
		$this->assertPageContains('<h3>Help heading</h3>');

		// Check that `$Projectname` has been translated properly
		$this->assertPageContains('Hubzilla help content');

		// Check that heading has been set
		$this->assertPageContains('Hubzilla Documentation: About');

		// Check that page title has been set
		$this->assertTrue(isset(\App::$page['title']), 'Page title not set');
		$this->assertStringContainsString('Help', \App::$page['title']);
		$this->assertStringContainsStringIgnoringCase('Help Topic', \App::$page['title']);

		// Check that nav selection has been set
		$this->assertTrue(isset(\App::$nav_sel['raw_name']), 'Nav selection raw name not set');
		$this->assertEquals('Help', \App::$nav_sel['raw_name']);

		$this->assertTrue(isset(\App::$nav_sel['name']), 'Navselection name not set');
		$this->assertEquals('Help', \App::$nav_sel['name']);
	}

	public function test_get_request_should_return_404_when_help_file_does_not_exist(): void {
		// Stub file exists, to only retur true for the file with the current
		// extension
		$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
		$fe_stub
			->expects($this->any())
			->willReturn(false);

		// Make sure `file_get_contents` is never called by the code.
		$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
		$fgc_stub->expects($this->never());

		$this->get("help/this_topic_does_not_exist");

		$this->assertPageContains('not found');
	}

	public function test_get_request_without_args_redirects_to_about_page(): void {
		$this->stub_goaway();
		$this->expectException(\Zotlabs\Tests\Unit\Module\RedirectException::class);
		$this->expectExceptionMessage('about/about');

		$this->get('help');
	}

	public function test_find_help_file_returns_first_match(): void {
		// Stub file exists, to always return true
		$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
		$fe_stub
			->expects($this->once())
			->willReturn(true);

		// Stub `file_get_contents` to plant our own content.
		$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
		$fgc_stub
			->expects($this->once())
			->with('doc/en/first.md')
			->willReturn('found');

		$this->get('help/first');
	}

	public function test_includes(): void {
		// Stub `file_get_contents` to plant our own content.
		$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
		$fgc_stub
			->expects($this->any())
			->willReturnCallback(
				function (string $path): string {
					if ($path === 'doc/en/sub.md') {
						return "### This is the included file.";
					} else {
						return "### Main topic\n\n#include doc/en/sub.md;";
					}
				}
			);

		// Stub file exists, to always return true
		$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
		$fe_stub
			->expects($this->any())
			->willReturn(true);

		$this->get('help/main');

		$this->assertPageContains('<h3>This is the included file.</h3>');
	}

	public function test_include_file_of_different_type_than_main_file(): void {
		// Stub `file_get_contents` to plant our own content.
		$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
		$fgc_stub
			->expects($this->any())
			->willReturnCallback(
				function (string $path): string {
					if ($path === 'doc/en/sub.md') {
						return "### This is the included file.";
					} else {
						return "[h3]Main topic[/h3]\n\n#include doc/en/sub.md;";
					}
				}
			);

		// Stub file exists, only return true for main.bb and sub.md
		$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
		$fe_stub
			->expects($this->any())
			->willReturnCallback(
				fn (string $path) => (
					$path === 'doc/en/main.bb' || $path === 'doc/en/sub.md'
				)
			);

		$this->get('help/main');

		$this->assertPageContains('<h3>This is the included file.</h3>');
	}

	/**
	 * Helper to simplify asserting contents in the rendered page.
	 *
	 * @param string $needle	The expected string to find.
	 */
	private function assertPageContains(string $needle): void {
		$this->assertStringContainsString($needle, \App::$page['content']);
	}
}