1+ import * as fs from "fs" ;
2+ import * as child from "child_process" ;
3+ import * as core from "@actions/core" ;
4+ import { XcodeSelector , XcodeVersion } from "../src/xcode-selector" ;
5+
6+ jest . mock ( "fs" ) ;
7+ jest . mock ( "child_process" ) ;
8+ jest . mock ( "@actions/core" ) ;
9+
10+ const buildFsDirentItem = ( name : string , opt : { isSymbolicLink : boolean ; isDirectory : boolean } ) : fs . Dirent => {
11+ return {
12+ name,
13+ isSymbolicLink : ( ) => opt . isSymbolicLink ,
14+ isDirectory : ( ) => opt . isDirectory
15+ } as fs . Dirent ;
16+ } ;
17+
18+ const fakeReadDirResults = [
19+ buildFsDirentItem ( "Xcode.app" , { isSymbolicLink : true , isDirectory : false } ) ,
20+ buildFsDirentItem ( "Xcode.app" , { isSymbolicLink : false , isDirectory : true } ) ,
21+ buildFsDirentItem ( "Xcode_11.1.app" , { isSymbolicLink : false , isDirectory : true } ) ,
22+ buildFsDirentItem ( "Xcode_11.1_beta.app" , { isSymbolicLink : true , isDirectory : false } ) ,
23+ buildFsDirentItem ( "Xcode_11.2.1.app" , { isSymbolicLink : false , isDirectory : true } ) ,
24+ buildFsDirentItem ( "Xcode_11.4.app" , { isSymbolicLink : true , isDirectory : false } ) ,
25+ buildFsDirentItem ( "Xcode_11.4_beta.app" , { isSymbolicLink : false , isDirectory : true } ) ,
26+ buildFsDirentItem ( "Xcode_11.app" , { isSymbolicLink : false , isDirectory : true } ) ,
27+ buildFsDirentItem ( "third_party_folder" , { isSymbolicLink : false , isDirectory : true } ) ,
28+ ] ;
29+
30+ const fakeGetVersionsResult : XcodeVersion [ ] = [
31+ { version : "11.4.0" , path : "" } ,
32+ { version : "11.2.1" , path : "" } ,
33+ { version : "11.2.0" , path : "" } ,
34+ { version : "11.0.0" , path : "" } ,
35+ { version : "10.3.0" , path : "" }
36+ ] ;
37+
38+ describe ( "XcodeSelector" , ( ) => {
39+ describe ( "getXcodeVersionFromAppPath" , ( ) => {
40+ it . each ( [
41+ [ "/temp/Xcode_11.app" , { version : "11.0.0" , path : "/temp/Xcode_11.app" } ] ,
42+ [ "/temp/Xcode_11.2.app" , { version : "11.2.0" , path : "/temp/Xcode_11.2.app" } ] ,
43+ [ "/temp/Xcode_11.2.1.app" , { version : "11.2.1" , path : "/temp/Xcode_11.2.1.app" } ] ,
44+ [ "/temp/Xcode_11.2.1_beta.app" , { version : "11.2.1" , path : "/temp/Xcode_11.2.1_beta.app" } ] ,
45+ [ "/temp/Xcode.app" , null ] ,
46+ [ "/temp/Xcode_11.2" , null ] ,
47+ [ "/temp/Xcode.11.2.app" , null ]
48+ ] ) ( "'%s' -> '%s'" , ( input : string , expected : XcodeVersion | null ) => {
49+ // test private method
50+ const actual = new XcodeSelector ( ) [ "getXcodeVersionFromAppPath" ] ( input ) ;
51+ expect ( actual ) . toEqual ( expected ) ;
52+ } ) ;
53+
54+ } ) ;
55+
56+ describe ( "getAllVersions" , ( ) => {
57+ beforeEach ( ( ) => {
58+ jest . spyOn ( fs , "readdirSync" ) . mockImplementation ( ( ) => fakeReadDirResults ) ;
59+ } ) ;
60+
61+ afterEach ( ( ) => {
62+ jest . resetAllMocks ( ) ;
63+ jest . clearAllMocks ( ) ;
64+ } ) ;
65+
66+ it ( "versions are filtered correctly" , ( ) => {
67+ const sel = new XcodeSelector ( ) ;
68+ const expectedVersions : XcodeVersion [ ] = [
69+ { version : "11.4.0" , path : "/Applications/Xcode_11.4_beta.app" } ,
70+ { version : "11.2.1" , path : "/Applications/Xcode_11.2.1.app" } ,
71+ { version : "11.1.0" , path : "/Applications/Xcode_11.1.app" } ,
72+ { version : "11.0.0" , path : "/Applications/Xcode_11.app" }
73+ ] ;
74+ expect ( sel . getAllVersions ( ) ) . toEqual ( expectedVersions ) ;
75+ } ) ;
76+ } ) ;
77+
78+ describe ( "findVersion" , ( ) => {
79+ it . each ( [
80+ [ "latest" , "11.4.0" ] ,
81+ [ "11" , "11.4.0" ] ,
82+ [ "11.x" , "11.4.0" ] ,
83+ [ "11.2.x" , "11.2.1" ] ,
84+ [ "11.2.0" , "11.2.0" ] ,
85+ [ "10.x" , "10.3.0" ] ,
86+ [ "~11.2.0" , "11.2.1" ] ,
87+ [ "^11.2.0" , "11.4.0" ] ,
88+ [ "< 11.0" , "10.3.0" ] ,
89+ [ "10.0.0 - 11.2.0" , "11.2.0" ] ,
90+ [ "give me latest version" , null ]
91+ ] as [ string , string | null ] [ ] ) ( "'%s' -> '%s'" , ( versionSpec : string , expected : string | null ) => {
92+ const sel = new XcodeSelector ( ) ;
93+ sel . getAllVersions = ( ) : XcodeVersion [ ] => fakeGetVersionsResult ;
94+ const matchedVersion = sel . findVersion ( versionSpec ) ?. version ?? null ;
95+ expect ( matchedVersion ) . toBe ( expected ) ;
96+ } ) ;
97+ } ) ;
98+
99+ describe ( "setVersion" , ( ) => {
100+ let coreExportVariableSpy : jest . SpyInstance ;
101+ let fsExistsSpy : jest . SpyInstance ;
102+ let fsSpawnSpy : jest . SpyInstance ;
103+ const xcodeVersion : XcodeVersion = {
104+ version : "11.4" ,
105+ path : "/Applications/Xcode_11.4.app"
106+ } ;
107+
108+ beforeEach ( ( ) => {
109+ coreExportVariableSpy = jest . spyOn ( core , "exportVariable" ) ;
110+ fsExistsSpy = jest . spyOn ( fs , "existsSync" ) ;
111+ fsSpawnSpy = jest . spyOn ( child , "spawnSync" ) ;
112+ } ) ;
113+
114+ afterEach ( ( ) => {
115+ jest . resetAllMocks ( ) ;
116+ jest . clearAllMocks ( ) ;
117+ } ) ;
118+
119+ it ( "works correctly" , ( ) => {
120+ fsExistsSpy . mockImplementation ( ( ) => true ) ;
121+ const sel = new XcodeSelector ( ) ;
122+ sel . setVersion ( xcodeVersion ) ;
123+ expect ( fsSpawnSpy ) . toHaveBeenCalledWith ( "sudo" , [ "xcode-select" , "-s" , "/Applications/Xcode_11.4.app" ] ) ;
124+ expect ( coreExportVariableSpy ) . toHaveBeenCalledWith ( "MD_APPLE_SDK_ROOT" , "/Applications/Xcode_11.4.app" ) ;
125+ } ) ;
126+
127+ it ( "error is thrown if version doesn't exist" , ( ) => {
128+ fsExistsSpy . mockImplementation ( ( ) => false ) ;
129+ const sel = new XcodeSelector ( ) ;
130+ expect ( ( ) => sel . setVersion ( xcodeVersion ) ) . toThrow ( ) ;
131+ } ) ;
132+ } ) ;
133+ } ) ;
0 commit comments