Skip to content

Commit 5d45b15

Browse files
authored
test: e2e tests batch-3 (#1097)
1 parent f7ed07a commit 5d45b15

11 files changed

Lines changed: 524 additions & 47 deletions

File tree

src/commands/actors/info.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ export class ActorsInfoCommand extends ApifyCommand<typeof ActorsInfoCommand> {
142142
}
143143

144144
simpleLog({ message: latest.build.readme, stdout: true });
145+
return;
145146
}
146147

147148
if (input) {
@@ -164,6 +165,7 @@ export class ActorsInfoCommand extends ApifyCommand<typeof ActorsInfoCommand> {
164165
}
165166

166167
simpleLog({ message: latest.build.inputSchema, stdout: true });
168+
return;
167169
}
168170

169171
const message = [

src/commands/builds/log.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
22
import { Args } from '../../lib/command-framework/args.js';
3-
import { error, info } from '../../lib/outputs.js';
3+
import { info } from '../../lib/outputs.js';
44
import { getLoggedClientOrThrow, outputJobLog } from '../../lib/utils.js';
55

66
export class BuildsLogCommand extends ApifyCommand<typeof BuildsLogCommand> {
@@ -32,20 +32,11 @@ export class BuildsLogCommand extends ApifyCommand<typeof BuildsLogCommand> {
3232
const build = await apifyClient.build(buildId).get();
3333

3434
if (!build) {
35-
error({ message: `Build with ID "${buildId}" was not found on your account.`, stdout: true });
36-
return;
35+
throw new Error(`Build with ID "${buildId}" was not found on your account.`);
3736
}
3837

3938
info({ message: `Log for build with ID "${buildId}":\n` });
4039

41-
try {
42-
await outputJobLog({ job: build, apifyClient });
43-
} catch (err) {
44-
// This should never happen...
45-
error({
46-
message: `Failed to get log for build with ID "${buildId}": ${(err as Error).message}`,
47-
stdout: true,
48-
});
49-
}
40+
await outputJobLog({ job: build, apifyClient });
5041
}
5142
}

src/commands/builds/rm.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type { ActorTaggedBuild, ApifyApiError } from 'apify-client';
1+
import type { ActorTaggedBuild } from 'apify-client';
22

33
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
44
import { Args } from '../../lib/command-framework/args.js';
55
import { YesFlag } from '../../lib/command-framework/flags.js';
66
import { useInputConfirmation } from '../../lib/hooks/user-confirmations/useInputConfirmation.js';
77
import { useYesNoConfirm } from '../../lib/hooks/user-confirmations/useYesNoConfirm.js';
8-
import { error, info, success } from '../../lib/outputs.js';
8+
import { info, success } from '../../lib/outputs.js';
99
import { getLoggedClientOrThrow } from '../../lib/utils.js';
1010

1111
export class BuildsRmCommand extends ApifyCommand<typeof BuildsRmCommand> {
@@ -47,8 +47,7 @@ export class BuildsRmCommand extends ApifyCommand<typeof BuildsRmCommand> {
4747
const build = await apifyClient.build(buildId).get();
4848

4949
if (!build) {
50-
error({ message: `Build with ID "${buildId}" was not found on your account.`, stdout: true });
51-
return;
50+
throw new Error(`Build with ID "${buildId}" was not found on your account.`);
5251
}
5352

5453
const actor = await apifyClient.actor(build.actId).get();
@@ -91,16 +90,11 @@ export class BuildsRmCommand extends ApifyCommand<typeof BuildsRmCommand> {
9190
return;
9291
}
9392

94-
try {
95-
await apifyClient.build(buildId).delete();
93+
await apifyClient.build(buildId).delete();
9694

97-
success({
98-
message: `Build with ID "${buildId}" was deleted.`,
99-
stdout: true,
100-
});
101-
} catch (err) {
102-
const casted = err as ApifyApiError;
103-
error({ message: `Failed to delete build "${buildId}".\n ${casted.message || casted}`, stdout: true });
104-
}
95+
success({
96+
message: `Build with ID "${buildId}" was deleted.`,
97+
stdout: true,
98+
});
10599
}
106100
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { access, writeFile } from 'node:fs/promises';
2+
import path from 'node:path';
3+
4+
import { runCli } from '../../__helpers__/run-cli.js';
5+
import { createTestActor, removeTestActor, type TestActor } from '../../__helpers__/test-actor.js';
6+
7+
describe('[e2e] actor generate-schema-types', () => {
8+
let actor: TestActor;
9+
10+
beforeAll(async () => {
11+
actor = await createTestActor();
12+
13+
const inputSchema = {
14+
title: 'Test input schema',
15+
description: 'A test input schema',
16+
type: 'object',
17+
schemaVersion: 1,
18+
properties: {
19+
testField: {
20+
title: 'Test Field',
21+
type: 'string',
22+
description: 'A test field',
23+
editor: 'textfield',
24+
},
25+
},
26+
};
27+
28+
await writeFile(path.join(actor.dir, '.actor', 'INPUT_SCHEMA.json'), JSON.stringify(inputSchema, null, 2));
29+
});
30+
31+
afterAll(async () => {
32+
if (actor) await removeTestActor(actor);
33+
});
34+
35+
it('generates TypeScript types from input schema', async () => {
36+
const result = await runCli('apify', ['actor', 'generate-schema-types'], { cwd: actor.dir });
37+
38+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
39+
expect(result.stderr).toContain('Generated types written to');
40+
41+
await expect(access(path.join(actor.dir, 'src', '.generated', 'actor', 'input.ts'))).resolves.toBeUndefined();
42+
});
43+
44+
it('respects --output flag', async () => {
45+
const customDir = path.join(actor.dir, 'custom-types');
46+
47+
const result = await runCli('apify', ['actor', 'generate-schema-types', '--output', customDir], {
48+
cwd: actor.dir,
49+
});
50+
51+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
52+
await expect(access(path.join(customDir, 'input.ts'))).resolves.toBeUndefined();
53+
});
54+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { randomBytes } from 'node:crypto';
2+
3+
import { runCli } from '../../__helpers__/run-cli.js';
4+
5+
describe('[e2e][api] actors info', () => {
6+
let authEnv: Record<string, string>;
7+
8+
beforeAll(async () => {
9+
const token = process.env.TEST_USER_TOKEN;
10+
if (!token) throw new Error('TEST_USER_TOKEN env var is required for actors info tests');
11+
12+
const authPath = `e2e-actors-info-${randomBytes(6).toString('hex')}`;
13+
authEnv = { __APIFY_INTERNAL_TEST_AUTH_PATH__: authPath };
14+
15+
const loginResult = await runCli('apify', ['login', '--token', token], { env: authEnv });
16+
if (loginResult.exitCode !== 0) {
17+
throw new Error(`Failed to login:\n${loginResult.stderr}`);
18+
}
19+
});
20+
21+
it('shows info for a public actor (--json)', async () => {
22+
const result = await runCli('apify', ['actors', 'info', 'apify/web-scraper', '--json'], { env: authEnv });
23+
24+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
25+
const data = JSON.parse(result.stdout);
26+
expect(data.name).toBe('web-scraper');
27+
});
28+
29+
it('shows README with --readme flag', async () => {
30+
const result = await runCli('apify', ['actors', 'info', 'apify/web-scraper', '--readme'], { env: authEnv });
31+
32+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
33+
expect(result.stdout.length).toBeGreaterThan(0);
34+
});
35+
36+
it('shows input schema with --input flag', async () => {
37+
const result = await runCli('apify', ['actors', 'info', 'apify/rag-web-browser', '--input'], { env: authEnv });
38+
39+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
40+
expect(() => JSON.parse(result.stdout)).not.toThrow();
41+
});
42+
43+
it('fails with invalid actor ID', async () => {
44+
const result = await runCli('apify', ['actors', 'info', 'nonexistent/actor-xyz'], { env: authEnv });
45+
46+
expect(result.stdout).toContain('was not found');
47+
});
48+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { randomBytes } from 'node:crypto';
2+
3+
import { runCli } from '../../__helpers__/run-cli.js';
4+
5+
describe('[e2e][api] actors ls', () => {
6+
let authEnv: Record<string, string>;
7+
8+
beforeAll(async () => {
9+
const token = process.env.TEST_USER_TOKEN;
10+
if (!token) throw new Error('TEST_USER_TOKEN env var is required for actors ls tests');
11+
12+
const authPath = `e2e-actors-ls-${randomBytes(6).toString('hex')}`;
13+
authEnv = { __APIFY_INTERNAL_TEST_AUTH_PATH__: authPath };
14+
15+
const loginResult = await runCli('apify', ['login', '--token', token], { env: authEnv });
16+
if (loginResult.exitCode !== 0) {
17+
throw new Error(`Failed to login:\n${loginResult.stderr}`);
18+
}
19+
});
20+
21+
it('lists recent actors (--json)', async () => {
22+
const result = await runCli('apify', ['actors', 'ls', '--json'], { env: authEnv });
23+
24+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
25+
expect(() => JSON.parse(result.stdout)).not.toThrow();
26+
});
27+
28+
it('lists own actors with --my flag', async () => {
29+
const result = await runCli('apify', ['actors', 'ls', '--my', '--json'], { env: authEnv });
30+
31+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
32+
expect(() => JSON.parse(result.stdout)).not.toThrow();
33+
});
34+
35+
it('respects --limit flag', async () => {
36+
const result = await runCli('apify', ['actors', 'ls', '--my', '--limit', '5', '--json'], { env: authEnv });
37+
38+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
39+
expect(() => JSON.parse(result.stdout)).not.toThrow();
40+
});
41+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { runCli } from '../../__helpers__/run-cli.js';
2+
3+
describe.concurrent('[e2e] actors search', () => {
4+
it('finds actors by query', async () => {
5+
const result = await runCli('apify', ['actors', 'search', 'web scraper', '--json']);
6+
7+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
8+
const data = JSON.parse(result.stdout);
9+
expect(data.items.length).toBeGreaterThan(0);
10+
});
11+
12+
it('respects --limit flag', async () => {
13+
const result = await runCli('apify', ['actors', 'search', 'scraper', '--limit', '3', '--json']);
14+
15+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
16+
const data = JSON.parse(result.stdout);
17+
expect(data.items.length).toBeLessThanOrEqual(3);
18+
});
19+
20+
it('filters by pricing model', async () => {
21+
const result = await runCli('apify', ['actors', 'search', '--pricing-model', 'FREE', '--limit', '5', '--json']);
22+
23+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
24+
const data = JSON.parse(result.stdout);
25+
expect(data.items.length).toBeLessThanOrEqual(5);
26+
});
27+
28+
it('returns empty results for nonexistent query', async () => {
29+
const result = await runCli('apify', ['actors', 'search', 'xyznonexistent12345absolutelyfake', '--json']);
30+
31+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
32+
const data = JSON.parse(result.stdout);
33+
expect(data.items.length).toBe(0);
34+
});
35+
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { randomBytes } from 'node:crypto';
2+
3+
import { runCli } from '../../__helpers__/run-cli.js';
4+
5+
describe('[e2e][api] auth login & token', () => {
6+
const authEnv = { __APIFY_INTERNAL_TEST_AUTH_PATH__: `e2e-login-${randomBytes(6).toString('hex')}` };
7+
8+
it('logs in with a valid token', async () => {
9+
const token = process.env.TEST_USER_TOKEN;
10+
if (!token) throw new Error('TEST_USER_TOKEN env var is required');
11+
12+
const result = await runCli('apify', ['login', '--token', token], { env: authEnv });
13+
14+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
15+
expect(result.stderr).toContain('You are logged in to Apify as');
16+
});
17+
18+
it('fails with an invalid token', async () => {
19+
const badAuthEnv = { __APIFY_INTERNAL_TEST_AUTH_PATH__: `e2e-badlogin-${randomBytes(6).toString('hex')}` };
20+
21+
const result = await runCli('apify', ['login', '--token', 'invalid-token-abc'], { env: badAuthEnv });
22+
23+
expect(result.stderr).toContain('Login to Apify failed');
24+
});
25+
26+
it('prints the current token after login', async () => {
27+
const token = process.env.TEST_USER_TOKEN;
28+
if (!token) throw new Error('TEST_USER_TOKEN env var is required');
29+
30+
// Ensure we're logged in
31+
await runCli('apify', ['login', '--token', token], { env: authEnv });
32+
33+
const result = await runCli('apify', ['auth', 'token'], { env: authEnv });
34+
35+
expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0);
36+
expect(result.stdout.trim().length).toBeGreaterThan(0);
37+
});
38+
});

0 commit comments

Comments
 (0)