diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 411065c..9910c30 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -8,6 +8,14 @@ Class { #package : 'DebuggingSpy-Browser-Tests' } +{ #category : 'asserting' } +DSRecordBrowserPresenterTest >> assertThat: aRecord equals: anotherRecord [ + "Verifies that all slots are equals between two records." + + self assert: aRecord class equals: anotherRecord class. + aRecord class allSlots do: [ :slot | self assert: (aRecord readSlot: slot) equals: (anotherRecord readSlot: slot) ] +] + { #category : 'helpers' } DSRecordBrowserPresenterTest >> filesPresenter [ @@ -16,6 +24,7 @@ DSRecordBrowserPresenterTest >> filesPresenter [ { #category : 'helpers' } DSRecordBrowserPresenterTest >> generateRecordsFile [ + "Generates a file of records and returns its file reference." ^ self generateRecordsFileFor: self getRecordExamples ] @@ -24,26 +33,7 @@ DSRecordBrowserPresenterTest >> generateRecordsFile [ DSRecordBrowserPresenterTest >> generateRecordsFileFor: someRecords [ "Generates a file of records and returns its file reference." - | recordFileRef writeStream | - - recordFileRef := self temporaryDirectory / ('ds-spy-test-' , UUID new asString). - recordFileRef ensureCreateFile. - writeStream := recordFileRef writeStream. - - writeStream nextPut: $[. - - someRecords doWithIndex: [ :record :index | - writeStream nextPutAll: (STON toString: record). - - index = someRecords size ifFalse: [ - writeStream nextPut: $,. - writeStream crlf ] ]. - - writeStream nextPut: $]. - - writeStream close. - - ^ recordFileRef + ^ self writeRecords: someRecords inFile: self temporaryDirectory / ('ds-spy-test-' , UUID new asString) ] { #category : 'helpers' } @@ -52,20 +42,16 @@ DSRecordBrowserPresenterTest >> getRecordExamples [ ^ OrderedCollection new add: (DSBrowseRecord new windowId: 1; - dateTime: (DateAndTime fromSeconds: 1); - yourself); + dateTime: (DateAndTime fromSeconds: 1)); add: (DSMouseEnterWindowRecord new windowId: 2; - dateTime: (DateAndTime fromSeconds: 2); - yourself); + dateTime: (DateAndTime fromSeconds: 2)); add: (DSMouseLeaveWindowRecord new windowId: 3; - dateTime: (DateAndTime fromSeconds: 3); - yourself); + dateTime: (DateAndTime fromSeconds: 3)); add: (DSInspectItRecord new windowId: 4; - dateTime: (DateAndTime fromSeconds: 4); - yourself); + dateTime: (DateAndTime fromSeconds: 4)); yourself ] @@ -107,24 +93,16 @@ DSRecordBrowserPresenterTest >> testAddFile [ | fileRef | fileRef := self generateRecordsFile. - browser addFile: fileRef. - self assert: browser files size equals: 1. - self assert: self filesPresenter items size equals: 1. + browser addFile: self temporaryDirectory. - self assert: self filesPresenter selectedItem equals: fileRef -] - -{ #category : 'tests' } -DSRecordBrowserPresenterTest >> testAddFileWhenAlreadyInList [ - - | fileRef | - fileRef := self generateRecordsFile. + self assert: browser files size equals: 1. + self assert: self filesPresenter roots size equals: 1. + self assert: self filesPresenter selectedItem equals: self temporaryDirectory. - browser addFile: fileRef. - browser addFile: fileRef. + browser addFile: fileRef. "fileRef is in temporary directory so it should not be added again" self assert: browser files size equals: 1. - self assert: self filesPresenter items size equals: 1. - self assert: self filesPresenter selectedItem equals: fileRef + self assert: self filesPresenter roots size equals: 1. + self assert: self filesPresenter selectedItem equals: self temporaryDirectory ] { #category : 'tests' } @@ -137,7 +115,7 @@ DSRecordBrowserPresenterTest >> testAddingMultipleFiles [ browser addFile: fileRef. self assert: browser files size equals: 2. - self assert: self filesPresenter items size equals: 2. + self assert: self filesPresenter roots size equals: 2. self assert: self filesPresenter selectedItem equals: fileRef ] @@ -145,7 +123,7 @@ DSRecordBrowserPresenterTest >> testAddingMultipleFiles [ DSRecordBrowserPresenterTest >> testBrowserEmpty [ self assertEmpty: browser files. - self assert: self filesPresenter items size equals: 0. + self assert: self filesPresenter roots size equals: 0. self assert: self filesPresenter selectedItem equals: nil. self assert: self recordsTablePresenter roots size equals: 0 ] @@ -187,6 +165,19 @@ DSRecordBrowserPresenterTest >> testCreatingAndOpeningBrowser [ DSRecordBrowserPresenter toggleBrowser ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testFileAdding [ + + | fileRef | + fileRef := self writeRecords: self getRecordExamples inFile: self temporaryDirectory / 'ds-spy/test'. + fileRef ensureCreateFile. + browser addFile: self temporaryDirectory. + + self assert: (browser isFileAdded: self temporaryDirectory). + self assert: (browser isFileAdded: fileRef). + self deny: (browser isFileAdded: 'notAddedFile' asFileReference) +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testFilterRecordClass [ @@ -255,6 +246,63 @@ DSRecordBrowserPresenterTest >> testGetRecordColorAssociationsFrom [ colorAssociations do: [ :association | self assert: association value equals: (Color fromHexString: '#70B77E') ] ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testGetRecordsFromFileReference [ + + | records fileRef fileRecords | + records := self getRecordExamples. + fileRef := self generateRecordsFileFor: records. + + fileRecords := browser getRecordsFromFileReference: fileRef. + + self assertThat: records first equals: fileRecords first. + self assertThat: records second equals: fileRecords second. + self assertThat: records third equals: fileRecords third. + self assertThat: records fourth equals: fileRecords fourth. + + fileRecords := browser getRecordsFromFileReference: self temporaryDirectory. + + self assertThat: records first equals: fileRecords first. + self assertThat: records second equals: fileRecords second. + self assertThat: records third equals: fileRecords third. + self assertThat: records fourth equals: fileRecords fourth +] + +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testGetRecordsFromFolderReference [ + + | records otherRecords fileRecords | + records := self getRecordExamples. + otherRecords := { + (DSPrintItRecord new + windowId: 0; + dateTime: (DateAndTime fromSeconds: 0)). + (DSMouseLeaveWindowRecord new + windowId: 7; + dateTime: (DateAndTime fromSeconds: 7)). + (DSMouseEnterWindowRecord new + windowId: 5; + dateTime: (DateAndTime fromSeconds: 5)). + (DSInspectItRecord new + windowId: 6; + dateTime: (DateAndTime fromSeconds: 6)) }. + + self generateRecordsFileFor: records. + self writeRecords: otherRecords inFile: self temporaryDirectory / 'otherRecords'. + + fileRecords := browser getRecordsFromFileReference: self temporaryDirectory. + self assert: fileRecords size equals: 8. + + self assertThat: fileRecords first equals: otherRecords first. + self assertThat: fileRecords second equals: records first. + self assertThat: fileRecords third equals: records second. + self assertThat: fileRecords fourth equals: records third. + self assertThat: fileRecords fifth equals: records fourth. + self assertThat: fileRecords sixth equals: otherRecords third. + self assertThat: fileRecords seventh equals: otherRecords fourth. + self assertThat: fileRecords eighth equals: otherRecords second +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testGetWindowFromRecord [ @@ -271,6 +319,15 @@ DSRecordBrowserPresenterTest >> testGetWindowFromRecord [ self assert: window name equals: record windowId ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testIsFileAdded [ + + browser files: { 'aFolder' asFileReference } asOrderedCollection. + self assert: (browser isFileAdded: 'aFolder' asFileReference). + self assert: (browser isFileAdded: 'aFolder/testFile' asFileReference). + self deny: (browser isFileAdded: 'notAddedFile' asFileReference) +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testRemoveFile [ @@ -283,7 +340,7 @@ DSRecordBrowserPresenterTest >> testRemoveFile [ browser removeFile: fileRef1. self assert: browser files size equals: 1. - self assert: self filesPresenter items size equals: 1. + self assert: self filesPresenter roots size equals: 1. self assert: self filesPresenter selectedItem equals: fileRef2 ] @@ -297,7 +354,7 @@ DSRecordBrowserPresenterTest >> testRemoveLastFile [ browser removeFile: fileRef1. self assert: browser files size equals: 0. - self assert: self filesPresenter items size equals: 0. + self assert: self filesPresenter roots size equals: 0. self assert: self filesPresenter selectedItem equals: nil ] @@ -422,3 +479,25 @@ DSRecordBrowserPresenterTest >> windowsPresenter [ ^ browser presenterAt: #windowsPresenter ] + +{ #category : 'writing' } +DSRecordBrowserPresenterTest >> writeRecords: someRecords inFile: aFileReference [ + "Write the specified records in the specified file in STON format." + + | writeStream | + aFileReference ensureCreateFile. + writeStream := aFileReference writeStream. + + writeStream nextPut: $[. + + someRecords doWithIndex: [ :record :index | + writeStream nextPutAll: (STON toString: record). + + index = someRecords size ifFalse: [ + writeStream nextPut: $,. + writeStream crlf ] ]. + + writeStream nextPut: $]. + writeStream close. + ^ aFileReference +] diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 9e34ca9..7306e97 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -115,7 +115,7 @@ DSRecordBrowserPresenter class >> windowType [ DSRecordBrowserPresenter >> addFile: aFileReference [ "Adds a file in the presenter and set is as selected, which updates the records displayed." - (files includes: aFileReference) + (self isFileAdded: aFileReference) ifTrue: [ ^ self inform: 'File already added !' ] ifFalse: [ files add: aFileReference. @@ -158,8 +158,8 @@ DSRecordBrowserPresenter >> colorReferential [ DSRecordBrowserPresenter >> connectPresenters [ "Updates the records and the timeline whenever the selected file is changed." - fileListPresenter whenSelectionChangedDo: [ :presenter | - selectedHistory := self getHistoryFrom: presenter selectedItem. + fileListPresenter whenSelectionChangedDo: [ + selectedHistory := self getHistoryFrom: fileListPresenter selectedItem. self updateRecordsTable. self updateWindowsPresenter. self updateStatisticsPresenter ]. @@ -190,13 +190,49 @@ DSRecordBrowserPresenter >> defaultLayout [ ] { #category : 'layout' } -DSRecordBrowserPresenter >> fileList [ +DSRecordBrowserPresenter >> fileListPresenter [ "Instanciates a new presenter with a list of added files." - ^ self newList - items: self files; - display: [ :file | file basenameWithoutExtension ]; - actions: self listAddedFilesActions; + ^ self newTreeTable + addColumn: (SpStringTableColumn new + evaluated: [ :file | file basenameWithoutExtension ]; + beNotSortable; + yourself); + roots: self files; + children: [ :file | + file isDirectory + ifTrue: [ file children ] + ifFalse: [ { } ] ]; + actions: self fileListPresenterActions; + hideColumnHeaders +] + +{ #category : 'layout' } +DSRecordBrowserPresenter >> fileListPresenterActions [ + "Returns a list of actions for the list of added files. Action are: inspecting raw records, inspecting history, or removing the selected file from the list." + + ^ SpActionGroup new + addActionWith: [ :anItem | + anItem + name: 'Inspect'; + iconName: #inspect; + description: 'Inspect the raw records'; + shortcutKey: $i meta; + action: [ selectedHistory records inspect ] ]; + addActionWith: [ :anItem | + anItem + name: 'Inspect history'; + iconName: #history; + description: 'Inspect the record history'; + shortcutKey: $h meta; + action: [ selectedHistory inspect ] ]; + addActionWith: [ :anItem | + anItem + name: 'Remove'; + iconName: #remove; + description: 'Remove the record from list'; + shortcutKey: $x meta; + action: [ self removeFile: fileListPresenter selectedItem ] ]; yourself ] @@ -206,6 +242,12 @@ DSRecordBrowserPresenter >> files [ ^ files ifNil: [ files := OrderedCollection new ] ] +{ #category : 'accessing' } +DSRecordBrowserPresenter >> files: newFiles [ + + files := newFiles +] + { #category : 'operations' } DSRecordBrowserPresenter >> filterRecordClass: aClass [ "Add the specified class to the records filter." @@ -231,7 +273,7 @@ DSRecordBrowserPresenter >> getHistoryFrom: aFileReference [ "Returns the generated history using the specified file reference which should countains DSSpy records." aFileReference ifNil: [ ^ nil ]. - ^ DSRecordHistory on: (DSSpy materialize: aFileReference) + ^ DSRecordHistory on: (self getRecordsFromFileReference: aFileReference) ] { #category : 'helpers' } @@ -248,6 +290,18 @@ DSRecordBrowserPresenter >> getRecordColorAssociationsFrom: aWindowRecordCollect ^ recordColorsAssociations sorted: [ :recordA :recordB | recordA key dateTime < recordB key dateTime ] ] +{ #category : 'helpers' } +DSRecordBrowserPresenter >> getRecordsFromFileReference: aFileReference [ + "Returns recursively a list of records taken in the specified file reference. If the argument is a folder, takes all its contained records." + + | records | + aFileReference isDirectory ifFalse: [ ^ DSSpy materialize: aFileReference ]. + + records := OrderedCollection new. + records addAll: (aFileReference children collect: [ :fileRef | self getRecordsFromFileReference: fileRef ]). + ^ records flattened sorted: [ :a :b | a dateTime < b dateTime ] +] + { #category : 'helpers' } DSRecordBrowserPresenter >> getWindowFromRecord: aRecord [ "Returns the record's corresponding window record in the history." @@ -261,40 +315,18 @@ DSRecordBrowserPresenter >> initializePresenters [ startRecordButtonPresenter := self startRecordButton. stopRecordButtonPresenter := self stopRecordButton. toolbarPresenter := self toolbar. - fileListPresenter := self fileList. + fileListPresenter := self fileListPresenter. recordsTablePresenter := self recordsTable. recordsFilter := self recordsFilter. windowsPresenter := self windowsPresenter. statisticsPresenter := self statisticsPresenter ] -{ #category : 'operations' } -DSRecordBrowserPresenter >> listAddedFilesActions [ - "Returns a list of actions for the list of added files. Action are: inspecting raw records, inspecting history, or removing the selected file from the list." +{ #category : 'testing' } +DSRecordBrowserPresenter >> isFileAdded: aFileReference [ + "Returns true if the specified file is already added in the files (or in a folder)." - ^ SpActionGroup new - addActionWith: [ :anItem | - anItem - name: 'Inspect'; - iconName: #inspect; - description: 'Inspect the raw records'; - shortcutKey: $i meta; - action: [ (DSSpy materialize: fileListPresenter selectedItem) inspect ] ]; - addActionWith: [ :anItem | - anItem - name: 'Inspect history'; - iconName: #history; - description: 'Inspect the record history'; - shortcutKey: $h meta; - action: [ selectedHistory inspect ] ]; - addActionWith: [ :anItem | - anItem - name: 'Remove'; - iconName: #remove; - description: 'Remove the record from list'; - shortcutKey: $x meta; - action: [ self removeFile: fileListPresenter selectedItem ] ]; - yourself + ^ files anySatisfy: [ :fileRef | aFileReference pathString includesSubstring: fileRef pathString ] ] { #category : 'operations' } @@ -305,7 +337,7 @@ DSRecordBrowserPresenter >> openAddFileDialog [ filesDirectory := DSSpy logger loggingDirectory. filesDirectory ensureCreateDirectory. - newFiles := StOpenFilePresenter new + newFiles := StOpenFileOrDirectoryPresenter new beMultipleSelection; defaultFolder: filesDirectory; openModal. @@ -348,7 +380,7 @@ DSRecordBrowserPresenter >> recordsTable [ yourself ] -{ #category : 'operations' } +{ #category : 'layout' } DSRecordBrowserPresenter >> recordsTableActions [ "Return a list of actions which can be done on a record from the table. For example, inspect the selected record."