11package protect .card_locker ;
22
3+ import static org .junit .Assert .assertEquals ;
34import static org .junit .Assert .assertFalse ;
5+ import static org .junit .Assert .assertNotNull ;
6+ import static org .junit .Assert .assertTrue ;
7+ import static org .mockito .ArgumentMatchers .any ;
8+ import static org .mockito .Mockito .atLeastOnce ;
9+ import static org .mockito .Mockito .mock ;
10+ import static org .mockito .Mockito .verify ;
11+ import static org .mockito .Mockito .when ;
412
13+ import android .content .Context ;
514import android .content .res .TypedArray ;
15+ import android .graphics .Bitmap ;
616import android .graphics .Color ;
17+ import android .widget .ImageView ;
718
819import androidx .test .core .app .ActivityScenario ;
920
1021import org .junit .Test ;
1122import org .junit .runner .RunWith ;
1223import org .robolectric .RobolectricTestRunner ;
1324
25+ import java .io .ByteArrayInputStream ;
26+ import java .io .File ;
27+ import java .io .FileInputStream ;
28+ import java .io .InputStream ;
29+ import java .util .Random ;
1430
1531@ RunWith (RobolectricTestRunner .class )
1632public class UtilsTest {
@@ -24,11 +40,212 @@ public void allDefaultCardColoursHaveWhiteForegroundTest() {
2440 TypedArray colors = activity .getApplicationContext ().getResources ().obtainTypedArray (R .array .letter_tile_colors );
2541
2642 for (int i = 0 ; i < colors .length (); i ++) {
27- // Grab white as fallback so that if the retrieval somehow fails the test is guaranteed to fail because a white background will have black foreground
2843 int color = colors .getColor (i , Color .WHITE );
2944 assertFalse (Utils .needsDarkForeground (color ));
3045 }
3146 });
3247 }
3348 }
49+
50+ /**
51+ * Test checksum method with a fake (small) input stream
52+ */
53+ @ Test
54+ public void testChecksum_withFakeInputStream () throws Exception {
55+ byte [] fakeContent = "test content" .getBytes ();
56+ InputStream fakeStream = new ByteArrayInputStream (fakeContent );
57+
58+ String checksum = Utils .checksum (fakeStream );
59+
60+ assertNotNull (checksum );
61+ assertTrue (checksum .matches ("[0-9a-f]+" ));
62+ }
63+
64+ /**
65+ * Test checksum method with large random content (1 MB)
66+ */
67+ @ Test
68+ public void testChecksum_withLargeContent () throws Exception {
69+ byte [] largeContent = new byte [1024 * 1024 ];
70+ new Random ().nextBytes (largeContent );
71+ InputStream largeStream = new ByteArrayInputStream (largeContent );
72+
73+ String checksum = Utils .checksum (largeStream );
74+
75+ assertNotNull (checksum );
76+ assertTrue (checksum .matches ("[0-9a-f]+" ));
77+ }
78+
79+ /**
80+ * Test checksum method using a mocked FileInputStream
81+ */
82+ @ Test
83+ public void testChecksum_withMockedFileInputStream () throws Exception {
84+ FileInputStream mockStream = mock (FileInputStream .class );
85+ when (mockStream .read (any (byte [].class ))).thenReturn (-1 );
86+
87+ String checksum = Utils .checksum (mockStream );
88+
89+ assertNotNull (checksum );
90+ verify (mockStream , atLeastOnce ()).read (any (byte [].class ));
91+ }
92+
93+ /**
94+ * Test getUnixTime method returns reasonable timestamp
95+ */
96+ @ Test
97+ public void testGetUnixTime () {
98+ long unixTime = Utils .getUnixTime ();
99+
100+ // Unix time should be positive
101+ assertTrue ("Unix time should be positive" , unixTime > 0 );
102+
103+ // Should be reasonable (after year 2020 and before year 2030)
104+ long year2020 = 1577836800L ; // Jan 1, 2020
105+ long year2030 = 1893456000L ; // Jan 1, 2030
106+
107+ assertTrue ("Unix time should be after 2020" , unixTime > year2020 );
108+ assertTrue ("Unix time should be before 2030" , unixTime < year2030 );
109+ }
110+
111+ /**
112+ * Test createTempFile method with mocked context
113+ */
114+ @ Test
115+ public void testCreateTempFile () {
116+ // Create a mock context
117+ Context mockContext = mock (Context .class );
118+ File mockCacheDir = new File ("/mock/cache" );
119+
120+ when (mockContext .getCacheDir ()).thenReturn (mockCacheDir );
121+
122+ // Test file creation
123+ String fileName = "test_file.txt" ;
124+ File result = Utils .createTempFile (mockContext , fileName );
125+
126+ assertNotNull ("Should return a File object" , result );
127+ assertTrue ("File path should contain cache directory" , result .getPath ().contains ("cache" ));
128+ assertTrue ("File path should contain filename" , result .getPath ().contains (fileName ));
129+ assertEquals ("Should create correct file path" , "\\ mock\\ cache\\ test_file.txt" , result .getPath ());
130+ }
131+
132+ /**
133+ * Test getComplementaryColor method
134+ */
135+ @ Test
136+ public void testGetComplementaryColor () {
137+ // Test with pure red
138+ int red = Color .rgb (255 , 0 , 0 );
139+ int complementRed = Utils .getComplementaryColor (red );
140+ assertEquals ("Complement of red should be cyan" , Color .rgb (0 , 255 , 255 ), complementRed );
141+
142+ // Test with white
143+ int white = Color .WHITE ;
144+ int complementWhite = Utils .getComplementaryColor (white );
145+ assertEquals ("Complement of white should be black" , Color .BLACK , complementWhite );
146+
147+ // Test with black
148+ int black = Color .BLACK ;
149+ int complementBlack = Utils .getComplementaryColor (black );
150+ assertEquals ("Complement of black should be white" , Color .WHITE , complementBlack );
151+
152+ // Test with gray (should remain the same)
153+ int gray = Color .rgb (128 , 128 , 128 );
154+ int complementGray = Utils .getComplementaryColor (gray );
155+ assertEquals ("Complement of gray should be gray" , Color .rgb (127 , 127 , 127 ), complementGray );
156+ }
157+
158+ /**
159+ * Test getRecommendedScaleTypeForThumbnailImage method
160+ */
161+ @ Test
162+ public void testGetRecommendedScaleTypeForThumbnailImage () {
163+ // Test with null bitmap
164+ ImageView .ScaleType result = Utils .getRecommendedScaleTypeForThumbnailImage (null );
165+ assertEquals ("Should return FIT_CENTER for null bitmap" , ImageView .ScaleType .FIT_CENTER , result );
166+
167+ // Create mock bitmaps with different aspect ratios
168+ Bitmap mockBitmapSquare = mock (Bitmap .class );
169+ when (mockBitmapSquare .getWidth ()).thenReturn (100 );
170+ when (mockBitmapSquare .getHeight ()).thenReturn (100 );
171+
172+ result = Utils .getRecommendedScaleTypeForThumbnailImage (mockBitmapSquare );
173+ assertEquals ("Should return FIT_CENTER for square image" , ImageView .ScaleType .FIT_CENTER , result );
174+
175+ // Test with ideal card ratio (around 1.58)
176+ Bitmap mockBitmapCard = mock (Bitmap .class );
177+ when (mockBitmapCard .getWidth ()).thenReturn (158 );
178+ when (mockBitmapCard .getHeight ()).thenReturn (100 );
179+
180+ result = Utils .getRecommendedScaleTypeForThumbnailImage (mockBitmapCard );
181+ assertEquals ("Should return CENTER_CROP for card-like aspect ratio" , ImageView .ScaleType .CENTER_CROP , result );
182+
183+ // Test with very wide image
184+ Bitmap mockBitmapWide = mock (Bitmap .class );
185+ when (mockBitmapWide .getWidth ()).thenReturn (300 );
186+ when (mockBitmapWide .getHeight ()).thenReturn (100 );
187+
188+ result = Utils .getRecommendedScaleTypeForThumbnailImage (mockBitmapWide );
189+ assertEquals ("Should return FIT_CENTER for very wide image" , ImageView .ScaleType .FIT_CENTER , result );
190+ }
191+
192+ /**
193+ * Test basicMDToHTML method with various markdown patterns
194+ */
195+ @ Test
196+ public void testBasicMDToHTML () {
197+ // Test heading conversion
198+ String input = "# Main Title\n ## Subtitle" ;
199+ String expected = "<h1>Main Title</h1>\n <h2>Subtitle</h2>" ;
200+ assertEquals ("Should convert headings correctly" , expected , Utils .basicMDToHTML (input ));
201+
202+ // Test link conversion
203+ input = "Visit [GitHub](https://github.com)" ;
204+ expected = "Visit <a href=\" https://github.com\" >GitHub</a>" ;
205+ assertEquals ("Should convert links correctly" , expected , Utils .basicMDToHTML (input ));
206+
207+ // Test bold text conversion
208+ input = "This is **bold** text" ;
209+ expected = "This is <b>bold</b> text" ;
210+ assertEquals ("Should convert bold text correctly" , expected , Utils .basicMDToHTML (input ));
211+
212+ // Test list item conversion
213+ input = "- First item\n - Second item" ;
214+ expected = "<ul><li> First item</li></ul>\n <ul><li> Second item</li></ul>" ;
215+ // The method should merge consecutive list items
216+ String actual = Utils .basicMDToHTML (input );
217+ assertTrue ("Should contain list items" , actual .contains ("<li> First item</li>" ));
218+ assertTrue ("Should contain list items" , actual .contains ("<li> Second item</li>" ));
219+ }
220+
221+ /**
222+ * Test linkify method for automatic link detection
223+ */
224+ @ Test
225+ public void testLinkify () {
226+ // Test email linkification
227+ String input = "Contact us at support@example.com" ;
228+ String result = Utils .linkify (input );
229+ assertTrue ("Should linkify email addresses" ,
230+ result .contains ("<a href=\" mailto:support@example.com\" >support@example.com</a>" ));
231+
232+ // Test URL linkification
233+ input = "Visit https://www.example.com for more info" ;
234+ result = Utils .linkify (input );
235+ assertTrue ("Should linkify URLs" ,
236+ result .contains ("<a href=\" https://www.example.com\" >https://www.example.com</a>" ));
237+
238+ // Test mixed content
239+ input = "Email: test@domain.org and website: http://example.net" ;
240+ result = Utils .linkify (input );
241+ assertTrue ("Should linkify email in mixed content" ,
242+ result .contains ("<a href=\" mailto:test@domain.org\" >test@domain.org</a>" ));
243+ assertTrue ("Should linkify URL in mixed content" ,
244+ result .contains ("<a href=\" http://example.net\" >http://example.net</a>" ));
245+
246+ // Test no links
247+ input = "Just plain text with no links" ;
248+ result = Utils .linkify (input );
249+ assertEquals ("Should not modify text without links" , input , result );
250+ }
34251}
0 commit comments