MDL-61363 tag: unit tests for tagging in different context

This commit is contained in:
Ryan Wyllie
2018-03-07 10:31:47 +08:00
parent 4c3f4d2c2a
commit 4823de0269
+294
View File
@@ -1289,6 +1289,278 @@ class core_tag_taglib_testcase extends advanced_testcase {
$this->assertEquals($expecteduser3tagnames, $actualuser3tagnames);
}
/**
* set_item_tags should remove any tags that aren't in the given list and should
* add any instances that are missing.
*/
public function test_set_item_tags_no_multiple_context_add_remove_instances() {
$tagnames = ['foo', 'bar', 'baz', 'bop'];
$collid = core_tag_collection::get_default();
$tags = core_tag_tag::create_if_missing($collid, $tagnames);
$user1 = $this->getDataGenerator()->create_user();
$context = context_user::instance($user1->id);
$component = 'core';
$itemtype = 'user';
$itemid = 1;
$tagareas = core_tag_area::get_areas();
$tagarea = $tagareas[$itemtype][$component];
$newtagnames = ['bar', 'baz', 'bop'];
// Make sure the tag area doesn't allow multiple contexts.
core_tag_area::update($tagarea, ['multiplecontexts' => false]);
// Create tag instances in separate contexts.
$this->add_tag_instance($tags['foo'], $component, $itemtype, $itemid, $context);
$this->add_tag_instance($tags['bar'], $component, $itemtype, $itemid, $context);
core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context, $newtagnames);
$result = core_tag_tag::get_item_tags($component, $itemtype, $itemid);
$actualtagnames = array_map(function($record) {
return $record->name;
}, $result);
sort($newtagnames);
sort($actualtagnames);
// The list of tags should match the $newtagnames which means 'foo'
// should have been removed while 'baz' and 'bop' were added. 'bar'
// should remain as it was in the new list of tags.
$this->assertEquals($newtagnames, $actualtagnames);
}
/**
* set_item_tags should set all of the tag instance context ids to the given
* context if the tag area for the items doesn't allow multiple contexts for
* the tag instances.
*/
public function test_set_item_tags_no_multiple_context_updates_context_of_instances() {
$tagnames = ['foo', 'bar'];
$collid = core_tag_collection::get_default();
$tags = core_tag_tag::create_if_missing($collid, $tagnames);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$context1 = context_user::instance($user1->id);
$context2 = context_user::instance($user2->id);
$component = 'core';
$itemtype = 'user';
$itemid = 1;
$tagareas = core_tag_area::get_areas();
$tagarea = $tagareas[$itemtype][$component];
// Make sure the tag area doesn't allow multiple contexts.
core_tag_area::update($tagarea, ['multiplecontexts' => false]);
// Create tag instances in separate contexts.
$this->add_tag_instance($tags['foo'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['bar'], $component, $itemtype, $itemid, $context2);
core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context1, $tagnames);
$result = core_tag_tag::get_item_tags($component, $itemtype, $itemid);
$this->assertCount(count($tagnames), $result);
foreach ($result as $tag) {
// The core user tag area doesn't allow multiple contexts for tag instances
// so set_item_tags should have set all of the tag instance context ids
// to match $context1.
$this->assertEquals($context1->id, $tag->taginstancecontextid);
}
}
/**
* set_item_tags should delete all of the tag instances that don't match
* the new set of tags, regardless of the context that the tag instance
* is in.
*/
public function test_set_item_tags_no_multiple_contex_deletes_old_instancest() {
$tagnames = ['foo', 'bar', 'baz', 'bop'];
$collid = core_tag_collection::get_default();
$tags = core_tag_tag::create_if_missing($collid, $tagnames);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$context1 = context_user::instance($user1->id);
$context2 = context_user::instance($user2->id);
$component = 'core';
$itemtype = 'user';
$itemid = 1;
$expectedtagnames = ['foo', 'baz'];
$tagareas = core_tag_area::get_areas();
$tagarea = $tagareas[$itemtype][$component];
// Make sure the tag area doesn't allow multiple contexts.
core_tag_area::update($tagarea, ['multiplecontexts' => false]);
// Create tag instances in separate contexts.
$this->add_tag_instance($tags['foo'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['bar'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['baz'], $component, $itemtype, $itemid, $context2);
$this->add_tag_instance($tags['bop'], $component, $itemtype, $itemid, $context2);
core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context1, $expectedtagnames);
$result = core_tag_tag::get_item_tags($component, $itemtype, $itemid);
$actualtagnames = array_map(function($record) {
return $record->name;
}, $result);
sort($expectedtagnames);
sort($actualtagnames);
// The list of tags should match the $expectedtagnames.
$this->assertEquals($expectedtagnames, $actualtagnames);
foreach ($result as $tag) {
// The core user tag area doesn't allow multiple contexts for tag instances
// so set_item_tags should have set all of the tag instance context ids
// to match $context1.
$this->assertEquals($context1->id, $tag->taginstancecontextid);
}
}
/**
* set_item_tags should not change tag instances in a different context to the one
* it's opertating on if the tag area allows instances from multiple contexts.
*/
public function test_set_item_tags_allow_multiple_context_doesnt_update_context() {
global $DB;
$tagnames = ['foo', 'bar', 'bop'];
$collid = core_tag_collection::get_default();
$tags = core_tag_tag::create_if_missing($collid, $tagnames);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$context1 = context_user::instance($user1->id);
$context2 = context_user::instance($user2->id);
$component = 'core';
$itemtype = 'user';
$itemid = 1;
$tagareas = core_tag_area::get_areas();
$tagarea = $tagareas[$itemtype][$component];
// Make sure the tag area allows multiple contexts.
core_tag_area::update($tagarea, ['multiplecontexts' => true]);
// Create tag instances in separate contexts.
$this->add_tag_instance($tags['foo'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['bar'], $component, $itemtype, $itemid, $context2);
// Set the list of tags for $context1. This includes a tag that already exists
// in that context and a new tag. There is another tag, 'bar', that exists in a
// different context ($context2) that should be ignored.
core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context1, ['foo', 'bop']);
$result = core_tag_tag::get_item_tags($component, $itemtype, $itemid);
$actualtagnames = array_map(function($record) {
return $record->name;
}, $result);
sort($tagnames);
sort($actualtagnames);
// The list of tags should match the $tagnames.
$this->assertEquals($tagnames, $actualtagnames);
foreach ($result as $tag) {
if ($tag->name == 'bar') {
// The tag instance for 'bar' should have been left untouched
// because it was in a different context.
$this->assertEquals($context2->id, $tag->taginstancecontextid);
} else {
$this->assertEquals($context1->id, $tag->taginstancecontextid);
}
}
}
/**
* set_item_tags should delete all of the tag instances that don't match
* the new set of tags only in the same context if the tag area allows
* multiple contexts.
*/
public function test_set_item_tags_allow_multiple_context_deletes_instances_in_same_context() {
$tagnames = ['foo', 'bar', 'baz', 'bop'];
$collid = core_tag_collection::get_default();
$tags = core_tag_tag::create_if_missing($collid, $tagnames);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$context1 = context_user::instance($user1->id);
$context2 = context_user::instance($user2->id);
$component = 'core';
$itemtype = 'user';
$itemid = 1;
$expectedtagnames = ['foo', 'bar', 'bop'];
$tagareas = core_tag_area::get_areas();
$tagarea = $tagareas[$itemtype][$component];
// Make sure the tag area allows multiple contexts.
core_tag_area::update($tagarea, ['multiplecontexts' => true]);
// Create tag instances in separate contexts.
$this->add_tag_instance($tags['foo'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['bar'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['baz'], $component, $itemtype, $itemid, $context1);
$this->add_tag_instance($tags['bop'], $component, $itemtype, $itemid, $context2);
core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context1, ['foo', 'bar']);
$result = core_tag_tag::get_item_tags($component, $itemtype, $itemid);
$actualtagnames = array_map(function($record) {
return $record->name;
}, $result);
sort($expectedtagnames);
sort($actualtagnames);
// The list of tags should match the $expectedtagnames, which includes the
// tag 'bop' because it was in a different context to the one being set
// even though it wasn't in the new set of tags.
$this->assertEquals($expectedtagnames, $actualtagnames);
}
/**
* set_item_tags should allow multiple instances of the same tag in different
* contexts if the tag area allows multiple contexts.
*/
public function test_set_item_tags_allow_multiple_context_same_tag_multiple_contexts() {
$tagnames = ['foo'];
$collid = core_tag_collection::get_default();
$tags = core_tag_tag::create_if_missing($collid, $tagnames);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$context1 = context_user::instance($user1->id);
$context2 = context_user::instance($user2->id);
$component = 'core';
$itemtype = 'user';
$itemid = 1;
$expectedtagnames = ['foo', 'bar', 'bop'];
$tagareas = core_tag_area::get_areas();
$tagarea = $tagareas[$itemtype][$component];
// Make sure the tag area allows multiple contexts.
core_tag_area::update($tagarea, ['multiplecontexts' => true]);
// Create first instance of 'foo' in $context1.
$this->add_tag_instance($tags['foo'], $component, $itemtype, $itemid, $context1);
core_tag_tag::set_item_tags($component, $itemtype, $itemid, $context2, ['foo']);
$result = core_tag_tag::get_item_tags($component, $itemtype, $itemid);
$tagsbycontext = array_reduce($result, function($carry, $tag) {
$contextid = $tag->taginstancecontextid;
if (isset($carry[$contextid])) {
$carry[$contextid][] = $tag;
} else {
$carry[$contextid] = [$tag];
}
return $carry;
}, []);
// The result should be two tag instances of 'foo' in each of the
// two contexts, $context1 and $context2.
$this->assertCount(1, $tagsbycontext[$context1->id]);
$this->assertCount(1, $tagsbycontext[$context2->id]);
$this->assertEquals('foo', $tagsbycontext[$context1->id][0]->name);
$this->assertEquals('foo', $tagsbycontext[$context2->id][0]->name);
}
/**
* Help method to return sorted array of names of correlated tags to use for assertions
* @param core_tag $tag
@@ -1301,4 +1573,26 @@ class core_tag_taglib_testcase extends advanced_testcase {
sort($rv);
return array_values($rv);
}
/**
* Add a tag instance.
*
* @param core_tag_tag $tag
* @param string $component
* @param string $itemtype
* @param int $itemid
* @param context $context
* @return stdClass
*/
protected function add_tag_instance(core_tag_tag $tag, $component, $itemtype, $itemid, $context) {
global $DB;
$record = (array) $tag->to_object();
$record['tagid'] = $record['id'];
$record['component'] = $component;
$record['itemtype'] = $itemtype;
$record['itemid'] = $itemid;
$record['contextid'] = $context->id;
$record['id'] = $DB->insert_record('tag_instance', $record);
return $record;
}
}