@@ -14,6 +14,29 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
+ /*
18
+ * # High Level Read Receipt Tests
19
+ *
20
+ * Tips for writing these tests:
21
+ *
22
+ * * Break up your tests into the smallest test case possible. The purpose of
23
+ * these tests is to understand hard-to-find bugs, so small tests are necessary.
24
+ * We know that Cypress recommends combining tests together for performance, but
25
+ * that will frustrate our goals here. (We will need to find a different way to
26
+ * reduce CI time.)
27
+ *
28
+ * * Try to assert something after every action, to make sure it has completed.
29
+ * E.g.:
30
+ * markAsRead(room2);
31
+ * assertRead(room2);
32
+ * You should especially follow this rule if you are jumping to a different
33
+ * room or similar straight afterwards.
34
+ *
35
+ * * Use assertStillRead() if you are asserting something is read when it was
36
+ * also read before. This waits a little while to make sure you're not getting a
37
+ * false positive.
38
+ */
39
+
17
40
/// <reference types="cypress" />
18
41
19
42
import type { MatrixClient , MatrixEvent , Room , IndexedDBStore } from "matrix-js-sdk/src/matrix" ;
@@ -137,6 +160,16 @@ describe("Read receipts", () => {
137
160
cy . get ( ".mx_ThreadView_timelinePanelWrapper" , { log : false } ) . should ( "have.length" , 1 ) ;
138
161
}
139
162
163
+ /**
164
+ * Close the threads panel. (Actually, close any right panel, but for these
165
+ * tests we only open the threads panel.)
166
+ */
167
+ function closeThreadsPanel ( ) {
168
+ cy . log ( "Close threads panel" ) ;
169
+ cy . get ( ".mx_RightPanel" ) . findByTitle ( "Close" ) . click ( ) ;
170
+ cy . get ( ".mx_RightPanel" ) . should ( "not.exist" ) ;
171
+ }
172
+
140
173
function sendMessageAsClient ( cli : MatrixClient , room : string , messages : Message [ ] ) {
141
174
findRoomByName ( room ) . then ( async ( { roomId } ) => {
142
175
const room = cli . getRoom ( roomId ) ;
@@ -1020,6 +1053,7 @@ describe("Read receipts", () => {
1020
1053
goTo ( room2 ) ;
1021
1054
openThread ( "Msg1" ) ;
1022
1055
assertRead ( room2 ) ;
1056
+ backToThreadsList ( ) ;
1023
1057
goTo ( room1 ) ;
1024
1058
receiveMessages ( room2 , [ editOf ( "Resp1" , "Edit1" ) ] ) ;
1025
1059
assertUnread ( room2 , 1 ) ;
@@ -1112,17 +1146,20 @@ describe("Read receipts", () => {
1112
1146
assertUnread ( room2 , 2 ) ;
1113
1147
goTo ( room2 ) ;
1114
1148
openThread ( "Msg1" ) ;
1149
+ backToThreadsList ( ) ;
1115
1150
assertRead ( room2 ) ;
1116
1151
goTo ( room1 ) ;
1117
1152
1118
1153
// When the thread root is edited
1119
1154
receiveMessages ( room2 , [ editOf ( "Msg1" , "Edit1" ) ] ) ;
1120
1155
1121
- // Then the room is unread but not the thread
1156
+ // Then the room is unread
1122
1157
assertUnread ( room2 , 1 ) ;
1158
+
1159
+ // But the thread is read
1123
1160
goTo ( room2 ) ;
1124
1161
assertRead ( room2 ) ;
1125
- assertReadThread ( "Msg1 " ) ;
1162
+ assertReadThread ( "Edit1 " ) ;
1126
1163
} ) ;
1127
1164
it ( "Reading an edit of a thread root makes the room read" , ( ) => {
1128
1165
// Given a fully-read thread exists
@@ -1614,24 +1651,242 @@ describe("Read receipts", () => {
1614
1651
} ) ;
1615
1652
1616
1653
describe ( "in threads" , ( ) => {
1617
- // One of the following two must be right:
1618
- it . skip ( "Redacting the threaded message pointed to by my receipt leaves the room read" , ( ) => { } ) ;
1619
- it . skip ( "Redacting a threaded message after it was read makes the room unread" , ( ) => { } ) ;
1654
+ it ( "Redacting the threaded message pointed to by my receipt leaves the room read" , ( ) => {
1655
+ // Given I have some threads
1656
+ goTo ( room1 ) ;
1657
+ receiveMessages ( room2 , [
1658
+ "Root" ,
1659
+ threadedOff ( "Root" , "ThreadMsg1" ) ,
1660
+ threadedOff ( "Root" , "ThreadMsg2" ) ,
1661
+ "Root2" ,
1662
+ threadedOff ( "Root2" , "Root2->A" ) ,
1663
+ ] ) ;
1664
+ assertUnread ( room2 , 5 ) ;
1665
+
1666
+ // And I have read them
1667
+ goTo ( room2 ) ;
1668
+ assertUnreadThread ( "Root" ) ;
1669
+ openThread ( "Root" ) ;
1670
+ assertUnreadLessThan ( room2 , 4 ) ;
1671
+ openThread ( "Root2" ) ;
1672
+ assertRead ( room2 ) ;
1673
+ closeThreadsPanel ( ) ;
1674
+ goTo ( room1 ) ;
1675
+ assertRead ( room2 ) ;
1676
+
1677
+ // When the latest message in a thread is redacted
1678
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg2" ) ] ) ;
1679
+
1680
+ // Then the room and thread are still read
1681
+ assertStillRead ( room2 ) ;
1682
+ goTo ( room2 ) ;
1683
+ assertReadThread ( "Root" ) ;
1684
+ } ) ;
1685
+
1686
+ // XXX: fails because the unread count is still 1 when it should be 0 (this is a genuine stuck unread case)
1687
+ it . skip ( "Reading an unread thread after a redaction of the latest message makes it read" , ( ) => {
1688
+ // Given an unread thread where the latest message was redacted
1689
+ goTo ( room1 ) ;
1690
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "ThreadMsg1" ) , threadedOff ( "Root" , "ThreadMsg2" ) ] ) ;
1691
+ assertUnread ( room2 , 3 ) ;
1692
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg2" ) ] ) ;
1693
+ assertUnread ( room2 , 2 ) ;
1694
+ goTo ( room2 ) ;
1695
+ assertUnreadThread ( "Root" ) ;
1696
+
1697
+ // When I read the thread
1698
+ openThread ( "Root" ) ;
1699
+ assertRead ( room2 ) ;
1700
+ closeThreadsPanel ( ) ;
1701
+ goTo ( room1 ) ;
1702
+
1703
+ // Then the thread is read
1704
+ assertRead ( room2 ) ;
1705
+ goTo ( room2 ) ;
1706
+ assertReadThread ( "Root" ) ;
1707
+ } ) ;
1708
+ // XXX: fails because the unread count is still 1 when it should be 0
1709
+ it . skip ( "Reading an unread thread after a redaction of the latest message makes it read after restart" , ( ) => {
1710
+ // Given a redacted message is not counted in the unread count
1711
+ goTo ( room1 ) ;
1712
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "ThreadMsg1" ) , threadedOff ( "Root" , "ThreadMsg2" ) ] ) ;
1713
+ assertUnread ( room2 , 3 ) ;
1714
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg2" ) ] ) ;
1715
+ assertUnread ( room2 , 2 ) ;
1716
+ goTo ( room2 ) ;
1717
+ assertUnreadThread ( "Root" ) ;
1718
+ openThread ( "Root" ) ;
1719
+ assertRead ( room2 ) ;
1720
+ closeThreadsPanel ( ) ;
1721
+ goTo ( room1 ) ;
1722
+ assertRead ( room2 ) ;
1723
+ goTo ( room2 ) ;
1724
+ assertReadThread ( "Root" ) ;
1725
+
1726
+ // When I restart
1727
+ saveAndReload ( ) ;
1728
+
1729
+ // Then the room is still read
1730
+ assertRead ( room2 ) ;
1731
+ } ) ;
1732
+ // XXX: fails because the unread count is still 1 when it should be 0
1733
+ it . skip ( "Reading an unread thread after a redaction of an older message makes it read" , ( ) => {
1734
+ // Given an unread thread where an older message was redacted
1735
+ goTo ( room1 ) ;
1736
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "ThreadMsg1" ) , threadedOff ( "Root" , "ThreadMsg2" ) ] ) ;
1737
+ assertUnread ( room2 , 3 ) ;
1738
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg1" ) ] ) ;
1739
+ assertUnread ( room2 , 2 ) ;
1740
+ goTo ( room2 ) ;
1741
+ assertUnreadThread ( "Root" ) ;
1742
+
1743
+ // When I read the thread
1744
+ openThread ( "Root" ) ;
1745
+ assertRead ( room2 ) ;
1746
+ closeThreadsPanel ( ) ;
1747
+ goTo ( room1 ) ;
1748
+
1749
+ // Then the thread is read
1750
+ assertRead ( room2 ) ;
1751
+ goTo ( room2 ) ;
1752
+ assertReadThread ( "Root" ) ;
1753
+ } ) ;
1754
+ // XXX: fails because the room has an unread dot after I marked it as read
1755
+ it . skip ( "Marking an unread thread as read after a redaction makes it read" , ( ) => {
1756
+ // Given an unread thread where an older message was redacted
1757
+ goTo ( room1 ) ;
1758
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "ThreadMsg1" ) , threadedOff ( "Root" , "ThreadMsg2" ) ] ) ;
1759
+ assertUnread ( room2 , 3 ) ;
1760
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg1" ) ] ) ;
1761
+ assertUnread ( room2 , 2 ) ;
1762
+
1763
+ // When I mark the room as read
1764
+ markAsRead ( room2 ) ;
1765
+ assertRead ( room2 ) ;
1766
+
1767
+ // Then the thread is read
1768
+ assertRead ( room2 ) ;
1769
+ goTo ( room2 ) ;
1770
+ assertReadThread ( "Root" ) ;
1771
+ } ) ;
1772
+ // XXX: fails because the room has an unread dot after I marked it as read
1773
+ it . skip ( "Sending and redacting a message after marking the thread as read leaves it read" , ( ) => {
1774
+ // Given a thread exists and is marked as read
1775
+ goTo ( room1 ) ;
1776
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "ThreadMsg1" ) , threadedOff ( "Root" , "ThreadMsg2" ) ] ) ;
1777
+ assertUnread ( room2 , 3 ) ;
1778
+ markAsRead ( room2 ) ;
1779
+ assertRead ( room2 ) ;
1780
+
1781
+ // When I send and redact a message
1782
+ receiveMessages ( room2 , [ threadedOff ( "Root" , "Msg3" ) ] ) ;
1783
+ assertUnread ( room2 , 1 ) ;
1784
+ receiveMessages ( room2 , [ redactionOf ( "Msg3" ) ] ) ;
1785
+
1786
+ // Then the room and thread are read
1787
+ assertRead ( room2 ) ;
1788
+ goTo ( room2 ) ;
1789
+ assertReadThread ( "Root" ) ;
1790
+ } ) ;
1791
+ // XXX: fails because the room has an unread dot after I marked it as read
1792
+ it . skip ( "Redacting a message after marking the thread as read leaves it read" , ( ) => {
1793
+ // Given a thread exists and is marked as read
1794
+ goTo ( room1 ) ;
1795
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "ThreadMsg1" ) , threadedOff ( "Root" , "ThreadMsg2" ) ] ) ;
1796
+ assertUnread ( room2 , 3 ) ;
1797
+ markAsRead ( room2 ) ;
1798
+ assertRead ( room2 ) ;
1799
+
1800
+ // When I redact a message
1801
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg1" ) ] ) ;
1802
+
1803
+ // Then the room and thread are read
1804
+ assertRead ( room2 ) ;
1805
+ goTo ( room2 ) ;
1806
+ assertReadThread ( "Root" ) ;
1807
+ } ) ;
1808
+ // TODO: Doesn't work because the test setup can't (yet) find the ID of a redacted message
1809
+ it . skip ( "Reacting to a redacted message leaves the thread read" , ( ) => {
1810
+ // Given a message in a thread was redacted and everything is read
1811
+ goTo ( room1 ) ;
1812
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "Msg2" ) , threadedOff ( "Root" , "Msg3" ) ] ) ;
1813
+ receiveMessages ( room2 , [ redactionOf ( "Msg2" ) ] ) ;
1814
+ assertUnread ( room2 , 2 ) ;
1815
+ goTo ( room2 ) ;
1816
+ assertUnread ( room2 , 1 ) ;
1817
+ openThread ( "Root" ) ;
1818
+ assertRead ( room2 ) ;
1819
+ goTo ( room1 ) ;
1820
+
1821
+ // When we receive a reaction to the redacted event
1822
+ // TODO: doesn't work yet because we need to be able to look up
1823
+ // the ID of Msg2 even though it has now disappeared from the
1824
+ // timeline.
1825
+ receiveMessages ( room2 , [ reactionTo ( room2 , "Msg2" ) ] ) ;
1620
1826
1621
- it . skip ( "Reading an unread thread after a redaction of the latest message makes it read" , ( ) => { } ) ;
1622
- it . skip ( "Reading an unread thread after a redaction of an older message makes it read" , ( ) => { } ) ;
1623
- it . skip ( "Marking an unread thread as read after a redaction makes it read" , ( ) => { } ) ;
1624
- it . skip ( "Sending and redacting a message after marking the thread as read makes it unread" , ( ) => { } ) ;
1625
- it . skip ( "?? Redacting a message after marking the thread as read makes it unread" , ( ) => { } ) ;
1626
- it . skip ( "Reacting to a redacted message leaves the thread read" , ( ) => { } ) ;
1627
- it . skip ( "Editing a redacted message leaves the thread read" , ( ) => { } ) ;
1827
+ // Then the room is unread
1828
+ assertStillRead ( room2 ) ;
1829
+ } ) ;
1830
+ // TODO: Doesn't work because the test setup can't (yet) find the ID of a redacted message
1831
+ it . skip ( "Editing a redacted message leaves the thread read" , ( ) => {
1832
+ // Given a message in a thread was redacted and everything is read
1833
+ goTo ( room1 ) ;
1834
+ receiveMessages ( room2 , [ "Root" , threadedOff ( "Root" , "Msg2" ) , threadedOff ( "Root" , "Msg3" ) ] ) ;
1835
+ receiveMessages ( room2 , [ redactionOf ( "Msg2" ) ] ) ;
1836
+ assertUnread ( room2 , 2 ) ;
1837
+ goTo ( room2 ) ;
1838
+ assertUnread ( room2 , 1 ) ;
1839
+ openThread ( "Root" ) ;
1840
+ assertRead ( room2 ) ;
1841
+ goTo ( room1 ) ;
1842
+
1843
+ // When we receive an edit of the redacted message
1844
+ // TODO: doesn't work yet because we need to be able to look up
1845
+ // the ID of Msg2 even though it has now disappeared from the
1846
+ // timeline.
1847
+ receiveMessages ( room2 , [ editOf ( "Msg2" , "New Msg2" ) ] ) ;
1848
+
1849
+ // Then the room is unread
1850
+ assertStillRead ( room2 ) ;
1851
+ } ) ;
1628
1852
1629
1853
it . skip ( "?? Reading a reaction to a redacted message marks the thread as read" , ( ) => { } ) ;
1630
1854
it . skip ( "?? Reading an edit of a redacted message marks the thread as read" , ( ) => { } ) ;
1631
1855
it . skip ( "Reading a reply to a redacted message marks the thread as read" , ( ) => { } ) ;
1856
+ it . skip ( "Reading a thread root when its only message has been redacted leaves the room read" , ( ) => { } ) ;
1632
1857
1633
1858
it . skip ( "A thread with an unread redaction is still unread after restart" , ( ) => { } ) ;
1634
- it . skip ( "A thread with a read redaction is still read after restart" , ( ) => { } ) ;
1859
+ it ( "A thread with a read redaction is still read after restart" , ( ) => {
1860
+ // Given my receipt points at a redacted thread message
1861
+ goTo ( room1 ) ;
1862
+ receiveMessages ( room2 , [
1863
+ "Root" ,
1864
+ threadedOff ( "Root" , "ThreadMsg1" ) ,
1865
+ threadedOff ( "Root" , "ThreadMsg2" ) ,
1866
+ "Root2" ,
1867
+ threadedOff ( "Root2" , "Root2->A" ) ,
1868
+ ] ) ;
1869
+ assertUnread ( room2 , 5 ) ;
1870
+ goTo ( room2 ) ;
1871
+ assertUnreadThread ( "Root" ) ;
1872
+ openThread ( "Root" ) ;
1873
+ assertUnreadLessThan ( room2 , 4 ) ;
1874
+ openThread ( "Root2" ) ;
1875
+ assertRead ( room2 ) ;
1876
+ closeThreadsPanel ( ) ;
1877
+ goTo ( room1 ) ;
1878
+ assertRead ( room2 ) ;
1879
+ receiveMessages ( room2 , [ redactionOf ( "ThreadMsg2" ) ] ) ;
1880
+ assertStillRead ( room2 ) ;
1881
+ goTo ( room2 ) ;
1882
+ assertReadThread ( "Root" ) ;
1883
+
1884
+ // When I restart
1885
+ saveAndReload ( ) ;
1886
+
1887
+ // Then the room is still read
1888
+ assertRead ( room2 ) ;
1889
+ } ) ;
1635
1890
it . skip ( "A thread with an unread reply to a redacted message is still unread after restart" , ( ) => { } ) ;
1636
1891
it . skip ( "A thread with a read replt to a redacted message is still read after restart" , ( ) => { } ) ;
1637
1892
} ) ;
0 commit comments