99 */
1010
1111import { ClassifierSdk , ImageFormat , parseAudience } from '@crispthinking/athena-classifier-sdk' ;
12+ import { Command , Option , InvalidArgumentError } from 'commander' ;
1213import fs from 'fs' ;
1314import path from 'path' ;
1415import { fileURLToPath } from 'url' ;
@@ -60,24 +61,40 @@ interface ImageComparisonResult {
6061}
6162
6263/**
63- * Display usage information
64+ * CLI options interface
6465 */
65- function showUsage ( ) : void {
66- console . log ( `
67- 🧪 Athena E2E Test Cases Runner
68-
69- Usage:
70- npx tsx index.ts [options]
71- npm start [options]
72-
73- Options:
74- -h, --help Show this help message
75- -t, --testset <name> Test set to run (default: integrator_sample)
76- Valid: integrator_sample, benign_model, live_model
77- -T, --tolerance <value> Comparison tolerance (default: 0.0001)
78- -v, --verbose Enable verbose output
79- -l, --list List available test sets and exit
66+ interface CliOptions {
67+ testset : TestSet ;
68+ tolerance : number ;
69+ verbose : boolean ;
70+ list : boolean ;
71+ }
8072
73+ /**
74+ * Setup and parse CLI arguments using commander
75+ */
76+ function parseArgs ( ) : CliOptions {
77+ const program = new Command ( ) ;
78+
79+ program
80+ . name ( 'athena-e2e-testcases' )
81+ . description ( 'Athena E2E Test Cases Runner\n\nRuns shared end-to-end test cases from athena-protobufs/testcases/ through the Athena classification service and validates results against expected outputs.' )
82+ . version ( '1.0.0' )
83+ . addOption (
84+ new Option ( '-t, --testset <name>' , 'Test set to run' )
85+ . choices ( VALID_TESTSETS as readonly string [ ] )
86+ . default ( 'integrator_sample' )
87+ )
88+ . option ( '-T, --tolerance <value>' , 'Comparison tolerance' , ( value ) => {
89+ const parsed = parseFloat ( value ) ;
90+ if ( isNaN ( parsed ) || parsed < 0 ) {
91+ throw new InvalidArgumentError ( 'Tolerance must be a positive number' ) ;
92+ }
93+ return parsed ;
94+ } , 0.0001 )
95+ . option ( '-v, --verbose' , 'Enable verbose output' , false )
96+ . option ( '-l, --list' , 'List available test sets and exit' , false )
97+ . addHelpText ( 'after' , `
8198Environment Variables (Required):
8299 ATHENA_CLIENT_ID OAuth client ID
83100 ATHENA_CLIENT_SECRET OAuth client secret
@@ -89,64 +106,24 @@ Environment Variables (Optional):
89106 ATHENA_AUDIENCE OAuth audience (default: crisp-athena-live)
90107
91108Examples:
92- # Run default test set
93- npx tsx index.ts
94-
95- # Run specific test set with custom tolerance
96- npx tsx index.ts --testset live_model --tolerance 0.01
97-
98- # Verbose output
99- npx tsx index.ts --verbose
109+ $ npx tsx index.ts
110+ $ npx tsx index.ts --testset live_model --tolerance 0.01
111+ $ npx tsx index.ts --verbose --list
100112
101113Setup:
102- # Create environment file
103114 cp ../.env.example ../.env
104- # Edit ../.env with your credentials
105- # Source with auto-export
106115 set -a && source ../.env && set +a
107116` ) ;
108- }
109117
110- /**
111- * Parse command line arguments
112- */
113- function parseArgs ( ) : { testset : TestSet ; tolerance : number ; verbose : boolean ; list : boolean ; help : boolean } {
114- const args = process . argv . slice ( 2 ) ;
115- const options = {
116- testset : 'integrator_sample' as TestSet ,
117- tolerance : 0.0001 ,
118- verbose : false ,
119- list : false ,
120- help : false ,
121- } ;
118+ program . parse ( ) ;
122119
123- for ( let i = 0 ; i < args . length ; i ++ ) {
124- const arg = args [ i ] ;
125-
126- if ( arg === '-h' || arg === '--help' ) {
127- options . help = true ;
128- } else if ( arg === '-v' || arg === '--verbose' ) {
129- options . verbose = true ;
130- } else if ( arg === '-l' || arg === '--list' ) {
131- options . list = true ;
132- } else if ( arg === '-t' || arg === '--testset' ) {
133- const value = args [ ++ i ] as TestSet ;
134- if ( ! VALID_TESTSETS . includes ( value ) ) {
135- console . error ( `Error: Invalid test set '${ value } '. Valid options: ${ VALID_TESTSETS . join ( ', ' ) } ` ) ;
136- process . exit ( 2 ) ;
137- }
138- options . testset = value ;
139- } else if ( arg === '-T' || arg === '--tolerance' ) {
140- const value = parseFloat ( args [ ++ i ] ) ;
141- if ( isNaN ( value ) || value < 0 ) {
142- console . error ( 'Error: Tolerance must be a positive number' ) ;
143- process . exit ( 2 ) ;
144- }
145- options . tolerance = value ;
146- }
147- }
148-
149- return options ;
120+ const opts = program . opts ( ) ;
121+ return {
122+ testset : opts . testset as TestSet ,
123+ tolerance : opts . tolerance as number ,
124+ verbose : opts . verbose as boolean ,
125+ list : opts . list as boolean ,
126+ } ;
150127}
151128
152129/**
@@ -262,11 +239,6 @@ function compareResults(
262239async function main ( ) : Promise < void > {
263240 const options = parseArgs ( ) ;
264241
265- if ( options . help ) {
266- showUsage ( ) ;
267- process . exit ( 0 ) ;
268- }
269-
270242 if ( options . list ) {
271243 listTestSets ( ) ;
272244 process . exit ( 0 ) ;
0 commit comments