first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,67 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_wiki\backup;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php");
/**
* Restore date tests.
*
* @package mod_wiki
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_date_test extends \restore_date_testcase {
/**
* Test restore dates.
*/
public function test_restore_dates(): void {
global $DB;
$record = ['editbegin' => 100, 'editend' => 100, 'timemodified' => 100];
list($course, $wiki) = $this->create_course_and_module('wiki', $record);
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$page = $wikigenerator->create_first_page($wiki);
$version = $DB->get_record('wiki_versions', ['pageid' => $page->id, 'version' => 1]);
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course);
$newwiki = $DB->get_record('wiki', ['course' => $newcourseid]);
$this->assertFieldsNotRolledForward($wiki, $newwiki, ['timecreated', 'timemodified']);
$props = ['editend', 'editbegin'];
$this->assertFieldsRolledForward($wiki, $newwiki, $props);
$newsubwiki = $DB->get_record('wiki_subwikis', ['wikiid' => $newwiki->id]);
$newpage = $DB->get_record('wiki_pages', ['subwikiid' => $newsubwiki->id]);
$newversion = $DB->get_record('wiki_versions', ['pageid' => $newpage->id, 'version' => 1]);
// Wiki page time checks.
$this->assertEquals($page->timecreated, $newpage->timecreated);
$this->assertEquals($page->timemodified, $newpage->timemodified);
$this->assertEquals($page->timerendered, $newpage->timerendered);
// Wiki version time checks.
$this->assertEquals($version->timecreated, $newversion->timecreated);
}
}
@@ -0,0 +1,80 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_wiki\backup;
/**
* Unit tests for wiki restoration process
*
* @package mod_wiki
* @copyright 2024 Laurent David <laurent.david@moodle.com>
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_format_test extends \advanced_testcase {
/**
* Data provider for test_duplicating_wiki_removes_unwanted_formats.
*
* @return array[]
*/
public static function restore_format_test_provider(): array {
return [
'creole' => [
'data' => 'creole',
'expected' => 'creole',
],
'html' => [
'data' => 'html',
'expected' => 'html',
],
'wikimarkup' => [
'data' => 'nwiki',
'expected' => 'nwiki',
],
'wrong format' => [
'data' => '../wrongformat123',
'expected' => 'wrongformat',
],
];
}
/**
* Test that duplicating a wiki removes unwanted / invalid format.
*
* @param string $format The format of the wiki.
* @param string $expected The expected format of the wiki after duplication.
*
* @covers \restore_wiki_activity_structure_step
* @dataProvider restore_format_test_provider
*/
public function test_duplicating_wiki_removes_unwanted_formats(string $format, string $expected): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Make a test course.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$wiki = $generator->create_module('wiki', array_merge(['course' => $course->id, 'defaultformat' => $format]));
// Duplicate the wiki.
$newwikicm = duplicate_module($course, get_fast_modinfo($course)->get_cm($wiki->cmid));
// Verify the settings of the duplicated activity.
$newwiki = $DB->get_record('wiki', ['id' => $newwikicm->instance]);
$this->assertEquals($expected, $newwiki->defaultformat);
}
}
+86
View File
@@ -0,0 +1,86 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Steps definitions related to mod_quiz.
*
* @package mod_wiki
* @category test
* @copyright 2023 Catalyst IT Europe Ltd.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
use Behat\Gherkin\Node\TableNode as TableNode;
use Behat\Mink\Exception\ExpectationException as ExpectationException;
/**
* Steps definitions related to mod_wiki.
*
* @copyright 2023 Catalyst IT Europe Ltd.
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_mod_wiki extends behat_base {
/**
* Add the specified pages to the specified wiki
*
* The first row should be column names:
* | wiki | user | group | title | content |
*
*
* wiki idnumber of the wiki course module
* user username of the user who is creating the page
* group (optional) idnumber of the group the page belongs to
* title (optional) the title text of the page
* content (optional) the content of the page
*
* @param TableNode $data The pages to add
*
* @Given /^the following wiki pages exist:$/
*/
public function the_following_wiki_pages_exist(TableNode $data): void {
global $DB;
$generator = behat_util::get_data_generator()->get_plugin_generator('mod_wiki');
// Add the pages.
foreach ($data->getHash() as $pagedata) {
if (!array_key_exists('wiki', $pagedata)) {
throw new ExpectationException('When adding pages to a wiki, ' .
'the wiki column is required containing the wiki idnumber.', $this->getSession());
}
$wikicm = $this->get_course_module_for_identifier($pagedata['wiki']);
$wiki = $DB->get_record('wiki', ['id' => $wikicm->instance]);
$wiki->cmid = $wikicm->cmid;
$pagedata['wikiid'] = $wiki->id;
unset($pagedata['wiki']);
if (array_key_exists('group', $pagedata)) {
$pagedata['group'] = $DB->get_field('groups', 'id', ['idnumber' => $pagedata['group']], MUST_EXIST);
}
if (array_key_exists('user', $pagedata)) {
$pagedata['userid'] = $DB->get_field('user', 'id', ['username' => $pagedata['user']], MUST_EXIST);
unset($pagedata['user']);
}
$generator->create_page($wiki, $pagedata);
}
}
}
@@ -0,0 +1,67 @@
@mod @mod_wiki
Feature: A teacher can set a wiki to be collaborative or individual
In order to allow both collaborative wikis and individual journals with history register
As a teacher
I need to select whether the wiki is collaborative or individual
@javascript
Scenario: Collaborative and individual wikis
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activities" exist:
| activity | course | name | firstpagetitle | wikimode |
| wiki | C1 | Collaborative wiki name | Collaborative index | collaborative |
| wiki | C1 | Individual wiki name | Individual index | individual |
And I am on the "Collaborative wiki name" "wiki activity" page logged in as teacher1
And I press "Create page"
And I set the following fields to these values:
| HTML format | Collaborative teacher1 edition |
And I press "Save"
And I am on the "Individual wiki name" "wiki activity" page
And I press "Create page"
And I set the following fields to these values:
| HTML format | Individual teacher1 edition |
And I press "Save"
And I am on the "Collaborative wiki name" "wiki activity" page logged in as student1
Then I should see "Collaborative teacher1 edition"
And I select "Edit" from the "jump" singleselect
And I set the following fields to these values:
| HTML format | Collaborative student1 edition |
And I press "Save"
And I should not see "Collaborative teacher1 edition"
And I should see "Collaborative student1 edition"
And I am on the "Individual wiki name" "wiki activity" page
And I should not see "Individual teacher1 edition"
And I press "Create page"
And I set the following fields to these values:
| HTML format | Individual student1 edition |
And I press "Save"
And I am on the "Individual wiki name" "wiki activity" page logged in as student2
And I should not see "Individual teacher1 edition"
And I should not see "Individual student1 edition"
And I press "Create page"
And I set the following fields to these values:
| HTML format | Individual student2 edition |
And I press "Save"
And I am on the "Collaborative wiki name" "wiki activity" page logged in as teacher1
And I should see "Collaborative student1 edition"
And I am on the "Individual wiki name" "wiki activity" page
And I should see "Individual teacher1 edition"
And I should not see "Individual student1 edition"
And I set the field "uid" to "Student 1"
And I should see "Individual student1 edition"
And I should not see "Individual teacher1 edition"
And I set the field "uid" to "Student 2"
And I should see "Individual student2 edition"
And I should not see "Individual teacher1 edition"
+66
View File
@@ -0,0 +1,66 @@
@mod @mod_wiki @core_tag @javascript
Feature: Edited wiki pages handle tags correctly
In order to get wiki pages properly labelled
As a user
I need to introduce the tags while editing
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| course | C1 |
| activity | wiki |
| name | Test wiki name |
| firstpagetitle | First page |
| wikimode | collaborative |
Scenario: Wiki page edition of custom tags works as expected
Given I am on the "Test wiki name" "wiki activity" page logged in as student1
And I press "Create page"
When I set the following fields to these values:
| HTML format | Student page contents to be tagged |
| Tags | Example, Page, Cool |
And I press "Save"
Then I should see "Example" in the ".wiki-tags" "css_element"
And I should see "Page" in the ".wiki-tags" "css_element"
And I should see "Cool" in the ".wiki-tags" "css_element"
And I select "Edit" from the "jump" singleselect
Then I should see "Example" in the ".form-autocomplete-selection" "css_element"
Then I should see "Page" in the ".form-autocomplete-selection" "css_element"
Then I should see "Cool" in the ".form-autocomplete-selection" "css_element"
And I press "Cancel"
@javascript
Scenario: Wiki page edition of standard tags works as expected
Given the following "tags" exist:
| name | isstandard |
| OT1 | 1 |
| OT2 | 1 |
| OT3 | 1 |
And I am on the "Test wiki name" "wiki activity" page logged in as student1
And I press "Create page"
And I open the autocomplete suggestions list
And I should see "OT1" in the ".form-autocomplete-suggestions" "css_element"
And I should see "OT2" in the ".form-autocomplete-suggestions" "css_element"
And I should see "OT3" in the ".form-autocomplete-suggestions" "css_element"
When I set the following fields to these values:
| HTML format | Student page contents to be tagged |
| Tags | OT1, OT3 |
And I press "Save"
Then I should see "OT1" in the ".wiki-tags" "css_element"
And I should see "OT3" in the ".wiki-tags" "css_element"
And I should not see "OT2" in the ".wiki-tags" "css_element"
And I select "Edit" from the "jump" singleselect
And I should see "OT1" in the ".form-autocomplete-selection" "css_element"
And I should see "OT3" in the ".form-autocomplete-selection" "css_element"
And I should not see "OT2" in the ".form-autocomplete-selection" "css_element"
And I press "Cancel"
+63
View File
@@ -0,0 +1,63 @@
@mod @mod_wiki
Feature: A history of each wiki page is available
In order to know how a wiki page evolved over the time and how changed what
As a user
I need to check the history of a wiki page
@javascript
Scenario: Wiki page edition history changes list
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activity" exists:
| course | C1 |
| activity | wiki |
| name | Test wiki name |
| firstpagetitle | First page |
| wikimode | collaborative |
And I am on the "Test wiki name" "wiki activity" page logged in as teacher1
And I press "Create page"
And I set the following fields to these values:
| HTML format | First edition |
And I press "Save"
When I am on the "Test wiki name" "wiki activity" page logged in as student1
And I select "Edit" from the "jump" singleselect
And I set the following fields to these values:
| HTML format | Second edition |
And I press "Save"
When I am on the "Test wiki name" "wiki activity" page logged in as student2
And I select "Edit" from the "jump" singleselect
And I set the following fields to these values:
| HTML format | Third edition |
And I press "Save"
And I select "History" from the "jump" singleselect
# Checking that there are 3 history items (the first one is are th)
And "//*[@id='region-main']/descendant::table/descendant::tr[4]" "xpath_element" should exist
And I click on "1" "link" in the "Teacher 1" "table_row"
And I should see "First edition"
And I should see "Teacher 1"
And I follow "Back"
And I click on "2" "link" in the "Student 1" "table_row"
And I should see "Second edition"
And I should see "Student 1"
And I follow "Back"
And I click on "3" "link" in the "Student 2" "table_row"
And I should see "Third edition"
And I should see "Student 2" in the "region-main" "region"
And I follow "Back"
And I click on "comparewith" "radio" in the "Student 1" "table_row"
And I click on "compare" "radio" in the "Teacher 1" "table_row"
And I press "Compare selected"
And I should see "Comparing version 1 with version 3"
And I follow "Next"
And I should see "Comparing version 2 with version 3"
+43
View File
@@ -0,0 +1,43 @@
@mod @mod_wiki
Feature: Edited wiki pages may be previewed before saving
In order to avoid silly mistakes
As a user
I need to preview pages before saving changes
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Test wiki name |
| wikimode | collaborative |
And I am on the "Test wiki name" "wiki activity" page logged in as student1
When I press "Create page"
And I set the following fields to these values:
| HTML format | Student page contents to be previewed |
And I press "Preview"
Then I expand all fieldsets
And I should see "This is a preview. Changes have not been saved yet"
And I should see "Student page contents to be previewed"
And I press "Save"
And I should see "Student page contents to be previewed"
And I select "Edit" from the "jump" singleselect
@javascript
Scenario: Page contents preview before saving with Javascript enabled
Then the field "HTML format" matches value "Student page contents to be previewed"
And I press "Cancel"
Scenario: Page contents preview before saving with Javascript disabled
Then the field "HTML format" matches value "Student page contents to be previewed"
And I press "Cancel"
@@ -0,0 +1,93 @@
@mod @mod_wiki @javascript @_file_upload
Feature: Teachers can reset wiki pages, tags and files
In order to remove wiki pages, tags and files
As a teacher
I need to be able to reset the pages, tags and files on the course level
Background: Create a wiki, add a page, tag and file, and reset them
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Test wiki name |
| wikimode | collaborative |
And I am on the "Test wiki name" "wiki activity" page logged in as teacher1
And I press "Create page"
And I set the following fields to these values:
| HTML format | Test wiki content |
| Tags | Test tag 1, Test tag 2, |
And I press "Save"
And I should see "Test tag 1" in the ".wiki-tags" "css_element"
And I should see "Test tag 2" in the ".wiki-tags" "css_element"
And I select "Comments" from the "jump" singleselect
And I follow "Add comment"
And I set the following fields to these values:
| Comment | Test comment |
And I press "Save changes"
And I should see "Test comment"
And I select "Files" from the "jump" singleselect
And I press "Edit wiki files"
And I upload "lib/tests/fixtures/empty.txt" file to "Files" filemanager
And I press "Save changes"
And I should see "empty.txt"
And I am on the "Course 1" "reset" page
Scenario: Reset page, tags and files
Given I set the following fields to these values:
| Delete all wiki pages | 1 |
| Remove all wiki tags | 1 |
| reset_wiki_comments | 1 |
And I press "Reset course"
And I should see "Delete all wiki pages"
And I should see "Wiki tags have been deleted"
And I should see "Delete all comments"
And I press "Continue"
And I am on the "Test wiki name" "wiki activity" page
And I press "Create page"
When I select "View" from the "jump" singleselect
Then I should not see "Test tag 1"
And I should not see "Test tag 2"
And I select "Comments" from the "jump" singleselect
And I should not see "Test comment"
And I select "Files" from the "jump" singleselect
And I should not see "empty.txt"
Scenario: Reset only tags
Given I set the following fields to these values:
| Remove all wiki tags | 1 |
When I press "Reset course"
And I should not see "Delete all wiki pages"
And I should see "Wiki tags have been deleted"
And I should not see "Delete all comments"
And I press "Continue"
And I am on the "Test wiki name" "wiki activity" page
Then I should not see "Test tag 1"
And I should not see "Test tag 2"
And I select "Comments" from the "jump" singleselect
And I should see "Test comment"
And I select "Files" from the "jump" singleselect
And I should see "empty.txt"
Scenario: Reset only comments
Given I set the following fields to these values:
| reset_wiki_comments | 1 |
When I press "Reset course"
And I should not see "Delete all wiki pages"
And I should not see "Wiki tags have been deleted"
And I should see "Delete all comments"
And I press "Continue"
And I am on the "Test wiki name" "wiki activity" page
Then I should see "Test tag 1"
And I should see "Test tag 2"
And I select "Comments" from the "jump" singleselect
And I should not see "Test comment"
And I select "Files" from the "jump" singleselect
And I should see "empty.txt"
@@ -0,0 +1,62 @@
@mod @mod_wiki @core_completion
Feature: View activity completion information in the Wiki activity
In order to have visibility of wiki completion requirements
As a student
I need to be able to view my wiki completion progress
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Vinnie | Student1 | student1@example.com |
| teacher1 | Darrell | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | enablecompletion | showcompletionconditions |
| Course 1 | C1 | 1 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
And the following "activity" exists:
| activity | wiki |
| course | C1 |
| idnumber | mh1 |
| name | Music history |
| completion | 2 |
| completionview | 1 |
And I am on the "Music history" "wiki activity" page logged in as teacher1
And I click on "Create page" "button"
Scenario: View automatic completion items as a teacher and confirm all tabs display conditions
When I am on the "Music history" "wiki activity" page logged in as teacher1
Then "Music history" should have the "View" completion condition
And I select "Edit" from the "jump" singleselect
And "Music history" should have the "View" completion condition
And I select "Comments" from the "jump" singleselect
And "Music history" should have the "View" completion condition
And I select "Map" from the "jump" singleselect
And "Music history" should have the "View" completion condition
And I select "Files" from the "jump" singleselect
And "Music history" should have the "View" completion condition
And I select "Administration" from the "jump" singleselect
And "Music history" should have the "View" completion condition
Scenario: View automatic completion items as a student
When I am on the "Music history" "wiki activity" page logged in as student1
Then the "View" completion condition of "Music history" is displayed as "done"
@javascript
Scenario: Use manual completion
Given I am on the "Music history" "wiki activity" page logged in as teacher1
And I am on the "Music history" "wiki activity editing" page
And I expand all fieldsets
And I press "Unlock completion settings"
And I expand all fieldsets
And I set the field "Students must manually mark the activity as done" to "1"
And I press "Save and display"
# Teacher view.
And the manual completion button for "Music history" should be disabled
# Student view.
When I am on the "Music history" "wiki activity" page logged in as student1
Then the manual completion button of "Music history" is displayed as "Mark as done"
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
@@ -0,0 +1,65 @@
@mod @mod_wiki
Feature: Users can comment on wiki pages
In order to discuss wiki pages
As a user
I need to be able to comment on wiki pages as well as editing and deleting comments
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Test wiki name |
| firstpagetitle | First page |
| wikimode | collaborative |
And I am on the "Test wiki name" "wiki activity" page logged in as teacher1
And I press "Create page"
And I set the following fields to these values:
| HTML format | First edition |
And I press "Save"
And I am on the "Test wiki name" "wiki activity" page logged in as student1
And I select "Comments" from the "jump" singleselect
And I follow "Add comment"
And I set the following fields to these values:
| Comment | student 1 original comment |
And I press "Save"
And I wait to be redirected
@javascript
Scenario: Student can edit and delete their own comment
When I click on "Edit" "link" in the "wiki-comments" "table"
And I set the following fields to these values:
| Comment | student 1 updated comment |
And I press "Save"
Then I should see "student 1 updated comment"
And "Edit" "link" should exist in the "wiki-comments" "table"
And "Delete" "link" should exist in the "wiki-comments" "table"
And I click on "Delete" "link" in the "wiki-comments" "table"
And I press "Continue"
And I should not see "student 1 updated comment"
@javascript
Scenario: Student cannot edit another student's comment
When I am on the "Test wiki name" "wiki activity" page logged in as student2
And I select "Comments" from the "jump" singleselect
Then "Edit" "link" should not exist in the "wiki-comments" "table"
And "Delete" "link" should not exist in the "wiki-comments" "table"
@javascript
Scenario: Teacher can delete a student comment
When I am on the "Test wiki name" "wiki activity" page logged in as teacher1
And I select "Comments" from the "jump" singleselect
Then "Edit" "link" should not exist in the "wiki-comments" "table"
And "Delete" "link" should exist in the "wiki-comments" "table"
+73
View File
@@ -0,0 +1,73 @@
@mod @mod_wiki
Feature: There is a choice of formats for editing a wiki page
In order to allow users to use their favorite wiki format
As a user
I need to choose which wiki format do I want to use
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Test wiki name |
| wikimode | collaborative |
| firstpagetitle | First page |
And I am on the "Test wiki name" "wiki activity" page logged in as teacher1
@javascript
Scenario: Creole format
When I set the following fields to these values:
| Creole format | 1 |
And I press "Create page"
Then "div.wikieditor-toolbar" "css_element" should exist
# Click on bold, italic, interal link and H1
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[1]" "xpath_element"
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[2]" "xpath_element"
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[4]" "xpath_element"
And the field "newcontent" matches value "**Bold text**//Italic text//[[Internal link]]"
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[8]" "xpath_element"
And I press "Save"
And I should see "Bold textItalic textInternal link"
And I should see "Level 1 Header"
And I should see "Table of contents"
And I click on "Level 1 Header" "link" in the ".wiki-toc" "css_element"
And I follow "Internal link"
And I should see "New page title"
@javascript
Scenario: NWiki format
When I set the following fields to these values:
| NWiki format | 1 |
And I press "Create page"
Then "div.wikieditor-toolbar" "css_element" should exist
# Click on italic, interal link and H1
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[2]" "xpath_element"
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[4]" "xpath_element"
And the field "newcontent" matches value "'''Italic text'''[[Internal link]]"
And I click on "//div[@class='wikieditor-toolbar']/descendant::a[8]" "xpath_element"
And I press "Save"
And I should see "Italic textInternal link"
And I should see "Level 1 Header"
And I should see "Table of contents"
And I click on "Level 1 Header" "link" in the ".wiki-toc" "css_element"
And I follow "Internal link"
And I should see "New page title"
@javascript
Scenario: HTML format
When I set the following fields to these values:
| HTML format | 1 |
And I press "Create page"
Then "#id_newcontent_editor" "css_element" should exist
And I set the following fields to these values:
| HTML format | I'm a text |
And I press "Save"
And I should see "I'm a text"
+112
View File
@@ -0,0 +1,112 @@
@mod @mod_wiki
Feature: Groups can have separate content on a wiki
In order to create a wiki with my group
As a user
I need to view and add wiki pages by group
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student1@example.com |
| student4 | Student | 4 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
Given the following "groups" exist:
| name | course | idnumber | participation |
| Group 1 | C1 | G1 | 1 |
| Group 2 | C1 | G2 | 1 |
| Group 3 | C1 | G3 | 0 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
| student3 | G3 |
And the following "activities" exist:
| activity | course | name | idnumber | wikimode | firstpagetitle | groupmode |
| wiki | C1 | Separate wiki | wiki1 | collaborative | Separate page 1 | 1 |
| wiki | C1 | Visible wiki | wiki2 | collaborative | Visible page 1 | 2 |
And the following wiki pages exist:
| wiki | title | content | group |
| wiki1 | Separate page 1 | Group 1 page | G1 |
| wiki1 | Separate page 1 | Group 2 page | G2 |
| wiki2 | Visible page 1 | Group 1 page | G1 |
| wiki2 | Visible page 1 | Group 2 page | G2 |
And the following wiki pages exist:
| wiki | title | content |
| wiki1 | Separate page 1 | No group page |
| wiki2 | Visible page 1 | No group page |
Scenario Outline: Teacher can see all participation group wikis
Given I am on the "<wiki>" "wiki activity" page logged in as teacher1
And I should see "All participants" in the "<mode> groups" "select"
And I should see "Group 1" in the "<mode> groups" "select"
And I should see "Group 2" in the "<mode> groups" "select"
And I should not see "Group 3" in the "<mode> groups" "select"
And I should see "No group page"
And I should not see "Group 1 page"
And I should not see "Group 2 page"
When I select "Group 1" from the "<mode> groups" singleselect
Then I should not see "No group page"
And I should see "Group 1 page"
And I should not see "Group 2 page"
Examples:
| wiki | mode |
| wiki1 | Separate |
| wiki2 | Visible |
Scenario Outline: Teacher can add a page to any participation group's wiki
Given I am on the "<wiki>" "wiki activity" page logged in as teacher1
And I select "Edit" from the "jump" singleselect
And I set the field "HTML format" to "[[Internal link]]"
And I press "Save"
When I follow "Internal link"
And I should see "New page"
Then I should see "All participants" in the "Group" "select"
And I should see "Group 1" in the "Group" "select"
And I should see "Group 2" in the "Group" "select"
And I should not see "Group 3" in the "Group" "select"
Examples:
| wiki |
| wiki1 |
| wiki2 |
Scenario Outline: Students should only see their participation groups' own wiki in separate groups mode
Given I am on the "wiki1" "wiki activity" page logged in as <user>
Then I should see "Separate groups: <group>"
And "Separate groups" "select" should not exist
And I should see "<page>"
Examples:
| user | group | page |
| student1 | Group 1 | Group 1 page |
| student2 | Group 2 | Group 2 page |
# The view page throws an exception if the user is not in a group, so we cannot test
# student3 and student4.
Scenario Outline: Students can see all participation groups' own wikis in visible groups mode
Given I am on the "wiki2" "wiki activity" page logged in as <user>
And I should see "All participants" in the "Visible groups" "select"
And I should see "Group 1" in the "Visible groups" "select"
And I should see "Group 2" in the "Visible groups" "select"
And I should not see "Group 3" in the "Visible groups" "select"
And I should see "<page>"
Examples:
| user | page |
| student1 | Group 1 page |
| student2 | Group 2 page |
| student3 | Group 1 page |
| student4 | Group 1 page |
+158
View File
@@ -0,0 +1,158 @@
@mod @mod_wiki
Feature: Users can search wikis
In order to find information in wiki
As a user
I need to be able to search individual and collaborative wikis
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
@javascript
Scenario: Searching collaborative wiki
Given the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Collaborative wiki name |
| wikimode | collaborative |
| firstpagetitle | First page |
And I am on the "Collaborative wiki name" "wiki activity" page logged in as teacher1
And I press "Create page"
And I set the following fields to these values:
| HTML format | Collaborative teacher1 page [[new page]] |
And I press "Save"
And I am on the "Collaborative wiki name" "wiki activity" page logged in as student1
And I follow "new page"
And I press "Create page"
And I set the following fields to these values:
| HTML format | New page created by student1 |
And I press "Save"
When I set the field "searchstring" to "page"
And I press "Search wikis"
Then I should see "New page created by student1"
And I should see "Collaborative teacher1 page"
And I set the field "searchstring" to "teacher1"
And I press "Search wikis"
And I should not see "New page created by student1"
And I should see "Collaborative teacher1 page"
And I set the field "searchstring" to "teacher1 page"
And I press "Search wikis"
And I should not see "New page created by student1"
And I should see "Collaborative teacher1 page"
@javascript
Scenario: Searching individual wiki
Given the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Individual wiki name |
| wikimode | individual |
| firstpagetitle | First page |
And I am on the "Individual wiki name" "wiki activity" page logged in as teacher1
And I press "Create page"
And I set the following fields to these values:
| HTML format | Individual teacher1 page |
And I press "Save"
And I am on the "Individual wiki name" "wiki activity" page logged in as student1
And I press "Create page"
And I set the following fields to these values:
| HTML format | Individual student1 page |
And I press "Save"
When I set the field "searchstring" to "page"
And I press "Search wikis"
Then I should see "Individual student1 page"
And I should not see "Individual teacher1 page"
And I am on the "Individual wiki name" "wiki activity" page logged in as student2
And I press "Create page"
And I set the following fields to these values:
| HTML format | Individual student2 page |
And I press "Save"
And I set the field "searchstring" to "page"
And I press "Search wikis"
And I should see "Individual student2 page"
And I should not see "Individual student1 page"
And I should not see "Individual teacher1 page"
And I am on the "Individual wiki name" "wiki activity" page logged in as teacher1
And I set the field "searchstring" to "page"
And I press "Search wikis"
And I should see "Individual teacher1 page"
And I should not see "Individual student1 page"
And I should not see "Individual student2 page"
And I set the field "uid" to "Student 1"
And I should not see "Individual teacher1 page"
And I should see "Individual student1 page"
And I should not see "Individual student2 page"
And I set the field "uid" to "Student 2"
And I should not see "Individual teacher1 page"
And I should not see "Individual student1 page"
And I should see "Individual student2 page"
@javascript
Scenario: Searching group wiki
Given the following "groups" exist:
| name | course | idnumber |
| Group1 | C1 | G1 |
| Group2 | C1 | G2 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
Given the following "activity" exists:
| activity | wiki |
| course | C1 |
| name | Group wiki name |
| wikimode | collaborative |
| firstpagetitle | Groups pag |
| groupmode | 1 |
And I am on the "Group wiki name" "wiki activity" page logged in as teacher1
And I set the field "Group" to "All participants"
And I press "Create page"
And I set the following fields to these values:
| HTML format | All participants teacher1 page |
And I press "Save"
And I set the field "group" to "Group1"
And I press "Create page"
And I set the following fields to these values:
| HTML format | Group1 teacher1 page [[new page1]] |
And I press "Save"
And I set the field "group" to "Group2"
And I press "Create page"
And I set the following fields to these values:
| HTML format | Group2 teacher1 page [[new page2]] |
And I press "Save"
And I am on the "Group wiki name" "wiki activity" page logged in as student1
And I follow "new page1"
And I press "Create page"
And I set the following fields to these values:
| HTML format | Group1 student1 new page |
And I press "Save"
When I set the field "searchstring" to "page"
And I press "Search wikis"
Then I should see "Group1 teacher1 page"
And I should not see "Group2 teacher1 page"
And I should see "Group1 student1 new page"
And I should not see "All participants teacher1 page"
And I am on the "Group wiki name" "wiki activity" page logged in as student2
And I follow "new page2"
And I press "Create page"
And I set the following fields to these values:
| HTML format | Group2 student2 new page |
And I press "Save"
And I set the field "searchstring" to "page"
And I press "Search wikis"
And I should not see "Group1 teacher1 page"
And I should see "Group2 teacher1 page"
And I should not see "Group1 student1 new page"
And I should not see "All participants teacher1 page"
And I should see "Group2 student2 new page"
+528
View File
@@ -0,0 +1,528 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Events tests.
*
* @package mod_wiki
* @category phpunit
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_wiki\event;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot.'/mod/wiki/locallib.php');
/**
* Events tests class.
*
* @package mod_wiki
* @category phpunit
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class events_test extends \advanced_testcase {
private $course;
private $wiki;
private $wikigenerator;
private $student;
private $teacher;
/**
* Setup test data.
*/
public function setUp(): void {
global $DB;
$this->resetAfterTest();
// Create course and wiki.
$this->course = $this->getDataGenerator()->create_course();
$this->wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $this->course->id));
$this->wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
// Create student and teacher in course.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
$this->student = $this->getDataGenerator()->create_user();
$this->teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $teacherrole->id);
$this->setAdminUser();
}
/**
* Test comment_created event.
*/
public function test_comment_created(): void {
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
wiki_add_comment($context, $page->id, 'Test comment', $this->wiki->defaultformat);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\comment_created', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->other['itemid']);
$this->assertEventContextNotUsed($event);
}
/**
* Test comment_deleted event.
*/
public function test_comment_deleted(): void {
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
// Add comment so we can delete it later.
wiki_add_comment($context, $page->id, 'Test comment', 'html');
$comment = wiki_get_comments($context->id, $page->id);
$this->assertCount(1, $comment);
$comment = array_shift($comment);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
wiki_delete_comment($comment->id, $context, $page->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\comment_deleted', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->other['itemid']);
$this->assertEventContextNotUsed($event);
}
/**
* Test comment_viewed event.
*/
public function test_comment_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id
);
$event = \mod_wiki\event\comments_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\comments_viewed', $event);
$this->assertEquals($context, $event->get_context());
}
/**
* Test instances_list_viewed event.
*/
public function test_course_module_instance_list_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$context = \context_course::instance($this->course->id);
$params = array('context' => $context);
$event = \mod_wiki\event\course_module_instance_list_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\course_module_instance_list_viewed', $event);
$this->assertEquals($context, $event->get_context());
}
/**
* Test course_module_viewed event.
*/
public function test_course_module_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $this->wiki->id
);
$event = \mod_wiki\event\course_module_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($this->wiki->id, $event->objectid);
}
/**
* Test page_viewed event.
*/
public function test_page_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id
);
$event = \mod_wiki\event\page_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
}
/**
* Test page_viewed event for prettypage view.
*/
public function test_pretty_page_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id,
'other' => array('prettyview' => true)
);
$event = \mod_wiki\event\page_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
}
/**
* Test page_created event.
*/
public function test_page_created(): void {
global $USER;
$this->setUp();
$context = \context_module::instance($this->wiki->cmid);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$page = $this->wikigenerator->create_first_page($this->wiki);
$events = $sink->get_events();
$this->assertCount(2, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_created', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
}
/**
* Test page_deleted and page_version_deleted and page_locks_deleted event.
*/
public function test_page_deleted(): void {
global $DB;
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$oldversions = $DB->get_records('wiki_versions', array('pageid' => $page->id));
$oldversion = array_shift($oldversions);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
wiki_delete_pages($context, array($page->id));
$events = $sink->get_events();
$this->assertCount(4, $events);
$event = array_shift($events);
// Checking that the event contains the page_version_deleted event.
$this->assertInstanceOf('\mod_wiki\event\page_version_deleted', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->other['pageid']);
$this->assertEquals($oldversion->id, $event->objectid);
// Checking that the event contains the page_deleted event.
$event = array_pop($events);
$this->assertInstanceOf('\mod_wiki\event\page_deleted', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
// Checking that the event contains the expected values.
$event = array_pop($events);
$this->assertInstanceOf('\mod_wiki\event\page_locks_deleted', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
// Delete all pages.
$page1 = $this->wikigenerator->create_first_page($this->wiki);
$page2 = $this->wikigenerator->create_content($this->wiki);
$page3 = $this->wikigenerator->create_content($this->wiki, array('title' => 'Custom title'));
// Triggering and capturing the event.
$sink = $this->redirectEvents();
wiki_delete_pages($context, array($page1->id, $page2->id));
$events = $sink->get_events();
$this->assertCount(8, $events);
$event = array_pop($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_deleted', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page2->id, $event->objectid);
}
/**
* Test page_updated event.
*/
public function test_page_updated(): void {
global $USER;
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
wiki_save_page($page, 'New content', $USER->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_updated', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
}
/**
* Test page_diff_viewed event.
*/
public function test_page_diff_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id,
'other' => array(
'comparewith' => 1,
'compare' => 2
)
);
$event = \mod_wiki\event\page_diff_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_diff_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
}
/**
* Test page_history_viewed event.
*/
public function test_page_history_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id
);
$event = \mod_wiki\event\page_history_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_history_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
}
/**
* Test page_map_viewed event.
*/
public function test_page_map_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id,
'other' => array(
'option' => 0
)
);
$event = \mod_wiki\event\page_map_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_map_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
$this->assertEquals(0, $event->other['option']);
}
/**
* Test page_version_viewed event.
*/
public function test_page_version_viewed(): void {
// There is no proper API to call or trigger this event, so simulating event
// to check if event returns the right information.
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$params = array(
'context' => $context,
'objectid' => $page->id,
'other' => array(
'versionid' => 1
)
);
$event = \mod_wiki\event\page_version_viewed::create($params);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_version_viewed', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($page->id, $event->objectid);
$this->assertEquals(1, $event->other['versionid']);
}
/**
* Test page_version_restored event.
*/
public function test_page_version_restored(): void {
$this->setUp();
$page = $this->wikigenerator->create_first_page($this->wiki);
$context = \context_module::instance($this->wiki->cmid);
$version = wiki_get_current_version($page->id);
// Triggering and capturing the event.
$sink = $this->redirectEvents();
wiki_restore_page($page, $version, $context);
$events = $sink->get_events();
$this->assertCount(2, $events);
$event = array_pop($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_version_restored', $event);
$this->assertEquals($context, $event->get_context());
$this->assertEquals($version->id, $event->objectid);
$this->assertEquals($page->id, $event->other['pageid']);
}
}
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
Donec semper, nunc nec imperdiet lacinia, dui magna gravida odio, ut pretium nisl sapien ut lacus. Pellentesque nec pede. Praesent condimentum. Aliquam porttitor mi ut odio! Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed laoreet mauris vitae tellus. Curabitur dignissim. Duis ac leo. Nam gravida pharetra sapien. Sed feugiat lobortis orci. Cras sed nisl. Curabitur congue mollis erat. Quisque dictum! Praesent a lectus. Pellentesque nulla nisi; tempus eget, tincidunt id; tincidunt vel, nisl.
Duis consequat vulputate felis. Praesent diam nisi, venenatis vitae; dignissim quis, feugiat ut, pede. Maecenas tincidunt iaculis elit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed sed nulla at eros mollis tempor. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam bibendum lorem at sem. Morbi blandit. Nullam volutpat mi. Suspendisse dapibus lacus vel nisl. Ut lacinia adipiscing mi! Maecenas ipsum erat, accumsan quis, cursus ut, ultrices in; metus. Nulla adipiscing rhoncus ante? Nulla hendrerit tortor sit amet mauris. Cras varius dui vel leo. Proin vulputate! Phasellus lacus arcu, eleifend a, accumsan at, vulputate sed, neque. Fusce leo ante, interdum ac, tincidunt non, scelerisque eu, velit. Suspendisse sed nunc. Aenean sodales turpis!
Suspendisse fringilla fermentum sem. Integer viverra dui id dolor! Mauris ornare eros vel nunc. Phasellus ligula nulla, vestibulum eget, vestibulum vel, aliquam eget, eros. Integer in pede. Fusce ultricies viverra ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque eget lorem ut mi vestibulum facilisis. Vestibulum augue. Curabitur arcu pede, fringilla eu, placerat id, condimentum sit amet, lectus. Fusce at diam eu justo semper interdum. Vivamus id turpis at justo tempus tempor. Maecenas eros libero, bibendum non, dictum ut, blandit id, augue. Pellentesque facilisis. Aenean aliquet sem. In tellus!
+19
View File
@@ -0,0 +1,19 @@
= Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Phasellus odio? Ut ac leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus enim justo, porttitor at, lacinia vitae; consectetuer et, ante? Maecenas eget libero. Duis est. Curabitur tincidunt dictum ligula. Nunc euismod lectus quis mi. Proin et enim sed nunc scelerisque posuere. Suspendisse enim purus, sodales non, tristique vel, sollicitudin ullamcorper, nulla. Aliquam condimentum; tellus eu vulputate facilisis, ante pede rhoncus elit, vel euismod nulla sapien et metus?
== Praesent tristique facilisis metus. ==
Quisque lectus? Morbi ultrices ultricies neque. In ligula sem; pretium eget, iaculis laoreet, pulvinar sed, dui. Proin mattis luctus diam. Aenean eget risus in mauris sagittis vehicula. Vivamus dapibus enim ac dolor. Pellentesque leo. Praesent tristique facilisis metus. Nulla imperdiet ante et urna? Maecenas leo nisi, lacinia sollicitudin, viverra at, aliquet et, justo. Quisque congue dolor.
=== Phasellus ut augue ut felis porttitor condimentum. ===
Aliquam erat volutpat. Phasellus ut augue ut felis porttitor condimentum. Nam sapien tellus, tempus sed; mattis quis, viverra quis, mauris. Suspendisse venenatis sollicitudin massa. Pellentesque lobortis dolor vitae nisl. Nulla interdum aliquet neque. Duis nisl pede, vestibulum in, tristique eget, viverra vitae, erat. Maecenas justo turpis, convallis sit amet, tristique eu, laoreet et, augue. Fusce sem. Pellentesque ut turpis? Morbi suscipit sollicitudin metus? Morbi pharetra, sem eget ornare tempor, neque erat dapibus lacus, ut tincidunt nisi leo sed nunc. Sed sodales dignissim eros. Duis vitae risus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed lobortis consequat sem. Nunc posuere vulputate velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vestibulum pellentesque neque.
==== Sed adipiscing dui at massa. Nulla consectetuer tristique lacus? ====
Maecenas lacus justo, pellentesque vitae, mattis vitae, rutrum sit amet, metus! Etiam aliquam odio vel nulla. Suspendisse ante. Pellentesque viverra leo at lorem! Ut pharetra egestas ante. Aliquam erat volutpat. Sed adipiscing dui at massa. Nulla consectetuer tristique lacus? Donec ante leo, condimentum non, consectetuer vel, sodales placerat, tortor. Etiam at diam at elit adipiscing ultrices. Etiam lectus sapien, congue sed, sodales quis, ultricies a, libero. Pellentesque tincidunt!
== Curabitur euismod sollicitudin nibh
Curabitur euismod sollicitudin nibh. Duis nec diam. Sed nunc quam, lobortis nec; tristique et, dignissim eget, massa. Suspendisse sagittis malesuada tortor. Nullam lectus diam, mollis id, malesuada at, gravida ut, nisl. In hac habitasse platea dictumst. Sed a purus. Etiam velit urna, lacinia et, imperdiet quis, varius quis, orci! Sed dolor ante, mollis in, ultrices in, vestibulum vitae; justo. Vestibulum accumsan vehicula risus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus sit amet diam lobortis urna tristique pretium. Quisque erat.
==== Duis nec diam.
Pellentesque lobortis dolor vitae nisl. Nulla interdum aliquet neque. Duis nisl pede, vestibulum in, tristique eget, viverra vitae, erat. Maecenas justo turpis, convallis sit amet, tristique eu, laoreet et, augue. Fusce sem. Pellentesque ut turpis? Morbi suscipit sollicitudin metus? Morbi pharetra, sem eget ornare tempor, neque erat dapibus lacus, ut tincidunt nisi leo sed nunc. Sed sodales dignissim eros. Duis vitae risus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed lobortis consequat sem. Nunc posuere vulputate velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vestibulum pellentesque neque.
+8
View File
@@ -0,0 +1,8 @@
= In nisi purus, varius in, mollis eget, interdum in, ipsum.
Vivamus lobortis. **Mauris dui dui, rutrum in, egestas nec, porttitor vehicula, risus!** Vivamus aliquam ultrices metus. //Donec ultricies, metus eget volutpat condimentum;// neque orci mattis dolor, non posuere eros dui et orci. Duis aliquam. Fusce sit amet nisl. Duis tempor dapibus diam? In venenatis congue mi? Aliquam metus erat; facilisis a, suscipit a, pretium vitae; ligula? Ut id metus a pede adipiscing commodo! **Praesent ultricies urna et sapien.** //Donec adipiscing.// Donec sit amet lacus.
== **In nisi purus**, //varius in,// mollis eget, interdum in, ipsum.
Duis feugiat ligula ac elit. %!34%!Nulla sed arcu a risus sodales mattis. Etiam magna arcu, accumsan vitae, sodales non, faucibus quis, nunc. Aenean ut elit. Pellentesque malesuada lacus a orci. Suspendisse in erat sed mi porta faucibus. Nullam a nibh. Suspendisse potenti. Nam malesuada lobortis nibh. Ut venenatis, nibh ac convallis iaculis, justo pede tristique sapien, vel ultricies massa diam id leo. Pellentesque ullamcorper condimentum urna. //Proin dui lacus; scelerisque nec, condimentum non, **lobortis ac, felis.
//Nullam ac neque. %!4%!**Praesent quis tellus. **Maecenas** et felis vitae lectus porttitor dignissim. Etiam at dui id nibh molestie semper. Sed vulputate nunc et neque. Fusce consectetur elit id leo. //Nulla facilisi. //Donec vitae nulla ac nisl mollis blandit. //Nulla adipiscing.** Phasellus quis odio sed eros viverra sodales. Suspendisse eget mauris id urna convallis fringilla. Aliquam dolor. Sed commodo. Quisque vestibulum, eros in mollis rutrum, odio risus aliquam turpis; nec convallis ante justo in dui? Pellentesque pharetra venenatis odio. Nulla placerat, libero at lacinia pellentesque; nisi massa sodales risus, at tincidunt orci pede sed ipsum. Etiam massa! Nullam aliquet justo at erat placerat convallis.
+10
View File
@@ -0,0 +1,10 @@
== Donec ultricies neque eu libero scelerisque feugiat.
**Donec ultricies //neque eu [[libero]] scelerisque //feugiat. //Cras sed ante.// Sed volutpat urna eu diam. Curabitur fringilla lacinia mi.** Quisque lorem. Etiam fringilla consequat dui. Nunc est est; aliquet eu, porttitor auctor; malesuada id, massa. [[Nullam|Nullam feugiat]], nulla eget vulputate facilisis, erat odio vestibulum mi, eget volutpat lorem enim vitae eros. Vestibulum convallis. Maecenas posuere pellentesque mi? Donec consectetur volutpat dolor. [[**Curabitur**]] non **[[//Tellus**|tellus nec ligula bibendum pulvinar.]]**
http://www.google.com
[[http://www.google.com]]
~http://www.apple.com
~[[Link que no va]]
+6
View File
@@ -0,0 +1,6 @@
= Integer eu leo? \\ Quisque posuere.
Nunc commodo nisi vitae quam. Etiam tincidunt; lectus eu tempus molestie, elit enim auctor tortor, in varius leo mi ac risus. Sed iaculis magna vel libero. Pellentesque iaculis, tellus in ullamcorper tempus, justo sapien scelerisque enim, eu ornare dui neque sed ligula. \\Vestibulum porta justo a dolor. Duis mollis quam vel sem. Quisque vel arcu. Pellentesque sem. Aliquam adipiscing neque quis turpis. Mauris placerat, elit quis iaculis vehicula, sem nulla imperdiet nunc, in elementum felis lectus non magna. Mauris cursus; odio eu sagittis sodales, nisi nibh pellentesque tortor, ut ultricies lacus tellus non odio. In semper, ligula eu condimentum posuere, sapien tellus blandit quam, dapibus iaculis lacus erat eget ipsum. Duis pulvinar molestie magna. Aliquam bibendum quam ac nulla!
== Fusce justo. Aliquam felis tellus, tempor vel, congue quis, tempus eu, ipsum. \\
\\Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi sed erat! Vivamus condimentum. Praesent euismod; nibh sed mollis feugiat, erat lorem commodo lectus, vitae tristique erat massa semper diam. Morbi vitae elit. \\Quisque sagittis leo non odio auctor faucibus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque mi pede, lacinia id, commodo faucibus, rhoncus in, nibh. Praesent vestibulum aliquet quam!
+18
View File
@@ -0,0 +1,18 @@
Donec sem est, dictum ac, blandit ut, commodo vitae, pede. Proin auctor egestas est. Aliquam fermentum, dui ac malesuada facilisis, mauris felis porttitor turpis, non adipiscing odio mi sit amet felis. Duis dignissim posuere sem. Fusce consequat convallis lectus. Ut suscipit neque sed massa. Etiam suscipit. Sed vitae elit. Nulla non mi. Aliquam risus erat, varius eget, eleifend eget, scelerisque sit amet, enim. Proin venenatis.
* Donec ligula enim
* viverra at
* ultricies rutrum
* volutpat sed
** ligula
** Aenean laoreet tortor at lorem
* Fusce varius nunc quis lacus sodales posuere
** Integer laoreet congue ligula**
* Vestibulum condimentum
**dui ac porta imperdiet**
**Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam accumsan lectus vel sapien. Quisque laoreet lorem non dolor. Ut diam dolor, facilisis non, tempus eu, varius id, nunc. Aliquam sit amet lorem. Cras congue ultricies enim. Nunc vehicula, odio eget volutpat pharetra, leo pede commodo tellus, eu scelerisque erat purus non felis. Sed sed sem eget massa convallis eleifend? Nam tristique. Aliquam justo. Sed risus mi, egestas in, viverra a; tincidunt ac, mauris! Nulla magna. Aenean mauris velit, facilisis ut, condimentum eget, hendrerit ac, sem. Phasellus lorem. Curabitur augue mi; iaculis sit amet, suscipit eget, commodo nec; nibh. Cras pellentesque hendrerit quam. Praesent arcu dui, rhoncus non, feugiat ut, laoreet vitae, velit.**
+4
View File
@@ -0,0 +1,4 @@
= In nisi purus, varius in, mollis eget, interdum in, ipsum.
Vivamus lobortis. **Mauris dui dui, rutrum in, egestas nec, porttitor vehicula, risus!** Vivamus aliquam ultrices metus. //Donec ultricies, metus eget volutpat condimentum;// neque orci mattis dolor, non posuere eros dui et orci. Duis aliquam. Fusce sit amet nisl. Duis tempor dapibus diam? In venenatis congue mi? Aliquam metus erat; facilisis a, suscipit a, pretium vitae; ligula? Ut id metus a pede adipiscing commodo! {{{**Praesent ultricies urna et sapien.** //Donec adipiscing.//}}} Donec sit amet lacus.
{{{ lkdsjflsdjflsdkjflskdjlfk }}}
+28
View File
@@ -0,0 +1,28 @@
== Testing some tables
Phasellus urna erat; venenatis ac, iaculis sed, pretium ut, pede. Suspendisse mauris tellus, rhoncus a, tempor id, mattis non, nibh. Aliquam magna odio; hendrerit at, eleifend sed, dignissim quis, orci. Donec mollis, ante sit amet convallis porta, augue nibh viverra magna, ac scelerisque dui ligula eu felis. Sed eget magna. Proin eget ligula. Vestibulum ornare; sem molestie congue sollicitudin, mi velit porta est, pellentesque dignissim libero est at velit. Donec congue adipiscing massa? Nunc eget nisi eget elit facilisis ornare. Vestibulum et felis id leo feugiat sagittis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed tellus velit, luctus et, tempor non, tempor vitae, magna. Aliquam viverra tortor sit amet tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nibh risus, dictum eu, tempor sit amet, posuere et, nulla.
Well formed table...
|= Name |= Surname |
| George | Washington |
| Abraham | Lincoln |
Not so well formed table
|= Name |= Surname |= Erroneous stuff |
| George | Washington |
| Abraham | Lincoln | Error error |
Bad headers:
| Name |= Surname |
|= George | Washington |
| Abraham |= Lincoln |
Two tables (treated as such) with some format:
|= Name |= Surname |
| **George** | //Washington// |
| Abraham | Lincoln |
+133
View File
@@ -0,0 +1,133 @@
= Top-level heading (1)
== This a test for creole 0.1 (2)
=== This is a Subheading (3)
==== Subsub (4)
===== Subsubsub (5)
The ending equal signs should not be displayed:
= Top-level heading (1) =
== This a test for creole 0.1 (2) ==
=== This is a Subheading (3) ===
==== Subsub (4) ====
===== Subsubsub (5) =====
You can make things **bold** or //italic// or **//both//** or //**both**//.
Character formatting extends across line breaks: **bold,
this is still bold. This line deliberately does not end in star-star.
Not bold. Character formatting does not cross paragraph boundaries.
You can use [[internal links]] or [[http://www.wikicreole.org|external links]],
give the link a [[internal links|different]] name.
Here's another sentence: This wisdom is taken from [[Ward Cunningham's]]
[[http://www.c2.com/doc/wikisym/WikiSym2006.pdf|Presentation at the Wikisym 06]].
Here's a external link without a description: [[http://www.wikicreole.org]]
Be careful that italic links are rendered properly: //[[http://my.book.example/|My Book Title]]//
Free links without braces should be rendered as well, like http://www.wikicreole.org/ and http://www.wikicreole.org/users/~example.
Creole1.0 specifies that http://bar and ftp://bar should not render italic, something like foo://bar should render as italic.//
You can use this to draw a line to separate the page:
----
You can use lists, start it at the first column for now, please...
unnumbered lists are like
* item a
* item b
* **bold item c**
blank space is also permitted before lists like:
* item a
* item b
* item c
** item c.a
or you can number them
# [[item 1]]
# item 2
# // italic item 3 //
## item 3.1
## item 3.2
up to five levels
* 1
** 2
*** 3
**** 4
***** 5
* You can have
multiline list items
* this is a second multiline
list item
You can use nowiki syntax if you would like do stuff like this:
{{{
Guitar Chord C:
||---|---|---|
||-0-|---|---|
||---|---|---|
||---|-0-|---|
||---|---|-0-|
||---|---|---|
}}}
You can also use it inline nowiki {{{ in a sentence }}} like this.
= Escapes =
Normal Link: http://wikicreole.org/ - now same link, but escaped: ~http://wikicreole.org/
Normal asterisks: ~**not bold~**
a tilde alone: ~
a tilde escapes itself: ~~xxx
=== Creole 0.2 ===
This should be a flower with the ALT text "this is a flower" if your wiki supports ALT text on images:
{{Red-Flower.jpg|here is a red flower}}
=== Creole 0.4 ===
Tables are done like this:
|=header col1|=header col2|
|col1|col2|
|you |can |
|also |align\\ it. |
You can format an address by simply forcing linebreaks:
My contact dates:\\
Pone: xyz\\
Fax: +45\\
Mobile: abc
=== Creole 0.5 ===
|= Header title |= Another header title |
| {{{ //not italic text// }}} | {{{ **not bold text** }}} |
| //italic text// | ** bold text ** |
=== Creole 1.0 ===
If interwiki links are setup in your wiki, this links to the WikiCreole page about Creole 1.0 test cases: [[WikiCreole:Creole1.0TestCases]].
+20
View File
@@ -0,0 +1,20 @@
<h1>Header1</h1>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
<h1>Header2</h1>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
+7
View File
@@ -0,0 +1,7 @@
<div class="spot">
<p class="spot-block">
<a href="/QA/Tools/Donate"><img style="border:none" class="newsImage" alt="I Love Validator" src="/QA/Tools/I_heart_validator.png" /></a>
[[Donate|Make a donation]] or become a
[[sponsor]]
of the http://validator.w3.org/ .</p>
</div>
+20
View File
@@ -0,0 +1,20 @@
<h3>Header1</h3>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
<h3>Header2</h3>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
+20
View File
@@ -0,0 +1,20 @@
= Header 1 =
First paragraph with no formats.
''This paragraph has bold text.''
== False header =
'''This part of the paragraph is italicized.''' But not this part.
==Header 2==
Some mix of '''italics''' and ''bold'', and some '''''italics & bold'''''.
And that '''italics and ''both'''''.
And this: '''italics and''' '''''both'''''.
---
----
+23
View File
@@ -0,0 +1,23 @@
= Links =
== Internal links ==
Some [[links]]. [[link|Another Link]].
=== Anchors ===
This is an [[#External links|anchor]] to the external links section.
And this is an [[link#Section|anchor to another page]].
== External links ==
A link to http://www.google.com , and a link to [http://www.apple.com|apple].
The same link to [http://www.apple.com Apple Corporation].
== Attachments & images ==
That's an [[attach:attachment.png|attachment]].
And that's an [[image:image.png|image]].
+22
View File
@@ -0,0 +1,22 @@
= Lists =
== Unordered lists ==
* 1
** 2
* 1
** 1
*** 3
***** ''bold''
* '''italic'''
== Ordered lists ==
# 1
#### 2
# 3
### 4
# 5
### 6
+13
View File
@@ -0,0 +1,13 @@
{|
| A
| B
|-
| C
| D
|}
{|
! A !! B
|-
| C || D
|}
View File
+3
View File
@@ -0,0 +1,3 @@
<p>Donec semper, nunc nec imperdiet lacinia, dui magna gravida odio, ut pretium nisl sapien ut lacus. Pellentesque nec pede. Praesent condimentum. Aliquam porttitor mi ut odio! Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed laoreet mauris vitae tellus. Curabitur dignissim. Duis ac leo. Nam gravida pharetra sapien. Sed feugiat lobortis orci. Cras sed nisl. Curabitur congue mollis erat. Quisque dictum! Praesent a lectus. Pellentesque nulla nisi; tempus eget, tincidunt id; tincidunt vel, nisl.</p>
<p>Duis consequat vulputate felis. Praesent diam nisi, venenatis vitae; dignissim quis, feugiat ut, pede. Maecenas tincidunt iaculis elit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed sed nulla at eros mollis tempor. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam bibendum lorem at sem. Morbi blandit. Nullam volutpat mi. Suspendisse dapibus lacus vel nisl. Ut lacinia adipiscing mi! Maecenas ipsum erat, accumsan quis, cursus ut, ultrices in; metus. Nulla adipiscing rhoncus ante? Nulla hendrerit tortor sit amet mauris. Cras varius dui vel leo. Proin vulputate! Phasellus lacus arcu, eleifend a, accumsan at, vulputate sed, neque. Fusce leo ante, interdum ac, tincidunt non, scelerisque eu, velit. Suspendisse sed nunc. Aenean sodales turpis!</p>
<p>Suspendisse fringilla fermentum sem. Integer viverra dui id dolor! Mauris ornare eros vel nunc. Phasellus ligula nulla, vestibulum eget, vestibulum vel, aliquam eget, eros. Integer in pede. Fusce ultricies viverra ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque eget lorem ut mi vestibulum facilisis. Vestibulum augue. Curabitur arcu pede, fringilla eu, placerat id, condimentum sit amet, lectus. Fusce at diam eu justo semper interdum. Vivamus id turpis at justo tempus tempor. Maecenas eros libero, bibendum non, dictum ut, blandit id, augue. Pellentesque facilisis. Aenean aliquet sem. In tellus!</p>
+12
View File
@@ -0,0 +1,12 @@
<h3><a name="toc-1"></a>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</h3>
<p>Phasellus odio? Ut ac leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus enim justo, porttitor at, lacinia vitae; consectetuer et, ante? Maecenas eget libero. Duis est. Curabitur tincidunt dictum ligula. Nunc euismod lectus quis mi. Proin et enim sed nunc scelerisque posuere. Suspendisse enim purus, sodales non, tristique vel, sollicitudin ullamcorper, nulla. Aliquam condimentum; tellus eu vulputate facilisis, ante pede rhoncus elit, vel euismod nulla sapien et metus?</p>
<h4><a name="toc-2"></a>Praesent tristique facilisis metus.</h4>
<p>Quisque lectus? Morbi ultrices ultricies neque. In ligula sem; pretium eget, iaculis laoreet, pulvinar sed, dui. Proin mattis luctus diam. Aenean eget risus in mauris sagittis vehicula. Vivamus dapibus enim ac dolor. Pellentesque leo. Praesent tristique facilisis metus. Nulla imperdiet ante et urna? Maecenas leo nisi, lacinia sollicitudin, viverra at, aliquet et, justo. Quisque congue dolor.</p>
<h5><a name="toc-3"></a>Phasellus ut augue ut felis porttitor condimentum.</h5>
<p>Aliquam erat volutpat. Phasellus ut augue ut felis porttitor condimentum. Nam sapien tellus, tempus sed; mattis quis, viverra quis, mauris. Suspendisse venenatis sollicitudin massa. Pellentesque lobortis dolor vitae nisl. Nulla interdum aliquet neque. Duis nisl pede, vestibulum in, tristique eget, viverra vitae, erat. Maecenas justo turpis, convallis sit amet, tristique eu, laoreet et, augue. Fusce sem. Pellentesque ut turpis? Morbi suscipit sollicitudin metus? Morbi pharetra, sem eget ornare tempor, neque erat dapibus lacus, ut tincidunt nisi leo sed nunc. Sed sodales dignissim eros. Duis vitae risus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed lobortis consequat sem. Nunc posuere vulputate velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vestibulum pellentesque neque.</p>
<h6>Sed adipiscing dui at massa. Nulla consectetuer tristique lacus?</h6>
<p>Maecenas lacus justo, pellentesque vitae, mattis vitae, rutrum sit amet, metus! Etiam aliquam odio vel nulla. Suspendisse ante. Pellentesque viverra leo at lorem! Ut pharetra egestas ante. Aliquam erat volutpat. Sed adipiscing dui at massa. Nulla consectetuer tristique lacus? Donec ante leo, condimentum non, consectetuer vel, sodales placerat, tortor. Etiam at diam at elit adipiscing ultrices. Etiam lectus sapien, congue sed, sodales quis, ultricies a, libero. Pellentesque tincidunt!</p>
<h4><a name="toc-4"></a>Curabitur euismod sollicitudin nibh</h4>
<p>Curabitur euismod sollicitudin nibh. Duis nec diam. Sed nunc quam, lobortis nec; tristique et, dignissim eget, massa. Suspendisse sagittis malesuada tortor. Nullam lectus diam, mollis id, malesuada at, gravida ut, nisl. In hac habitasse platea dictumst. Sed a purus. Etiam velit urna, lacinia et, imperdiet quis, varius quis, orci! Sed dolor ante, mollis in, ultrices in, vestibulum vitae; justo. Vestibulum accumsan vehicula risus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus sit amet diam lobortis urna tristique pretium. Quisque erat.</p>
<h6>Duis nec diam.</h6>
<p>Pellentesque lobortis dolor vitae nisl. Nulla interdum aliquet neque. Duis nisl pede, vestibulum in, tristique eget, viverra vitae, erat. Maecenas justo turpis, convallis sit amet, tristique eu, laoreet et, augue. Fusce sem. Pellentesque ut turpis? Morbi suscipit sollicitudin metus? Morbi pharetra, sem eget ornare tempor, neque erat dapibus lacus, ut tincidunt nisi leo sed nunc. Sed sodales dignissim eros. Duis vitae risus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed lobortis consequat sem. Nunc posuere vulputate velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vestibulum pellentesque neque.</p>
+5
View File
@@ -0,0 +1,5 @@
<h3><a name="toc-1"></a>In nisi purus, varius in, mollis eget, interdum in, ipsum.</h3>
<p>Vivamus lobortis. <strong>Mauris dui dui, rutrum in, egestas nec, porttitor vehicula, risus!</strong> Vivamus aliquam ultrices metus. <em>Donec ultricies, metus eget volutpat condimentum;</em> neque orci mattis dolor, non posuere eros dui et orci. Duis aliquam. Fusce sit amet nisl. Duis tempor dapibus diam? In venenatis congue mi? Aliquam metus erat; facilisis a, suscipit a, pretium vitae; ligula? Ut id metus a pede adipiscing commodo! <strong>Praesent ultricies urna et sapien.</strong> <em>Donec adipiscing.</em> Donec sit amet lacus.</p>
<h4><a name="toc-2"></a>**In nisi purus**, //varius in,// mollis eget, interdum in, ipsum.</h4>
<p>Duis feugiat ligula ac elit. %!34%!Nulla sed arcu a risus sodales mattis. Etiam magna arcu, accumsan vitae, sodales non, faucibus quis, nunc. Aenean ut elit. Pellentesque malesuada lacus a orci. Suspendisse in erat sed mi porta faucibus. Nullam a nibh. Suspendisse potenti. Nam malesuada lobortis nibh. Ut venenatis, nibh ac convallis iaculis, justo pede tristique sapien, vel ultricies massa diam id leo. Pellentesque ullamcorper condimentum urna. //Proin dui lacus; scelerisque nec, condimentum non, <strong>lobortis ac, felis.</strong></p>
<p>//Nullam ac neque. %!4%!<strong>Praesent quis tellus. </strong>Maecenas<strong> et felis vitae lectus porttitor dignissim. Etiam at dui id nibh molestie semper. Sed vulputate nunc et neque. Fusce consectetur elit id leo. <em>Nulla facilisi. </em>Donec vitae nulla ac nisl mollis blandit. //Nulla adipiscing.</strong> Phasellus quis odio sed eros viverra sodales. Suspendisse eget mauris id urna convallis fringilla. Aliquam dolor. Sed commodo. Quisque vestibulum, eros in mollis rutrum, odio risus aliquam turpis; nec convallis ante justo in dui? Pellentesque pharetra venenatis odio. Nulla placerat, libero at lacinia pellentesque; nisi massa sodales risus, at tincidunt orci pede sed ipsum. Etiam massa! Nullam aliquet justo at erat placerat convallis.</p>
+6
View File
@@ -0,0 +1,6 @@
<h4><a name="toc-1"></a>Donec ultricies neque eu libero scelerisque feugiat.</h4>
<p><strong>Donec ultricies <em>neque eu <a href="http://libero">libero</a> scelerisque </em>feugiat. <em>Cras sed ante.</em> Sed volutpat urna eu diam. Curabitur fringilla lacinia mi.</strong> Quisque lorem. Etiam fringilla consequat dui. Nunc est est; aliquet eu, porttitor auctor; malesuada id, massa. <a href="http://Nullam">Nullam feugiat</a>, nulla eget vulputate facilisis, erat odio vestibulum mi, eget volutpat lorem enim vitae eros. Vestibulum convallis. Maecenas posuere pellentesque mi? Donec consectetur volutpat dolor. <a href="http://%2A%2ACurabitur%2A%2A">**Curabitur**</a> non <strong><a href="http://%2F%2FTellus%2A%2A">tellus nec ligula bibendum pulvinar.</a></strong></p>
<p><a href="http://www.google.com">http://www.google.com</a>
<a href="http://www.google.com">http://www.google.com</a></p>
<p>http://www.apple.com
[[Link que no va]]</p>
+4
View File
@@ -0,0 +1,4 @@
<h3><a name="toc-1"></a>Integer eu leo? \\ Quisque posuere.</h3>
<p>Nunc commodo nisi vitae quam. Etiam tincidunt; lectus eu tempus molestie, elit enim auctor tortor, in varius leo mi ac risus. Sed iaculis magna vel libero. Pellentesque iaculis, tellus in ullamcorper tempus, justo sapien scelerisque enim, eu ornare dui neque sed ligula. <br />Vestibulum porta justo a dolor. Duis mollis quam vel sem. Quisque vel arcu. Pellentesque sem. Aliquam adipiscing neque quis turpis. Mauris placerat, elit quis iaculis vehicula, sem nulla imperdiet nunc, in elementum felis lectus non magna. Mauris cursus; odio eu sagittis sodales, nisi nibh pellentesque tortor, ut ultricies lacus tellus non odio. In semper, ligula eu condimentum posuere, sapien tellus blandit quam, dapibus iaculis lacus erat eget ipsum. Duis pulvinar molestie magna. Aliquam bibendum quam ac nulla!</p>
<h4><a name="toc-2"></a>Fusce justo. Aliquam felis tellus, tempor vel, congue quis, tempus eu, ipsum. \\</h4>
<p><br />Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi sed erat! Vivamus condimentum. Praesent euismod; nibh sed mollis feugiat, erat lorem commodo lectus, vitae tristique erat massa semper diam. Morbi vitae elit. <br />Quisque sagittis leo non odio auctor faucibus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque mi pede, lacinia id, commodo faucibus, rhoncus in, nibh. Praesent vestibulum aliquet quam!</p>
+21
View File
@@ -0,0 +1,21 @@
<p>Donec sem est, dictum ac, blandit ut, commodo vitae, pede. Proin auctor egestas est. Aliquam fermentum, dui ac malesuada facilisis, mauris felis porttitor turpis, non adipiscing odio mi sit amet felis. Duis dignissim posuere sem. Fusce consequat convallis lectus. Ut suscipit neque sed massa. Etiam suscipit. Sed vitae elit. Nulla non mi. Aliquam risus erat, varius eget, eleifend eget, scelerisque sit amet, enim. Proin venenatis.</p>
<ul>
<li>Donec ligula enim</li>
<li>viverra at</li>
<li>ultricies rutrum</li>
</ul>
<ul>
<li>volutpat sed
<ul>
<li>ligula</li>
<li>Aenean laoreet tortor at lorem</li>
</ul>
</li>
<li>Fusce varius nunc quis lacus sodales posuere</li>
</ul>
<p><strong> Integer laoreet congue ligula</strong></p>
<ul>
<li>Vestibulum condimentum</li>
</ul>
<p><strong>dui ac porta imperdiet</strong></p>
<p><strong>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam accumsan lectus vel sapien. Quisque laoreet lorem non dolor. Ut diam dolor, facilisis non, tempus eu, varius id, nunc. Aliquam sit amet lorem. Cras congue ultricies enim. Nunc vehicula, odio eget volutpat pharetra, leo pede commodo tellus, eu scelerisque erat purus non felis. Sed sed sem eget massa convallis eleifend? Nam tristique. Aliquam justo. Sed risus mi, egestas in, viverra a; tincidunt ac, mauris! Nulla magna. Aenean mauris velit, facilisis ut, condimentum eget, hendrerit ac, sem. Phasellus lorem. Curabitur augue mi; iaculis sit amet, suscipit eget, commodo nec; nibh. Cras pellentesque hendrerit quam. Praesent arcu dui, rhoncus non, feugiat ut, laoreet vitae, velit.</strong></p>
+3
View File
@@ -0,0 +1,3 @@
<h3><a name="toc-1"></a>In nisi purus, varius in, mollis eget, interdum in, ipsum.</h3>
<p>Vivamus lobortis. <strong>Mauris dui dui, rutrum in, egestas nec, porttitor vehicula, risus!</strong> Vivamus aliquam ultrices metus. <em>Donec ultricies, metus eget volutpat condimentum;</em> neque orci mattis dolor, non posuere eros dui et orci. Duis aliquam. Fusce sit amet nisl. Duis tempor dapibus diam? In venenatis congue mi? Aliquam metus erat; facilisis a, suscipit a, pretium vitae; ligula? Ut id metus a pede adipiscing commodo! <tt>**Praesent ultricies urna et sapien.** //Donec adipiscing.//</tt> Donec sit amet lacus.</p>
<pre> lkdsjflsdjflsdkjflskdjlfk </pre>
+85
View File
@@ -0,0 +1,85 @@
<h4><a name="toc-1"></a>Testing some tables</h4>
<p>Phasellus urna erat; venenatis ac, iaculis sed, pretium ut, pede. Suspendisse mauris tellus, rhoncus a, tempor id, mattis non, nibh. Aliquam magna odio; hendrerit at, eleifend sed, dignissim quis, orci. Donec mollis, ante sit amet convallis porta, augue nibh viverra magna, ac scelerisque dui ligula eu felis. Sed eget magna. Proin eget ligula. Vestibulum ornare; sem molestie congue sollicitudin, mi velit porta est, pellentesque dignissim libero est at velit. Donec congue adipiscing massa? Nunc eget nisi eget elit facilisis ornare. Vestibulum et felis id leo feugiat sagittis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed tellus velit, luctus et, tempor non, tempor vitae, magna. Aliquam viverra tortor sit amet tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nibh risus, dictum eu, tempor sit amet, posuere et, nulla.</p>
<p>Well formed table...</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
</tr>
</thead>
<tbody>
<tr>
<td>George</td>
<td>Washington</td>
</tr>
<tr>
<td>Abraham</td>
<td>Lincoln</td>
</tr>
</tbody>
</table>
<p>Not so well formed table</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Erroneous stuff</th>
</tr>
</thead>
<tbody>
<tr>
<td>George</td>
<td>Washington</td>
<td></td>
</tr>
<tr>
<td>Abraham</td>
<td>Lincoln</td>
<td>Error error</td>
</tr>
</tbody>
</table>
<p>Bad headers:</p>
<table>
<thead>
<tr>
<td>Name</td>
<th>Surname</th>
</tr>
</thead>
<tbody>
<tr>
<th>George</th>
<td>Washington</td>
</tr>
<tr>
<td>Abraham</td>
<th>Lincoln</th>
</tr>
</tbody>
</table>
<p>Two tables (treated as such) with some format:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>George</strong></td>
<td><em>Washington</em></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>Abraham</td>
<td>Lincoln</td>
</tr>
</tbody>
</table>
+146
View File
@@ -0,0 +1,146 @@
<h3><a name="toc-1"></a>Top-level heading (1)</h3>
<h4><a name="toc-2"></a>This a test for creole 0.1 (2)</h4>
<h5><a name="toc-3"></a>This is a Subheading (3)</h5>
<h6>Subsub (4)</h6>
<h6>Subsubsub (5)</h6>
<p>The ending equal signs should not be displayed:</p>
<p>Top-level heading (1)</p>
<h4><a name="toc-4"></a>This a test for creole 0.1 (2)</h4>
<h5><a name="toc-5"></a>This is a Subheading (3)</h5>
<h6>Subsub (4)</h6>
<h6>Subsubsub (5)</h6>
<p>You can make things <strong>bold</strong> or <em>italic</em> or <strong><em>both</em></strong> or <em><strong>both</strong></em>.</p>
<p>Character formatting extends across line breaks: <strong>bold,
this is still bold. This line deliberately does not end in star-star.</strong></p>
<p>Not bold. Character formatting does not cross paragraph boundaries.</p>
<p>You can use <a href="http://internal+links">internal links</a> or <a href="http://www.wikicreole.org">external links</a>,
give the link a <a href="http://internal+links">different</a> name.</p>
<p>Here's another sentence: This wisdom is taken from <a href="http://Ward+Cunningham%27s">Ward Cunningham's</a>
<a href="http://www.c2.com/doc/wikisym/WikiSym2006.pdf">Presentation at the Wikisym 06</a>.</p>
<p>Here's a external link without a description: <a href="http://www.wikicreole.org">http://www.wikicreole.org</a></p>
<p>Be careful that italic links are rendered properly: <em><a href="http://my.book.example/">My Book Title</a></em> </p>
<p>Free links without braces should be rendered as well, like <a href="http://www.wikicreole.org/">http://www.wikicreole.org/</a> and <a href="http://www.wikicreole.org/users/~example">http://www.wikicreole.org/users/~example</a>. </p>
<p>Creole1.0 specifies that <a href="http://bar">http://bar</a> and <a href="ftp://bar">ftp://bar</a> should not render italic, something like foo:<em>bar should render as italic.</em></p>
<p>You can use this to draw a line to separate the page:</p>
<hr />
<p>You can use lists, start it at the first column for now, please...</p>
<p>unnumbered lists are like</p>
<ul>
<li>item a</li>
<li>item b</li>
<li><strong>bold item c</strong></li>
</ul>
<p>blank space is also permitted before lists like:</p>
<ul>
<li>item a</li>
<li>item b</li>
<li>item c
<ul>
<li>item c.a</li>
</ul>
</li>
</ul>
<p>or you can number them</p>
<ol>
<li><a href="http://item+1">item 1</a></li>
<li>item 2</li>
<li><em> italic item 3 </em>
<ol>
<li>item 3.1</li>
<li>item 3.2</li>
</ol>
</li>
</ol>
<p>up to five levels</p>
<ul>
<li>1
<ul>
<li>2
<ul>
<li>3
<ul>
<li>4
<ul>
<li>5</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>You can havemultiline list items</li>
<li>this is a second multilinelist item</li>
</ul>
<p>You can use nowiki syntax if you would like do stuff like this:</p>
<pre>
Guitar Chord C:
||---|---|---|
||-0-|---|---|
||---|---|---|
||---|-0-|---|
||---|---|-0-|
||---|---|---|
</pre>
<p>You can also use it inline nowiki <tt> in a sentence </tt> like this.</p>
<h3><a name="toc-6"></a>Escapes</h3>
<p>Normal Link: <a href="http://wikicreole.org/">http://wikicreole.org/</a> - now same link, but escaped: http://wikicreole.org/ </p>
<p>Normal asterisks: **not bold**</p>
<p>a tilde alone: ~</p>
<p>a tilde escapes itself: ~xxx</p>
<h5><a name="toc-7"></a>Creole 0.2</h5>
<p>This should be a flower with the ALT text &quot;this is a flower&quot; if your wiki supports ALT text on images:</p>
<p><div class="wiki_image_left"><p></p><img src="Red-Flower.jpg" alt="here is a red flower" /></div></p>
<h5><a name="toc-8"></a>Creole 0.4</h5>
<p>Tables are done like this:</p>
<table>
<thead>
<tr>
<th>header col1</th>
<th>header col2</th>
</tr>
</thead>
<tbody>
<tr>
<td>col1</td>
<td>col2</td>
</tr>
<tr>
<td>you</td>
<td>can</td>
</tr>
<tr>
<td>also</td>
<td>align<br /> it.</td>
</tr>
</tbody>
</table>
<p>You can format an address by simply forcing linebreaks:</p>
<p>My contact dates:<br />
Pone: xyz<br />
Fax: +45<br />
Mobile: abc</p>
<h5><a name="toc-9"></a>Creole 0.5</h5>
<table>
<thead>
<tr>
<th>Header title</th>
<th>Another header title</th>
</tr>
</thead>
<tbody>
<tr>
<td><tt> //not italic text// </tt></td>
<td><tt> **not bold text** </tt></td>
</tr>
<tr>
<td><em>italic text</em></td>
<td><strong> bold text </strong></td>
</tr>
</tbody>
</table>
<h5><a name="toc-10"></a>Creole 1.0</h5>
<p>If interwiki links are setup in your wiki, this links to the WikiCreole page about Creole 1.0 test cases: <a href="http://WikiCreole%3ACreole1.0TestCases">WikiCreole:Creole1.0TestCases</a>.</p>
+20
View File
@@ -0,0 +1,20 @@
<h3><a name="toc-1"></a>Header1</h3>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
<h3><a name="toc-2"></a>Header2</h3>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
+7
View File
@@ -0,0 +1,7 @@
<div class="spot">
<p class="spot-block">
<a href="/QA/Tools/Donate"><img style="border:none" class="newsImage" alt="I Love Validator" src="/QA/Tools/I_heart_validator.png" /></a>
<a href="http://Donate">Make a donation</a> or become a
<a href="http://sponsor">sponsor</a>
of the <a href="http://validator.w3.org/">http://validator.w3.org/</a> .</p>
</div>
+20
View File
@@ -0,0 +1,20 @@
<h3><a name="toc-1"></a>Header1</h3>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
<h3><a name="toc-2"></a>Header2</h3>
<p>
Etiam eget nibh leo. In luctus orci quis tellus sagittis egestas. Praesent et turpis augue, ac accumsan orci? Pellentesque porttitor sodales tortor; vitae faucibus dui auctor vel. Phasellus sit amet sem leo; eu adipiscing ipsum. Aliquam vehicula ipsum at diam imperdiet a condimentum urna commodo? Nunc ac lacus non lorem porttitor malesuada et sit amet diam! Aenean pulvinar lectus et dolor dignissim viverra placerat nisl mattis! Nunc non leo a massa imperdiet porta vel eu tellus. Sed ac est quis orci viverra cursus. Nam tellus mauris, facilisis nec faucibus sit amet, consequat in felis. Ut volutpat lacinia est ut fringilla. Pellentesque augue dui, aliquet et ornare euismod, egestas nec arcu! Vivamus gravida, lorem vitae suscipit condimentum, turpis arcu iaculis tortor; vel ullamcorper lorem ante id nisi. Ut sit amet sem tempor quam dignissim interdum. Nam aliquam, odio vitae volutpat semper; sapien turpis feugiat neque, ac ullamcorper felis enim vitae arcu. Morbi viverra feugiat justo, at ullamcorper ipsum posuere non.
</p>
<p>
Proin ultricies gravida dui a mattis. Integer nec nisl ante. Mauris euismod, tortor et fermentum semper; est mi adipiscing erat, non pellentesque orci dui ac arcu. Nam vitae metus augue. Integer magna nibh, elementum nec molestie eget; commodo sed turpis. Duis neque mi, vehicula sed aliquet id, ultricies sed tortor. Aliquam pharetra ante sapien. Etiam accumsan ipsum sed dolor bibendum congue sollicitudin enim fringilla. Nulla eros risus, auctor placerat vestibulum eget, tincidunt ac eros. Duis ut turpis leo, sit amet ornare arcu. Aliquam eu lorem in arcu accumsan iaculis. Integer placerat lacus in nibh sollicitudin euismod? Sed a urna vel dui sagittis varius cursus sit amet dolor. Nulla ut sem at magna fringilla hendrerit sed nec sapien. Aenean nisi elit, feugiat vel euismod non, laoreet sit amet ligula. Aenean a dui quam.
</p>
<p>
Curabitur dolor ligula, suscipit et eleifend nec, faucibus varius sapien. Quisque ornare felis ac leo tincidunt quis malesuada elit lobortis? Suspendisse potenti. Vestibulum tempus porta dui, at ullamcorper mauris sollicitudin vel? In convallis risus id elit ultrices pellentesque. Sed id quam lectus. Duis tincidunt egestas urna, in tempor tortor rhoncus ac. Sed commodo, nunc sit amet sodales vulputate, purus nisi malesuada urna, ut cursus nisl nunc vel enim. Mauris ut imperdiet risus. Integer sagittis; odio at laoreet venenatis, purus neque fermentum nisi, non elementum urna libero sed ipsum.
</p>
+11
View File
@@ -0,0 +1,11 @@
<h3><a name="toc-1"></a>Header 1</h3>
<p>First paragraph with no formats.</p>
<p><strong>This paragraph has bold text.</strong></p>
<p>== False header =</p>
<p><em>This part of the paragraph is italicized.</em> But not this part.</p>
<h4><a name="toc-2"></a>Header 2</h4>
<p>Some mix of <em>italics</em> and <strong>bold</strong>, and some <em><strong>italics & bold</strong></em>.</p>
<p>And that <em>italics and <strong>both</strong></em>.</p>
<p>And this: <em>italics and</em> <em><strong>both</strong></em>.</p>
<hr />
<hr />
+12
View File
@@ -0,0 +1,12 @@
<h3><a name="toc-1"></a>Links</h3>
<h4><a name="toc-2"></a>Internal links</h4>
<p>Some <a href="http://links">links</a>. <a href="http://link">Another Link</a>.</p>
<h5><a name="toc-3"></a>Anchors</h5>
<p>This is an <a href="#External+links">anchor</a> to the external links section.</p>
<p>And this is an <a href="http://link#Section">anchor to another page</a>.</p>
<h4><a name="toc-4"></a>External links</h4>
<p>A link to <a href="http://www.google.com">http://www.google.com</a> , and a link to <a href="http://www.apple.com">apple</a>. </p>
<p>The same link to <a href="http://www.apple.com">Apple Corporation</a>.</p>
<h4><a name="toc-5"></a>Attachments & images</h4>
<p>That's an <a href="attachment.png" class="wiki-attachment">attachment</a>.</p>
<p>And that's an <div class="wiki_image_left"><p></p><img src="image.png" alt="image" /></div>.</p>
+39
View File
@@ -0,0 +1,39 @@
<h3><a name="toc-1"></a>Lists</h3>
<h4><a name="toc-2"></a>Unordered lists</h4>
<ul>
<li>1
<ul>
<li>2</li>
</ul>
</li>
<li>1</li>
</ul>
<ul>
<li>1
<ul>
<li>3
<ul>
<li><strong>bold</strong></li>
</ul>
</li>
</ul>
</li>
<li><em>italic</em></li>
</ul>
<h4><a name="toc-3"></a>Ordered lists</h4>
<ol>
<li>1
<ol>
<li>2</li>
</ol>
</li>
<li>3</li>
</ol>
<ol>
<li>4</li>
<li>5
<ol>
<li>6</li>
</ol>
</li>
</ol>
+26
View File
@@ -0,0 +1,26 @@
<table>
<tbody>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
</tr>
</thead>
<tbody>
<tr>
<td>C</td>
<td>D</td>
</tr>
</tbody>
</table>
+1
View File
@@ -0,0 +1 @@
+159
View File
@@ -0,0 +1,159 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* mod_wiki data generator.
*
* @package mod_wiki
* @category test
* @copyright 2013 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* mod_wiki data generator class.
*
* @package mod_wiki
* @category test
* @copyright 2013 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_wiki_generator extends testing_module_generator {
/**
* @var int keep track of how many pages have been created.
*/
protected $pagecount = 0;
/**
* To be called from data reset code only,
* do not use in tests.
* @return void
*/
public function reset() {
$this->pagecount = 0;
parent::reset();
}
public function create_instance($record = null, array $options = null) {
// Add default values for wiki.
$record = (array)$record + array(
'wikimode' => 'collaborative',
'firstpagetitle' => 'Front page for wiki '.($this->instancecount+1),
'defaultformat' => 'html',
'forceformat' => 0
);
return parent::create_instance($record, (array)$options);
}
public function create_content($wiki, $record = array()) {
$record = (array)$record + array(
'wikiid' => $wiki->id
);
return $this->create_page($wiki, $record);
}
public function create_first_page($wiki, $record = array()) {
$record = (array)$record + array(
'title' => $wiki->firstpagetitle,
);
return $this->create_page($wiki, $record);
}
/**
* Retrieves or generates a subwiki and returns its id
*
* @param stdClass $wiki
* @param int $subwikiid
* @param int $group
* @param int $userid
* @return int
*/
public function get_subwiki($wiki, $subwikiid = null, $group = null, $userid = null) {
global $USER, $DB;
if ($subwikiid) {
$params = ['id' => $subwikiid, 'wikiid' => $wiki->id];
if ($group !== null) {
$params['group'] = $group;
}
if ($userid !== null) {
$params['userid'] = $userid;
}
return $DB->get_field('wiki_subwikis', 'id', $params, MUST_EXIST);
}
if ($userid === null) {
$userid = ($wiki->wikimode == 'individual') ? $USER->id : 0;
}
if ($group === null) {
$group = 0;
}
if ($subwiki = wiki_get_subwiki_by_group($wiki->id, $group, $userid)) {
return $subwiki->id;
} else {
return wiki_add_subwiki($wiki->id, $group, $userid);
}
}
/**
* Generates a page in wiki.
*
* @param stdClass wiki object returned from create_instance (if known)
* @param stdClass|array $record data to insert as wiki entry.
* @return stdClass
* @throws coding_exception if neither $record->wikiid nor $wiki->id is specified
*/
public function create_page($wiki, $record = array()) {
global $CFG, $USER;
require_once($CFG->dirroot.'/mod/wiki/locallib.php');
$this->pagecount++;
$record = (array)$record + array(
'title' => 'wiki page '.$this->pagecount,
'wikiid' => $wiki->id,
'subwikiid' => 0,
'group' => null,
'userid' => null,
'content' => 'Wiki page content '.$this->pagecount,
'format' => $wiki->defaultformat
);
if (empty($record['wikiid']) && empty($record['subwikiid'])) {
throw new coding_exception('wiki page generator requires either wikiid or subwikiid');
}
$record['subwikiid'] = $this->get_subwiki($wiki, $record['subwikiid'], $record['group'], $record['userid']);
$wikipage = wiki_get_page_by_title($record['subwikiid'], $record['title']);
if (!$wikipage) {
$pageid = wiki_create_page($record['subwikiid'], $record['title'], $record['format'], $USER->id);
$wikipage = wiki_get_page($pageid);
}
$rv = wiki_save_page($wikipage, $record['content'], $USER->id);
if (array_key_exists('tags', $record)) {
$tags = is_array($record['tags']) ? $record['tags'] : preg_split('/,/', $record['tags']);
if (empty($wiki->cmid)) {
$cm = get_coursemodule_from_instance('wiki', $wiki->id, isset($wiki->course) ? $wiki->course : 0);
$wiki->cmid = $cm->id;
}
core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $wikipage->id,
context_module::instance($wiki->cmid), $tags);
}
return $rv['page'];
}
}
+120
View File
@@ -0,0 +1,120 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_wiki;
/**
* Genarator tests class for mod_wiki.
*
* @package mod_wiki
* @category test
* @copyright 2013 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class generator_test extends \advanced_testcase {
public function test_create_instance(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$this->assertFalse($DB->record_exists('wiki', array('course' => $course->id)));
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course));
$records = $DB->get_records('wiki', array('course' => $course->id), 'id');
$this->assertEquals(1, count($records));
$this->assertTrue(array_key_exists($wiki->id, $records));
$params = array('course' => $course->id, 'name' => 'Another wiki');
$wiki = $this->getDataGenerator()->create_module('wiki', $params);
$records = $DB->get_records('wiki', array('course' => $course->id), 'id');
$this->assertEquals(2, count($records));
$this->assertEquals('Another wiki', $records[$wiki->id]->name);
}
public function test_create_content(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course));
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$page1 = $wikigenerator->create_first_page($wiki);
$page2 = $wikigenerator->create_content($wiki);
$page3 = $wikigenerator->create_content($wiki, array('title' => 'Custom title', 'tags' => array('Cats', 'mice')));
unset($wiki->cmid);
$page4 = $wikigenerator->create_content($wiki, array('tags' => 'Cats, dogs'));
$subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id), 'id');
$this->assertEquals(1, count($subwikis));
$subwikiid = key($subwikis);
$records = $DB->get_records('wiki_pages', array('subwikiid' => $subwikiid), 'id');
$this->assertEquals(4, count($records));
$this->assertEquals($page1->id, $records[$page1->id]->id);
$this->assertEquals($page2->id, $records[$page2->id]->id);
$this->assertEquals($page3->id, $records[$page3->id]->id);
$this->assertEquals('Custom title', $records[$page3->id]->title);
$this->assertEquals(array('Cats', 'mice'),
array_values(\core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page3->id)));
$this->assertEquals(array('Cats', 'dogs'),
array_values(\core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page4->id)));
}
public function test_create_content_individual(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$wiki = $this->getDataGenerator()->create_module('wiki',
array('course' => $course, 'wikimode' => 'individual'));
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$page1 = $wikigenerator->create_first_page($wiki);
$page2 = $wikigenerator->create_content($wiki);
$page3 = $wikigenerator->create_content($wiki, array('title' => 'Custom title for admin'));
$subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id), 'id');
$this->assertEquals(1, count($subwikis));
$subwikiid = key($subwikis);
$records = $DB->get_records('wiki_pages', array('subwikiid' => $subwikiid), 'id');
$this->assertEquals(3, count($records));
$this->assertEquals($page1->id, $records[$page1->id]->id);
$this->assertEquals($page2->id, $records[$page2->id]->id);
$this->assertEquals($page3->id, $records[$page3->id]->id);
$this->assertEquals('Custom title for admin', $records[$page3->id]->title);
$user = $this->getDataGenerator()->create_user();
$role = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);
$this->setUser($user);
$page1s = $wikigenerator->create_first_page($wiki);
$page2s = $wikigenerator->create_content($wiki);
$page3s = $wikigenerator->create_content($wiki, array('title' => 'Custom title for student'));
$subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id), 'id');
$this->assertEquals(2, count($subwikis));
next($subwikis);
$subwikiid = key($subwikis);
$records = $DB->get_records('wiki_pages', array('subwikiid' => $subwikiid), 'id');
$this->assertEquals(3, count($records));
$this->assertEquals($page1s->id, $records[$page1s->id]->id);
$this->assertEquals($page2s->id, $records[$page2s->id]->id);
$this->assertEquals($page3s->id, $records[$page3s->id]->id);
$this->assertEquals('Custom title for student', $records[$page3s->id]->title);
}
}
+925
View File
@@ -0,0 +1,925 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for mod_wiki lib
*
* @package mod_wiki
* @category external
* @copyright 2015 Dani Palou <dani@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.1
*/
namespace mod_wiki;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/wiki/lib.php');
require_once($CFG->dirroot . '/mod/wiki/locallib.php');
require_once($CFG->libdir . '/completionlib.php');
/**
* Unit tests for mod_wiki lib
*
* @package mod_wiki
* @category external
* @copyright 2015 Dani Palou <dani@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.1
*/
class lib_test extends \advanced_testcase {
/**
* Test wiki_view.
*
* @return void
*/
public function test_wiki_view(): void {
global $CFG;
$CFG->enablecompletion = COMPLETION_ENABLED;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => COMPLETION_ENABLED));
$options = array('completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => COMPLETION_VIEW_REQUIRED);
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id), $options);
$context = \context_module::instance($wiki->cmid);
$cm = get_coursemodule_from_instance('wiki', $wiki->id);
// Trigger and capture the event.
$sink = $this->redirectEvents();
wiki_view($wiki, $course, $cm, $context);
$events = $sink->get_events();
// 2 additional events thanks to completion.
$this->assertCount(3, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$moodleurl = new \moodle_url('/mod/wiki/view.php', array('id' => $cm->id));
$this->assertEquals($moodleurl, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Check completion status.
$completion = new \completion_info($course);
$completiondata = $completion->get_data($cm);
$this->assertEquals(1, $completiondata->completionstate);
}
/**
* Test wiki_page_view.
*
* @return void
*/
public function test_wiki_page_view(): void {
global $CFG;
$CFG->enablecompletion = COMPLETION_ENABLED;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => COMPLETION_ENABLED));
$options = array('completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => COMPLETION_VIEW_REQUIRED);
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id), $options);
$context = \context_module::instance($wiki->cmid);
$cm = get_coursemodule_from_instance('wiki', $wiki->id);
$firstpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($wiki);
// Trigger and capture the event.
$sink = $this->redirectEvents();
wiki_page_view($wiki, $firstpage, $course, $cm, $context);
$events = $sink->get_events();
// 2 additional events thanks to completion.
$this->assertCount(3, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_wiki\event\page_viewed', $event);
$this->assertEquals($context, $event->get_context());
$pageurl = new \moodle_url('/mod/wiki/view.php', array('pageid' => $firstpage->id));
$this->assertEquals($pageurl, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Check completion status.
$completion = new \completion_info($course);
$completiondata = $completion->get_data($cm);
$this->assertEquals(1, $completiondata->completionstate);
}
/**
* Test wiki_user_can_edit without groups.
*
* @return void
*/
public function test_wiki_user_can_edit(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$indwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'individual'));
$colwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'collaborative'));
// Create users.
$student = self::getDataGenerator()->create_user();
$teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
// Simulate collaborative subwiki.
$swcol = new \stdClass();
$swcol->id = -1;
$swcol->wikiid = $colwiki->id;
$swcol->groupid = 0;
$swcol->userid = 0;
// Simulate individual subwikis (1 per user).
$swindstudent = clone($swcol);
$swindstudent->wikiid = $indwiki->id;
$swindstudent->userid = $student->id;
$swindteacher = clone($swindstudent);
$swindteacher->userid = $teacher->id;
$this->setUser($student);
// Check that the student can edit the collaborative subwiki.
$this->assertTrue(wiki_user_can_edit($swcol));
// Check that the student can edit his individual subwiki.
$this->assertTrue(wiki_user_can_edit($swindstudent));
// Check that the student cannot edit teacher's individual subwiki.
$this->assertFalse(wiki_user_can_edit($swindteacher));
// Now test as a teacher.
$this->setUser($teacher);
// Check that the teacher can edit the collaborative subwiki.
$this->assertTrue(wiki_user_can_edit($swcol));
// Check that the teacher can edit his individual subwiki.
$this->assertTrue(wiki_user_can_edit($swindteacher));
// Check that the teacher can edit student's individual subwiki.
$this->assertTrue(wiki_user_can_edit($swindstudent));
}
/**
* Test wiki_user_can_edit using collaborative wikis with groups.
*
* @return void
*/
public function test_wiki_user_can_edit_with_groups_collaborative(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$wikisepcol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => SEPARATEGROUPS, 'wikimode' => 'collaborative'));
$wikiviscol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => VISIBLEGROUPS, 'wikimode' => 'collaborative'));
// Create users.
$student = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
// Create groups.
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
// Simulate all the possible subwikis.
// Subwikis in collaborative wikis: 1 subwiki per group + 1 subwiki for all participants.
$swsepcolg1 = new \stdClass();
$swsepcolg1->id = -1;
$swsepcolg1->wikiid = $wikisepcol->id;
$swsepcolg1->groupid = $group1->id;
$swsepcolg1->userid = 0;
$swsepcolg2 = clone($swsepcolg1);
$swsepcolg2->groupid = $group2->id;
$swsepcolallparts = clone($swsepcolg1); // All participants.
$swsepcolallparts->groupid = 0;
$swviscolg1 = clone($swsepcolg1);
$swviscolg1->wikiid = $wikiviscol->id;
$swviscolg2 = clone($swviscolg1);
$swviscolg2->groupid = $group2->id;
$swviscolallparts = clone($swviscolg1); // All participants.
$swviscolallparts->groupid = 0;
$this->setUser($student);
// Check that the student can edit his group's subwiki both in separate and visible groups.
$this->assertTrue(wiki_user_can_edit($swsepcolg1));
$this->assertTrue(wiki_user_can_edit($swviscolg1));
// Check that the student cannot edit subwiki from group 2 both in separate and visible groups.
$this->assertFalse(wiki_user_can_edit($swsepcolg2));
$this->assertFalse(wiki_user_can_edit($swviscolg2));
// Now test as student 2.
$this->setUser($student2);
// Check that the student 2 can edit subwikis from both groups both in separate and visible groups.
$this->assertTrue(wiki_user_can_edit($swsepcolg1));
$this->assertTrue(wiki_user_can_edit($swviscolg1));
$this->assertTrue(wiki_user_can_edit($swsepcolg2));
$this->assertTrue(wiki_user_can_edit($swviscolg2));
// Check that the student 2 cannot edit subwikis from all participants.
$this->assertFalse(wiki_user_can_edit($swsepcolallparts));
$this->assertFalse(wiki_user_can_edit($swviscolallparts));
// Now test it as a teacher.
$this->setUser($teacher);
// Check that teacher can edit all subwikis.
$this->assertTrue(wiki_user_can_edit($swsepcolg1));
$this->assertTrue(wiki_user_can_edit($swviscolg1));
$this->assertTrue(wiki_user_can_edit($swsepcolg2));
$this->assertTrue(wiki_user_can_edit($swviscolg2));
$this->assertTrue(wiki_user_can_edit($swsepcolallparts));
$this->assertTrue(wiki_user_can_edit($swviscolallparts));
}
/**
* Test wiki_user_can_edit using individual wikis with groups.
*
* @return void
*/
public function test_wiki_user_can_edit_with_groups_individual(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$wikisepind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => SEPARATEGROUPS, 'wikimode' => 'individual'));
$wikivisind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => VISIBLEGROUPS, 'wikimode' => 'individual'));
// Create users.
$student = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
// Create groups.
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
// Simulate all the possible subwikis.
// Subwikis in collaborative wikis: 1 subwiki per group + 1 subwiki for all participants.
$swsepindg1s1 = new \stdClass();
$swsepindg1s1->id = -1;
$swsepindg1s1->wikiid = $wikisepind->id;
$swsepindg1s1->groupid = $group1->id;
$swsepindg1s1->userid = $student->id;
$swsepindg1s2 = clone($swsepindg1s1);
$swsepindg1s2->userid = $student2->id;
$swsepindg2s2 = clone($swsepindg1s2);
$swsepindg2s2->groupid = $group2->id;
$swsepindteacher = clone($swsepindg1s1);
$swsepindteacher->userid = $teacher->id;
$swsepindteacher->groupid = 0;
$swvisindg1s1 = clone($swsepindg1s1);
$swvisindg1s1->wikiid = $wikivisind->id;
$swvisindg1s2 = clone($swvisindg1s1);
$swvisindg1s2->userid = $student2->id;
$swvisindg2s2 = clone($swvisindg1s2);
$swvisindg2s2->groupid = $group2->id;
$swvisindteacher = clone($swvisindg1s1);
$swvisindteacher->userid = $teacher->id;
$swvisindteacher->groupid = 0;
$this->setUser($student);
// Check that the student can edit his subwiki both in separate and visible groups.
$this->assertTrue(wiki_user_can_edit($swsepindg1s1));
$this->assertTrue(wiki_user_can_edit($swvisindg1s1));
// Check that the student cannot edit subwikis from another user even if he belongs to his group.
$this->assertFalse(wiki_user_can_edit($swsepindg1s2));
$this->assertFalse(wiki_user_can_edit($swvisindg1s2));
// Now test as student 2.
$this->setUser($student2);
// Check that the student 2 can edit his subwikis from both groups both in separate and visible groups.
$this->assertTrue(wiki_user_can_edit($swsepindg1s2));
$this->assertTrue(wiki_user_can_edit($swvisindg1s2));
$this->assertTrue(wiki_user_can_edit($swsepindg2s2));
$this->assertTrue(wiki_user_can_edit($swvisindg2s2));
// Now test it as a teacher.
$this->setUser($teacher);
// Check that teacher can edit all subwikis.
$this->assertTrue(wiki_user_can_edit($swsepindg1s1));
$this->assertTrue(wiki_user_can_edit($swsepindg1s2));
$this->assertTrue(wiki_user_can_edit($swsepindg2s2));
$this->assertTrue(wiki_user_can_edit($swsepindteacher));
$this->assertTrue(wiki_user_can_edit($swvisindg1s1));
$this->assertTrue(wiki_user_can_edit($swvisindg1s2));
$this->assertTrue(wiki_user_can_edit($swvisindg2s2));
$this->assertTrue(wiki_user_can_edit($swvisindteacher));
}
/**
* Test wiki_get_visible_subwikis without groups.
*
* @return void
*/
public function test_wiki_get_visible_subwikis_without_groups(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$indwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'individual'));
$colwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'collaborative'));
// Create users.
$student = self::getDataGenerator()->create_user();
$teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
$this->setUser($student);
// Check that not passing a wiki returns empty array.
$result = wiki_get_visible_subwikis(null);
$this->assertEquals(array(), $result);
// Check that the student can get the only subwiki from the collaborative wiki.
$expectedsubwikis = array();
$expectedsubwiki = new \stdClass();
$expectedsubwiki->id = -1; // We haven't created any page so the subwiki hasn't been created.
$expectedsubwiki->wikiid = $colwiki->id;
$expectedsubwiki->groupid = 0;
$expectedsubwiki->userid = 0;
$expectedsubwikis[] = $expectedsubwiki;
$result = wiki_get_visible_subwikis($colwiki);
$this->assertEquals($expectedsubwikis, $result);
// Create a page now so the subwiki is created.
$colfirstpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($colwiki);
// Call the function again, now we expect to have a subwiki ID.
$expectedsubwikis[0]->id = $colfirstpage->subwikiid;
$result = wiki_get_visible_subwikis($colwiki);
$this->assertEquals($expectedsubwikis, $result);
// Check that the teacher can see it too.
$this->setUser($teacher);
$result = wiki_get_visible_subwikis($colwiki);
$this->assertEquals($expectedsubwikis, $result);
// Check that the student can only see his subwiki in the individual wiki.
$this->setUser($student);
$expectedsubwikis[0]->id = -1;
$expectedsubwikis[0]->wikiid = $indwiki->id;
$expectedsubwikis[0]->userid = $student->id;
$result = wiki_get_visible_subwikis($indwiki);
$this->assertEquals($expectedsubwikis, $result);
// Check that the teacher can see his subwiki and the student subwiki in the individual wiki.
$this->setUser($teacher);
$teachersubwiki = new \stdClass();
$teachersubwiki->id = -1;
$teachersubwiki->wikiid = $indwiki->id;
$teachersubwiki->groupid = 0;
$teachersubwiki->userid = $teacher->id;
$expectedsubwikis[] = $teachersubwiki;
$result = wiki_get_visible_subwikis($indwiki);
$this->assertEqualsCanonicalizing($expectedsubwikis, $result); // Compare without order.
}
/**
* Test wiki_get_visible_subwikis using collaborative wikis with groups.
*
* @return void
*/
public function test_wiki_get_visible_subwikis_with_groups_collaborative(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$wikisepcol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => SEPARATEGROUPS, 'wikimode' => 'collaborative'));
$wikiviscol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => VISIBLEGROUPS, 'wikimode' => 'collaborative'));
// Create users.
$student = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$student3 = self::getDataGenerator()->create_user();
$teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
// Create groups.
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student3->id, 'groupid' => $group2->id));
$this->setUser($student);
// Create all the possible subwikis. We haven't created any page so ids will be -1.
// Subwikis in collaborative wikis: 1 subwiki per group + 1 subwiki for all participants.
$swsepcolg1 = new \stdClass();
$swsepcolg1->id = -1;
$swsepcolg1->wikiid = $wikisepcol->id;
$swsepcolg1->groupid = $group1->id;
$swsepcolg1->userid = 0;
$swsepcolg2 = clone($swsepcolg1);
$swsepcolg2->groupid = $group2->id;
$swsepcolallparts = clone($swsepcolg1); // All participants.
$swsepcolallparts->groupid = 0;
$swviscolg1 = clone($swsepcolg1);
$swviscolg1->wikiid = $wikiviscol->id;
$swviscolg2 = clone($swviscolg1);
$swviscolg2->groupid = $group2->id;
$swviscolallparts = clone($swviscolg1); // All participants.
$swviscolallparts->groupid = 0;
// Check that the student can get only the subwiki from his group in collaborative wiki with separate groups.
$expectedsubwikis = array($swsepcolg1);
$result = wiki_get_visible_subwikis($wikisepcol);
$this->assertEquals($expectedsubwikis, $result);
// Check that he can get subwikis from both groups in collaborative wiki with visible groups, and also all participants.
$expectedsubwikis = array($swviscolallparts, $swviscolg1, $swviscolg2);
$result = wiki_get_visible_subwikis($wikiviscol);
$this->assertEqualsCanonicalizing($expectedsubwikis, $result);
// Now test it as a teacher. No need to check visible groups wikis because the result is the same as student.
$this->setUser($teacher);
// Check that he can get the subwikis from all the groups in collaborative wiki with separate groups.
$expectedsubwikis = array($swsepcolg1, $swsepcolg2, $swsepcolallparts);
$result = wiki_get_visible_subwikis($wikisepcol);
$this->assertEqualsCanonicalizing($expectedsubwikis, $result);
}
/**
* Test wiki_get_visible_subwikis using individual wikis with groups.
*
* @return void
*/
public function test_wiki_get_visible_subwikis_with_groups_individual(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$wikisepind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => SEPARATEGROUPS, 'wikimode' => 'individual'));
$wikivisind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
'groupmode' => VISIBLEGROUPS, 'wikimode' => 'individual'));
// Create users.
$student = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$student3 = self::getDataGenerator()->create_user();
$teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
// Create groups.
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
$this->getDataGenerator()->create_group_member(array('userid' => $student3->id, 'groupid' => $group2->id));
$this->setUser($student);
// Create all the possible subwikis to be returned. We haven't created any page so ids will be -1.
// Subwikis in individual wikis: 1 subwiki per user and group. If user doesn't belong to any group then groupid is 0.
$swsepindg1s1 = new \stdClass();
$swsepindg1s1->id = -1;
$swsepindg1s1->wikiid = $wikisepind->id;
$swsepindg1s1->groupid = $group1->id;
$swsepindg1s1->userid = $student->id;
$swsepindg1s2 = clone($swsepindg1s1);
$swsepindg1s2->userid = $student2->id;
$swsepindg2s2 = clone($swsepindg1s2);
$swsepindg2s2->groupid = $group2->id;
$swsepindg2s3 = clone($swsepindg1s1);
$swsepindg2s3->userid = $student3->id;
$swsepindg2s3->groupid = $group2->id;
$swsepindteacher = clone($swsepindg1s1);
$swsepindteacher->userid = $teacher->id;
$swsepindteacher->groupid = 0;
$swvisindg1s1 = clone($swsepindg1s1);
$swvisindg1s1->wikiid = $wikivisind->id;
$swvisindg1s2 = clone($swvisindg1s1);
$swvisindg1s2->userid = $student2->id;
$swvisindg2s2 = clone($swvisindg1s2);
$swvisindg2s2->groupid = $group2->id;
$swvisindg2s3 = clone($swvisindg1s1);
$swvisindg2s3->userid = $student3->id;
$swvisindg2s3->groupid = $group2->id;
$swvisindteacher = clone($swvisindg1s1);
$swvisindteacher->userid = $teacher->id;
$swvisindteacher->groupid = 0;
// Check that student can get the subwikis from his group in individual wiki with separate groups.
$expectedsubwikis = array($swsepindg1s1, $swsepindg1s2);
$result = wiki_get_visible_subwikis($wikisepind);
$this->assertEqualsCanonicalizing($expectedsubwikis, $result);
// Check that he can get subwikis from all users and groups in individual wiki with visible groups.
$expectedsubwikis = array($swvisindg1s1, $swvisindg1s2, $swvisindg2s2, $swvisindg2s3, $swvisindteacher);
$result = wiki_get_visible_subwikis($wikivisind);
$this->assertEqualsCanonicalizing($expectedsubwikis, $result);
// Now test it as a teacher. No need to check visible groups wikis because the result is the same as student.
$this->setUser($teacher);
// Check that teacher can get the subwikis from all the groups in individual wiki with separate groups.
$expectedsubwikis = array($swsepindg1s1, $swsepindg1s2, $swsepindg2s2, $swsepindg2s3, $swsepindteacher);
$result = wiki_get_visible_subwikis($wikisepind);
$this->assertEqualsCanonicalizing($expectedsubwikis, $result);
}
public function test_mod_wiki_get_tagged_pages(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$course3 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course1 = $this->getDataGenerator()->create_course();
$wiki1 = $this->getDataGenerator()->create_module('wiki', array('course' => $course1->id));
$wiki2 = $this->getDataGenerator()->create_module('wiki', array('course' => $course2->id));
$wiki3 = $this->getDataGenerator()->create_module('wiki', array('course' => $course3->id));
$page11 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats', 'Dogs')));
$page12 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats', 'mice')));
$page13 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats')));
$page14 = $wikigenerator->create_content($wiki1);
$page15 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats')));
$page21 = $wikigenerator->create_content($wiki2, array('tags' => array('Cats')));
$page22 = $wikigenerator->create_content($wiki2, array('tags' => array('Cats', 'Dogs')));
$page23 = $wikigenerator->create_content($wiki2, array('tags' => array('mice', 'Cats')));
$page31 = $wikigenerator->create_content($wiki3, array('tags' => array('mice', 'Cats')));
$tag = \core_tag_tag::get_by_name(0, 'Cats');
// Admin can see everything.
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */0);
$this->assertMatchesRegularExpression('/'.$page11->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page12->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page13->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page14->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page15->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page21->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page22->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page23->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page31->title.'/', $res->content);
$this->assertEmpty($res->prevpageurl);
$this->assertNotEmpty($res->nextpageurl);
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */1);
$this->assertDoesNotMatchRegularExpression('/'.$page11->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page12->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page13->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page14->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page15->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page21->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page22->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page23->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page31->title.'/', $res->content);
$this->assertNotEmpty($res->prevpageurl);
$this->assertEmpty($res->nextpageurl);
// Create and enrol a user.
$student = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual');
$this->setUser($student);
\core_tag_index_builder::reset_caches();
// User can not see pages in course 3 because he is not enrolled.
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */1);
$this->assertMatchesRegularExpression('/'.$page22->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page23->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page31->title.'/', $res->content);
// User can search wiki pages inside a course.
$coursecontext = \context_course::instance($course1->id);
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */$coursecontext->id, /*$rec = */1, /*$page = */0);
$this->assertMatchesRegularExpression('/'.$page11->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page12->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page13->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page14->title.'/', $res->content);
$this->assertMatchesRegularExpression('/'.$page15->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page21->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page22->title.'/', $res->content);
$this->assertDoesNotMatchRegularExpression('/'.$page23->title.'/', $res->content);
$this->assertEmpty($res->nextpageurl);
}
public function test_wiki_core_calendar_provide_event_action(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Create the activity.
$course = $this->getDataGenerator()->create_course();
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $wiki->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('view'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_wiki_core_calendar_provide_event_action_for_non_user(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
// Create the activity.
$course = $this->getDataGenerator()->create_course();
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $wiki->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
public function test_wiki_core_calendar_provide_event_action_for_user(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
// Create the activity.
$course = $this->getDataGenerator()->create_course();
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id));
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create a calendar event.
$event = $this->create_action_event($course->id, $wiki->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Now log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('view'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_wiki_core_calendar_provide_event_action_already_completed(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->enablecompletion = 1;
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Get some additional data.
$cm = get_coursemodule_from_instance('wiki', $wiki->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $wiki->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory);
// Ensure result was null.
$this->assertNull($actionevent);
}
public function test_wiki_core_calendar_provide_event_action_already_completed_for_user(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->enablecompletion = 1;
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Create 2 students and enrol them into the course.
$student1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
$student2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Get some additional data.
$cm = get_coursemodule_from_instance('wiki', $wiki->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $wiki->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed for the $student1.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm, $student1->id);
// Now log in as $student2.
$this->setUser($student2);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for $student1.
$actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory, $student1->id);
// Ensure result was null.
$this->assertNull($actionevent);
}
/**
* Creates an action event.
*
* @param int $courseid The course id.
* @param int $instanceid The instance id.
* @param string $eventtype The event type.
* @return bool|calendar_event
*/
private function create_action_event($courseid, $instanceid, $eventtype) {
$event = new \stdClass();
$event->name = 'Calendar event';
$event->modulename = 'wiki';
$event->courseid = $courseid;
$event->instance = $instanceid;
$event->type = CALENDAR_EVENT_TYPE_ACTION;
$event->eventtype = $eventtype;
$event->timestart = time();
return \calendar_event::create($event);
}
}
+654
View File
@@ -0,0 +1,654 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Data provider tests.
*
* @package mod_wiki
* @category test
* @copyright 2018 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_wiki\privacy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use mod_wiki\privacy\provider;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\writer;
require_once($CFG->dirroot.'/mod/wiki/locallib.php');
/**
* Data provider testcase class.
*
* @package mod_wiki
* @category test
* @copyright 2018 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
/** @var array */
protected $users = [];
/** @var array */
protected $pages = [];
/** @var array */
protected $contexts = [];
/** @var array */
protected $subwikis = [];
/** @var array */
protected $pagepaths = [];
/**
* Set up for each test.
*
* There are three users and four wikis.
* 1 : collaborative wiki, has context $this->contexts[1] and has a single subwiki $this->subwikis[1]
* 2 : individual wiki, has context $this->contexts[2] and three subwikis (one for each user):
* $this->subwikis[21], $this->subwikis[22], $this->subwikis[23],
* the subwiki for the third user is empty
* 3 : collaborative wiki, has context $this->contexts[3] and has a single subwiki $this->subwikis[3]
* 4 : collaborative wiki, has context $this->contexts[4], this wiki is empty
*
* Each subwiki (except for "23") has pages, for example, in $this->subwiki[1] there are pages
* $this->pages[1][1], $this->pages[1][2] and $this->pages[1][3]
* In the export data they have paths:
* $this->pagepaths[1][1], $this->pagepaths[1][2], $this->pagepaths[1][3]
*/
public function setUp(): void {
global $DB;
$this->resetAfterTest();
$dg = $this->getDataGenerator();
$course = $dg->create_course();
$this->users[1] = $dg->create_user();
$this->users[2] = $dg->create_user();
$this->users[3] = $dg->create_user();
$this->users[4] = $dg->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($this->users[1]->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($this->users[2]->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($this->users[3]->id, $course->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($this->users[4]->id, $course->id, $studentrole->id, 'manual');
$cm1 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]);
$cm2 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id, 'wikimode' => 'individual']);
$cm3 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]);
$cm4 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]); // Empty.
// User1.
$this->setUser($this->users[1]);
// Create and modify pages in collaborative wiki.
$this->pages[1][1] = $this->create_first_page($cm1);
$this->pages[1][2] = $this->create_page($cm1, ['content' => 'initial content']);
$this->update_page($cm1, $this->pages[1][2], ['content' => 'update1 <img src="@@PLUGINFILE@@/Dog%20jump.jpg">']);
$this->attach_file($cm1, "Dog jump.jpg", 'jpg:Doggy');
$this->update_page($cm1, $this->pages[1][2], ['content' => 'update2']);
// Create pages in individual wiki, add files that are not used in text.
$this->pages[21][1] = $this->create_first_page($cm2);
$this->pages[21][2] = $this->create_page($cm2);
$this->attach_file($cm2, "mycat.jpg", 'jpg:Cat');
// User2.
$this->setUser($this->users[2]);
// Modify existing pages in the first collaborative wiki.
$this->update_page($cm1, $this->pages[1][2], ['content' => 'update3 <img src="@@PLUGINFILE@@/Hamster.jpg">']);
$this->attach_file($cm1, "Hamster.jpg", 'jpg:Hamster');
// Create pages in individual wiki.
$this->pages[22][1] = $this->create_first_page($cm2);
$this->pages[22][2] = $this->create_page($cm2);
// Create pages in the third wiki.
$this->pages[3][1] = $this->create_first_page($cm3);
// User3 (testing locks and empty subwiki).
$this->setUser($this->users[3]);
// Create a subwiki in the individual wiki without any pages.
$subwiki23 = $dg->get_plugin_generator('mod_wiki')->get_subwiki($cm2);
// Create a page in the first wiki and then lock it.
$this->pages[1][3] = $this->create_page($cm1);
wiki_set_lock($this->pages[1][3]->id, $this->users[3]->id, null, true);
// Lock a page in the third wiki without having any revisions on it.
wiki_set_lock($this->pages[3][1]->id, $this->users[3]->id, null, true);
// User 4 - added to the first wiki, so all users are not part of all edited contexts.
$this->setUser($this->users[4]);
$this->pages[1][4] = $this->create_page($cm1);
$this->subwikis = [
1 => $this->pages[1][1]->subwikiid,
21 => $this->pages[21][1]->subwikiid,
22 => $this->pages[22][1]->subwikiid,
23 => $subwiki23,
3 => $this->pages[3][1]->subwikiid,
];
$this->contexts = [
1 => \context_module::instance($cm1->cmid),
2 => \context_module::instance($cm2->cmid),
3 => \context_module::instance($cm3->cmid),
4 => \context_module::instance($cm4->cmid),
];
$this->pagepaths = [
1 => [
1 => $this->pages[1][1]->id . ' ' . $this->pages[1][1]->title,
2 => $this->pages[1][2]->id . ' ' . $this->pages[1][2]->title,
3 => $this->pages[1][3]->id . ' ' . $this->pages[1][3]->title,
4 => $this->pages[1][4]->id . ' ' . $this->pages[1][4]->title,
],
21 => [
1 => $this->pages[21][1]->id . ' ' . $this->pages[21][1]->title,
2 => $this->pages[21][2]->id . ' ' . $this->pages[21][2]->title,
],
22 => [
1 => $this->pages[22][1]->id . ' ' . $this->pages[22][1]->title,
2 => $this->pages[22][2]->id . ' ' . $this->pages[22][2]->title,
],
3 => [
1 => $this->pages[3][1]->id . ' ' . $this->pages[3][1]->title,
]
];
}
/**
* Generate first page in wiki as current user
*
* @param stdClass $wiki
* @param array $record
* @return mixed
*/
protected function create_first_page($wiki, $record = []) {
$dg = $this->getDataGenerator();
$wg = $dg->get_plugin_generator('mod_wiki');
return $wg->create_first_page($wiki, $record);
}
/**
* Generate a page in wiki as current user
*
* @param stdClass $wiki
* @param array $record
* @return mixed
*/
protected function create_page($wiki, $record = []) {
$dg = $this->getDataGenerator();
$wg = $dg->get_plugin_generator('mod_wiki');
return $wg->create_page($wiki, $record);
}
/**
* Update an existing page in wiki as current user
*
* @param stdClass $wiki
* @param stdClass $page
* @param array $record
* @return mixed
*/
protected function update_page($wiki, $page, $record = []) {
$dg = $this->getDataGenerator();
$wg = $dg->get_plugin_generator('mod_wiki');
return $wg->create_page($wiki, ['title' => $page->title] + $record);
}
/**
* Attach file to a wiki as a current user
*
* @param stdClass $wiki
* @param string $filename
* @param string $filecontent
* @return stored_file
*/
protected function attach_file($wiki, $filename, $filecontent) {
$dg = $this->getDataGenerator();
$wg = $dg->get_plugin_generator('mod_wiki');
$subwikiid = $wg->get_subwiki($wiki);
$fs = get_file_storage();
return $fs->create_file_from_string([
'contextid' => \context_module::instance($wiki->cmid)->id,
'component' => 'mod_wiki',
'filearea' => 'attachments',
'itemid' => $subwikiid,
'filepath' => '/',
'filename' => $filename,
], $filecontent);
}
/**
* Test getting the contexts for a user.
*/
public function test_get_contexts_for_userid(): void {
// Get contexts for the first user.
$contextids = provider::get_contexts_for_userid($this->users[1]->id)->get_contextids();
$this->assertEqualsCanonicalizing([
$this->contexts[1]->id,
$this->contexts[2]->id,
], $contextids);
// Get contexts for the second user.
$contextids = provider::get_contexts_for_userid($this->users[2]->id)->get_contextids();
$this->assertEqualsCanonicalizing([
$this->contexts[1]->id,
$this->contexts[2]->id,
$this->contexts[3]->id,
], $contextids);
// Get contexts for the third user.
$contextids = provider::get_contexts_for_userid($this->users[3]->id)->get_contextids();
$this->assertEqualsCanonicalizing([
$this->contexts[1]->id,
$this->contexts[2]->id,
$this->contexts[3]->id,
], $contextids);
}
/**
* Test getting the users within a context.
*/
public function test_get_users_in_context(): void {
global $DB;
$component = 'mod_wiki';
// Add a comment from user 4 in context 3.
$this->setUser($this->users[4]);
$this->add_comment($this->pages[3][1], 'Look at me, getting involved!');
// Ensure userlist for context 1 contains all users.
$userlist = new \core_privacy\local\request\userlist($this->contexts[1], $component);
provider::get_users_in_context($userlist);
$this->assertCount(4, $userlist);
$expected = [$this->users[1]->id, $this->users[2]->id, $this->users[3]->id, $this->users[4]->id];
$actual = $userlist->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);
// Ensure userlist for context 2 contains users 1-3 only.
$userlist = new \core_privacy\local\request\userlist($this->contexts[2], $component);
provider::get_users_in_context($userlist);
$this->assertCount(3, $userlist);
$expected = [$this->users[1]->id, $this->users[2]->id, $this->users[3]->id];
$actual = $userlist->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);
// Ensure userlist for context 3 contains users 2, 3 and 4 only.
$userlist = new \core_privacy\local\request\userlist($this->contexts[3], $component);
provider::get_users_in_context($userlist);
$this->assertCount(3, $userlist);
$expected = [$this->users[2]->id, $this->users[3]->id, $this->users[4]->id];
$actual = $userlist->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);
// Ensure userlist for context 4 is empty.
$userlist = new \core_privacy\local\request\userlist($this->contexts[4], $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
}
/**
* Export data for user 1
*/
public function test_export_user_data1(): void {
// Export all contexts for the first user.
$contextids = array_values(array_map(function($c) {
return $c->id;
}, $this->contexts));
$appctx = new approved_contextlist($this->users[1], 'mod_wiki', $contextids);
provider::export_user_data($appctx);
// First wiki has two pages ever touched by this user.
$data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
$this->assertEquals([
$this->pagepaths[1][1],
$this->pagepaths[1][2]
], array_keys($data));
// First page was initially created by this user and all its information is returned to this user.
$data11 = $data[$this->pagepaths[1][1]];
$this->assertEquals($this->pages[1][1]->cachedcontent, $data11['page']['cachedcontent']);
$this->assertNotEmpty($data11['page']['timecreated']);
// Wiki creates two revisions when page is created, first one with empty content.
$this->assertEquals(2, count($data11['revisions']));
$this->assertFalse(array_key_exists('locks', $data11));
// Only one file is returned that was in the revision made by this user.
// The second page was last modified by a different user, so userid in the wiki_pages table is different,
// additional page information is not exported.
$data12 = $data[$this->pagepaths[1][2]];
$this->assertFalse(isset($data12['page']['timecreated']));
// There are two revisions for creating the page and two additional revisions made by this user.
$this->assertEquals(4, count($data12['revisions']));
$lastrevision = array_pop($data12['revisions']);
$this->assertEquals('update2', $lastrevision['content']);
// There is one file that was used in this user's contents - "Dog face.jpg" and one file in page cachedcontents.
$files = writer::with_context($this->contexts[1])->get_files([$this->subwikis[1]]);
$this->assertEqualsCanonicalizing(['Dog jump.jpg', 'Hamster.jpg'], array_keys($files));
// Second (individual) wiki for the first user, two pages are returned for this user's subwiki.
$data = writer::with_context($this->contexts[2])->get_related_data([$this->subwikis[21]]);
$this->assertEquals([
$this->pagepaths[21][1],
$this->pagepaths[21][2]
], array_keys($data));
$files = writer::with_context($this->contexts[2])->get_files([$this->subwikis[21]]);
$this->assertEquals(['mycat.jpg'], array_keys($files));
// Second (individual) wiki for the first user, nothing is returned for the second user's subwiki.
$this->assertFalse(writer::with_context($this->contexts[2])->has_any_data([$this->subwikis[22]]));
// Third wiki for the first user, there were no contributions by the first user.
$this->assertFalse(writer::with_context($this->contexts[3])->has_any_data([$this->subwikis[3]]));
}
/**
* Test export data for user 2
*/
public function test_export_user_data2(): void {
// Export all contexts for the second user.
$contextids = array_values(array_map(function($c) {
return $c->id;
}, $this->contexts));
$appctx = new approved_contextlist($this->users[2], 'mod_wiki', $contextids);
provider::export_user_data($appctx);
// First wiki - this user only modified the second page.
$data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
$this->assertEquals([
$this->pagepaths[1][2]
], array_keys($data));
// This user was the last one to modify this page, so the page info is returned.
$data12 = $data[$this->pagepaths[1][2]];
$this->assertEquals('update3 <img src="files/Hamster.jpg" alt="Hamster.jpg" />', trim($data12['page']['cachedcontent']));
// He made one revision.
$this->assertEquals(1, count($data12['revisions']));
$lastrevision = reset($data12['revisions']);
$this->assertEquals('update3 <img src="files/Hamster.jpg">', trim($lastrevision['content']));
// Only one file was used in the first wiki by this user - Hamster.jpg.
$files = writer::with_context($this->contexts[1])->get_files([$this->subwikis[1]]);
$this->assertEquals(['Hamster.jpg'], array_keys($files));
// Export second (individual) wiki, nothing is returned for the other user's subwiki.
$this->assertFalse(writer::with_context($this->contexts[2])->has_any_data([$this->subwikis[21]]));
// Export second (individual) wiki, two pages are returned for this user's subwiki.
$data = writer::with_context($this->contexts[2])->get_related_data([$this->subwikis[22]]);
$this->assertEquals([
$this->pagepaths[22][1],
$this->pagepaths[22][2]
], array_keys($data));
$files = writer::with_context($this->contexts[2])->get_files([$this->subwikis[22]]);
$this->assertEmpty($files);
// Second user made contributions to the third wiki.
$data = writer::with_context($this->contexts[3])->get_related_data([$this->subwikis[3]]);
$this->assertEquals([
$this->pagepaths[3][1]
], array_keys($data));
$files = writer::with_context($this->contexts[3])->get_files([$this->subwikis[3]]);
$this->assertEmpty($files);
}
/**
* Test export data for user 3 (locks, empty individual wiki)
*/
public function test_export_user_data3(): void {
// Export all contexts for the third user.
$contextids = array_values(array_map(function($c) {
return $c->id;
}, $this->contexts));
$appctx = new approved_contextlist($this->users[3], 'mod_wiki', $contextids);
provider::export_user_data($appctx);
// For the third page of the first wiki there are 2 revisions and 1 lock.
$data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
$this->assertEquals([
$this->pagepaths[1][3]
], array_keys($data));
$data13 = $data[$this->pagepaths[1][3]];
$this->assertNotEmpty($data13['page']['timecreated']);
$this->assertEquals(2, count($data13['revisions']));
$this->assertEquals(1, count($data13['locks']));
$files = writer::with_context($this->contexts[1])->get_files([$this->subwikis[1]]);
$this->assertEmpty($files);
// Empty individual wiki.
$this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
$data = writer::with_context($this->contexts[2])->get_data([$this->subwikis[23]]);
$this->assertEquals((object)[
'groupid' => 0,
'userid' => $this->users[3]->id
], $data);
$files = writer::with_context($this->contexts[2])->get_files([$this->subwikis[23]]);
$this->assertEmpty($files);
// For the third wiki there is no page information, no revisions and one lock.
$data = writer::with_context($this->contexts[3])->get_related_data([$this->subwikis[3]]);
$this->assertEquals([
$this->pagepaths[3][1]
], array_keys($data));
$data31 = $data[$this->pagepaths[3][1]];
$this->assertTrue(empty($data31['page']['timecreated']));
$this->assertTrue(empty($data31['revisions']));
$this->assertEquals(1, count($data31['locks']));
$files = writer::with_context($this->contexts[3])->get_files([$this->subwikis[3]]);
$this->assertEmpty($files);
// No data for the forth wiki.
$this->assertFalse(writer::with_context($this->contexts[4])->has_any_data());
}
/**
* Creates a comment object
*
* @param stdClass $page
* @param string $text
* @return comment The comment object.
*/
protected function add_comment($page, $text) {
global $DB, $CFG, $USER;
require_once($CFG->dirroot . '/comment/lib.php');
$record = $DB->get_record_sql('SELECT cm.id, cm.course FROM {course_modules} cm
JOIN {modules} m ON m.name = ? AND m.id = cm.module
JOIN {wiki} w ON cm.instance = w.id
JOIN {wiki_subwikis} s ON s.wikiid = w.id
WHERE s.id=?', ['wiki', $page->subwikiid]);
$context = \context_module::instance($record->id);
$args = new \stdClass;
$args->context = $context;
$args->courseid = $record->course;
$args->area = 'wiki_page';
$args->itemid = $page->id;
$args->component = 'mod_wiki';
$comment = new \comment($args);
$comment->set_post_permission(true);
$comment->add($text);
return $comment;
}
/**
* Test export data when there are comments.
*/
public function test_export_user_data_with_comments(): void {
global $DB;
// Comment on each page in the first wiki as the first user.
$this->setUser($this->users[1]);
$this->add_comment($this->pages[1][1], 'Hello111');
$this->add_comment($this->pages[1][2], 'Hello112');
$this->add_comment($this->pages[1][3], 'Hello113');
// Comment on second and third page as the third user.
$this->setUser($this->users[3]);
$this->add_comment($this->pages[1][2], 'Hello312');
$this->add_comment($this->pages[1][3], 'Hello313');
// Export all contexts for the third user.
$contextids = array_values(array_map(function($c) {
return $c->id;
}, $this->contexts));
$appctx = new approved_contextlist($this->users[3], 'mod_wiki', $contextids);
provider::export_user_data($appctx);
$data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
// Now user has two pages (comparing to previous test where he had one).
$this->assertEquals([
$this->pagepaths[1][2],
$this->pagepaths[1][3]
], array_keys($data));
// Page 1-2 was exported and it has one comment that this user made (comment from another user was not exported).
$data12 = $data[$this->pagepaths[1][2]];
$this->assertTrue(empty($data12['page']['timecreated']));
$this->assertTrue(empty($data12['revisions']));
$this->assertTrue(empty($data12['locks']));
$this->assertEquals(1, count($data12['page']['comments']));
// Page 1-3 was exported same way as in the previous test and it has two comments.
$data13 = $data[$this->pagepaths[1][3]];
$this->assertNotEmpty($data13['page']['timecreated']);
$this->assertEquals(2, count($data13['revisions']));
$this->assertEquals(1, count($data13['locks']));
$this->assertEquals(2, count($data13['page']['comments']));
}
/**
* Test for delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context(): void {
provider::delete_data_for_all_users_in_context($this->contexts[1]);
$appctx = new approved_contextlist($this->users[1], 'mod_wiki',
[$this->contexts[1]->id, $this->contexts[2]->id]);
provider::export_user_data($appctx);
$this->assertFalse(writer::with_context($this->contexts[1])->has_any_data());
$this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
writer::reset();
$appctx = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[1]->id]);
provider::export_user_data($appctx);
$this->assertFalse(writer::with_context($this->contexts[1])->has_any_data());
writer::reset();
$appctx = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[1]->id]);
provider::export_user_data($appctx);
$this->assertFalse(writer::with_context($this->contexts[1])->has_any_data());
}
/**
* Test for delete_data_for_user().
*/
public function test_delete_data_for_user(): void {
$appctx = new approved_contextlist($this->users[1], 'mod_wiki',
[$this->contexts[1]->id, $this->contexts[1]->id]);
provider::delete_data_for_user($appctx);
provider::export_user_data($appctx);
$this->assertTrue(writer::with_context($this->contexts[1])->has_any_data());
$this->assertFalse(writer::with_context($this->contexts[2])->has_any_data());
}
/**
* Test for delete_data_for_users().
*/
public function test_delete_data_for_users(): void {
$component = 'mod_wiki';
// Ensure data exists within context 2 - individual wikis.
// Since each user owns their own subwiki in this context, they can be deleted.
$u1ctx2 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u1ctx2);
$u2ctx2 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u2ctx2);
$u3ctx2 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u3ctx2);
$this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
writer::reset();
// Delete user 1 and 2 data, user 3's wiki still remains.
$approveduserids = [$this->users[1]->id, $this->users[2]->id];
$approvedlist = new approved_userlist($this->contexts[2], $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
$u1ctx2 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u1ctx2);
$u2ctx2 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u2ctx2);
$u3ctx2 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u3ctx2);
$this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
writer::reset();
// Delete user 3's wiki. All 3 subwikis now deleted, so ensure no data is found in this context.
$approveduserids = [$this->users[3]->id];
$approvedlist = new approved_userlist($this->contexts[2], $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
$u1ctx2 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u1ctx2);
$u2ctx2 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u2ctx2);
$u3ctx2 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[2]->id]);
provider::export_user_data($u3ctx2);
$this->assertFalse(writer::with_context($this->contexts[2])->has_any_data());
writer::reset();
// Ensure Context 1 still contains data.
$u1ctx1 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[1]->id]);
provider::export_user_data($u1ctx1);
$u2ctx1 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[1]->id]);
provider::export_user_data($u2ctx1);
$u3ctx1 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[1]->id]);
provider::export_user_data($u3ctx1);
$this->assertTrue(writer::with_context($this->contexts[1])->has_any_data());
}
}
+230
View File
@@ -0,0 +1,230 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Wiki global search unit tests.
*
* @package mod_wiki
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_wiki\search;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
/**
* Provides the unit tests for wiki global search.
*
* @package mod_wiki
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class search_test extends \advanced_testcase {
/**
* @var string Area id
*/
protected $wikicollabpageareaid = null;
public function setUp(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
set_config('enableglobalsearch', true);
$this->wikicollabpageareaid = \core_search\manager::generate_areaid('mod_wiki', 'collaborative_page');
// Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
$search = \testable_core_search::instance();
}
/**
* Availability.
*
* @return void
*/
public function test_search_enabled(): void {
$searcharea = \core_search\manager::get_search_area($this->wikicollabpageareaid);
list($componentname, $varname) = $searcharea->get_config_var_name();
// Enabled by default once global search is enabled.
$this->assertTrue($searcharea->is_enabled());
set_config($varname . '_enabled', 0, $componentname);
$this->assertFalse($searcharea->is_enabled());
set_config($varname . '_enabled', 1, $componentname);
$this->assertTrue($searcharea->is_enabled());
}
/**
* Indexing collaborative page contents.
*
* @return void
*/
public function test_collaborative_page_indexing(): void {
global $DB;
// Returns the instance as long as the area is supported.
$searcharea = \core_search\manager::get_search_area($this->wikicollabpageareaid);
$this->assertInstanceOf('\mod_wiki\search\collaborative_page', $searcharea);
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$course1 = self::getDataGenerator()->create_course();
$collabwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course1->id));
$cpage1 = $wikigenerator->create_first_page($collabwiki);
$cpage2 = $wikigenerator->create_content($collabwiki);
$cpage3 = $wikigenerator->create_content($collabwiki);
$indwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course1->id, 'wikimode' => 'individual'));
$ipage1 = $wikigenerator->create_first_page($indwiki);
$ipage2 = $wikigenerator->create_content($indwiki);
$ipage3 = $wikigenerator->create_content($indwiki);
// All records.
$recordset = $searcharea->get_recordset_by_timestamp(0);
$this->assertTrue($recordset->valid());
$nrecords = 0;
foreach ($recordset as $record) {
$this->assertInstanceOf('stdClass', $record);
$doc = $searcharea->get_document($record);
$this->assertInstanceOf('\core_search\document', $doc);
// Static caches are working.
$dbreads = $DB->perf_get_reads();
$doc = $searcharea->get_document($record);
$this->assertEquals($dbreads, $DB->perf_get_reads());
$this->assertInstanceOf('\core_search\document', $doc);
$nrecords++;
}
// If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
$recordset->close();
// We expect 3 (not 6) pages.
$this->assertEquals(3, $nrecords);
// The +2 is to prevent race conditions.
$recordset = $searcharea->get_recordset_by_timestamp(time() + 2);
// No new records.
$this->assertFalse($recordset->valid());
$recordset->close();
// Add another wiki with one page.
$collabwiki2 = $this->getDataGenerator()->create_module('wiki', ['course' => $course1->id]);
$wikigenerator->create_first_page($collabwiki2);
// Test indexing contexts.
$rs = $searcharea->get_document_recordset(0, \context_module::instance($collabwiki->cmid));
$this->assertEquals(3, iterator_count($rs));
$rs->close();
$rs = $searcharea->get_document_recordset(0, \context_module::instance($collabwiki2->cmid));
$this->assertEquals(1, iterator_count($rs));
$rs->close();
$rs = $searcharea->get_document_recordset(0, \context_course::instance($course1->id));
$this->assertEquals(4, iterator_count($rs));
$rs->close();
}
/**
* Group support for wiki entries.
*/
public function test_collaborative_page_group_support(): void {
// Get the search area and test generators.
$searcharea = \core_search\manager::get_search_area($this->wikicollabpageareaid);
$generator = $this->getDataGenerator();
$wikigenerator = $generator->get_plugin_generator('mod_wiki');
// Create a course, a user, and two groups.
$course = $generator->create_course();
$user = $generator->create_user();
$generator->enrol_user($user->id, $course->id, 'teacher');
$group1 = $generator->create_group(['courseid' => $course->id]);
$group2 = $generator->create_group(['courseid' => $course->id]);
// Separate groups wiki.
$wiki = self::getDataGenerator()->create_module('wiki', ['course' => $course->id,
'groupmode' => SEPARATEGROUPS]);
// Create page with each group and one for all groups.
$wikigenerator->create_page($wiki, ['title' => 'G1', 'group' => $group1->id]);
$wikigenerator->create_page($wiki, ['title' => 'G2', 'group' => $group2->id]);
$wikigenerator->create_page($wiki, ['title' => 'ALLGROUPS']);
// Do the indexing of all 3 pages.
$rs = $searcharea->get_recordset_by_timestamp(0);
$results = [];
foreach ($rs as $rec) {
$results[$rec->title] = $rec;
}
$rs->close();
$this->assertCount(3, $results);
// Check each document has the correct groupid.
$doc = $searcharea->get_document($results['G1']);
$this->assertTrue($doc->is_set('groupid'));
$this->assertEquals($group1->id, $doc->get('groupid'));
$doc = $searcharea->get_document($results['G2']);
$this->assertTrue($doc->is_set('groupid'));
$this->assertEquals($group2->id, $doc->get('groupid'));
$doc = $searcharea->get_document($results['ALLGROUPS']);
$this->assertFalse($doc->is_set('groupid'));
// While we're here, also test that the search area requests restriction by group.
$modinfo = get_fast_modinfo($course);
$this->assertTrue($searcharea->restrict_cm_access_by_group($modinfo->get_cm($wiki->cmid)));
// In visible groups mode, it won't request restriction by group.
set_coursemodule_groupmode($wiki->cmid, VISIBLEGROUPS);
$modinfo = get_fast_modinfo($course);
$this->assertFalse($searcharea->restrict_cm_access_by_group($modinfo->get_cm($wiki->cmid)));
}
/**
* Check collaborative_page check access.
*
* @return void
*/
public function test_collaborative_page_check_access(): void {
global $DB;
// Returns the instance as long as the area is supported.
$searcharea = \core_search\manager::get_search_area($this->wikicollabpageareaid);
$this->assertInstanceOf('\mod_wiki\search\collaborative_page', $searcharea);
$user1 = self::getDataGenerator()->create_user();
$course1 = self::getDataGenerator()->create_course();
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$collabwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course1->id));
$cpage1 = $wikigenerator->create_first_page($collabwiki);
$this->setAdminUser();
$this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($cpage1->id));
$this->setUser($user1);
$this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($cpage1->id));
$this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access($cpage1->id + 10));
}
}
+383
View File
@@ -0,0 +1,383 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
namespace mod_wiki;
use wiki_parser_proxy;
defined('MOODLE_INTERNAL') || die;
global $CFG;
require_once($CFG->dirroot . '/mod/wiki/parser/parser.php');
/**
* Unit tests for the wiki parser
*
* @package mod_wiki
* @category test
* @copyright 2009 Marc Alier, Jordi Piguillem marc.alier@upc.edu
* @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu
*
* @author Jordi Piguillem
* @author Marc Alier
* @author David Jimenez
* @author Josep Arus
* @author Kenneth Riba
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class wikiparser_test extends \advanced_testcase {
/**
* URL inside the clickable text of some link should not be turned into a new link via the url_tag_rule.
*
* @dataProvider urls_inside_link_text_provider
* @param string $markup Markup of the Wiki page the text is part of.
* @param string $input The input text.
* @param string $output The expected output HTML as a result of the parsed input text.
*/
public function test_urls_inside_link_text(string $markup, string $input, string $output): void {
$parsingresult = wiki_parser_proxy::parse($input, $markup, [
'link_callback' => '/mod/wiki/locallib.php:wiki_parser_link',
'link_callback_args' => ['swid' => 1],
]);
$this->assertStringContainsString($output, $parsingresult['parsed_text']);
}
/**
* Provides data sets for {@see self::test_urls_inside_link_text()}.
*
* @return array
*/
public function urls_inside_link_text_provider() {
return [
'creole implicit link' => [
'markup' => 'creole',
'input' => 'Visit https://site.url for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'creole explicit link' => [
'markup' => 'creole',
'input' => 'Visit [[https://site.url]] for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'creole explicit link with text' => [
'markup' => 'creole',
'input' => 'Visit [[https://site.url|http://www.site.url]] for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'nwiki implicit link' => [
'markup' => 'nwiki',
'input' => 'Visit https://site.url for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'nwiki explicit link' => [
'markup' => 'nwiki',
'input' => 'Visit [https://site.url] for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'nwiki explicit link with space separated text' => [
'markup' => 'nwiki',
'input' => 'Visit [https://site.url http://www.site.url] for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'nwiki explicit link with pipe separated text' => [
'markup' => 'nwiki',
'input' => 'Visit [https://site.url|http://www.site.url] for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'html implicit link' => [
'markup' => 'html',
'input' => 'Visit https://site.url for more information.',
'output' => 'Visit <a href="https://site.url">https://site.url</a> for more information.',
],
'html explicit link with text' => [
'markup' => 'html',
'input' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
'output' => 'Visit <a href="https://site.url">http://www.site.url</a> for more information.',
],
'html wiki link to non-existing page' => [
'markup' => 'html',
'input' => 'Visit [[Another page]] for more information.',
'output' => 'Visit <a class="wiki_newentry" ' .
'href="https://www.example.com/moodle/mod/wiki/create.php?swid=1&amp;title=Another+page&amp;action=new">' .
'Another page</a> for more information.',
],
'html wiki link inside an explicit link' => [
// The explicit href URL takes precedence here, the [[...]] is not turned into a wiki link.
'markup' => 'html',
'input' => 'Visit <a href="https://site.url">[[Another page]]</a> for more information.',
'output' => 'Visit <a href="https://site.url">[[Another page]]</a> for more information.',
],
];
}
function testCreoleMarkup() {
$this->assertTestFiles('creole');
}
function testNwikiMarkup() {
$this->assertTestFiles('nwiki');
}
function testHtmlMarkup() {
$this->assertTestFiles('html');
}
private function assertTestFile($num, $markup) {
if(!file_exists(__DIR__."/fixtures/input/$markup/$num") || !file_exists(__DIR__."/fixtures/output/$markup/$num")) {
return false;
}
$input = file_get_contents(__DIR__."/fixtures/input/$markup/$num");
$output = file_get_contents(__DIR__."/fixtures/output/$markup/$num");
$result = wiki_parser_proxy::parse($input, $markup, array('pretty_print' => true));
//removes line breaks to avoid line break encoding causing tests to fail.
$result['parsed_text'] = preg_replace('~[\r\n]~', '', $result['parsed_text']);
$output = preg_replace('~[\r\n]~', '', $output);
$this->assertEquals($output, $result['parsed_text'], 'Failed asserting that two strings are equal. Markup = '.$markup.", num = $num");
return true;
}
private function assertTestFiles($markup) {
$i = 1;
while($this->assertTestFile($i, $markup)) {
$i++;
}
}
/**
* Check that headings with special characters work as expected with HTML.
*
* - The heading itself is well displayed,
* - The TOC heading is well display,
* - The edit link points to the right page,
* - The links properly works with get_section.
*/
public function test_special_headings(): void {
// First testing HTML markup.
// Test section name using HTML entities.
$input = '<h1>Code &amp; Test</h1>';
$output = '<h3><a name="toc-1"></a>Code &amp; Test <a href="edit.php?pageid=&amp;section=Code+%26amp%3B+Test" '.
'class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Code &amp; Test <a href="edit.php?pageid=&amp;section=Code+%26amp%3B+'.
'Test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'html', 'Code &amp; Test');
$actual = wiki_parser_proxy::parse($input, 'html');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section name using non-ASCII characters.
$input = '<h1>Another áéíóúç€ test</h1>';
$output = '<h3><a name="toc-1"></a>Another áéíóúç€ test <a href="edit.php?pageid=&amp;section=Another+%C'.
'3%A1%C3%A9%C3%AD%C3%B3%C3%BA%C3%A7%E2%82%AC+test" class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Another áéíóúç€ test <a href="edit.php?pageid=&amp;section=Another+%C'.
'3%A1%C3%A9%C3%AD%C3%B3%C3%BA%C3%A7%E2%82%AC+test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'html', 'Another áéíóúç€ test');
$actual = wiki_parser_proxy::parse($input, 'html');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section name with a URL.
$input = '<h1>Another http://moodle.org test</h1>';
$output = '<h3><a name="toc-1"></a>Another <a href="http://moodle.org">http://moodle.org</a> test <a href="edit.php'.
'?pageid=&amp;section=Another+http%3A%2F%2Fmoodle.org+test" class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Another http://moodle.org test <a href="edit.php?pageid=&amp;section='.
'Another+http%3A%2F%2Fmoodle.org+test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'html', 'Another http://moodle.org test');
$actual = wiki_parser_proxy::parse($input, 'html', array(
'link_callback' => '/mod/wiki/locallib.php:wiki_parser_link'
));
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test toc section names being wikilinks.
$input = '<h1>[[Heading 1]]</h1><h2>[[Heading A]]</h2><h2>Heading D</h2>';
$regexpoutput = '!<h3><a name="toc-1"></a>' .
'<a class="wiki_newentry" href.*mod/wiki/create\.php\?.*title=Heading\+1.*action=new.*>Heading 1<.*' .
'<h4><a name="toc-2"></a>' .
'<a class="wiki_newentry" href.*mod/wiki/create\.php\?.*title=Heading\+A.*action=new.*>Heading A<.*' .
'<h4><a name="toc-3"></a>' .
'Heading D!ms';
$regexptoc = '!<a href="#toc-1">Heading 1.*<a href="#toc-2">Heading A</a>.*<a href="#toc-3">Heading D</a>!ms';
$section = wiki_parser_proxy::get_section($input, 'html', 'Another [[wikilinked]] test');
$actual = wiki_parser_proxy::parse($input, 'html', array(
'link_callback' => '/mod/wiki/locallib.php:wiki_parser_link',
'link_callback_args' => array('swid' => 1)
));
$this->assertMatchesRegularExpression($regexpoutput, $actual['parsed_text']);
$this->assertMatchesRegularExpression($regexptoc, $actual['toc']);
// Now going to test Creole markup.
// Note that Creole uses links to the escaped version of the section.
// Test section name using HTML entities.
$input = '= Code & Test =';
$output = '<h3><a name="toc-1"></a>Code &amp; Test <a href="edit.php?pageid=&amp;section=Code+%26amp%3B+Test" '.
'class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Code &amp; Test <a href="edit.php?pageid=&amp;section=Code+%26amp%3B+'.
'Test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'creole', 'Code &amp; Test');
$actual = wiki_parser_proxy::parse($input, 'creole');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section name using non-ASCII characters.
$input = '= Another áéíóúç€ test =';
$output = '<h3><a name="toc-1"></a>Another áéíóúç€ test <a href="edit.php?pageid=&amp;section=Another+%C'.
'3%A1%C3%A9%C3%AD%C3%B3%C3%BA%C3%A7%E2%82%AC+test" class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Another áéíóúç€ test <a href="edit.php?pageid=&amp;section=Another+%C'.
'3%A1%C3%A9%C3%AD%C3%B3%C3%BA%C3%A7%E2%82%AC+test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'creole', 'Another áéíóúç€ test');
$actual = wiki_parser_proxy::parse($input, 'creole');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section name with a URL, creole does not support linking links in a heading.
$input = '= Another http://moodle.org test =';
$output = '<h3><a name="toc-1"></a>Another http://moodle.org test <a href="edit.php'.
'?pageid=&amp;section=Another+http%3A%2F%2Fmoodle.org+test" class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Another http://moodle.org test <a href="edit.php?pageid=&amp;section='.
'Another+http%3A%2F%2Fmoodle.org+test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'creole', 'Another http://moodle.org test');
$actual = wiki_parser_proxy::parse($input, 'creole');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Now going to test NWiki markup.
// Note that Creole uses links to the escaped version of the section.
// Test section name using HTML entities.
$input = '= Code & Test =';
$output = '<h3><a name="toc-1"></a>Code & Test <a href="edit.php?pageid=&amp;section=Code+%26+Test" '.
'class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Code & Test <a href="edit.php?pageid=&amp;section=Code+%26+'.
'Test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'nwiki', 'Code & Test');
$actual = wiki_parser_proxy::parse($input, 'nwiki');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section name using non-ASCII characters.
$input = '= Another áéíóúç€ test =';
$output = '<h3><a name="toc-1"></a>Another áéíóúç€ test <a href="edit.php?pageid=&amp;section=Another+%C'.
'3%A1%C3%A9%C3%AD%C3%B3%C3%BA%C3%A7%E2%82%AC+test" class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Another áéíóúç€ test <a href="edit.php?pageid=&amp;section=Another+%C'.
'3%A1%C3%A9%C3%AD%C3%B3%C3%BA%C3%A7%E2%82%AC+test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'nwiki', 'Another áéíóúç€ test');
$actual = wiki_parser_proxy::parse($input, 'nwiki');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section name with a URL, nwiki does not support linking links in a heading.
$input = '= Another http://moodle.org test =';
$output = '<h3><a name="toc-1"></a>Another http://moodle.org test <a href="edit.php'.
'?pageid=&amp;section=Another+http%3A%2F%2Fmoodle.org+test" class="wiki_edit_section">[edit]</a></h3>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Another http://moodle.org test <a href="edit.php?pageid=&amp;section='.
'Another+http%3A%2F%2Fmoodle.org+test" class="wiki_edit_section">[edit]</a></a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'nwiki', 'Another http://moodle.org test');
$actual = wiki_parser_proxy::parse($input, 'nwiki');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
// Test section names when headings start with level 3.
$input = '<h3>Heading test</h3><h4>Subsection</h4>';
$output = '<h3><a name="toc-1"></a>Heading test <a href="edit.php?pageid=&amp;section=Heading+test" '.
'class="wiki_edit_section">[edit]</a></h3>'. "\n" . '<h4><a name="toc-2"></a>Subsection</h4>' . "\n";
$toc = '<div class="wiki-toc"><p class="wiki-toc-title">Table of contents</p><p class="wiki-toc-section-1 '.
'wiki-toc-section">1. <a href="#toc-1">Heading test <a href="edit.php?pageid=&amp;section=Heading+'.
'test" class="wiki_edit_section">[edit]</a></a></p><p class="wiki-toc-section-2 wiki-toc-section">'.
'1.1. <a href="#toc-2">Subsection</a></p></div>';
$section = wiki_parser_proxy::get_section($input, 'html', 'Heading test');
$actual = wiki_parser_proxy::parse($input, 'html');
$this->assertEquals($output, $actual['parsed_text']);
$this->assertEquals($toc, $actual['toc']);
$this->assertNotEquals(false, $section);
}
/**
* Test that format that are not supported are raising an exception
*
* @param string $format
* @param string $expected
* @covers \wiki_parser_proxy::parse
* @dataProvider format_parser_provider
*/
public function test_format_parser(string $format, string $expected): void {
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$wiki = $generator->create_module('wiki', array_merge(['course' => $course->id, 'defaultformat' => $format]));
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
if ($expected === 'exception') {
$this->expectException(\moodle_exception::class);
}
$page = $wikigenerator->create_page($wiki);
$version = wiki_get_current_version($page->id);
$this->assertEquals($expected, $version->contentformat);
}
/**
* Data provider for test_format_parser
*
* @return array[]
*/
public static function format_parser_provider(): array {
return [
'creole' => [
'data' => 'creole',
'expected' => 'creole',
],
'html' => [
'data' => 'html',
'expected' => 'html',
],
'wikimarkup' => [
'data' => 'nwiki',
'expected' => 'nwiki',
],
'wrong format' => [
'data' => '../wrongformat123',
'expected' => 'exception',
],
];
}
}