Skip to content

Commit f326b73

Browse files
committed
fix test suite, clean up
1 parent 2e41b61 commit f326b73

File tree

3 files changed

+50
-114
lines changed

3 files changed

+50
-114
lines changed

src/input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function processInput(originalInput: Partial<Input>): Input {
2727
input.actors = [];
2828
}
2929

30-
// enableAddingActors is deprecated, use enableActorAutoLoading instead
30+
// enableActorAutoLoading is deprecated, use enableAddingActors instead
3131
if (input.enableAddingActors === undefined) {
3232
if (input.enableActorAutoLoading !== undefined) {
3333
log.warning('enableActorAutoLoading is deprecated, use enableAddingActors instead');

src/mcp/server.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,6 @@ export class ActorsMcpServer {
192192
}
193193
}
194194

195-
// Methods for toggling dynamic tools have been removed; add/remove helper tools
196-
// should be managed via the unified input loader.
197-
198195
/** Delete tools from the server and notify the handler.
199196
*/
200197
public removeToolsByName(toolNames: string[], shouldNotifyToolsChangedHandler = false): string[] {
@@ -404,6 +401,7 @@ export class ActorsMcpServer {
404401
apifyToken,
405402
userRentedActorIds,
406403
progressTracker,
404+
// Passing as argument to prevent circular dependency
407405
getActorsAsTools,
408406
}) as object;
409407

tests/integration/suite.ts

Lines changed: 48 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from
66
import { defaults, HelperTools } from '../../src/const.js';
77
import { latestNewsOnTopicPrompt } from '../../src/prompts/latest-news-on-topic.js';
88
import { addTool } from '../../src/tools/helpers.js';
9-
import { defaultTools, toolCategories, toolCategoriesEnabledByDefault } from '../../src/tools/index.js';
9+
import { defaultTools, toolCategories } from '../../src/tools/index.js';
1010
import { actorNameToToolName } from '../../src/tools/utils.js';
1111
import type { ToolCategory } from '../../src/types.js';
1212
import { getExpectedToolNamesByCategories } from '../../src/utils/tools.js';
@@ -89,12 +89,11 @@ export function createIntegrationTestsSuite(
8989
it('should list all default tools and Actors', async () => {
9090
const client = await createClientFn();
9191
const tools = await client.listTools();
92-
expect(tools.tools.length).toEqual(defaultTools.length + defaults.actors.length + 1);
92+
expect(tools.tools.length).toEqual(defaultTools.length + defaults.actors.length);
9393

9494
const names = getToolNames(tools);
9595
expectToolNamesToContain(names, DEFAULT_TOOL_NAMES);
9696
expectToolNamesToContain(names, DEFAULT_ACTOR_NAMES);
97-
expectToolNamesToContain(names, [addTool.tool.name]);
9897
await client.close();
9998
});
10099

@@ -118,34 +117,36 @@ export function createIntegrationTestsSuite(
118117
expectToolNamesToContain(names, DEFAULT_ACTOR_NAMES);
119118
await client.close();
120119
});
120+
121+
it('should override enableAddingActors false with experimental tool category', async () => {
122+
const client = await createClientFn({ enableAddingActors: false, tools: ['experimental'] });
123+
const names = getToolNames(await client.listTools());
124+
expect(names).toHaveLength(toolCategories.experimental.length);
125+
expect(names).toContain(addTool.tool.name);
126+
await client.close();
127+
});
121128

122-
it('should list all default tools and two loaded Actors', async () => {
129+
it('should list two loaded Actors', async () => {
123130
const actors = ['apify/python-example', 'apify/rag-web-browser'];
124131
const client = await createClientFn({ actors, enableAddingActors: false });
125132
const names = getToolNames(await client.listTools());
126-
expect(names.length).toEqual(defaultTools.length + actors.length);
127-
expectToolNamesToContain(names, DEFAULT_TOOL_NAMES);
133+
expect(names.length).toEqual(actors.length);
128134
expectToolNamesToContain(names, actors.map((actor) => actorNameToToolName(actor)));
129135

130136
await client.close();
131137
});
132138

133-
it('should not add any tools from categories if tools param is empty', async () => {
139+
it('should not add any tools if tools param is empty', async () => {
134140
const client = await createClientFn({ enableAddingActors: true, tools: [] });
135141
const names = getToolNames(await client.listTools());
136-
expect(names.length).toEqual(1 + defaults.actors.length);
137-
expectToolNamesToContain(names, [addTool.tool.name]);
138-
expectToolNamesToContain(names, defaults.actors.map((actor) => actorNameToToolName(actor)));
142+
expect(names).toHaveLength(0);
139143
await client.close();
140144
});
141145

142-
it('should not load any Actors when param empty', async () => {
146+
it('should not load any tools when actors param empty', async () => {
143147
const client = await createClientFn({ enableAddingActors: true, actors: [] });
144148
const names = getToolNames(await client.listTools());
145-
const expectedCategoryNames = getExpectedToolNamesByCategories(toolCategoriesEnabledByDefault);
146-
expect(names.length).toEqual(1 + expectedCategoryNames.length);
147-
expectToolNamesToContain(names, [addTool.tool.name]);
148-
expectToolNamesToContain(names, expectedCategoryNames);
149+
expect(names.length).toEqual(0);
149150
await client.close();
150151
});
151152

@@ -156,30 +157,33 @@ export function createIntegrationTestsSuite(
156157
await client.close();
157158
});
158159

159-
it('should load only specified Actors via tools selectors when actors param omitted', async () => {
160+
it.only('should load only specified Actors via tools selectors when actors param omitted', async () => {
160161
const actors = ['apify/python-example'];
161-
const client = await createClientFn({ enableAddingActors: false, tools: actors });
162+
const client = await createClientFn({ tools: actors });
162163
const names = getToolNames(await client.listTools());
164+
console.log(names);
165+
// Only the Actor should be loaded
166+
expect(names).toHaveLength(actors.length);
163167
expect(names).toContain(actorNameToToolName(actors[0]));
164-
// Only the selected actor plus default internal categories are not expected since tools specified
165-
expect(names.every((n) => n === actorNameToToolName(actors[0]))).toBe(true);
166168
await client.close();
167169
});
168170

169171
it('should merge actors param into tools selectors (backward compatibility)', async () => {
170172
const actors = ['apify/python-example'];
171-
const client = await createClientFn({ enableAddingActors: false, tools: ['docs'], actors });
173+
const categories = ['docs'] as ToolCategory[];
174+
const client = await createClientFn({ tools: categories, actors });
172175
const names = getToolNames(await client.listTools());
173-
const docsToolNames = toolCategories.docs.map((t) => t.tool.name);
176+
const docsToolNames = getExpectedToolNamesByCategories(categories);
174177
const expected = [...docsToolNames, actorNameToToolName(actors[0])];
175-
expect(expected.every((n) => names.includes(n))).toBe(true);
176-
expect(names.length).toEqual(expected.length);
178+
expect(names).toHaveLength(expected.length);
179+
const containsExpected = expected.every((n) => names.includes(n));
180+
expect(containsExpected).toBe(true);
177181
await client.close();
178182
});
179183

180184
it('should load only docs tools', async () => {
181185
const categories = ['docs'] as ToolCategory[];
182-
const client = await createClientFn({ enableAddingActors: false, tools: categories, actors: [] });
186+
const client = await createClientFn({ tools: categories, actors: [] });
183187
const names = getToolNames(await client.listTools());
184188
const expected = getExpectedToolNamesByCategories(categories);
185189
expect(names.length).toEqual(expected.length);
@@ -188,22 +192,22 @@ export function createIntegrationTestsSuite(
188192
});
189193

190194
it('should load only a specific tool when tools includes a tool name', async () => {
191-
const client = await createClientFn({ enableAddingActors: false, tools: ['get-actor-details'], actors: [] });
195+
const client = await createClientFn({ tools: ['get-actor-details'], actors: [] });
192196
const names = getToolNames(await client.listTools());
193197
expect(names).toEqual(['get-actor-details']);
194198
await client.close();
195199
});
196200

197-
it('should not add any internal tools when tools param is empty and enableAddingActors is disabled', async () => {
198-
const client = await createClientFn({ enableAddingActors: false, tools: [] });
201+
it('should not add any internal tools when tools param is empty', async () => {
202+
const client = await createClientFn({ tools: [] });
199203
const names = getToolNames(await client.listTools());
200204
expect(names.length).toEqual(defaults.actors.length);
201205
expectToolNamesToContain(names, defaults.actors.map((actor) => actorNameToToolName(actor)));
202206
await client.close();
203207
});
204208

205-
it('should not add any internal tools when tools param is empty and enableAddingActors is disabled and use custom Actor if specified', async () => {
206-
const client = await createClientFn({ enableAddingActors: false, tools: [], actors: [ACTOR_PYTHON_EXAMPLE] });
209+
it('should not add any internal tools when tools param is empty and use custom Actor if specified', async () => {
210+
const client = await createClientFn({ tools: [], actors: [ACTOR_PYTHON_EXAMPLE] });
207211
const names = getToolNames(await client.listTools());
208212
expect(names.length).toEqual(1);
209213
expect(names).toContain(actorNameToToolName(ACTOR_PYTHON_EXAMPLE));
@@ -214,16 +218,16 @@ export function createIntegrationTestsSuite(
214218
const selectedToolName = actorNameToToolName(ACTOR_PYTHON_EXAMPLE);
215219
const client = await createClientFn({ enableAddingActors: true });
216220
const names = getToolNames(await client.listTools());
217-
const numberOfTools = defaultTools.length + 1 + defaults.actors.length;
218-
expect(names.length).toEqual(numberOfTools);
219-
// Check that the Actor is not in the tools list
221+
// Only the add tool should be added
222+
expect(names).toHaveLength(1);
223+
expect(names).toContain('add-actor');
220224
expect(names).not.toContain(selectedToolName);
221225
// Add Actor dynamically
222226
await addActor(client, ACTOR_PYTHON_EXAMPLE);
223227

224228
// Check if tools was added
225229
const namesAfterAdd = getToolNames(await client.listTools());
226-
expect(namesAfterAdd.length).toEqual(numberOfTools + 1);
230+
expect(namesAfterAdd.length).toEqual(2);
227231
expect(namesAfterAdd).toContain(selectedToolName);
228232
await callPythonExampleActor(client, selectedToolName);
229233

@@ -234,16 +238,17 @@ export function createIntegrationTestsSuite(
234238
const selectedToolName = actorNameToToolName(ACTOR_PYTHON_EXAMPLE);
235239
const client = await createClientFn({ enableAddingActors: true, tools: ['actors'] });
236240
const names = getToolNames(await client.listTools());
237-
const numberOfTools = 1 + defaults.actors.length + toolCategories.actors.length;
238-
expect(names.length).toEqual(numberOfTools);
241+
// Only the actors category and add-actor should be loaded
242+
const numberOfTools = toolCategories.actors.length + 1;
243+
expect(names).toHaveLength(numberOfTools);
239244
// Check that the Actor is not in the tools list
240245
expect(names).not.toContain(selectedToolName);
241246
// Add Actor dynamically
242247
await addActor(client, ACTOR_PYTHON_EXAMPLE);
243248

244249
// Check if tools was added
245250
const namesAfterAdd = getToolNames(await client.listTools());
246-
expect(namesAfterAdd.length).toEqual(numberOfTools + 1);
251+
expect(namesAfterAdd).toHaveLength(numberOfTools + 1);
247252
expect(namesAfterAdd).toContain(selectedToolName);
248253

249254
const result = await client.callTool({
@@ -271,64 +276,6 @@ export function createIntegrationTestsSuite(
271276
await client.close();
272277
});
273278

274-
it('should not call Actor via call-actor tool if it is not added', async () => {
275-
const selectedToolName = actorNameToToolName(ACTOR_PYTHON_EXAMPLE);
276-
const client = await createClientFn({ enableAddingActors: true, tools: ['actors'] });
277-
const names = getToolNames(await client.listTools());
278-
const numberOfTools = 1 + defaults.actors.length + toolCategories.actors.length;
279-
expect(names.length).toEqual(numberOfTools);
280-
// Check that the Actor is not in the tools list
281-
expect(names).not.toContain(selectedToolName);
282-
283-
const result = await client.callTool({
284-
name: HelperTools.ACTOR_CALL,
285-
arguments: {
286-
actor: ACTOR_PYTHON_EXAMPLE,
287-
input: {
288-
first_number: 1,
289-
second_number: 2,
290-
},
291-
},
292-
});
293-
294-
// TODO: make some more change-tolerant assertion, it's hard to verify text message result without exact match
295-
expect(result).toEqual(
296-
{
297-
content: [
298-
{
299-
text: "Actor 'apify/python-example' is not added. Add it with the 'add-actor' tool. Available Actors are: apify/rag-web-browser",
300-
type: 'text',
301-
},
302-
],
303-
},
304-
);
305-
306-
await client.close();
307-
});
308-
309-
// TODO: disabled for now, remove tools is disabled and might be removed in the future
310-
it.skip('should remove Actor from tools list', async () => {
311-
const actor = ACTOR_PYTHON_EXAMPLE;
312-
const selectedToolName = actorNameToToolName(actor);
313-
const client = await createClientFn({
314-
actors: [actor],
315-
enableAddingActors: true,
316-
});
317-
318-
// Verify actor is in the tools list
319-
const namesBefore = getToolNames(await client.listTools());
320-
expect(namesBefore).toContain(selectedToolName);
321-
322-
// Remove the actor
323-
await client.callTool({ name: HelperTools.ACTOR_REMOVE, arguments: { toolName: selectedToolName } });
324-
325-
// Verify actor is removed
326-
const namesAfter = getToolNames(await client.listTools());
327-
expect(namesAfter).not.toContain(selectedToolName);
328-
329-
await client.close();
330-
});
331-
332279
it('should find Actors in store search', async () => {
333280
const query = 'python-example';
334281
const client = await createClientFn({
@@ -413,14 +360,14 @@ export function createIntegrationTestsSuite(
413360

414361
const toolNamesBefore = getToolNames(await client.listTools());
415362
const searchToolCountBefore = toolNamesBefore.filter((name) => name.includes(HelperTools.STORE_SEARCH)).length;
416-
expect(searchToolCountBefore).toBe(1);
363+
expect(searchToolCountBefore).toBe(0);
417364

418365
// Add self as an Actorized MCP server
419366
await addActor(client, ACTOR_MCP_SERVER_ACTOR_NAME);
420367

421368
const toolNamesAfter = getToolNames(await client.listTools());
422369
const searchToolCountAfter = toolNamesAfter.filter((name) => name.includes(HelperTools.STORE_SEARCH)).length;
423-
expect(searchToolCountAfter).toBe(2);
370+
expect(searchToolCountAfter).toBe(1);
424371

425372
// Find the search tool from the Actorized MCP server
426373
const actorizedMCPSearchTool = toolNamesAfter.find(
@@ -496,8 +443,7 @@ export function createIntegrationTestsSuite(
496443
const loadedTools = await client.listTools();
497444
const toolNames = getToolNames(loadedTools);
498445

499-
const expectedTools = toolCategories[category as ToolCategory];
500-
const expectedToolNames = expectedTools.map((tool) => tool.tool.name);
446+
const expectedToolNames = getExpectedToolNamesByCategories([category as ToolCategory]);
501447
// Only assert that all tools from the selected category are present.
502448
for (const expectedToolName of expectedToolNames) {
503449
expect(toolNames).toContain(expectedToolName);
@@ -556,18 +502,10 @@ export function createIntegrationTestsSuite(
556502
const loadedTools = await client.listTools();
557503
const toolNames = getToolNames(loadedTools);
558504

559-
const expectedTools = [
560-
...toolCategories.docs,
561-
...toolCategories.runs,
562-
...toolCategories.storage,
563-
];
564-
const expectedToolNames = expectedTools.map((tool) => tool.tool.name);
565-
566-
const numberOfToolsExpected = defaults.actors.length + 1 + expectedTools.length;
567-
expect(toolNames.length).toEqual(numberOfToolsExpected);
568-
for (const expectedToolName of expectedToolNames) {
569-
expect(toolNames).toContain(expectedToolName);
570-
}
505+
const expectedToolNames = getExpectedToolNamesByCategories(categories);
506+
expect(toolNames).toHaveLength(expectedToolNames.length);
507+
const containsExpectedTools = toolNames.every((name) => expectedToolNames.includes(name));
508+
expect(containsExpectedTools).toBe(true);
571509

572510
await client.close();
573511
});

0 commit comments

Comments
 (0)