public function testUserCanAccessMethod_projectPageDto_NotAMember_false()
 {
     $userId = $this->environ->createUser('user', 'user', '*****@*****.**', SystemRoles::USER);
     $project = $this->environ->createProject('projectForTest', 'projTestCode');
     $project->appName = 'sfchecks';
     $project->write();
     $projectId = $project->id->asString();
     $project = ProjectModel::getById($projectId);
     $rh = new RightsHelper($userId, $project, $this->environ->website);
     $result = $rh->userCanAccessMethod('project_pageDto', array());
     $this->assertFalse($result);
 }
 public function testEncode_ArchivedText_ManagerCanViewContributorCannot()
 {
     $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $managerId = $this->environ->createUser("manager", "manager", "*****@*****.**");
     $contributorId = $this->environ->createUser("contributor1", "contributor1", "*****@*****.**");
     $project->addUser($managerId, ProjectRoles::MANAGER);
     $project->addUser($contributorId, ProjectRoles::CONTRIBUTOR);
     $project->write();
     // Question not archived but Text is archived
     $text = new TextModel($project);
     $text->title = "Text 1";
     $text->isArchived = true;
     $textId = $text->write();
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     $dto = QuestionCommentDto::encode($project->id->asString(), $questionId, $managerId);
     // Manager can view Question of archived Text
     $this->assertEqual($dto['question']['title'], 'the question');
     // Contributor cannot view Question of archived Text, throw Exception
     $this->environ->inhibitErrorDisplay();
     $this->expectException();
     $dto = QuestionCommentDto::encode($project->id->asString(), $questionId, $contributorId);
     // nothing runs in the current test function after an exception. IJH 2014-11
 }
 public function testProjectCodeExists_codeDoesNotExist_false()
 {
     $this->environ->clean();
     $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $project->write();
     $this->assertFalse(ProjectCommands::projectCodeExists('randomcode'));
 }
 public function testGetProperties_ConstructsCorrectTypes()
 {
     $environ = new MongoTestEnvironment();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $entry = new LexEntryModel($project);
     $this->assertInstanceOf(ArrayOf::class, $entry->senses);
     $this->assertInstanceOf(MapOf::class, $entry->customFields);
     $this->assertInstanceOf(LexAuthorInfo::class, $entry->authorInfo);
     $this->assertInstanceOf(LexMultiText::class, $entry->lexeme);
     $this->assertInstanceOf(LexMultiText::class, $entry->pronunciation);
     $this->assertInstanceOf(LexMultiText::class, $entry->cvPattern);
     $this->assertInstanceOf(LexMultiText::class, $entry->citationForm);
     $this->assertInstanceOf(LexMultiText::class, $entry->etymology);
     $this->assertInstanceOf(LexMultiText::class, $entry->etymologyGloss);
     $this->assertInstanceOf(LexMultiText::class, $entry->etymologyComment);
     $this->assertInstanceOf(LexMultiText::class, $entry->etymologySource);
     $this->assertInstanceOf(LexMultiText::class, $entry->note);
     $this->assertInstanceOf(LexMultiText::class, $entry->literalMeaning);
     $this->assertInstanceOf(LexMultiText::class, $entry->entryBibliography);
     $this->assertInstanceOf(LexMultiText::class, $entry->entryRestrictions);
     $this->assertInstanceOf(LexMultiText::class, $entry->summaryDefinition);
     // Removed import residue. Its no longer a field we import CP 2014-10
     // $this->assertInstanceOf(LexMultiText::class, $entry->entryImportResidue);
     $this->assertInstanceOf(LexMultiText::class, $entry->tone);
     $this->assertInstanceOf(LexMultiValue::class, $entry->environments);
     $this->assertInstanceOf(LexValue::class, $entry->location);
 }
 public function testEncode_userProjectHasNoUserProfileProperties_noProjectSettings()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $userId = $environ->createUser("User", "Name", "*****@*****.**");
     $user = new UserProfileModel($userId);
     $user->role = SiteRoles::USER;
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($userId, ProjectRoles::CONTRIBUTOR);
     $user->addProject($projectId);
     // user profile has data; but the encode method ignores it because the project has not enabled the 'city' property
     $projectUserProfile = new SfchecksUserProfile();
     $projectUserProfile->city = 'myCity';
     $user->projectUserProfiles[$projectId] = $projectUserProfile;
     $user->write();
     $project->write();
     $dto = UserProfileDto::encode($userId, $environ->website);
     $this->assertInternalType('array', $dto['userProfile']);
     $this->assertEquals($userId, $dto['userProfile']['id']);
     $this->assertEquals('Name', $dto['userProfile']['name']);
     $this->assertEquals(SiteRoles::USER, $dto['userProfile']['role']);
     $this->assertArrayHasKey('avatar_shape', $dto['userProfile']);
     $this->assertArrayHasKey('avatar_color', $dto['userProfile']);
     $this->assertFalse(isset($dto['userProfile']['projects']));
     $this->assertInternalType('array', $dto['projectsSettings']);
     $this->assertEquals(0, count($dto['projectsSettings']));
 }
 public function testGetProperties_ConstructsCorrectTypes()
 {
     $e = new MongoTestEnvironment();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $entry = new LexEntryModel($project);
     $this->assertIsA($entry->senses, 'Api\\Model\\Mapper\\ArrayOf');
     $this->assertIsA($entry->customFields, 'Api\\Model\\Mapper\\MapOf');
     $this->assertIsA($entry->authorInfo, 'Api\\Model\\Languageforge\\Lexicon\\AuthorInfo');
     $this->assertIsA($entry->lexeme, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->pronunciation, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->cvPattern, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->citationForm, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->etymology, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->etymologyGloss, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->etymologyComment, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->etymologySource, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->note, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->literalMeaning, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->entryBibliography, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->entryRestrictions, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->summaryDefinition, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     // Removed import residue. Its no longer a field we import CP 2014-10
     // $this->assertIsA($entry->entryImportResidue, 'models\languageforge\lexicon\MultiText');
     $this->assertIsA($entry->tone, 'Api\\Model\\Languageforge\\Lexicon\\MultiText');
     $this->assertIsA($entry->environments, 'Api\\Model\\Languageforge\\Lexicon\\LexiconMultiValueField');
     $this->assertIsA($entry->location, 'Api\\Model\\Languageforge\\Lexicon\\LexiconField');
 }
 public function testAnswerCRUD_Works()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $textRef = MongoTestEnvironment::mockId();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     // Create Question
     $question = new QuestionModel($project);
     $question->title = "Some Question";
     $question->textRef->id = $textRef;
     $questionId = $question->write();
     // List
     $question->read($questionId);
     $count = count($question->answers);
     $this->assertEqual(0, $count);
     // Create
     $answer = new AnswerModel();
     $answer->content = 'Some answer';
     $id = $question->writeAnswer($answer);
     $comment = new CommentModel();
     $comment->content = 'Some comment';
     $commentId = QuestionModel::writeComment($project->databaseName(), $questionId, $id, $comment);
     $this->assertNotNull($id);
     $this->assertIsA($id, 'string');
     $this->assertEqual(24, strlen($id));
     $this->assertEqual($id, $answer->id->asString());
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherAnswer = $otherQuestion->answers[$id];
     $this->assertEqual($id, $otherAnswer->id->asString());
     $this->assertEqual('Some answer', $otherAnswer->content);
     $this->assertEqual(1, count($otherAnswer->comments));
     // Update
     $otherAnswer->content = 'Other answer';
     // Note: Updates to the AnswerModel should not clobber child nodes such as comments. Hence this test.
     // See https://github.com/sillsdev/sfwebchecks/issues/39
     unset($otherAnswer->comments[$commentId]);
     $otherQuestion->read($otherQuestion->id->asString());
     $otherId = $otherQuestion->writeAnswer($otherAnswer);
     $this->assertEqual($id, $otherId);
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherAnswer = $otherQuestion->answers[$id];
     $this->assertEqual($id, $otherAnswer->id->asString());
     $this->assertEqual('Other answer', $otherAnswer->content);
     $this->assertEqual(1, count($otherAnswer->comments));
     // List
     $this->assertEqual(1, count($otherQuestion->answers));
     // Delete
     QuestionModel::removeAnswer($project->databaseName(), $questionId, $id);
     // List
     $otherQuestion->read($questionId);
     $this->assertEqual(0, count($otherQuestion->answers));
 }
 public function testAnswerCRUD_Works()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $textRef = MongoTestEnvironment::mockId();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     // Create Question
     $question = new QuestionModel($project);
     $question->title = "Some Question";
     $question->textRef->id = $textRef;
     $questionId = $question->write();
     // Create Answer
     $answer = new AnswerModel();
     $answer->content = 'Some answer';
     $answerId = $question->writeAnswer($answer);
     // List
     $question->read($questionId);
     $count = count($question->answers[$answerId]->comments);
     $this->assertEquals(0, $count);
     // Create
     $comment = new CommentModel();
     $comment->content = 'Some comment';
     $id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment);
     $this->assertNotNull($id);
     $this->assertInternalType('string', $id);
     $this->assertEquals(24, strlen($id));
     $this->assertEquals($comment->id->asString(), $id);
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherComment = $otherQuestion->answers[$answerId]->comments[$id];
     $this->assertEquals($id, $otherComment->id->asString());
     $this->assertEquals('Some comment', $otherComment->content);
     // Update
     $otherComment->content = 'Other comment';
     $otherId = $question->writeComment($project->databaseName(), $questionId, $answerId, $otherComment);
     $this->assertEquals($id, $otherId);
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherComment = $otherQuestion->answers[$answerId]->comments[$id];
     $this->assertEquals($id, $otherComment->id->asString());
     $this->assertEquals('Other comment', $otherComment->content);
     // List
     $count = count($otherQuestion->answers[$answerId]->comments);
     $this->assertEquals(1, $count);
     // Delete
     QuestionModel::removeComment($project->databaseName(), $questionId, $answerId, $id);
     // List
     $otherQuestion->read($questionId);
     $count = count($otherQuestion->answers[$answerId]->comments);
     $this->assertEquals(0, $count);
 }
 public function create()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $this->website = $environ->website;
     $this->project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $this->project->appName = 'sfchecks';
     $this->project->write();
     $this->question = new QuestionModel($this->project);
     $this->question->write();
     $this->userId = $environ->createUser('test_user', 'Test User', '*****@*****.**');
     $this->projectId = $this->project->id->asString();
     $this->questionId = $this->question->id->asString();
 }
 public function testUpdateThenRemove_NewProject_CreatesThenRemovesProjectDatabase()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $databaseName = $project->databaseName();
     $project->remove();
     $this->assertEquals(0, MongoStore::countCollections($databaseName));
     $text = new TextModel($project);
     $text->title = 'Some Title';
     $text->write();
     $this->assertTrue(MongoStore::hasDB($databaseName));
     $this->assertEquals(1, MongoStore::countCollections($databaseName));
     $project->remove();
     $this->assertEquals(0, MongoStore::countCollections($databaseName));
 }
 public function testTextReference_NullRefValidRef_AllowsNullRef()
 {
     $e = new MongoTestEnvironment();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $mockTextRef = (string) new \MongoId();
     // Test create with null textRef
     $question = new QuestionModel($project);
     $id = $question->write();
     $otherQuestion = new QuestionModel($project, $id);
     $this->assertEqual('', $otherQuestion->textRef->id);
     // Test update with textRef
     $question->textRef->id = $mockTextRef;
     $question->write();
     $otherQuestion = new QuestionModel($project, $id);
     $this->assertEqual($mockTextRef, $otherQuestion->textRef->id);
 }
 public function testEncode_ProjectWithUser_DtoCorrect()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $userId = $e->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $user->role = SystemRoles::USER;
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($userId, ProjectRoles::CONTRIBUTOR);
     $user->addProject($projectId);
     $user->write();
     $project->write();
     $dto = ManageUsersDto::encode($projectId);
     $this->assertEqual($dto['userCount'], 1);
     $this->assertIsA($dto['users'], 'array');
     $this->assertEqual($dto['users'][0]['id'], $userId);
     $this->assertEqual($dto['users'][0]['name'], 'Name');
     $this->assertEqual($dto['users'][0]['role'], ProjectRoles::CONTRIBUTOR);
 }
 public function testUserEngagementReport_simpleProjectWithQuestionsAndAnswers_AsExpected()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $user1Id = $e->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $e->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $e->createUser("user3", "user3", "*****@*****.**");
     ProjectCommands::updateUserRole($project->id->asString(), $user1Id);
     ProjectCommands::updateUserRole($project->id->asString(), $user2Id);
     ProjectCommands::updateUserRole($project->id->asString(), $user3Id);
     // Workflow is first to create a question
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "first answer";
     $answer->score = 10;
     $answer->userRef->id = $user3Id;
     $answer->textHightlight = "text highlight";
     $answerId = $question->writeAnswer($answer);
     // Followed by comments
     $comment1 = new CommentModel();
     $comment1->content = "first comment";
     $comment1->userRef->id = $user1Id;
     $comment1Id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment1);
     $comment2 = new CommentModel();
     $comment2->content = "second comment";
     $comment2->userRef->id = $user2Id;
     $comment2Id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment2);
     $data = SfchecksReports::UserEngagementReport($project->id->asString());
     $this->assertTrue($data['output']);
 }
 public function testSendInvite_SendInvite_PropertiesFromToBodyOk()
 {
     $this->environ->clean();
     $inviterUserId = $this->environ->createUser("inviteruser", "Inviter Name", "*****@*****.**");
     $toEmail = '*****@*****.**';
     $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $project->projectCode = 'someProjectCode';
     $project->write();
     $delivery = new MockUserCommandsDelivery();
     $toUserId = UserCommands::sendInvite($project->id->asString(), $inviterUserId, $this->environ->website, $toEmail, $delivery);
     // What's in the delivery?
     $toUser = new UserModel($toUserId);
     $senderEmail = 'no-reply@' . $this->environ->website->domain;
     $expectedFrom = array($senderEmail => $this->environ->website->name);
     $expectedTo = array($toUser->emailPending => $toUser->name);
     $this->assertEqual($expectedFrom, $delivery->from);
     $this->assertEqual($expectedTo, $delivery->to);
     $this->assertPattern('/Inviter Name/', $delivery->content);
     $this->assertPattern('/Test Project/', $delivery->content);
     $this->assertPattern('/' . $toUser->validationKey . '/', $delivery->content);
 }
 public function testEncode_ProjectWith2Users1Unvalidated_DtoCorrect1User()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $user1Id = $environ->createUser('', '', '');
     $user1 = new UserModel($user1Id);
     $user1->role = SystemRoles::USER;
     $user2Id = $environ->createUser('User', 'Name', '*****@*****.**');
     $user2 = new UserModel($user2Id);
     $user2->role = SystemRoles::USER;
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($user1Id, ProjectRoles::CONTRIBUTOR);
     $user1->addProject($projectId);
     $user1->write();
     $project->addUser($user2Id, ProjectRoles::CONTRIBUTOR);
     $user2->addProject($projectId);
     $user2->write();
     $project->write();
     $text1 = new TextModel($project);
     $text1->title = 'Some Title';
     $text1->write();
     $text2 = new TextModel($project);
     $text2->title = 'Archived Title';
     $text2->isArchived = true;
     $text2->write();
     $dto = ProjectSettingsDto::encode($projectId, $user2Id);
     $this->assertEquals(1, $dto['count']);
     $this->assertInternalType('array', $dto['entries']);
     $this->assertEquals($user2Id, $dto['entries'][0]['id']);
     $this->assertEquals('Name', $dto['entries'][0]['name']);
     $this->assertEquals(ProjectRoles::CONTRIBUTOR, $dto['entries'][0]['role']);
     $this->assertCount(1, $dto['archivedTexts']);
     $this->assertEquals('Archived Title', $dto['archivedTexts'][0]['title']);
     $this->assertTrue(count($dto['rights']) > 0, 'No rights in dto');
     $this->assertEquals('settings', $dto['bcs']['op']);
     $this->assertEquals(array('id' => $projectId, 'crumb' => SF_TESTPROJECT), $dto['bcs']['project']);
     $this->assertFalse(isset($dto['project']['users']));
     $this->assertEquals($projectId, $dto['project']['id']);
 }
 public function testEncode_ProjectWith2Users1Unvalidated_DtoCorrect1User()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $user1Id = $e->createUser("", "", "");
     $user1 = new UserModel($user1Id);
     $user1->role = SystemRoles::USER;
     $user2Id = $e->createUser("User", "Name", "*****@*****.**");
     $user2 = new UserModel($user2Id);
     $user2->role = SystemRoles::USER;
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($user1Id, ProjectRoles::CONTRIBUTOR);
     $user1->addProject($projectId);
     $user1->write();
     $project->addUser($user2Id, ProjectRoles::CONTRIBUTOR);
     $user2->addProject($projectId);
     $user2->write();
     $project->write();
     $text1 = new TextModel($project);
     $text1->title = "Some Title";
     $text1->write();
     $text2 = new TextModel($project);
     $text2->title = "Archived Title";
     $text2->isArchived = true;
     $text2->write();
     $dto = ProjectSettingsDto::encode($projectId, $user2Id);
     $this->assertEqual($dto['count'], 1);
     $this->assertIsA($dto['entries'], 'array');
     $this->assertEqual($dto['entries'][0]['id'], $user2Id);
     $this->assertEqual($dto['entries'][0]['name'], 'Name');
     $this->assertEqual($dto['entries'][0]['role'], ProjectRoles::CONTRIBUTOR);
     $this->assertEqual(count($dto['archivedTexts']), 1);
     $this->assertEqual($dto['archivedTexts'][0]['title'], 'Archived Title');
     $this->assertTrue(count($dto['rights']) > 0, "No rights in dto");
     $this->assertEqual($dto['bcs']['op'], 'settings');
     $this->assertEqual($dto['bcs']['project'], array('id' => $projectId, 'crumb' => SF_TESTPROJECT));
     $this->assertFalse(isset($dto['project']['users']));
     $this->assertEqual($dto['project']['id'], $projectId);
 }
 public function testUpdateProject_ReadOnlyProperties_PropertiesNotChanged()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $userId = $environ->createUser('User', 'Name', '*****@*****.**');
     $user = new UserModel($userId);
     $user->role = SystemRoles::USER;
     $hackerId = $environ->createUser('Hacker', 'Hacker', '*****@*****.**');
     $hacker = new UserModel($hackerId);
     $hacker->role = SystemRoles::USER;
     $hacker->write();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($userId, ProjectRoles::MANAGER);
     $project->ownerRef = $user->id->asString();
     $user->addProject($projectId);
     $user->write();
     $project->write();
     $hackedData = 'hacked';
     $params = ProjectCommands::readProject($projectId);
     $params['projectName'] = 'new project name';
     $params['id'] = $hackedData;
     $params['ownerRef'] = $hacker->id->asString();
     $params['users'][$hacker->id->asString()]['role'] = ProjectRoles::MANAGER;
     $params['projectCode'] = $hackedData;
     $params['siteName'] = $hackedData;
     $params['appName'] = $hackedData;
     $params['userProperties']['userProfilePickLists']['city']['name'] = $hackedData;
     SfchecksProjectCommands::updateProject($projectId, $userId, $params);
     $updatedProject = ProjectCommands::readProject($projectId);
     $this->assertEquals('new project name', $updatedProject['projectName']);
     $this->assertNotEquals($hackedData, $updatedProject['id']);
     $this->assertNotEquals($hacker->id->asString(), $updatedProject['ownerRef']);
     $this->assertFalse(isset($updatedProject['users'][$hacker->id->asString()]));
     $this->assertNotEquals($hackedData, $updatedProject['projectCode']);
     $this->assertNotEquals($hackedData, $updatedProject['siteName']);
     $this->assertNotEquals($hackedData, $updatedProject['appName']);
     $this->assertNotEquals($hackedData, $updatedProject['userProperties']['userProfilePickLists']['city']['name']);
 }
 public function testPublishTexts_2ArchivedTexts_1Published()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text1 = new TextModel($project);
     $text1->title = "Some Title";
     $text1->isArchived = true;
     $text1->write();
     $text2 = new TextModel($project);
     $text2->title = "Another Title";
     $text2->isArchived = true;
     $text2->write();
     $this->assertEqual($text1->isArchived, true);
     $this->assertEqual($text2->isArchived, true);
     $count = TextCommands::publishTexts($project->id->asString(), array($text1->id->asString()));
     $text1->read($text1->id->asString());
     $text2->read($text2->id->asString());
     $this->assertEqual($count, 1);
     $this->assertEqual($text1->isArchived, false);
     $this->assertEqual($text2->isArchived, true);
 }
 public function testEncode_ProjectWithUser_DtoCorrect()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $userId = $e->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE, 'sfchecks');
     $project->ownerRef->id = $userId;
     $projectId = $project->id->asString();
     $project->addUser($userId, ProjectRoles::CONTRIBUTOR);
     $user->addProject($projectId);
     $user->write();
     $project->write();
     $dto = ProjectManagementDto::encode($projectId);
     $this->assertTrue(count($dto['reports']) > 0);
     $foundUserEngagementReport = false;
     foreach ($dto['reports'] as $report) {
         if ($report['id'] == 'sfchecks_userEngagementReport') {
             $foundUserEngagementReport = true;
         }
     }
     $this->assertTrue($foundUserEngagementReport);
 }
 function testCleanupFiles_4Files2Allowed_2Removed()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->write();
     $text = new TextModel($project);
     $textId = $text->write();
     $fakeId = new Id();
     $fakeTextId = $fakeId->asString();
     $folderPath = $project->getAssetsFolderPath();
     FileUtilities::createAllFolders($folderPath);
     $allowedExtensions = array(".mp2", ".mp3");
     // put a copy of the test files in the folderPath
     $fileName1 = 'TestAudio1.mp1';
     $filePath1 = SfchecksUploadCommands::mediaFilePath($folderPath, $textId, $fileName1);
     copy(TestPath . 'common/TestAudio.mp3', $filePath1);
     $fileName2 = 'TestAudio2.mp2';
     $filePath2 = SfchecksUploadCommands::mediaFilePath($folderPath, $textId, $fileName2);
     copy(TestPath . 'common/TestAudio.mp3', $filePath2);
     $fileName3 = 'TestAudio3.mp3';
     $filePath3 = SfchecksUploadCommands::mediaFilePath($folderPath, $textId, $fileName3);
     copy(TestPath . 'common/TestAudio.mp3', $filePath3);
     $fileName4 = 'TestAudio4.mp3';
     $filePath4 = SfchecksUploadCommands::mediaFilePath($folderPath, $fakeTextId, $fileName4);
     copy(TestPath . 'common/TestAudio.mp3', $filePath4);
     $this->assertTrue(file_exists($filePath1), 'File should exist before cleanup');
     $this->assertTrue(file_exists($filePath2), 'File should exist before cleanup');
     $this->assertTrue(file_exists($filePath3), 'File should exist before cleanup');
     $this->assertTrue(file_exists($filePath4), 'File should exist before cleanup');
     SfchecksUploadCommands::cleanupFiles($folderPath, $textId, $allowedExtensions);
     $this->assertTrue(file_exists($filePath1), 'File should exist after cleanup');
     $this->assertFalse(file_exists($filePath2), 'File should not exist after cleanup');
     $this->assertFalse(file_exists($filePath3), 'File should not exist after cleanup');
     $this->assertTrue(file_exists($filePath4), 'File should exist after cleanup');
     $environ->cleanupTestFiles($folderPath);
 }
 public function testEncode_2Questions1Archived_DtoCorrect1ArchivedQuestion()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $userId = $e->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $user->role = SystemRoles::USER;
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($userId, ProjectRoles::MANAGER);
     $user->addProject($projectId);
     $user->write();
     $project->write();
     $text = new TextModel($project);
     $text->title = "Text Title";
     $textId = $text->write();
     $question1 = new QuestionModel($project);
     $question1->title = "Some Title";
     $question1->textRef->id = $textId;
     $question1->write();
     $question2 = new QuestionModel($project);
     $question2->title = "Archived Title";
     $question2->textRef->id = $textId;
     $question2->isArchived = true;
     $question2->write();
     $dto = TextSettingsDto::encode($projectId, $textId, $userId);
     $this->assertIsA($dto['text'], 'array');
     $this->assertEqual($dto['text']['id'], $textId);
     $this->assertEqual($dto['text']['title'], 'Text Title');
     $this->assertIsA($dto['archivedQuestions'], 'array');
     $this->assertEqual(count($dto['archivedQuestions']), 1);
     $this->assertEqual($dto['archivedQuestions'][0]['title'], 'Archived Title');
     $this->assertTrue(count($dto['rights']) > 0, "No rights in dto");
     $this->assertEqual($dto['bcs']['op'], 'settings');
     $this->assertEqual($dto['bcs']['project'], array('id' => $projectId, 'crumb' => SF_TESTPROJECT));
 }
 public function testEncode_ArchivedText_ManagerCanViewContributorCannot()
 {
     $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     // archived Text
     $text = new TextModel($project);
     $text->title = "Chapter 3";
     $text->isArchived = true;
     $textId = $text->write();
     // Answers are tied to specific users, so let's create some sample users
     $managerId = $this->environ->createUser("jcarter", "John Carter", "*****@*****.**");
     $contributorId = $this->environ->createUser("dthoris", "Dejah Thoris", "*****@*****.**");
     $project->addUser($managerId, ProjectRoles::MANAGER);
     $project->addUser($contributorId, ProjectRoles::CONTRIBUTOR);
     $project->write();
     $dto = QuestionListDto::encode($projectId, $textId, $managerId);
     // Manager can view archived Text
     $this->assertEqual($dto['text']['title'], "Chapter 3");
     // Contributor cannot view archived Text, throw Exception
     $this->environ->inhibitErrorDisplay();
     $this->expectException();
     $dto = QuestionListDto::encode($projectId, $textId, $contributorId);
     // nothing runs in the current test function after an exception. IJH 2014-11
 }
 public function testExportCommentsForText_QuestionArchived_NoneExported()
 {
     $e = new MongoTestEnvironment();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $user1Id = $e->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $e->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $e->createUser("user3", "user3", "*****@*****.**");
     // Workflow is first to create a question
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $question->isArchived = true;
     $questionId = $question->write();
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "first answer";
     $answer->score = 10;
     $answer->userRef->id = $user1Id;
     $answer->tags->exchangeArray(array('export', 'to review'));
     $answer->isToBeExported = true;
     $answerId = $question->writeAnswer($answer);
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "second answer - very long";
     $answer->score = 2;
     $answer->userRef->id = $user2Id;
     $answer->tags->exchangeArray(array('to review'));
     $answer->isToBeExported = false;
     $answerId = $question->writeAnswer($answer);
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "third answer - very very very very long";
     $answer->userRef->id = $user3Id;
     $answer->tags->exchangeArray(array('export'));
     $answer->isToBeExported = true;
     $answerId = $question->writeAnswer($answer);
     $params = array('textId' => $textId, 'exportComments' => true, 'exportFlagged' => true, 'tags' => array());
     $download = ParatextExport::exportCommentsForText($project->id->asString(), $textId, $params);
     //echo "<pre>" . print_r($download) . "</pre>";
     $this->assertNoPattern('/<Contents>third answer - very very very very long \\(by user3/', $download['xml']);
     $this->assertNoPattern('/<Contents>second answer/', $download['xml']);
     $this->assertNoPattern('/<Contents>first answer/', $download['xml']);
 }
 public function testEncode_TextWithQuestions_DtoReturnsExpectedData()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     // Two texts, with different numbers of questions for each text and different create dates
     $text1 = new TextModel($project);
     $text1->title = 'Chapter 3';
     $text1->content = 'I opened my eyes upon a strange and weird landscape. I knew that I was on Mars; …';
     $text1->write();
     $text1->dateCreated->addSeconds(-date_interval_create_from_date_string('1 day')->s);
     $text1Id = $text1->write();
     $text2 = new TextModel($project);
     $text2->title = 'Chapter 4';
     $text2->content = 'We had gone perhaps ten miles when the ground began to rise very rapidly. …';
     $text2Id = $text2->write();
     // Answers are tied to specific users, so let's create some sample users
     $user1Id = $environ->createUser('jcarter', 'John Carter', '*****@*****.**');
     $user2Id = $environ->createUser('dthoris', 'Dejah Thoris', '*****@*****.**');
     // Two questions for text 1...
     $question1 = new QuestionModel($project);
     $question1->title = 'Who is speaking?';
     $question1->description = 'Who is telling the story in this text?';
     $question1->textRef->id = $text1Id;
     $question1->write();
     $question2 = new QuestionModel($project);
     $question2->title = 'Where is the storyteller?';
     $question2->description = 'The person telling this story has just arrived somewhere. Where is he?';
     $question2->textRef->id = $text1Id;
     $question2Id = $question2->write();
     // ... and one question for text 2.
     $question3 = new QuestionModel($project);
     $question3->title = 'How far had they travelled?';
     $question3->description = 'How far had the group just travelled when this text begins?';
     $question3->textRef->id = $text2Id;
     $question3->write();
     // One answer for question 1...
     $answer1 = new AnswerModel();
     $answer1->content = 'Me, John Carter.';
     $answer1->score = 10;
     $answer1->userRef->id = $user1Id;
     $answer1->textHightlight = 'I knew that I was on Mars';
     $question1->writeAnswer($answer1);
     // ... and two answers for question 2...
     $answer2 = new AnswerModel();
     $answer2->content = 'On Mars.';
     $answer2->score = 1;
     $answer2->userRef->id = $user1Id;
     $answer2->textHightlight = 'I knew that I was on Mars';
     $question2->writeAnswer($answer2);
     $answer3 = new AnswerModel();
     $answer3->content = 'On the planet we call Barsoom, which you inhabitants of Earth normally call Mars.';
     $answer3->score = 7;
     $answer3->userRef->id = $user2Id;
     $answer3->textHightlight = 'I knew that I was on Mars';
     $answer3Id = $question2->writeAnswer($answer3);
     // ... and 1 comment.
     $comment1 = new CommentModel();
     $comment1->content = 'By the way, our name for Earth is Jasoom.';
     $comment1->userRef->id = $user2Id;
     QuestionModel::writeComment($project->databaseName(), $question2Id, $answer3Id, $comment1);
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     $encodedTexts = MongoTestEnvironment::indexItemsBy($dto['texts'], 'id');
     $encodedText1 = $encodedTexts[$text1Id];
     $encodedText2 = $encodedTexts[$text2Id];
     // Now check that it all looks right
     $this->assertInternalType('array', $dto['texts']);
     $this->assertEquals($text2Id, $encodedText2['id']);
     $this->assertEquals($text1Id, $encodedText1['id']);
     $this->assertEquals('Chapter 4', $encodedText2['title']);
     $this->assertEquals('Chapter 3', $encodedText1['title']);
     $this->assertEquals(1, $encodedText2['questionCount']);
     $this->assertEquals(2, $encodedText1['questionCount']);
     $this->assertEquals(0, $encodedText2['responseCount']);
     $this->assertEquals(4, $encodedText1['responseCount']);
     // archive 1 Question
     $question2->isArchived = true;
     $question2->write();
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     $encodedTexts = MongoTestEnvironment::indexItemsBy($dto['texts'], 'id');
     $encodedText1 = $encodedTexts[$text1Id];
     $encodedText2 = $encodedTexts[$text2Id];
     $this->assertEquals(1, $encodedText2['questionCount']);
     $this->assertEquals(1, $encodedText1['questionCount']);
     $this->assertEquals(0, $encodedText2['responseCount']);
     $this->assertEquals(1, $encodedText1['responseCount']);
 }
 public function testUpdateComment_ExistingComment_OriginalAuthorIsPreserved()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $question = new QuestionModel($project);
     $question->textRef->id = $textId;
     $questionId = $question->write();
     $user1Id = $e->createUser("user1", "user1", "user1");
     $user2Id = $e->createUser("user2", "user2", "user2");
     $answer = new AnswerModel();
     $answer->content = "the answer";
     $answer->userRef->id = $user2Id;
     $answerId = $question->writeAnswer($answer);
     $comment = new CommentModel();
     $comment->userRef->id = $user1Id;
     $comment->content = "the comment";
     $commentId = $question->writeComment($project->databaseName(), $questionId, $answerId, $comment);
     $commentArray = array("id" => $commentId, "content" => "updated comment");
     QuestionCommands::updateComment($project->id->asString(), $questionId, $answerId, $commentArray, $user2Id);
     $question->read($questionId);
     $newComment = $question->readComment($answerId, $commentId);
     $this->assertEqual($user1Id, $newComment->userRef->asString());
 }
 public function testEncode_TextWithQuestions_DtoReturnsExpectedData()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     // Two texts, with different numbers of questions for each text and different create dates
     $text1 = new TextModel($project);
     $text1->title = "Chapter 3";
     $text1->content = "I opened my eyes upon a strange and weird landscape. I knew that I was on Mars; …";
     $text1->write();
     $text1->dateCreated->sub(date_interval_create_from_date_string('1 day'));
     $text1Id = $text1->write();
     $text2 = new TextModel($project);
     $text2->title = "Chapter 4";
     $text2->content = "We had gone perhaps ten miles when the ground began to rise very rapidly. …";
     $text2Id = $text2->write();
     // Answers are tied to specific users, so let's create some sample users
     $user1Id = $e->createUser("jcarter", "John Carter", "*****@*****.**");
     $user2Id = $e->createUser("dthoris", "Dejah Thoris", "*****@*****.**");
     // Two questions for text 1...
     $question1 = new QuestionModel($project);
     $question1->title = "Who is speaking?";
     $question1->description = "Who is telling the story in this text?";
     $question1->textRef->id = $text1Id;
     $question1Id = $question1->write();
     $question2 = new QuestionModel($project);
     $question2->title = "Where is the storyteller?";
     $question2->description = "The person telling this story has just arrived somewhere. Where is he?";
     $question2->textRef->id = $text1Id;
     $question2Id = $question2->write();
     // ... and one question for text 2.
     $question3 = new QuestionModel($project);
     $question3->title = "How far had they travelled?";
     $question3->description = "How far had the group just travelled when this text begins?";
     $question3->textRef->id = $text2Id;
     $question3Id = $question3->write();
     // One answer for question 1...
     $answer1 = new AnswerModel();
     $answer1->content = "Me, John Carter.";
     $answer1->score = 10;
     $answer1->userRef->id = $user1Id;
     $answer1->textHightlight = "I knew that I was on Mars";
     $answer1Id = $question1->writeAnswer($answer1);
     // ... and two answers for question 2...
     $answer2 = new AnswerModel();
     $answer2->content = "On Mars.";
     $answer2->score = 1;
     $answer2->userRef->id = $user1Id;
     $answer2->textHightlight = "I knew that I was on Mars";
     $answer2Id = $question2->writeAnswer($answer2);
     $answer3 = new AnswerModel();
     $answer3->content = "On the planet we call Barsoom, which you inhabitants of Earth normally call Mars.";
     $answer3->score = 7;
     $answer3->userRef->id = $user2Id;
     $answer3->textHightlight = "I knew that I was on Mars";
     $answer3Id = $question2->writeAnswer($answer3);
     // ... and 1 comment.
     $comment1 = new CommentModel();
     $comment1->content = "By the way, our name for Earth is Jasoom.";
     $comment1->userRef->id = $user2Id;
     $comment1Id = QuestionModel::writeComment($project->databaseName(), $question2Id, $answer3Id, $comment1);
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     // Now check that it all looks right
     $this->assertIsa($dto['texts'], 'array');
     $this->assertEqual($dto['texts'][0]['id'], $text2Id);
     $this->assertEqual($dto['texts'][1]['id'], $text1Id);
     $this->assertEqual($dto['texts'][0]['title'], "Chapter 4");
     $this->assertEqual($dto['texts'][1]['title'], "Chapter 3");
     $this->assertEqual($dto['texts'][0]['questionCount'], 1);
     $this->assertEqual($dto['texts'][1]['questionCount'], 2);
     $this->assertEqual($dto['texts'][0]['responseCount'], 0);
     $this->assertEqual($dto['texts'][1]['responseCount'], 4);
     // archive 1 Question
     $question2->isArchived = true;
     $question2->write();
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     $this->assertEqual($dto['texts'][0]['questionCount'], 1);
     $this->assertEqual($dto['texts'][1]['questionCount'], 1);
     $this->assertEqual($dto['texts'][0]['responseCount'], 0);
     $this->assertEqual($dto['texts'][1]['responseCount'], 1);
 }
 public function testEncode_UserOf1Project2Projects_DtoReturnsProjectCount1()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $userId = $e->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $user->role = SystemRoles::USER;
     $user->write();
     $project1 = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId1 = $project1->id->asString();
     $project1->addUser($userId, ProjectRoles::CONTRIBUTOR);
     $project1->ownerRef->id = $userId;
     $project1->write();
     $project2 = $e->createProject(SF_TESTPROJECT2, SF_TESTPROJECTCODE2);
     $project2->ownerRef->id = $userId;
     $project2->write();
     $dto = ProjectListDto::encode($userId, $e->website);
     $this->assertEqual($dto['count'], 1);
     $this->assertIsA($dto['entries'], 'array');
     $this->assertEqual($dto['entries'][0]['id'], $projectId1);
     $this->assertEqual($dto['entries'][0]['projectName'], SF_TESTPROJECT);
     $this->assertEqual($dto['entries'][0]['role'], ProjectRoles::CONTRIBUTOR);
 }
 public function testUserRemove_UserMemberOfProject_ProjectLinkRemovedAsWell()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $userId = $environ->createUser('user1', 'user1', 'user1');
     $user = new UserModel($userId);
     $project = $environ->createProject('testProject', 'testProjectCode');
     $project->addUser($userId, ProjectRoles::CONTRIBUTOR);
     $project->write();
     $user->addProject($project->id->asString());
     $user->write();
     // delete the user
     $user->remove();
     // re-read the project
     $project->read($project->id->asString());
     $this->assertFalse($project->userIsMember($userId));
 }
 public function testSendSignup_WithProject_PropertiesToFromBodyOk()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $userId = $e->createUser('User', 'Name', '*****@*****.**');
     $user = new UserModel($userId);
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $project->projectCode = 'test_project';
     $project->write();
     $delivery = new MockCommunicateDelivery();
     $website = Website::get('scriptureforge.org');
     $website->defaultProjectCode = 'test_project';
     Communicate::sendSignup($user, $website, $delivery);
     // What's in the delivery?
     $senderEmail = 'no-reply@' . $e->website->domain;
     $expectedTo = array($user->emailPending => $user->name);
     $this->assertPattern('/' . $e->website->name . '/', $delivery->from[$senderEmail]);
     $this->assertEqual($expectedTo, $delivery->to);
     $this->assertPattern('/' . $e->website->name . '/', $delivery->subject);
     $this->assertPattern('/Name/', $delivery->content);
     $this->assertPattern('/' . $user->validationKey . '/', $delivery->content);
 }
 public function testMultipleUnreadModels_multipleUsers_multipleUpdates_multipleVisitsToQuestionPage_usersHaveDifferentUnreadStates()
 {
     $project = self::$environ->createProject("unread_test", "unreadCode");
     $projectId = $project->id->asString();
     $userId1 = self::$environ->createUser('user1', 'user1', 'user1');
     $user1 = new UserModel($userId1);
     $user1->addProject($project->id->asString());
     $user1->write();
     $userId2 = self::$environ->createUser('user2', 'user2', 'user2');
     $user2 = new UserModel($userId2);
     $user2->addProject($project->id->asString());
     $user2->write();
     $userId3 = self::$environ->createUser('user3', 'user3', 'user3');
     $user3 = new UserModel($userId3);
     $user3->addProject($project->id->asString());
     $user3->write();
     $answer1 = array('content' => "test answer 1", 'id' => '');
     $answer2 = array('content' => "test answer 2", 'id' => '');
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $question = new QuestionModel($project);
     $question->title = "test question";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     QuestionCommands::updateAnswer($projectId, $questionId, $answer1, $userId1);
     QuestionCommands::updateAnswer($projectId, $questionId, $answer2, $userId2);
     // the answer author does NOT get their answer marked as unread
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(1, $unreadModel->unreadItems());
     // the answer author does NOT get their answer marked as unread
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(1, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(2, $unreadModel->unreadItems());
     // user1 visits question page
     QuestionCommentDto::encode($projectId, $questionId, $userId1);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(1, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(2, $unreadModel->unreadItems());
     // user2 visits question page
     QuestionCommentDto::encode($projectId, $questionId, $userId2);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(2, $unreadModel->unreadItems());
     // user2 visits question page
     QuestionCommentDto::encode($projectId, $questionId, $userId3);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
 }