Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/MCP-Spec-Tests/MCPToolsCatalogPresenterTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ MCPToolsCatalogPresenterTest >> testLongOperationListsAreSummarizedForCatalogRow
presenter := MCPToolsCatalogPresenter new.
summary := presenter toolCatalogOperationSummaryFor:
MCPToolEditRepository new.
self assert: summary equals: 'create | attach | +9'.
self assert: summary equals: 'create | attach | +10'.
self assert: summary size < 24
]

Expand Down Expand Up @@ -48,5 +48,5 @@ MCPToolsCatalogPresenterTest >> testSummarizedOperationListsExposeFullOperationH
assert:
(presenter toolCatalogOperationHelpFor: MCPToolEditRepository new)
equals:
'Operations: create | attach | update | export | diff | commit | fetch | pull | push | createBranch | switchBranch'
'Operations: create | attach | update | export | diff | commit | adoptHead | fetch | pull | push | createBranch | switchBranch'
]
54 changes: 54 additions & 0 deletions src/MCP-Tests/MCPRepositorySpecTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,60 @@ MCPRepositorySpecTest >> requestWithArguments: aDictionary [
yourself
]

{ #category : 'tests' }
MCPRepositorySpecTest >> testRepositoryAdoptHeadRequestParsesTypedInput [

| adoptHeadRequest |
adoptHeadRequest := MCPRepositoryAdoptHeadRequest
fromRequest: (self requestWithArguments: {
(#repositoryName -> 'MCP Repo').
(#branchName -> 'main') } asDictionary)
tool: nil.
self assert: adoptHeadRequest operation equals: 'adoptHead'.
self
assert: adoptHeadRequest repositoryReference name
equals: 'MCP Repo'.
self assert: adoptHeadRequest branchName equals: 'main'.
self
assert: (adoptHeadRequest requestedContext at: #branchName)
equals: 'main'
]

{ #category : 'tests' }
MCPRepositorySpecTest >> testRepositoryAdoptHeadResultReturnsDictionary [

| data repository result |
repository := MCPTestIceRepository
named: 'MCP Adopt Head Repository'
location: 'memory://adopt-head'.
repository modifiedPackageNames: #( 'MCP' ).
repository workingCopy referenceCommit:
(MCPTestRepositoryCommit id: 'after').
result := MCPRepositoryAdoptHeadResult
repositoryBefore:
(MCPRepositoryInfo fromRepository: repository)
after: repository
previousReferenceCommit:
(MCPTestRepositoryCommit id: 'before')
adoptedCommit: (MCPTestRepositoryCommit id: 'after')
didAdopt: true.
data := result asDictionary.
self
assert: ((data at: #repository) at: #name)
equals: 'MCP Adopt Head Repository'.
self assert: (data at: #previousReferenceCommitId) equals: 'before'.
self assert: (data at: #referenceCommitId) equals: 'after'.
self assert: (data at: #adoptedCommitId) equals: 'after'.
self assert: (data at: #didAdopt).
self
assert: (data at: #modifiedPackageNamesBefore)
equals: #( 'MCP' ).
self assert: (data at: #modifiedPackageNamesAfter) equals: #( 'MCP' ).
self
assert: (data at: #repositoryLocation)
equals: 'memory://adopt-head'
]

{ #category : 'tests' }
MCPRepositorySpecTest >> testRepositoryAttachRequestParsesTypedInput [

Expand Down
25 changes: 24 additions & 1 deletion src/MCP-Tests/MCPTestRepositoryWorkingCopy.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Class {
#instVars : [
'repository',
'packageNames',
'modifiedPackages'
'modifiedPackages',
'referenceCommit'
],
#category : 'MCP-Tests-Internal',
#package : 'MCP-Tests',
Expand All @@ -23,6 +24,16 @@ MCPTestRepositoryWorkingCopy class >> packageNames: packageNameCollection modifi
yourself
]

{ #category : 'API - commits' }
MCPTestRepositoryWorkingCopy >> adoptCommit: aCommit [

self referenceCommit = aCommit ifTrue: [ ^ self ].
referenceCommit := aCommit.
self repository ifNotNil: [ :owningRepository |
owningRepository recordAction: 'adoptCommit:' , aCommit id asString.
owningRepository modifiedPackageNames: #( ) ]
]

{ #category : 'testing' }
MCPTestRepositoryWorkingCopy >> isModified [

Expand Down Expand Up @@ -59,6 +70,18 @@ MCPTestRepositoryWorkingCopy >> packages [
^ #( )
]

{ #category : 'API - commits' }
MCPTestRepositoryWorkingCopy >> referenceCommit [

^ referenceCommit ifNil: [ MCPTestRepositoryCommit id: '' ]
]

{ #category : 'accessing' }
MCPTestRepositoryWorkingCopy >> referenceCommit: aCommit [

referenceCommit := aCommit
]

{ #category : 'accessing' }
MCPTestRepositoryWorkingCopy >> repository [

Expand Down
107 changes: 100 additions & 7 deletions src/MCP-Tests/MCPToolContractsTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ MCPToolContractsTest >> testDictionaryShapedCommandResultsUseDTOClasses [
-> MCPRepositoryDiffResult).
(MCPCommitRepositoryCommand
-> MCPRepositoryCommitResult).
(MCPAdoptRepositoryHeadCommand
-> MCPRepositoryAdoptHeadResult).
(MCPFetchRepositoryCommand
-> MCPRepositoryFetchResult).
(MCPPullRepositoryCommand
Expand Down Expand Up @@ -281,7 +283,7 @@ MCPToolContractsTest >> testDisplayToolsCatalogSummarizesToolOperations [
self
assert:
(presenter toolCatalogOperationSummaryFor: MCPToolEditRepository new)
equals: 'create | attach | +9'.
equals: 'create | attach | +10'.
self
assert:
(presenter toolCatalogOperationSummaryFor: MCPToolEditMethod new)
Expand Down Expand Up @@ -534,6 +536,86 @@ MCPToolContractsTest >> testEditMethodSchemaAdvertisesMethodState [
'newProtocol' 'critiques' ) asSet
]

{ #category : 'tests' }
MCPToolContractsTest >> testEditRepositoryDescriptionDocumentsRepositoryOperations [

| branchNameDescription description locationDescription messageDescription packageNamesDescription removePackageNamesDescription repositoryNameDescription tool |
tool := MCPToolEditRepository new.
description := tool description.
messageDescription := (self
inputPropertyNamed: 'message'
inTool: tool) description.
branchNameDescription := (self
inputPropertyNamed: 'branchName'
inTool: tool) description.
repositoryNameDescription := (self
inputPropertyNamed: 'repositoryName'
inTool: tool) description.
locationDescription := (self
inputPropertyNamed: 'location'
inTool: tool) description.
packageNamesDescription := (self
inputPropertyNamed: 'packageNames'
inTool: tool) description.
removePackageNamesDescription := (self
inputPropertyNamed:
'removePackageNames'
inTool: tool) description.
self assert: (description includesSubstring: 'repositoryName').
self assert: (description includesSubstring: 'operation=attach').
self assert: (description includesSubstring: 'existing Git checkout').
self assert: (description includesSubstring: 'without creating').
self assert: (description includesSubstring: 'operation=diff').
self assert: (description includesSubstring: 'without writing files').
self assert: (description includesSubstring: 'should be preferred').
self assert: (description includesSubstring: 'operation=export').
self assert: (description includesSubstring: 'escape hatch').
self assert:
(description includesSubstring: 'without staging or committing').
self assert: (description includesSubstring: 'operation=commit').
self assert:
(description includesSubstring: 'IceRepository>>commitWithMessage:').
self assert: (description includesSubstring: 'operation=adoptHead').
self assert:
(description includesSubstring: 'IceWorkingCopy>>adoptCommit:').
self assert:
(description includesSubstring: 'before/after modified packages').
self assert: (description includesSubstring: 'operation=fetch').
self assert: (description includesSubstring: 'IceRepository>>fetch').
self assert: (description includesSubstring: 'operation=pull').
self assert: (description includesSubstring: 'IceRepository>>pull').
self assert: (description includesSubstring: 'operation=push').
self assert: (description includesSubstring: 'IceRepository>>push').
self assert:
(description includesSubstring: 'operation=createBranch').
self assert:
(description includesSubstring: 'operation=switchBranch').
self assert:
(messageDescription includesSubstring: 'operation=commit').
self assert:
(branchNameDescription includesSubstring: 'operation=createBranch').
self assert:
(branchNameDescription includesSubstring: 'operation=switchBranch').
self assert:
(branchNameDescription includesSubstring: 'operation=adoptHead').
self assert:
(repositoryNameDescription includesSubstring: 'existing repository').
self assert:
(repositoryNameDescription includesSubstring:
'Combine with location').
self assert:
(locationDescription includesSubstring: 'operation=create').
self assert:
(locationDescription includesSubstring: 'operation=attach').
self assert: (locationDescription includesSubstring: 'disambiguate').
self assert: (packageNamesDescription includesSubstring:
'operation=create or operation=attach').
self assert: (packageNamesDescription includesSubstring:
'replaces the full managed package list').
self assert:
(removePackageNamesDescription includesSubstring: 'does not unload')
]

{ #category : 'tests' }
MCPToolContractsTest >> testEditRepositoryDescriptionExplainsPackageAndFilesystemSemantics [

Expand Down Expand Up @@ -632,8 +714,8 @@ MCPToolContractsTest >> testEditRepositoryHasAccurateNameAndRequiredArguments [
self
assert: (operationProperty extraProperties at: #enum) asArray
equals:
#( 'create' 'attach' 'update' 'export' 'diff' 'commit' 'fetch'
'pull' 'push' 'createBranch' 'switchBranch' )
#( 'create' 'attach' 'update' 'export' 'diff' 'commit' 'adoptHead'
'fetch' 'pull' 'push' 'createBranch' 'switchBranch' )
]

{ #category : 'tests' }
Expand All @@ -646,6 +728,15 @@ MCPToolContractsTest >> testEditRepositoryOutputSchemaUsesActionForExecutedActio
required := ((outputSchema at: #properties) at: 'data') at: #required.
self assert: (dataProperties includesKey: 'action').
self assert: (dataProperties includesKey: 'restoredOrderOnlyPaths').
self assert:
(dataProperties includesKey: 'modifiedPackageNamesBefore').
self assert:
(dataProperties includesKey: 'modifiedPackageNamesAfter').
self assert:
(dataProperties includesKey: 'previousReferenceCommitId').
self assert: (dataProperties includesKey: 'referenceCommitId').
self assert: (dataProperties includesKey: 'adoptedCommitId').
self assert: (dataProperties includesKey: 'didAdopt').
self deny: (dataProperties includesKey: 'operation').
self assert: (required includes: 'action').
self deny: (required includes: 'operation')
Expand All @@ -667,7 +758,8 @@ MCPToolContractsTest >> testEditToolSchemasAdvertiseOperationEnumsWithoutComposi
methodOperationProperty := self
inputPropertyNamed: 'operation'
inTool: editMethod.
self deny: (editRepository inputSchema asJRPCJSON includesKey: #oneOf).
self deny:
(editRepository inputSchema asJRPCJSON includesKey: #oneOf).
self deny: (editClass inputSchema asJRPCJSON includesKey: #oneOf).
self deny: (editMethod inputSchema asJRPCJSON includesKey: #oneOf).
self
Expand All @@ -680,10 +772,11 @@ MCPToolContractsTest >> testEditToolSchemasAdvertiseOperationEnumsWithoutComposi
assert: editMethod inputSchema required asSet
equals: #( 'operation' 'className' ) asSet.
self
assert: (repositoryOperationProperty extraProperties at: #enum) asArray
assert:
(repositoryOperationProperty extraProperties at: #enum) asArray
equals:
#( 'create' 'attach' 'update' 'export' 'diff' 'commit' 'fetch'
'pull' 'push' 'createBranch' 'switchBranch' ).
#( 'create' 'attach' 'update' 'export' 'diff' 'commit' 'adoptHead'
'fetch' 'pull' 'push' 'createBranch' 'switchBranch' ).
self
assert: (classOperationProperty extraProperties at: #enum) asArray
equals: #( 'create' 'update' ).
Expand Down
83 changes: 83 additions & 0 deletions src/MCP-Tests/MCPToolEditRepositoryTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,89 @@ MCPToolEditRepositoryTest >> temporaryRepositoryLocationNamed: aName [
^ FileLocator imageDirectory / aName
]

{ #category : 'tests' }
MCPToolEditRepositoryTest >> testAdoptHeadAdoptsRepositoryHeadAndReportsBeforeAfterModifiedPackages [

| data repository result |
repository := self newTestRepositoryNamed:
'MCP Adopt Head Test Repository'.
repository headCommitId: 'head-2'.
repository headDescription: 'branch main'.
repository modifiedPackageNames: #( 'MCP' 'MCP-Tests' ).
repository workingCopy referenceCommit:
(MCPTestRepositoryCommit id: 'head-1').
self withRegisteredRepository: repository do: [
result := self callToolWith: {
(#operation -> 'adoptHead').
(#repositoryName -> repository name).
(#branchName -> 'main') } asDictionary.
data := self dataFrom: result.
self deny: (result at: #isError ifAbsent: [ false ]).
self
assert: repository actionLog asArray
equals: #( 'adoptCommit:head-2' ).
self assert: (data at: #action) equals: 'adoptHead'.
self
assert: (data at: #modifiedPackageNamesBefore)
equals: #( 'MCP' 'MCP-Tests' ).
self assert: (data at: #modifiedPackageNamesAfter) equals: #( ).
self assert: (data at: #modifiedPackageNames) equals: #( ).
self assert: (data at: #previousReferenceCommitId) equals: 'head-1'.
self assert: (data at: #adoptedCommitId) equals: 'head-2'.
self assert: (data at: #referenceCommitId) equals: 'head-2'.
self assert: (data at: #didAdopt).
self
assert: ((data at: #repositoryBefore) at: #modifiedPackageNames)
equals: #( 'MCP' 'MCP-Tests' ).
self
assert: ((data at: #repository) at: #modifiedPackageNames)
equals: #( ) ]
]

{ #category : 'tests' }
MCPToolEditRepositoryTest >> testAdoptHeadOperationRequiresRepositoryAndParses [

| command parsedRequest rawRequest tool |
tool := MCPToolEditRepository new.
rawRequest := tool requestFromToolCallArguments: {
(#operation -> 'adoptHead').
(#repositoryName -> 'MCP').
(#branchName -> 'main') } asDictionary.
parsedRequest := tool parsedRequestFromToolRequest: rawRequest.
command := tool commandForRequest: parsedRequest.
self
assert: parsedRequest class
equals: MCPRepositoryAdoptHeadRequest.
self assert: parsedRequest operation equals: 'adoptHead'.
self assert: parsedRequest branchName equals: 'main'.
self assert: command class equals: MCPAdoptRepositoryHeadCommand
]

{ #category : 'tests' }
MCPToolEditRepositoryTest >> testAdoptHeadValidatesExpectedBranch [

| errorDetails repository result |
repository := self newTestRepositoryNamed:
'MCP Adopt Head Branch Guard Test Repository'.
repository branchName: 'main'.
repository headCommitId: 'head-1'.
self withRegisteredRepository: repository do: [
result := self callToolWith: {
(#operation -> 'adoptHead').
(#repositoryName -> repository name).
(#branchName -> 'feature') } asDictionary.
self assert: (result at: #isError ifAbsent: [ false ]).
self assert:
((self summaryFrom: result) includesSubstring: 'branch mismatch').
errorDetails := self errorFrom: result.
self assert: (errorDetails at: #action) equals: 'adoptHead'.
self
assert: (errorDetails at: #expectedBranchName)
equals: 'feature'.
self assert: (errorDetails at: #actualBranchName) equals: 'main'.
self assert: repository actionLog asArray equals: #( ) ]
]

{ #category : 'tests' }
MCPToolEditRepositoryTest >> testAttachParsesAndDispatchesToAttachCommand [

Expand Down
Loading
Loading