Skip to content
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ node_modules

#!.yarn/cache
.pnp.*

dist/
3 changes: 0 additions & 3 deletions dist/index.d.ts

This file was deleted.

1 change: 0 additions & 1 deletion dist/index.d.ts.map

This file was deleted.

83 changes: 0 additions & 83 deletions dist/index.js

This file was deleted.

1 change: 0 additions & 1 deletion dist/index.js.map

This file was deleted.

96 changes: 93 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ interface Project {
[key: string]: any;
}

interface ApiResponse {
data?: Project[];
interface Folder {
id: number;
name: string;
parent_id?: number;
[key: string]: any;
}

interface ApiResponse<T = any> {
data?: T;
error?: string;
}

Expand Down Expand Up @@ -42,7 +49,7 @@ class TestQualityClient {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json() as ApiResponse;
const data = await response.json() as ApiResponse<Project[]>;

if (data.error) {
throw new Error(data.error);
Expand All @@ -56,6 +63,44 @@ class TestQualityClient {
throw new Error('Failed to fetch projects: Unknown error');
}
}

async getFolders(projectId?: number): Promise<Folder[]> {
try {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};

if (this.apiKey) {
headers['Authorization'] = `Bearer ${this.apiKey}`;
}

const endpoint = projectId
? `${this.baseUrl}/api/folder?project_id=${projectId}`
: `${this.baseUrl}/api/folder`;

const response = await fetch(endpoint, {
method: 'GET',
headers,
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json() as ApiResponse<Folder[]>;

if (data.error) {
throw new Error(data.error);
}

return data.data || [];
} catch (error) {
if (error instanceof Error) {
throw new Error(`Failed to fetch folders: ${error.message}`);
}
throw new Error('Failed to fetch folders: Unknown error');
}
}
}

const program = new Command();
Expand Down Expand Up @@ -100,6 +145,51 @@ program
}
});

program
.command('folders')
.description('List all folders from TestQuality')
.option('-k, --api-key <key>', 'API key for authentication')
.option('-u, --url <url>', 'Base URL for TestQuality API', 'https://api.testquality.com')
.option('-p, --project-id <id>', 'Filter folders by project ID')
.option('-j, --json', 'Output as JSON')
.action(async (options) => {
try {
const client = new TestQualityClient(options.url, options.apiKey);
const projectId = options.projectId ? parseInt(options.projectId, 10) : undefined;

if (projectId && isNaN(projectId)) {
throw new Error('Invalid project ID. Must be a number.');
}

const folders = await client.getFolders(projectId);

if (folders.length === 0) {
console.log('No folders found.');
return;
}

if (options.json) {
console.log(JSON.stringify(folders, null, 2));
} else {
console.log('\nTestQuality Folders:');
console.log('====================');
folders.forEach((folder, index) => {
console.log(`\n${index + 1}. ${folder.name}`);
console.log(` ID: ${folder.id}`);
if (folder.parent_id) {
console.log(` Parent ID: ${folder.parent_id}`);
}
if (folder.description) {
console.log(` Description: ${folder.description}`);
}
});
}
} catch (error) {
console.error('Error:', error instanceof Error ? error.message : 'Unknown error');
process.exit(1);
}
});

program.parse(process.argv);

if (!process.argv.slice(2).length) {
Expand Down
13 changes: 12 additions & 1 deletion tests.csv
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ Production,Run Compiled Version,Run 'yarn start projects' after build,Execute co
Error Handling,Invalid Command,Run 'yarn tq invalid-command',Display error message for unknown command
Error Handling,Missing Required Options,Run command that requires options without providing them,Display appropriate error message
Error Handling,API Response Error,Mock API returning error status,Display HTTP error status message
Error Handling,Malformed JSON Response,Mock API returning invalid JSON,Display parsing error message
Error Handling,Malformed JSON Response,Mock API returning invalid JSON,Display parsing error message
Folder Commands,Display Folders Help,Run 'yarn tq folders --help',Display folders command help with available options
Folder Commands,Fetch All Folders,Run 'yarn tq folders',Either display folders list or authentication error message
Folder Commands,Fetch Folders With Auth,Run 'yarn tq folders -k <API_KEY>' with valid API key,Display list of folders from TestQuality API
Folder Commands,Fetch Folders By Project,Run 'yarn tq folders -p <PROJECT_ID>' with valid project ID,Display folders filtered by project ID
Folder Commands,Fetch Folders JSON Format,Run 'yarn tq folders --json',Output folders in JSON format with proper indentation
Folder Commands,Invalid Project ID,Run 'yarn tq folders -p invalid',Display error message for invalid project ID
Folder Commands,Handle Empty Folders List,Run command when no folders exist,Display 'No folders found.' message
Folder Commands,Custom API URL for Folders,Run 'yarn tq folders -u https://custom.api.url',Attempt to fetch folders from custom URL
Folder Commands,Folders With Parent ID,Run 'yarn tq folders' with folders that have parent_id,Display folders showing parent ID relationship
Folder Commands,Network Error for Folders,Disconnect network and run 'yarn tq folders',Display network error message gracefully
Folder Commands,Invalid API Key for Folders,Run 'yarn tq folders -k INVALID_KEY',Display authentication error message