package tests;
import java.util.List;
import models.Question;
import models.Tag;
import models.User;
import models.database.IQuestionDatabase;
import models.database.ITagDatabase;
import models.database.HotDatabase.HotQuestionDatabase;
import models.database.HotDatabase.HotTagDatabase;
import models.helpers.SetOperations;
import org.junit.Before;
import org.junit.Test;
public class TagTest extends MockedUnitTest {
private ITagDatabase tagDB;
private Question question1;
private Question question2;
private User douglas;
private String tagName;
@Before
public void setUp() {
tagDB = new HotTagDatabase();
douglas = new User("Douglas");
question1 = new Question(douglas,
"Why did the chicken cross the road?", tagDB, null);
question2 = new Question(douglas, "Is this question meaningless?",
tagDB, null);
tagName = "tag";
}
@Test
public void shouldHaveName() {
Tag tag = new Tag(tagName, null);
assertNotNull(tag.getName());
assertEquals(tag.getName(), tagName);
assertNull(tagDB.get("space "));
String invalidNames[] = { null, "UpperCase",
"012345678901234567890123456789012" };
for (String name : invalidNames) {
boolean hasThrown = false;
try {
new Tag(name, null);
} catch (IllegalArgumentException ex) {
hasThrown = true;
}
assertTrue("Should throw for name " + name, hasThrown);
}
}
@Test
public void shouldAssociateWithQuestions() {
assertEquals(countTags(tagName), 0);
assertEquals(question1.getTags().size(), 0);
question1.setTagString(tagName);
assertEquals(question1.getTags().size(), 1);
assertEquals(countTags(tagName), 1);
Tag tag1 = tagDB.get(tagName);
assertNotNull(tag1);
assertTrue(question1.getTags().contains(tag1));
assertTrue(tag1.getQuestions().contains(question1));
assertFalse(question2.getTags().contains(tag1));
assertFalse(tag1.getQuestions().contains(question2));
question2.setTagString(tagName);
assertEquals(countTags(tagName), 1);
assertTrue(question1.getTags().contains(tag1));
assertTrue(tag1.getQuestions().contains(question1));
assertTrue(question2.getTags().contains(tag1));
assertTrue(tag1.getQuestions().contains(question2));
assertEquals(tag1.getQuestions().size(), 2);
assertEquals(question1.getTags().size(), 1);
assertEquals(question2.getTags().size(), 1);
assertEquals(question1.getTags().get(0), question2.getTags().get(0));
question1.setTagString("");
assertEquals(question1.getTags().size(), 0);
assertFalse(question1.getTags().contains(tag1));
assertFalse(tag1.getQuestions().contains(question1));
assertTrue(question2.getTags().contains(tag1));
assertTrue(tag1.getQuestions().contains(question2));
assertEquals(countTags(tagName), 1);
question2.setTagString("");
assertEquals(question2.getTags().size(), 0);
assertFalse(question2.getTags().contains(tag1));
assertFalse(tag1.getQuestions().contains(question2));
assertTrue(tag1.getQuestions().isEmpty());
assertEquals(countTags(tagName), 0);
}
@Test
public void shouldSetTagString() {
question1.setTagString("012345678901234567890123456789012");
assertEquals(question1.getTags().get(0).getName(),
"01234567890123456789012345678901");
question1.setTagString("012345678901234567890123456789012");
assertEquals(question1.getTags().size(), 1);
}
@Test
public void shouldOrderAlphabetically() {
Tag tagC = tagDB.get("c" + tagName);
Tag tagA = tagDB.get("a" + tagName);
Tag tagB = tagDB.get("b" + tagName);
question1.setTagString(tagC.getName() + " " + tagA.getName() + ","
+ tagB.getName());
assertEquals(question1.getTags().get(0), tagA);
assertEquals(question1.getTags().get(1), tagB);
assertEquals(question1.getTags().get(2), tagC);
question1.setTagString(null);
}
@Test
public void shouldNotListQuestionWithZeroTags() {
IQuestionDatabase questionDB = new HotQuestionDatabase(this.tagDB);
User A = new User("A");
User B = new User("B");
User C = new User("C");
User D = new User("D");
Question questionK = questionDB.add(A, "K?");
Question questionL = questionDB.add(B, "L?");
Question questionM = questionDB.add(C, "M?");
Question questionN = questionDB.add(D, "N?");
Question questionO = questionDB.add(D, "O?");
questionK.setTagString(" J K Z");
questionL.setTagString(" ");
questionM.setTagString(" ");
questionN.setTagString("");
questionO.setTagString("");
List<Question> similarK = questionDB.findSimilar(questionK);
List<Question> similarL = questionDB.findSimilar(questionL);
List<Question> similarM = questionDB.findSimilar(questionM);
List<Question> similarN = questionDB.findSimilar(questionN);
List<Question> similarO = questionDB.findSimilar(questionO);
assertTrue(similarK.isEmpty());
assertTrue(similarL.isEmpty());
assertTrue(similarM.isEmpty());
assertTrue(similarN.isEmpty());
assertTrue(similarO.isEmpty());
}
@Test
public void shouldListCorrectOrderOfSimilarQuestions() {
IQuestionDatabase questionDB = new HotQuestionDatabase(this.tagDB);
User A = new User("A");
User B = new User("B");
User C = new User("C");
User D = new User("D");
Question questionA = questionDB.add(A, "A?");
Question questionB = questionDB.add(B, "B?");
Question questionC = questionDB.add(C, "C?");
Question questionD = questionDB.add(D, "D?");
Question questionE = questionDB.add(D, "E?");
Question questionF = questionDB.add(A, "F?");
questionA.setTagString("A B C D");
questionB.setTagString("A B C D");
questionC.setTagString("A B C");
questionD.setTagString("A B");
questionE.setTagString("A");
// To check if duplicate values are allowed
questionF.setTagString("A B C D");
Question[] possibility1 = { questionB, questionF, questionC, questionD,
questionE };
Question[] possibility2 = { questionF, questionB, questionC, questionD,
questionE };
List<Question> similar = questionDB.findSimilar(questionA);
assertEquals(similar.size(), 5);
assertTrue(SetOperations.arrayEquals(possibility1, similar.toArray())
|| SetOperations.arrayEquals(possibility2, similar.toArray()));
}
@Test
public void shouldIgnoreDuplicates() {
question1.setTagString("double double double");
assertEquals(countTags("double"), 1);
assertEquals(question1.getTags().size(), 1);
assertEquals(question1.getTags().get(0), tagDB.get("double"));
}
@Test
public void shouldSuggestTags() {
question1.setTagString("tag1 tag2 nag3");
List<String> tagNames = tagDB.suggestTagNames("ta");
assertEquals(2, tagNames.size());
assertEquals("tag1", tagNames.get(0));
assertEquals("tag2", tagNames.get(1));
tagNames = tagDB.suggestTagNames("TA");
assertEquals(2, tagNames.size());
assertEquals("tag1", tagNames.get(0));
assertEquals("tag2", tagNames.get(1));
tagNames = tagDB.suggestTagNames("Na");
assertEquals(1, tagNames.size());
assertEquals("nag3", tagNames.get(0));
tagNames = tagDB.suggestTagNames("tag1");
assertEquals(1, tagNames.size());
assertEquals("tag1", tagNames.get(0));
tagNames = tagDB.suggestTagNames(null);
assertEquals(3, tagNames.size());
assertEquals("nag3", tagNames.get(0));
assertEquals("tag1", tagNames.get(1));
assertEquals("tag2", tagNames.get(2));
}
@Test
public void shouldAllowStandaloneTags() {
Tag tag = new Tag(tagName, null);
tag.addQuestion(question1);
assertEquals(1, tag.getQuestions().size());
tag.removeQuestion(question1);
assertEquals(0, tag.getQuestions().size());
}
private int countTags(String name) {
int count = 0;
for (Tag tag : tagDB.all())
if (tag.getName().equals(name))
count++;
return count;
}
}