@@ -34,6 +34,7 @@ describe('socket scan reach', async () => {
3434 --json Output as JSON
3535 --markdown Output as Markdown
3636 --org Force override the organization slug, overrides the default org from config
37+ --output Path to write the reachability report to (must end with .json). Defaults to .socket.facts.json in the current working directory.
3738
3839 Reachability Options
3940 --reach-analysis-memory-limit The maximum memory in MB to use for the reachability analysis. The default is 8192MB.
@@ -44,7 +45,8 @@ describe('socket scan reach', async () => {
4445 --reach-skip-cache Skip caching-based optimizations. By default, the reachability analysis will use cached configurations from previous runs to speed up the analysis.
4546
4647 Runs the Socket reachability analysis without creating a scan in Socket.
47- The output is written to .socket.facts.json in the current working directory.
48+ The output is written to .socket.facts.json in the current working directory
49+ unless the --output flag is specified.
4850
4951 Note: Manifest files are uploaded to Socket's backend services because the
5052 reachability analysis requires creating a Software Bill of Materials (SBOM)
@@ -53,7 +55,9 @@ describe('socket scan reach', async () => {
5355 Examples
5456 $ socket scan reach
5557 $ socket scan reach ./proj
56- $ socket scan reach ./proj --reach-ecosystems npm,pypi"
58+ $ socket scan reach ./proj --reach-ecosystems npm,pypi
59+ $ socket scan reach --output custom-report.json
60+ $ socket scan reach ./proj --output ./reports/analysis.json"
5761 ` )
5862 expect ( `\n ${ stderr } ` ) . toMatchInlineSnapshot ( `
5963 "
@@ -718,6 +722,131 @@ describe('socket scan reach', async () => {
718722 )
719723 } )
720724
725+ describe ( 'output path tests' , ( ) => {
726+ cmdit (
727+ [
728+ 'scan' ,
729+ 'reach' ,
730+ FLAG_DRY_RUN ,
731+ '--output' ,
732+ 'custom-report.json' ,
733+ '--org' ,
734+ 'fakeOrg' ,
735+ FLAG_CONFIG ,
736+ '{"apiToken":"fakeToken"}' ,
737+ ] ,
738+ 'should accept --output flag with .json extension' ,
739+ async cmd => {
740+ const { code, stdout } = await spawnSocketCli ( binCliPath , cmd )
741+ expect ( stdout ) . toMatchInlineSnapshot ( `"[DryRun]: Bailing now"` )
742+ expect ( code , 'should exit with code 0' ) . toBe ( 0 )
743+ } ,
744+ )
745+
746+ cmdit (
747+ [
748+ 'scan' ,
749+ 'reach' ,
750+ FLAG_DRY_RUN ,
751+ '-o' ,
752+ 'report.json' ,
753+ '--org' ,
754+ 'fakeOrg' ,
755+ FLAG_CONFIG ,
756+ '{"apiToken":"fakeToken"}' ,
757+ ] ,
758+ 'should accept -o short flag with .json extension' ,
759+ async cmd => {
760+ const { code, stdout } = await spawnSocketCli ( binCliPath , cmd )
761+ expect ( stdout ) . toMatchInlineSnapshot ( `"[DryRun]: Bailing now"` )
762+ expect ( code , 'should exit with code 0' ) . toBe ( 0 )
763+ } ,
764+ )
765+
766+ cmdit (
767+ [
768+ 'scan' ,
769+ 'reach' ,
770+ FLAG_DRY_RUN ,
771+ '--output' ,
772+ './reports/analysis.json' ,
773+ '--org' ,
774+ 'fakeOrg' ,
775+ FLAG_CONFIG ,
776+ '{"apiToken":"fakeToken"}' ,
777+ ] ,
778+ 'should accept --output flag with path' ,
779+ async cmd => {
780+ const { code, stdout } = await spawnSocketCli ( binCliPath , cmd )
781+ expect ( stdout ) . toMatchInlineSnapshot ( `"[DryRun]: Bailing now"` )
782+ expect ( code , 'should exit with code 0' ) . toBe ( 0 )
783+ } ,
784+ )
785+
786+ cmdit (
787+ [
788+ 'scan' ,
789+ 'reach' ,
790+ FLAG_DRY_RUN ,
791+ '--output' ,
792+ 'report.txt' ,
793+ '--org' ,
794+ 'fakeOrg' ,
795+ FLAG_CONFIG ,
796+ '{"apiToken":"fakeToken"}' ,
797+ ] ,
798+ 'should fail when --output does not end with .json' ,
799+ async cmd => {
800+ const { code, stderr, stdout } = await spawnSocketCli ( binCliPath , cmd )
801+ const output = stdout + stderr
802+ expect ( output ) . toContain ( 'The --output path must end with .json' )
803+ expect ( code , 'should exit with non-zero code' ) . not . toBe ( 0 )
804+ } ,
805+ )
806+
807+ cmdit (
808+ [
809+ 'scan' ,
810+ 'reach' ,
811+ FLAG_DRY_RUN ,
812+ '--output' ,
813+ 'report' ,
814+ '--org' ,
815+ 'fakeOrg' ,
816+ FLAG_CONFIG ,
817+ '{"apiToken":"fakeToken"}' ,
818+ ] ,
819+ 'should fail when --output has no extension' ,
820+ async cmd => {
821+ const { code, stderr, stdout } = await spawnSocketCli ( binCliPath , cmd )
822+ const output = stdout + stderr
823+ expect ( output ) . toContain ( 'The --output path must end with .json' )
824+ expect ( code , 'should exit with non-zero code' ) . not . toBe ( 0 )
825+ } ,
826+ )
827+
828+ cmdit (
829+ [
830+ 'scan' ,
831+ 'reach' ,
832+ FLAG_DRY_RUN ,
833+ '--output' ,
834+ 'report.JSON' ,
835+ '--org' ,
836+ 'fakeOrg' ,
837+ FLAG_CONFIG ,
838+ '{"apiToken":"fakeToken"}' ,
839+ ] ,
840+ 'should fail when --output ends with .JSON (uppercase)' ,
841+ async cmd => {
842+ const { code, stderr, stdout } = await spawnSocketCli ( binCliPath , cmd )
843+ const output = stdout + stderr
844+ expect ( output ) . toContain ( 'The --output path must end with .json' )
845+ expect ( code , 'should exit with non-zero code' ) . not . toBe ( 0 )
846+ } ,
847+ )
848+ } )
849+
721850 describe ( 'error handling and usability tests' , ( ) => {
722851 cmdit (
723852 [
0 commit comments