@@ -14,16 +14,30 @@ import { POLLING_INTERVAL } from '../constants'
1414const mocks = vi . hoisted ( ( ) => {
1515 return {
1616 parseLogFile : vi . fn ( ) ,
17+ parseLogString : vi . fn ( ) ,
1718 logger : {
1819 debug : vi . fn ( ) ,
1920 warn : vi . fn ( ) ,
21+ error : vi . fn ( ) ,
2022 } ,
2123 getLog : vi . fn ( ) ,
2224 pollLog : vi . fn ( ) ,
2325 showError : vi . fn ( ) ,
2426 }
2527} )
2628
29+ vi . mock ( '@nextcloud/dialogs' , ( ) => ( {
30+ showError : mocks . showError
31+ } ) )
32+
33+ vi . mock ( '../utils/logfile.ts' , ( ) => {
34+ return {
35+ parseLogFile : mocks . parseLogFile ,
36+ parseLogString : mocks . parseLogString ,
37+ parseRawLogEntry : vi . fn ( ( v ) => v ) ,
38+ }
39+ } )
40+
2741class ServerError extends Error {
2842
2943 public status = 500
@@ -162,13 +176,6 @@ describe('store:logging', () => {
162176 } )
163177
164178 it ( 'loads entries from file' , async ( ) => {
165- vi . mock ( '../utils/logfile.ts' , ( ) => {
166- return {
167- parseLogFile : mocks . parseLogFile ,
168- parseRawLogEntry : vi . fn ( ( v ) => v ) ,
169- }
170- } )
171-
172179 vi . mocked ( mocks . parseLogFile ) . mockImplementation ( async ( ) => {
173180 return [ { message : 'hello' } ]
174181 } )
@@ -197,13 +204,6 @@ describe('store:logging', () => {
197204 } )
198205
199206 it ( 'does not load file if no file was selected' , async ( ) => {
200- vi . mock ( '../utils/logfile.ts' , ( ) => {
201- return {
202- parseLogFile : mocks . parseLogFile ,
203- parseRawLogEntry : vi . fn ( ( v ) => v ) ,
204- }
205- } )
206-
207207 vi . mock ( '../utils/logger.ts' , ( ) => {
208208 return {
209209 logger : mocks . logger ,
@@ -227,6 +227,121 @@ describe('store:logging', () => {
227227 expect ( mocks . parseLogFile ) . not . toBeCalled ( )
228228 } )
229229
230+ it ( 'loads entries from clipboard' , async ( ) => {
231+ mocks . parseLogString . mockImplementationOnce ( ( ) => [ { message : 'hello' } ] )
232+
233+ // clean pinia
234+ createTestingPinia ( {
235+ fakeApp : true ,
236+ createSpy : vi . fn ,
237+ stubActions : false ,
238+ } )
239+
240+ const clipboard = '{message: "hello"}'
241+ window . navigator . clipboard . readText = vi . fn ( ( ) => Promise . resolve ( clipboard ) )
242+
243+ const store = useLogStore ( )
244+ const settings = useSettingsStore ( )
245+
246+ store . hasRemainingEntries = true
247+ expect ( store . hasRemainingEntries ) . toBe ( true )
248+
249+ await store . loadClipboard ( )
250+
251+ // File parsed, so there are no remaining entries
252+ expect ( store . hasRemainingEntries ) . toBe ( false )
253+ expect ( window . navigator . clipboard . readText ) . toBeCalled ( )
254+ expect ( settings . localFileName ) . toBe ( 'Clipboard' )
255+ expect ( mocks . parseLogString ) . toBeCalledWith ( clipboard )
256+ expect ( store . allEntries ) . toEqual ( [ { message : 'hello' } ] )
257+ } )
258+
259+ it ( 'handles unsupported Clipboard API' , async ( ) => {
260+ mocks . parseLogString . mockImplementationOnce ( ( ) => [ { message : 'hello' } ] )
261+
262+ // clean pinia
263+ createTestingPinia ( {
264+ fakeApp : true ,
265+ createSpy : vi . fn ,
266+ stubActions : false ,
267+ } )
268+
269+ const clipboard = '{message: "hello"}'
270+ window . navigator . clipboard . readText = vi . fn ( ( ) => Promise . reject ( new Error ( ) ) )
271+ window . prompt = vi . fn ( ( ) => clipboard )
272+
273+ const store = useLogStore ( )
274+ const settings = useSettingsStore ( )
275+
276+ store . hasRemainingEntries = true
277+ expect ( store . hasRemainingEntries ) . toBe ( true )
278+
279+ await store . loadClipboard ( )
280+
281+ // File parsed, so there are no remaining entries
282+ expect ( store . hasRemainingEntries ) . toBe ( false )
283+ expect ( window . navigator . clipboard . readText ) . toBeCalled ( )
284+ expect ( window . prompt ) . toBeCalled ( )
285+ expect ( settings . localFileName ) . toBe ( 'Clipboard' )
286+ expect ( mocks . parseLogString ) . toBeCalledWith ( clipboard )
287+ expect ( store . allEntries ) . toEqual ( [ { message : 'hello' } ] )
288+ } )
289+
290+ it ( 'handles empty clipboard paste' , async ( ) => {
291+ // clean pinia
292+ createTestingPinia ( {
293+ fakeApp : true ,
294+ createSpy : vi . fn ,
295+ stubActions : false ,
296+ } )
297+
298+ window . navigator . clipboard . readText = vi . fn ( ( ) => Promise . reject ( new Error ( ) ) )
299+ window . prompt = vi . fn ( ( ) => null )
300+
301+ const store = useLogStore ( )
302+ const settings = useSettingsStore ( )
303+
304+ store . hasRemainingEntries = true
305+ expect ( store . hasRemainingEntries ) . toBe ( true )
306+
307+ await store . loadClipboard ( )
308+
309+ // File parsed, so there are no remaining entries
310+ expect ( store . hasRemainingEntries ) . toBe ( true )
311+ expect ( window . navigator . clipboard . readText ) . toBeCalled ( )
312+ expect ( window . prompt ) . toBeCalled ( )
313+ expect ( settings . localFile ) . toBe ( undefined )
314+ expect ( settings . localFileName ) . toBe ( '' )
315+ } )
316+
317+ it ( 'handles invalid clipboard paste' , async ( ) => {
318+ // clean pinia
319+ createTestingPinia ( {
320+ fakeApp : true ,
321+ createSpy : vi . fn ,
322+ stubActions : false ,
323+ } )
324+
325+ window . navigator . clipboard . readText = vi . fn ( ( ) => Promise . resolve ( 'invalid' ) )
326+ // throw an error
327+ mocks . parseLogString . mockImplementationOnce ( ( ) => { throw new Error ( ) } )
328+
329+ const store = useLogStore ( )
330+ const settings = useSettingsStore ( )
331+
332+ store . hasRemainingEntries = true
333+ expect ( store . hasRemainingEntries ) . toBe ( true )
334+
335+ await store . loadClipboard ( )
336+
337+ // File parsed, so there are no remaining entries
338+ expect ( store . hasRemainingEntries ) . toBe ( true )
339+ expect ( window . navigator . clipboard . readText ) . toBeCalled ( )
340+ expect ( mocks . showError ) . toBeCalled ( )
341+ expect ( settings . localFile ) . toBe ( undefined )
342+ expect ( settings . localFileName ) . toBe ( '' )
343+ } )
344+
230345 it ( 'loads more from server' , async ( ) => {
231346 vi . mock ( '../api.ts' , ( ) => {
232347 return {
@@ -547,11 +662,6 @@ describe('store:logging', () => {
547662 logger : mocks . logger ,
548663 }
549664 } )
550- vi . mock ( '@nextcloud/dialogs' , ( ) => {
551- return {
552- showError : mocks . showError ,
553- }
554- } )
555665 vi . mocked ( mocks . pollLog ) . mockImplementationOnce ( ( ) => { throw Error ( ) } )
556666
557667 // clean pinia
@@ -581,11 +691,6 @@ describe('store:logging', () => {
581691 logger : mocks . logger ,
582692 }
583693 } )
584- vi . mock ( '@nextcloud/dialogs' , ( ) => {
585- return {
586- showError : mocks . showError ,
587- }
588- } )
589694 vi . mocked ( mocks . pollLog ) . mockImplementationOnce ( ( ) => { throw new ServerError ( ) } )
590695
591696 // clean pinia
0 commit comments