/** * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.waveprotocol.box.webclient.client.state; import junit.framework.TestCase; import org.waveprotocol.wave.client.state.ThreadReadStateMonitor; import org.waveprotocol.wave.client.state.ThreadReadStateMonitorImpl; import org.waveprotocol.wave.model.conversation.ConversationBlip; import org.waveprotocol.wave.model.conversation.ConversationThread; import org.waveprotocol.wave.model.conversation.WaveBasedConversationView; import org.waveprotocol.wave.model.conversation.WaveletBasedConversation; import org.waveprotocol.wave.model.id.IdGenerator; import org.waveprotocol.wave.model.supplement.LiveSupplementedWaveImpl; import org.waveprotocol.wave.model.supplement.ObservablePrimitiveSupplement; import org.waveprotocol.wave.model.supplement.ObservableSupplementedWave; import org.waveprotocol.wave.model.supplement.SupplementedWaveImpl.DefaultFollow; import org.waveprotocol.wave.model.supplement.WaveletBasedSupplement; import org.waveprotocol.wave.model.testing.BasicFactories; import org.waveprotocol.wave.model.testing.FakeIdGenerator; import org.waveprotocol.wave.model.testing.FakeWaveView; import org.waveprotocol.wave.model.wave.ParticipantId; import org.waveprotocol.wave.model.wave.Wavelet; /** * Test the thread state monitor class to ensure proper counting of total, read * and unread blips in the root thread as well as ensuring that counts are * properly aggregated when nested threads are present. * * @author Michael MacFadden */ public class ThreadReadStateMonitorTest extends TestCase { private static final ParticipantId viewer = new ParticipantId("nobody@nowhere.com"); private static final IdGenerator idgen = FakeIdGenerator.create(); private ObservableSupplementedWave supplementedWave; private ConversationThread rootThread; private ThreadReadStateMonitor monitor; @Override protected void setUp() throws Exception { super.setUp(); FakeWaveView view = BasicFactories.fakeWaveViewBuilder().with(idgen).build(); Wavelet userDataWavelet = view.createUserData(); ObservablePrimitiveSupplement primitiveSupplement = WaveletBasedSupplement.create(userDataWavelet); WaveBasedConversationView conversationView = WaveBasedConversationView.create(view, idgen); WaveletBasedConversation rootConversation = conversationView.createRoot(); supplementedWave = new LiveSupplementedWaveImpl(primitiveSupplement, view, viewer, DefaultFollow.ALWAYS, conversationView); monitor = ThreadReadStateMonitorImpl.create(supplementedWave, conversationView); rootThread = rootConversation.getRootThread(); } /** * This test verifies the total counts of blips in the root thread. */ public void testEmptyRootThread() throws Exception { assertEquals(0, monitor.getTotalCount(rootThread)); } /** * This test verifies the total counts of blips in the root thread. */ public void testRootThreadBlips() throws Exception { rootThread.appendBlip(); rootThread.appendBlip(); rootThread.appendBlip(); assertEquals(3, monitor.getTotalCount(rootThread)); } /** * This test verifies the count in an empty root thread. */ public void testRootThreadDeleteBlip() throws Exception { rootThread.appendBlip(); rootThread.appendBlip(); rootThread.appendBlip().delete(); assertEquals(2, monitor.getTotalCount(rootThread)); } /** * This test verifies the count in an empty inline thread. */ public void testEmptyInlineThread() throws Exception { ConversationBlip rb1 = rootThread.appendBlip(); ConversationThread t1 = rb1.addReplyThread(0); assertEquals(1, monitor.getTotalCount(rootThread)); assertEquals(0, monitor.getTotalCount(t1)); } /** * This test ensures that the total blip counts aggregate properly up through * nested inline threads. */ public void testNestedThreadBlips() throws Exception { ConversationBlip rb1 = rootThread.appendBlip(); ConversationThread t1 = rb1.addReplyThread(0); t1.appendBlip(); t1.appendBlip(); ConversationBlip rb2 = rootThread.appendBlip(); ConversationThread t2 = rb2.addReplyThread(0); t2.appendBlip(); ConversationBlip t2b2 = t2.appendBlip(); ConversationThread t3 = t2b2.addReplyThread(); t3.appendBlip(); assertEquals(2, monitor.getTotalCount(t1)); assertEquals(3, monitor.getTotalCount(t2)); assertEquals(1, monitor.getTotalCount(t3)); assertEquals(7, monitor.getTotalCount(rootThread)); } /** * This test verifies that blips counts are aggregated properly when a blip is * deleted which contains an inline thread. */ public void testNestedThreadDeleteBlip() throws Exception { ConversationBlip rb1 = rootThread.appendBlip(); ConversationThread t1 = rb1.addReplyThread(0); t1.appendBlip(); t1.appendBlip(); ConversationBlip rb2 = rootThread.appendBlip(); ConversationThread t2 = rb2.addReplyThread(0); t2.appendBlip(); ConversationBlip t2b2 = t2.appendBlip(); ConversationThread t3 = t2b2.addReplyThread(); t3.appendBlip(); t2b2.delete(); assertEquals(2, monitor.getTotalCount(t1)); assertEquals(1, monitor.getTotalCount(t2)); assertEquals(0, monitor.getTotalCount(t3)); assertEquals(5, monitor.getTotalCount(rootThread)); } /** * This test verifies read / unread blips are counted correctly in the root * thread. */ public void testRootThreadReading() throws Exception { rootThread.appendBlip(); rootThread.appendBlip(); ConversationBlip blip = rootThread.appendBlip(); supplementedWave.markAsRead(blip); assertEquals(1, monitor.getReadCount(rootThread)); assertEquals(2, monitor.getUnreadCount(rootThread)); assertEquals(3, monitor.getTotalCount(rootThread)); assertEquals(monitor.getTotalCount(rootThread), monitor.getUnreadCount(rootThread) + monitor.getReadCount(rootThread)); } /** * This test verifies the read and unread state in both the root thread as * well as an inline thread. */ public void testNestedThreadReading() throws Exception { ConversationBlip rb1 = rootThread.appendBlip(); ConversationThread t1 = rb1.addReplyThread(0); t1.appendBlip(); t1.appendBlip(); ConversationBlip rb2 = rootThread.appendBlip(); ConversationThread t2 = rb2.addReplyThread(0); t2.appendBlip(); ConversationBlip t2b2 = t2.appendBlip(); ConversationThread t3 = t2b2.addReplyThread(); ConversationBlip t3b1 = t3.appendBlip(); supplementedWave.markAsRead(t3b1); assertEquals(0, monitor.getReadCount(t1)); assertEquals(2, monitor.getUnreadCount(t1)); assertEquals(1, monitor.getReadCount(t2)); assertEquals(2, monitor.getUnreadCount(t2)); assertEquals(1, monitor.getReadCount(t3)); assertEquals(0, monitor.getUnreadCount(t3)); assertEquals(1, monitor.getReadCount(rootThread)); assertEquals(6, monitor.getUnreadCount(rootThread)); } /** * This test verifies the read and unread state when a thread with read and * unread blips is deleted. */ public void testNestedThreadWithDeleteReading() throws Exception { ConversationBlip rb1 = rootThread.appendBlip(); ConversationThread t1 = rb1.addReplyThread(0); t1.appendBlip(); ConversationBlip t1b2 = t1.appendBlip(); ConversationBlip rb2 = rootThread.appendBlip(); ConversationThread t2 = rb2.addReplyThread(0); t2.appendBlip(); ConversationBlip t2b2 = t2.appendBlip(); ConversationThread t3 = t2b2.addReplyThread(); t3.appendBlip(); ConversationBlip t3b1 = t3.appendBlip(); supplementedWave.markAsRead(t3b1); supplementedWave.markAsRead(t1b2); t2b2.delete(); assertEquals(1, monitor.getReadCount(t1)); assertEquals(1, monitor.getUnreadCount(t1)); assertEquals(0, monitor.getReadCount(t2)); assertEquals(1, monitor.getUnreadCount(t2)); assertEquals(0, monitor.getReadCount(t3)); assertEquals(0, monitor.getUnreadCount(t3)); assertEquals(1, monitor.getReadCount(rootThread)); assertEquals(4, monitor.getUnreadCount(rootThread)); } }