@sentry/wizard 4.7.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +19 -19
  3. package/dist/e2e-tests/tests/angular-17.test.d.ts +1 -0
  4. package/dist/e2e-tests/tests/angular-17.test.js +196 -0
  5. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -0
  6. package/dist/e2e-tests/tests/angular-19.test.d.ts +1 -0
  7. package/dist/e2e-tests/tests/angular-19.test.js +194 -0
  8. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -0
  9. package/dist/e2e-tests/tests/expo.test.d.ts +1 -0
  10. package/dist/e2e-tests/tests/expo.test.js +103 -0
  11. package/dist/e2e-tests/tests/expo.test.js.map +1 -0
  12. package/dist/e2e-tests/tests/help-message.test.js +2 -2
  13. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/react-native.test.d.ts +1 -0
  15. package/dist/e2e-tests/tests/react-native.test.js +132 -0
  16. package/dist/e2e-tests/tests/react-native.test.js.map +1 -0
  17. package/dist/e2e-tests/tests/remix.test.js +4 -4
  18. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  19. package/dist/e2e-tests/tests/sveltekit.test.js +2 -2
  20. package/dist/e2e-tests/tests/sveltekit.test.js.map +1 -1
  21. package/dist/e2e-tests/utils/index.d.ts +7 -0
  22. package/dist/e2e-tests/utils/index.js +32 -7
  23. package/dist/e2e-tests/utils/index.js.map +1 -1
  24. package/dist/lib/Constants.d.ts +1 -0
  25. package/dist/lib/Constants.js +3 -0
  26. package/dist/lib/Constants.js.map +1 -1
  27. package/dist/lib/Helper/SentryCli.d.ts +0 -11
  28. package/dist/lib/Helper/SentryCli.js +0 -52
  29. package/dist/lib/Helper/SentryCli.js.map +1 -1
  30. package/dist/src/android/templates.js +2 -0
  31. package/dist/src/android/templates.js.map +1 -1
  32. package/dist/src/angular/angular-wizard.d.ts +3 -0
  33. package/dist/src/angular/angular-wizard.js +186 -0
  34. package/dist/src/angular/angular-wizard.js.map +1 -0
  35. package/dist/src/angular/codemods/app-config.d.ts +3 -0
  36. package/dist/src/angular/codemods/app-config.js +211 -0
  37. package/dist/src/angular/codemods/app-config.js.map +1 -0
  38. package/dist/src/angular/codemods/main.d.ts +20 -0
  39. package/dist/src/angular/codemods/main.js +62 -0
  40. package/dist/src/angular/codemods/main.js.map +1 -0
  41. package/dist/src/angular/codemods/sourcemaps.d.ts +21 -0
  42. package/dist/src/angular/codemods/sourcemaps.js +94 -0
  43. package/dist/src/angular/codemods/sourcemaps.js.map +1 -0
  44. package/dist/src/angular/example-component.d.ts +8 -0
  45. package/dist/src/angular/example-component.js +286 -0
  46. package/dist/src/angular/example-component.js.map +1 -0
  47. package/dist/src/angular/sdk-setup.d.ts +6 -0
  48. package/dist/src/angular/sdk-setup.js +99 -0
  49. package/dist/src/angular/sdk-setup.js.map +1 -0
  50. package/dist/src/apple/code-tools.d.ts +4 -2
  51. package/dist/src/apple/code-tools.js +21 -11
  52. package/dist/src/apple/code-tools.js.map +1 -1
  53. package/dist/src/apple/inject-code-snippet.js +5 -3
  54. package/dist/src/apple/inject-code-snippet.js.map +1 -1
  55. package/dist/src/apple/macos-system-helper.d.ts +5 -0
  56. package/dist/src/apple/macos-system-helper.js +86 -0
  57. package/dist/src/apple/macos-system-helper.js.map +1 -0
  58. package/dist/src/apple/templates.js +10 -0
  59. package/dist/src/apple/templates.js.map +1 -1
  60. package/dist/src/apple/xcode-manager.d.ts +237 -11
  61. package/dist/src/apple/xcode-manager.js +736 -65
  62. package/dist/src/apple/xcode-manager.js.map +1 -1
  63. package/dist/src/apple/xcode-project-object-with-id.d.ts +5 -0
  64. package/dist/src/apple/xcode-project-object-with-id.js +3 -0
  65. package/dist/src/apple/xcode-project-object-with-id.js.map +1 -0
  66. package/dist/src/flutter/flutter-wizard.js +10 -2
  67. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  68. package/dist/src/flutter/templates.js +7 -1
  69. package/dist/src/flutter/templates.js.map +1 -1
  70. package/dist/src/nextjs/nextjs-wizard.js +27 -15
  71. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  72. package/dist/src/nextjs/templates.js +56 -7
  73. package/dist/src/nextjs/templates.js.map +1 -1
  74. package/dist/src/nuxt/nuxt-wizard.js +1 -3
  75. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  76. package/dist/src/nuxt/templates.js +30 -0
  77. package/dist/src/nuxt/templates.js.map +1 -1
  78. package/dist/src/react-native/expo-env-file.js +5 -0
  79. package/dist/src/react-native/expo-env-file.js.map +1 -1
  80. package/dist/src/react-native/expo-metro.js +22 -6
  81. package/dist/src/react-native/expo-metro.js.map +1 -1
  82. package/dist/src/react-native/expo.js +11 -1
  83. package/dist/src/react-native/expo.js.map +1 -1
  84. package/dist/src/react-native/glob.js +14 -4
  85. package/dist/src/react-native/glob.js.map +1 -1
  86. package/dist/src/react-native/gradle.js +14 -4
  87. package/dist/src/react-native/gradle.js.map +1 -1
  88. package/dist/src/react-native/javascript.d.ts +9 -4
  89. package/dist/src/react-native/javascript.js +52 -23
  90. package/dist/src/react-native/javascript.js.map +1 -1
  91. package/dist/src/react-native/metro.d.ts +1 -1
  92. package/dist/src/react-native/metro.js +36 -4
  93. package/dist/src/react-native/metro.js.map +1 -1
  94. package/dist/src/react-native/react-native-wizard.d.ts +4 -0
  95. package/dist/src/react-native/react-native-wizard.js +32 -4
  96. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  97. package/dist/src/react-native/xcode.js +29 -10
  98. package/dist/src/react-native/xcode.js.map +1 -1
  99. package/dist/src/remix/remix-wizard.js +1 -3
  100. package/dist/src/remix/remix-wizard.js.map +1 -1
  101. package/dist/src/remix/sdk-example.js +30 -1
  102. package/dist/src/remix/sdk-example.js.map +1 -1
  103. package/dist/src/remix/sdk-setup.js +11 -5
  104. package/dist/src/remix/sdk-setup.js.map +1 -1
  105. package/dist/src/run.d.ts +1 -1
  106. package/dist/src/run.js +5 -0
  107. package/dist/src/run.js.map +1 -1
  108. package/dist/src/sourcemaps/sourcemaps-wizard.d.ts +1 -1
  109. package/dist/src/sourcemaps/sourcemaps-wizard.js +35 -20
  110. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  111. package/dist/src/sourcemaps/tools/angular.d.ts +1 -0
  112. package/dist/src/sourcemaps/tools/angular.js +7 -7
  113. package/dist/src/sourcemaps/tools/angular.js.map +1 -1
  114. package/dist/src/sourcemaps/tools/sentry-cli.d.ts +5 -1
  115. package/dist/src/sourcemaps/tools/sentry-cli.js +6 -3
  116. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  117. package/dist/src/sourcemaps/tools/tsc.js +5 -1
  118. package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
  119. package/dist/src/sourcemaps/tools/vite.js +4 -1
  120. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  121. package/dist/src/sourcemaps/tools/webpack.js +4 -1
  122. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  123. package/dist/src/sveltekit/sdk-example.js +1 -1
  124. package/dist/src/sveltekit/sdk-example.js.map +1 -1
  125. package/dist/src/sveltekit/sveltekit-wizard.js +3 -5
  126. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  127. package/dist/src/sveltekit/templates.js +28 -1
  128. package/dist/src/sveltekit/templates.js.map +1 -1
  129. package/dist/src/utils/clack/index.d.ts +13 -15
  130. package/dist/src/utils/clack/index.js +17 -50
  131. package/dist/src/utils/clack/index.js.map +1 -1
  132. package/dist/src/utils/git.d.ts +11 -0
  133. package/dist/src/utils/git.js +69 -0
  134. package/dist/src/utils/git.js.map +1 -0
  135. package/dist/src/utils/sentrycli-utils.js +13 -4
  136. package/dist/src/utils/sentrycli-utils.js.map +1 -1
  137. package/dist/src/version.d.ts +1 -1
  138. package/dist/src/version.js +1 -1
  139. package/dist/src/version.js.map +1 -1
  140. package/dist/test/angular/angular-wizard.test.d.ts +1 -0
  141. package/dist/test/angular/angular-wizard.test.js +27 -0
  142. package/dist/test/angular/angular-wizard.test.js.map +1 -0
  143. package/dist/test/angular/codemods/sourcemaps.test.d.ts +1 -0
  144. package/dist/test/angular/codemods/sourcemaps.test.js +237 -0
  145. package/dist/test/angular/codemods/sourcemaps.test.js.map +1 -0
  146. package/dist/test/angular/example-component.test.d.ts +1 -0
  147. package/dist/test/angular/example-component.test.js +105 -0
  148. package/dist/test/angular/example-component.test.js.map +1 -0
  149. package/dist/test/apple/code-tools.test.js +54 -35
  150. package/dist/test/apple/code-tools.test.js.map +1 -1
  151. package/dist/test/apple/configure-sentry-cli.test.d.ts +1 -0
  152. package/dist/test/apple/configure-sentry-cli.test.js +131 -0
  153. package/dist/test/apple/configure-sentry-cli.test.js.map +1 -0
  154. package/dist/test/apple/macos-system-helper-mocked.test.d.ts +1 -0
  155. package/dist/test/apple/macos-system-helper-mocked.test.js +46 -0
  156. package/dist/test/apple/macos-system-helper-mocked.test.js.map +1 -0
  157. package/dist/test/apple/macos-system-helper.test.d.ts +1 -0
  158. package/dist/test/apple/macos-system-helper.test.js +88 -0
  159. package/dist/test/apple/macos-system-helper.test.js.map +1 -0
  160. package/dist/test/apple/templates.test.js +10 -0
  161. package/dist/test/apple/templates.test.js.map +1 -1
  162. package/dist/test/apple/xcode-manager.test.js +745 -379
  163. package/dist/test/apple/xcode-manager.test.js.map +1 -1
  164. package/dist/test/flutter/templates.test.js +9 -0
  165. package/dist/test/flutter/templates.test.js.map +1 -1
  166. package/dist/test/react-native/javascript.test.js +119 -0
  167. package/dist/test/react-native/javascript.test.js.map +1 -1
  168. package/dist/test/react-native/metro.test.js +113 -0
  169. package/dist/test/react-native/metro.test.js.map +1 -1
  170. package/dist/test/remix/client-entry.test.js +10 -10
  171. package/dist/test/remix/client-entry.test.js.map +1 -1
  172. package/dist/test/utils/git.test.d.ts +1 -0
  173. package/dist/test/utils/git.test.js +70 -0
  174. package/dist/test/utils/git.test.js.map +1 -0
  175. package/package.json +1 -1
@@ -22,13 +22,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
29
  const fs = __importStar(require("node:fs"));
27
30
  const os = __importStar(require("node:os"));
28
31
  const path = __importStar(require("node:path"));
32
+ const node_process_1 = __importDefault(require("node:process"));
33
+ const vitest_1 = require("vitest");
29
34
  const templates_1 = require("../../src/apple/templates");
30
35
  const xcode_manager_1 = require("../../src/apple/xcode-manager");
31
- const vitest_1 = require("vitest");
32
36
  vitest_1.vi.mock('node:fs', async () => ({
33
37
  __esModule: true,
34
38
  ...(await vitest_1.vi.importActual('node:fs')),
@@ -43,6 +47,8 @@ vitest_1.vi.mock('@clack/prompts', () => ({
43
47
  const appleProjectsPath = path.resolve(__dirname, '../../fixtures/test-applications/apple');
44
48
  const damagedProjectPath = path.join(appleProjectsPath, 'damaged-missing-configuration-list/Project.xcodeproj/project.pbxproj');
45
49
  const noTargetsProjectPath = path.join(appleProjectsPath, 'no-targets/Project.xcodeproj/project.pbxproj');
50
+ const noFilesInTargetProjectPath = path.join(appleProjectsPath, 'no-files-in-target/Project.xcodeproj/project.pbxproj');
51
+ const projectWithSynchronizedFolders = path.join(appleProjectsPath, 'project-with-synchronized-folders/Project.xcodeproj/project.pbxproj');
46
52
  const singleTargetProjectPath = path.join(appleProjectsPath, 'spm-swiftui-single-target/Project.xcodeproj/project.pbxproj');
47
53
  const multiTargetProjectPath = path.join(appleProjectsPath, 'spm-swiftui-multi-targets/Project.xcodeproj/project.pbxproj');
48
54
  const projectData = {
@@ -56,6 +62,22 @@ const projectData = {
56
62
  keys: [{ dsn: { public: 'https://sentry.io/1234567890' } }],
57
63
  };
58
64
  (0, vitest_1.describe)('XcodeManager', () => {
65
+ (0, vitest_1.beforeEach)(() => {
66
+ if (node_process_1.default.platform !== 'darwin') {
67
+ // The macOS system helpers are only available on macOS
68
+ // As the test suite is also run on non-macOS platforms, we need to mock the system helpers
69
+ // The path to the Xcode.app can be different on different machines, so we allow overwriting it using environment variables
70
+ vitest_1.vi.mock('../../src/apple/macos-system-helper', () => ({
71
+ MacOSSystemHelpers: {
72
+ findSDKRootDirectoryPath: vitest_1.vi.fn(() => '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk'),
73
+ findDeveloperDirectoryPath: vitest_1.vi.fn(() => '/Applications/Xcode.app/Contents/Developer'),
74
+ readXcodeBuildSettings: vitest_1.vi.fn(() => ({
75
+ CONFIGURATION_BUILD_DIR: path.join(appleProjectsPath, 'project-with-synchronized-folders/build/Release-unknown'),
76
+ })),
77
+ },
78
+ }));
79
+ }
80
+ });
59
81
  (0, vitest_1.afterEach)(() => {
60
82
  vitest_1.vi.clearAllMocks();
61
83
  });
@@ -376,475 +398,819 @@ const projectData = {
376
398
  });
377
399
  });
378
400
  });
379
- });
380
- (0, vitest_1.describe)('filesForTarget', () => {
381
- (0, vitest_1.describe)('targets are undefined', () => {
382
- (0, vitest_1.it)('should return undefined', () => {
383
- // -- Arrange --
384
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
385
- xcodeProject.objects.PBXNativeTarget = undefined;
386
- // -- Act --
387
- const files = xcodeProject.filesForTarget('Project');
388
- // -- Assert --
389
- (0, vitest_1.expect)(files).toBeUndefined();
390
- });
391
- });
392
- (0, vitest_1.describe)('target not found', () => {
393
- (0, vitest_1.it)('should return undefined', () => {
394
- // -- Arrange --
395
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
396
- // -- Act --
397
- const files = xcodeProject.filesForTarget('NonExistentTarget');
398
- // -- Assert --
399
- (0, vitest_1.expect)(files).toBeUndefined();
400
- });
401
- });
402
- (0, vitest_1.describe)('target build phases are undefined', () => {
403
- (0, vitest_1.it)('should return undefined', () => {
404
- // -- Arrange --
405
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
406
- xcodeProject.objects.PBXNativeTarget = {
407
- Project: {
408
- isa: 'PBXNativeTarget',
409
- name: 'Project',
410
- buildPhases: undefined,
411
- },
412
- };
413
- // -- Act --
414
- const files = xcodeProject.filesForTarget('Project');
415
- // -- Assert --
416
- (0, vitest_1.expect)(files).toBeUndefined();
417
- });
418
- });
419
- (0, vitest_1.describe)('build phases are undefined', () => {
420
- (0, vitest_1.it)('should return undefined', () => {
421
- // -- Arrange --
422
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
423
- xcodeProject.objects.PBXNativeTarget = {
424
- Project: {
425
- isa: 'PBXNativeTarget',
426
- name: 'Project',
427
- buildPhases: undefined,
428
- },
429
- };
430
- xcodeProject.objects.PBXSourcesBuildPhase = undefined;
431
- // -- Act --
432
- const files = xcodeProject.filesForTarget('Project');
433
- // -- Assert --
434
- (0, vitest_1.expect)(files).toBeUndefined();
401
+ (0, vitest_1.describe)('getSourceFilesForTarget', () => {
402
+ (0, vitest_1.describe)('targets are undefined', () => {
403
+ (0, vitest_1.it)('should return undefined', () => {
404
+ // -- Arrange --
405
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
406
+ xcodeProject.objects.PBXNativeTarget = undefined;
407
+ // -- Act --
408
+ const files = xcodeProject.getSourceFilesForTarget('Project');
409
+ // -- Assert --
410
+ (0, vitest_1.expect)(files).toBeUndefined();
411
+ });
435
412
  });
436
- });
437
- (0, vitest_1.describe)('referenced build phase is undefined', () => {
438
- (0, vitest_1.it)('should return undefined', () => {
439
- // -- Arrange --
440
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
441
- xcodeProject.objects.PBXNativeTarget = {
442
- Project: {
443
- isa: 'PBXNativeTarget',
444
- name: 'Project',
445
- buildPhases: [
446
- {
447
- value: 'random-build-phase',
448
- },
449
- ],
450
- },
451
- };
452
- // -- Act --
453
- const files = xcodeProject.filesForTarget('Project');
454
- // -- Assert --
455
- (0, vitest_1.expect)(files).toBeUndefined();
413
+ (0, vitest_1.describe)('target not found', () => {
414
+ (0, vitest_1.it)('should return undefined', () => {
415
+ // -- Arrange --
416
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
417
+ // -- Act --
418
+ const files = xcodeProject.getSourceFilesForTarget('NonExistentTarget');
419
+ // -- Assert --
420
+ (0, vitest_1.expect)(files).toBeUndefined();
421
+ });
456
422
  });
457
- });
458
- (0, vitest_1.describe)('build phase files are undefined', () => {
459
- (0, vitest_1.it)('should return empty array', () => {
460
- // -- Arrange --
461
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
462
- xcodeProject.objects.PBXNativeTarget = {
463
- Project: {
464
- isa: 'PBXNativeTarget',
465
- name: 'Project',
466
- buildPhases: [
467
- {
468
- value: 'build-phase-key',
469
- },
470
- ],
471
- },
472
- };
473
- xcodeProject.objects.PBXSourcesBuildPhase = {
474
- 'build-phase-key': {
475
- isa: 'PBXSourcesBuildPhase',
476
- files: undefined,
477
- },
478
- };
479
- // -- Act --
480
- const files = xcodeProject.filesForTarget('Project');
481
- // -- Assert --
482
- (0, vitest_1.expect)(files).toEqual([]);
423
+ (0, vitest_1.describe)('target build phases are undefined', () => {
424
+ (0, vitest_1.it)('should return empty array', () => {
425
+ // -- Arrange --
426
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
427
+ xcodeProject.objects.PBXNativeTarget = {
428
+ Project: {
429
+ isa: 'PBXNativeTarget',
430
+ name: 'Project',
431
+ buildPhases: undefined,
432
+ },
433
+ };
434
+ // -- Act --
435
+ const files = xcodeProject.getSourceFilesForTarget('Project');
436
+ // -- Assert --
437
+ (0, vitest_1.expect)(files).toEqual([]);
438
+ });
483
439
  });
484
- });
485
- (0, vitest_1.describe)('build phase has no files', () => {
486
- (0, vitest_1.it)('should return empty array', () => {
487
- // -- Arrange --
488
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
489
- // -- Act --
490
- const files = xcodeProject.filesForTarget('Project');
491
- // -- Assert --
492
- (0, vitest_1.expect)(files).toEqual([]);
440
+ (0, vitest_1.describe)('build phases are undefined', () => {
441
+ (0, vitest_1.it)('should return empty array', () => {
442
+ // -- Arrange --
443
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
444
+ xcodeProject.objects.PBXNativeTarget = {
445
+ Project: {
446
+ isa: 'PBXNativeTarget',
447
+ name: 'Project',
448
+ buildPhases: undefined,
449
+ },
450
+ };
451
+ xcodeProject.objects.PBXSourcesBuildPhase = undefined;
452
+ // -- Act --
453
+ const files = xcodeProject.getSourceFilesForTarget('Project');
454
+ // -- Assert --
455
+ (0, vitest_1.expect)(files).toEqual([]);
456
+ });
493
457
  });
494
- });
495
- (0, vitest_1.describe)('build phase with files', () => {
496
- let xcodeProject;
497
- (0, vitest_1.beforeEach)(() => {
498
- xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
499
- xcodeProject.objects.PBXNativeTarget = {
500
- 'some-target': {
501
- isa: 'PBXNativeTarget',
502
- name: 'some-target',
503
- buildPhases: [
504
- {
505
- value: 'build-phase-key',
506
- },
507
- ],
508
- },
509
- };
510
- xcodeProject.objects.PBXSourcesBuildPhase = {
511
- 'build-phase-key': {
512
- isa: 'PBXSourcesBuildPhase',
513
- files: [
514
- {
515
- value: 'file-key',
516
- },
517
- ],
518
- },
519
- };
520
- xcodeProject.objects.PBXBuildFile = {
521
- 'file-key': {
522
- isa: 'PBXBuildFile',
523
- fileRef: 'file-ref-key',
524
- },
525
- };
526
- xcodeProject.files = [
527
- {
528
- key: 'file-ref-key',
529
- path: 'file-path',
530
- },
531
- ];
458
+ (0, vitest_1.describe)('referenced build phase is undefined', () => {
459
+ (0, vitest_1.it)('should return empty array', () => {
460
+ // -- Arrange --
461
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
462
+ xcodeProject.objects.PBXNativeTarget = {
463
+ Project: {
464
+ isa: 'PBXNativeTarget',
465
+ name: 'Project',
466
+ buildPhases: [
467
+ {
468
+ value: 'random-build-phase',
469
+ },
470
+ ],
471
+ },
472
+ };
473
+ // -- Act --
474
+ const files = xcodeProject.getSourceFilesForTarget('Project');
475
+ // -- Assert --
476
+ (0, vitest_1.expect)(files).toEqual([]);
477
+ });
532
478
  });
533
- (0, vitest_1.describe)('build file objects are not defined', () => {
479
+ (0, vitest_1.describe)('build phase files are undefined', () => {
534
480
  (0, vitest_1.it)('should return empty array', () => {
535
481
  // -- Arrange --
536
- xcodeProject.objects.PBXBuildFile = undefined;
482
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
483
+ xcodeProject.objects.PBXNativeTarget = {
484
+ Project: {
485
+ isa: 'PBXNativeTarget',
486
+ name: 'Project',
487
+ buildPhases: [
488
+ {
489
+ value: 'build-phase-key',
490
+ },
491
+ ],
492
+ },
493
+ };
494
+ xcodeProject.objects.PBXSourcesBuildPhase = {
495
+ 'build-phase-key': {
496
+ isa: 'PBXSourcesBuildPhase',
497
+ files: undefined,
498
+ },
499
+ };
537
500
  // -- Act --
538
- const files = xcodeProject.filesForTarget('some-target');
501
+ const files = xcodeProject.getSourceFilesForTarget('Project');
539
502
  // -- Assert --
540
503
  (0, vitest_1.expect)(files).toEqual([]);
541
504
  });
542
505
  });
543
- (0, vitest_1.describe)('build file object is not found', () => {
506
+ (0, vitest_1.describe)('build phase has no files', () => {
544
507
  (0, vitest_1.it)('should return empty array', () => {
545
508
  // -- Arrange --
546
- xcodeProject.objects.PBXBuildFile = {};
509
+ const xcodeProject = new xcode_manager_1.XcodeProject(noFilesInTargetProjectPath);
547
510
  // -- Act --
548
- const files = xcodeProject.filesForTarget('some-target');
511
+ const files = xcodeProject.getSourceFilesForTarget('Project');
549
512
  // -- Assert --
550
513
  (0, vitest_1.expect)(files).toEqual([]);
551
514
  });
552
515
  });
553
- (0, vitest_1.describe)('build file object exists', () => {
554
- (0, vitest_1.describe)('file reference is undefined', () => {
555
- (0, vitest_1.it)('should ignore the file', () => {
516
+ (0, vitest_1.describe)('build phase with files', () => {
517
+ let xcodeProject;
518
+ (0, vitest_1.beforeEach)(() => {
519
+ xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
520
+ xcodeProject.objects.PBXNativeTarget = {
521
+ 'some-target': {
522
+ isa: 'PBXNativeTarget',
523
+ name: 'some-target',
524
+ buildPhases: [
525
+ {
526
+ value: 'build-phase-key',
527
+ },
528
+ ],
529
+ },
530
+ };
531
+ xcodeProject.objects.PBXSourcesBuildPhase = {
532
+ 'build-phase-key': {
533
+ isa: 'PBXSourcesBuildPhase',
534
+ files: [
535
+ {
536
+ value: 'file-key',
537
+ },
538
+ ],
539
+ },
540
+ };
541
+ xcodeProject.objects.PBXBuildFile = {
542
+ 'file-key': {
543
+ isa: 'PBXBuildFile',
544
+ fileRef: 'file-ref-key',
545
+ },
546
+ };
547
+ });
548
+ (0, vitest_1.describe)('build file objects are not defined', () => {
549
+ (0, vitest_1.it)('should return empty array', () => {
550
+ // -- Arrange --
551
+ xcodeProject.objects.PBXBuildFile = undefined;
552
+ // -- Act --
553
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
554
+ // -- Assert --
555
+ (0, vitest_1.expect)(files).toEqual([]);
556
+ });
557
+ });
558
+ (0, vitest_1.describe)('build file object is not found', () => {
559
+ (0, vitest_1.it)('should return empty array', () => {
560
+ // -- Arrange --
561
+ xcodeProject.objects.PBXBuildFile = {};
562
+ // -- Act --
563
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
564
+ // -- Assert --
565
+ (0, vitest_1.expect)(files).toEqual([]);
566
+ });
567
+ });
568
+ (0, vitest_1.describe)('build file object is invalid', () => {
569
+ (0, vitest_1.it)('should return empty array', () => {
570
+ // -- Arrange --
571
+ xcodeProject.objects.PBXBuildFile = {
572
+ 'file-key': 'invalid-object',
573
+ };
574
+ // -- Act --
575
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
576
+ // -- Assert --
577
+ (0, vitest_1.expect)(files).toEqual([]);
578
+ });
579
+ });
580
+ (0, vitest_1.describe)('file reference is missing', () => {
581
+ (0, vitest_1.it)('should return empty array', () => {
556
582
  // -- Arrange --
557
- xcodeProject.files = [];
583
+ xcodeProject.objects.PBXBuildFile = {
584
+ 'file-key': {
585
+ isa: 'PBXBuildFile',
586
+ },
587
+ };
588
+ // -- Act --
589
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
590
+ // -- Assert --
591
+ (0, vitest_1.expect)(files).toEqual([]);
592
+ });
593
+ });
594
+ (0, vitest_1.describe)('file reference is invalid', () => {
595
+ (0, vitest_1.it)('should return empty array', () => {
596
+ // -- Arrange --
597
+ xcodeProject.objects.PBXFileReference = {
598
+ 'file-ref-key': 'invalid-object',
599
+ };
600
+ // -- Act --
601
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
602
+ // -- Assert --
603
+ (0, vitest_1.expect)(files).toEqual([]);
604
+ });
605
+ });
606
+ (0, vitest_1.describe)('file reference path is missing', () => {
607
+ (0, vitest_1.it)('should return empty array', () => {
608
+ // -- Arrange --
609
+ xcodeProject.objects.PBXFileReference = {
610
+ 'file-ref-key': {
611
+ isa: 'PBXFileReference',
612
+ path: undefined,
613
+ sourceTree: 'SOURCE_ROOT',
614
+ },
615
+ };
558
616
  // -- Act --
559
- const files = xcodeProject.filesForTarget('some-target');
617
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
560
618
  // -- Assert --
561
619
  (0, vitest_1.expect)(files).toEqual([]);
562
620
  });
563
621
  });
564
- (0, vitest_1.it)('should return array of file paths', () => {
622
+ (0, vitest_1.describe)('valid file reference', () => {
623
+ (0, vitest_1.it)('should return array with file path', () => {
624
+ // -- Arrange --
625
+ xcodeProject.objects.PBXFileReference = {
626
+ 'file-ref-key': {
627
+ isa: 'PBXFileReference',
628
+ path: 'test.swift',
629
+ sourceTree: 'SOURCE_ROOT',
630
+ },
631
+ };
632
+ // -- Act --
633
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
634
+ // -- Assert --
635
+ (0, vitest_1.expect)(files).toEqual([
636
+ path.join(xcodeProject.baseDir, 'test.swift'),
637
+ ]);
638
+ });
639
+ });
640
+ });
641
+ (0, vitest_1.describe)('synchronized root groups', () => {
642
+ (0, vitest_1.it)('should handle missing fileSystemSynchronizedGroups', () => {
643
+ // -- Arrange --
644
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
645
+ xcodeProject.objects.PBXNativeTarget = {
646
+ 'some-target': {
647
+ isa: 'PBXNativeTarget',
648
+ name: 'some-target',
649
+ },
650
+ };
565
651
  // -- Act --
566
- const files = xcodeProject.filesForTarget('some-target');
652
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
567
653
  // -- Assert --
568
- (0, vitest_1.expect)(files).toEqual([
569
- path.join(appleProjectsPath, 'spm-swiftui-single-target', 'file-path'),
570
- ]);
654
+ (0, vitest_1.expect)(files).toEqual([]);
655
+ });
656
+ (0, vitest_1.it)('should handle empty fileSystemSynchronizedGroups', () => {
657
+ // -- Arrange --
658
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
659
+ xcodeProject.objects.PBXNativeTarget = {
660
+ 'some-target': {
661
+ isa: 'PBXNativeTarget',
662
+ name: 'some-target',
663
+ fileSystemSynchronizedGroups: [],
664
+ },
665
+ };
666
+ // -- Act --
667
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
668
+ // -- Assert --
669
+ (0, vitest_1.expect)(files).toEqual([]);
670
+ });
671
+ (0, vitest_1.it)('should handle invalid synchronized root group', () => {
672
+ // -- Arrange --
673
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
674
+ xcodeProject.objects.PBXNativeTarget = {
675
+ 'some-target': {
676
+ isa: 'PBXNativeTarget',
677
+ name: 'some-target',
678
+ fileSystemSynchronizedGroups: [
679
+ {
680
+ value: 'invalid-group',
681
+ },
682
+ ],
683
+ },
684
+ };
685
+ // -- Act --
686
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
687
+ // -- Assert --
688
+ (0, vitest_1.expect)(files).toEqual([]);
689
+ });
690
+ (0, vitest_1.it)('should handle synchronized root group with missing path', () => {
691
+ // -- Arrange --
692
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
693
+ xcodeProject.objects.PBXNativeTarget = {
694
+ 'some-target': {
695
+ isa: 'PBXNativeTarget',
696
+ name: 'some-target',
697
+ fileSystemSynchronizedGroups: [
698
+ {
699
+ value: 'group-key',
700
+ },
701
+ ],
702
+ },
703
+ };
704
+ xcodeProject.objects.PBXFileSystemSynchronizedRootGroup = {
705
+ 'group-key': {
706
+ isa: 'PBXFileSystemSynchronizedRootGroup',
707
+ path: undefined,
708
+ sourceTree: 'SOURCE_ROOT',
709
+ },
710
+ };
711
+ // -- Act --
712
+ const files = xcodeProject.getSourceFilesForTarget('some-target');
713
+ // -- Assert --
714
+ (0, vitest_1.expect)(files).toEqual([]);
715
+ });
716
+ (0, vitest_1.it)('should exclude files in membership exceptions', () => {
717
+ // -- Arrange --
718
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
719
+ // The subfolder 1-1-1 is a synchronized root group containing two files:
720
+ // - File-1-1-1-1.swift
721
+ // - File-1-1-1-2.swift
722
+ //
723
+ // The membership exceptions are:
724
+ // - File-1-1-1-2.swift
725
+ //
726
+ // The expected result is that File-1-1-1-1.swift is excluded from the build, but
727
+ // included due to the membership exception.
728
+ // The File-1-1-1-2.swift is excluded from the build due to the membership exception.
729
+ // Pre-condition: File-1-1-1-1.swift exists
730
+ const file1111 = path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-1', 'Subfolder 1-1-1', 'File-1-1-1-1.swift');
731
+ (0, vitest_1.expect)(fs.existsSync(file1111)).toBe(true);
732
+ // Pre-condition: File-1-1-1-2.swift exists
733
+ const file1112 = path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-1', 'Subfolder 1-1-1', 'File-1-1-1-2.swift');
734
+ (0, vitest_1.expect)(fs.existsSync(file1112)).toBe(true);
735
+ // -- Act --
736
+ const files = xcodeProject.getSourceFilesForTarget('Project');
737
+ // -- Assert --
738
+ // Known Issue:
739
+ // The file `File-1-1-1-1.swift` is included in the source build phase, but not in the list of files.
740
+ //
741
+ // This is the group structure:
742
+ // <main group> / Group 1 / Subgroup 1-1 / Subfolder 1-1-1 / File-1-1-1-1.swift
743
+ //
744
+ // - <main group> is the root group
745
+ // - Group 1 is a group
746
+ // - Subgroup 1-1 is a nested group
747
+ // - Subfolder 1-1-1 is a synchronized root group
748
+ // - File-1-1-1-1.swift is a file in the synchronized root group Subfolder 1-1-1
749
+ //
750
+ // For no apparent reason, Xcode is picking up the file, but Group 1 is not mentioned anywhere other then the main group.
751
+ // This would require us to consider every root group as a potential source of files, which seems excessive if a project has multiple targets.
752
+ // expect(files).toContain(file1111);
753
+ (0, vitest_1.expect)(files).not.toContain(file1112);
754
+ });
755
+ (0, vitest_1.it)('should return synchronized files and files in main group', () => {
756
+ // -- Arrange --
757
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
758
+ // -- Act --
759
+ const files = xcodeProject.getSourceFilesForTarget('Project');
760
+ // -- Assert --
761
+ // The order is not guaranteed, so we need to check for each file individually
762
+ // The order in this test case is the one displayed in the Xcode UI
763
+ const group1DirPath = path.join(xcodeProject.baseDir, 'Group 1');
764
+ const subgroup1_1DirPath = path.join(group1DirPath, 'Subgroup 1-1');
765
+ const subgroup1_2DirPath = path.join(group1DirPath, 'Subgroup 1-2');
766
+ const subgroup1_1_2DirPath = path.join(subgroup1_1DirPath, 'Subgroup 1-1-2');
767
+ const sourcesDirPath = path.join(xcodeProject.baseDir, 'Sources');
768
+ const subfolder1DirPath = path.join(sourcesDirPath, 'Subfolder 1');
769
+ const subfolder2DirPath = path.join(sourcesDirPath, 'Subfolder 2');
770
+ const groupRef1_3DirPath = path.join(xcodeProject.baseDir, 'Group Reference 1-3');
771
+ (0, vitest_1.expect)(files).toContain(path.join(subgroup1_2DirPath, 'File-1-2-2.swift'));
772
+ (0, vitest_1.expect)(files).toContain(path.join(subfolder1DirPath, 'ContentView.swift'));
773
+ (0, vitest_1.expect)(files).toContain(path.join(subgroup1_2DirPath, 'File-1-2-3--relative-to-group.swift'));
774
+ (0, vitest_1.expect)(files).toContain(path.join(sourcesDirPath, 'MainApp.swift'));
775
+ (0, vitest_1.expect)(files).toContain(path.join(subfolder2DirPath, 'File.swift'));
776
+ // Absolute path
777
+ (0, vitest_1.expect)(files).toContain('/System/Library/CoreServices/SystemVersion.plist');
778
+ // Path relative to the SDK
779
+ (0, vitest_1.expect)(files).toContain('/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/SDKSettings.plist');
780
+ // Path relative to the developer directory
781
+ (0, vitest_1.expect)(files).toContain('/Applications/Xcode.app/Contents/Developer/usr/bin/git');
782
+ // Path relative to the build products directory
783
+ // NOT SUPPORTED YET
784
+ // Path relative to the project
785
+ (0, vitest_1.expect)(files).toContain(path.join(subgroup1_2DirPath, 'File-1-2-1.swift'));
786
+ (0, vitest_1.expect)(files).toContain(path.join(groupRef1_3DirPath, 'File-1-3-1.swift'));
787
+ (0, vitest_1.expect)(files).toContain(path.join(subgroup1_2DirPath, 'File-1-2-3--relative-to-project.swift'));
788
+ (0, vitest_1.expect)(files).toContain(path.join(subgroup1_1_2DirPath, 'File-1-1-2-1.swift'));
789
+ // Known Issue:
790
+ // The file `File-1-1-1-1.swift` is included in the source build phase, but not in the list of files.
791
+ //
792
+ // This is the group structure:
793
+ // <main group> / Group 1 / Subgroup 1-1 / Subfolder 1-1-1 / File-1-1-1-1.swift
794
+ //
795
+ // - <main group> is the root group
796
+ // - Group 1 is a group
797
+ // - Subgroup 1-1 is a nested group
798
+ // - Subfolder 1-1-1 is a synchronized root group
799
+ // - File-1-1-1-1.swift is a file in the synchronized root group Subfolder 1-1-1
800
+ //
801
+ // For no apparent reason, Xcode is picking up the file, but Group 1 is not mentioned anywhere other then the main group.
802
+ // This would require us to consider every root group as a potential source of files, which seems excessive if a project has multiple targets.
803
+ // expect(files).toContain(
804
+ // path.join(
805
+ // xcodeProject.baseDir,
806
+ // 'Group 1',
807
+ // 'Subgroup 1-1',
808
+ // 'Subfolder 1-1-1',
809
+ // 'File-1-1-1-1.swift',
810
+ // ),
811
+ // );
812
+ // Assert that there are no other file paths in the list
813
+ (0, vitest_1.expect)(files).toHaveLength(12);
571
814
  });
572
815
  });
573
816
  });
574
- });
575
- (0, vitest_1.describe)('projectFiles', () => {
576
- (0, vitest_1.describe)('no groups in project', () => {
577
- (0, vitest_1.it)('should return empty array', () => {
578
- // -- Arrange --
579
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
580
- xcodeProject.objects.PBXGroup = undefined;
581
- // -- Act --
582
- const files = xcodeProject.projectFiles();
583
- // -- Assert --
584
- (0, vitest_1.expect)(files).toEqual([]);
585
- });
586
- });
587
- (0, vitest_1.describe)('main group not found', () => {
588
- (0, vitest_1.it)('should return empty array', () => {
589
- // -- Arrange --
590
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
591
- const project = xcodeProject.objects.PBXProject?.['D4E604C52D50CEEC00CAB00F'];
592
- if (project) {
593
- delete project.mainGroup;
594
- }
595
- // -- Act --
596
- const files = xcodeProject.projectFiles();
597
- // -- Assert --
598
- (0, vitest_1.expect)(files).toEqual([]);
817
+ (0, vitest_1.describe)('findFilesInSourceBuildPhase', () => {
818
+ (0, vitest_1.describe)('when build phase is not found', () => {
819
+ (0, vitest_1.it)('should return empty array', () => {
820
+ // -- Arrange --
821
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
822
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
823
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
824
+ nativeTarget.buildPhases = undefined;
825
+ // -- Act --
826
+ const files = xcodeProject.findFilesInSourceBuildPhase({
827
+ id: nativeTargetId,
828
+ obj: nativeTarget,
829
+ });
830
+ // -- Assert --
831
+ (0, vitest_1.expect)(files).toEqual([]);
832
+ });
599
833
  });
600
- });
601
- (0, vitest_1.describe)('main group found', () => {
602
- (0, vitest_1.it)('should return array of file paths', () => {
603
- // -- Arrange --
604
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
605
- // -- Act --
606
- const files = xcodeProject.projectFiles();
607
- // -- Assert --
608
- (0, vitest_1.expect)(files).toEqual([
609
- {
610
- key: 'D4E604CD2D50CEEC00CAB00F',
611
- path: 'Project.app',
612
- },
613
- ]);
834
+ (0, vitest_1.describe)('build phase files are undefined', () => {
835
+ (0, vitest_1.it)('should return empty array', () => {
836
+ // -- Arrange --
837
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
838
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
839
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
840
+ nativeTarget.buildPhases = [
841
+ {
842
+ value: 'build-phase-key',
843
+ },
844
+ ];
845
+ xcodeProject.objects.PBXSourcesBuildPhase = {
846
+ 'build-phase-key': {
847
+ isa: 'PBXSourcesBuildPhase',
848
+ files: undefined,
849
+ },
850
+ };
851
+ // -- Act --
852
+ const files = xcodeProject.findFilesInSourceBuildPhase({
853
+ id: nativeTargetId,
854
+ obj: nativeTarget,
855
+ });
856
+ // -- Assert --
857
+ (0, vitest_1.expect)(files).toEqual([]);
858
+ });
614
859
  });
615
- (0, vitest_1.it)('should cache the result', () => {
616
- // -- Arrange --
617
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
618
- // Smoke test
619
- (0, vitest_1.expect)(xcodeProject.files).toBeUndefined();
620
- // -- Act --
621
- const files = xcodeProject.projectFiles();
622
- // -- Assert --
623
- (0, vitest_1.expect)(xcodeProject.files).toBeDefined();
624
- (0, vitest_1.expect)(xcodeProject.files).toEqual(files);
860
+ (0, vitest_1.describe)('build phase files are empty', () => {
861
+ (0, vitest_1.it)('should return empty array', () => {
862
+ // -- Arrange --
863
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
864
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
865
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
866
+ nativeTarget.buildPhases = [
867
+ {
868
+ value: 'build-phase-key',
869
+ },
870
+ ];
871
+ xcodeProject.objects.PBXSourcesBuildPhase = {
872
+ 'build-phase-key': {
873
+ isa: 'PBXSourcesBuildPhase',
874
+ files: [],
875
+ },
876
+ };
877
+ // -- Act --
878
+ const files = xcodeProject.findFilesInSourceBuildPhase({
879
+ id: nativeTargetId,
880
+ obj: nativeTarget,
881
+ });
882
+ // -- Assert --
883
+ (0, vitest_1.expect)(files).toEqual([]);
884
+ });
625
885
  });
626
- });
627
- });
628
- (0, vitest_1.describe)('buildGroup', () => {
629
- (0, vitest_1.describe)('group has undefined children', () => {
630
- (0, vitest_1.it)('should return empty array', () => {
631
- // -- Arrange --
632
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
633
- const group = {
634
- isa: 'PBXGroup',
635
- children: undefined,
636
- path: '',
637
- };
638
- // -- Act --
639
- const files = xcodeProject.buildGroup(group);
640
- // -- Assert --
641
- (0, vitest_1.expect)(files).toEqual([]);
886
+ (0, vitest_1.describe)('build phase file is a comment', () => {
887
+ (0, vitest_1.it)('should return empty array', () => {
888
+ // -- Arrange --
889
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
890
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
891
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
892
+ nativeTarget.buildPhases = [
893
+ {
894
+ value: 'build-phase-key',
895
+ },
896
+ ];
897
+ xcodeProject.objects.PBXSourcesBuildPhase = {
898
+ 'build-phase-key': 'this is a comment',
899
+ };
900
+ // Smoke test to ensure native target is defined
901
+ (0, vitest_1.expect)(nativeTarget).toBeDefined();
902
+ // -- Act --
903
+ const files = xcodeProject.findFilesInSourceBuildPhase({
904
+ id: nativeTargetId,
905
+ obj: nativeTarget,
906
+ });
907
+ // -- Assert --
908
+ (0, vitest_1.expect)(files).toEqual([]);
909
+ });
642
910
  });
643
- });
644
- (0, vitest_1.describe)('group has no children', () => {
645
- (0, vitest_1.it)('should return empty array', () => {
646
- // -- Arrange --
647
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
648
- const group = {
649
- isa: 'PBXGroup',
650
- };
651
- // -- Act --
652
- const files = xcodeProject.buildGroup(group);
653
- // -- Assert --
654
- (0, vitest_1.expect)(files).toEqual([]);
911
+ (0, vitest_1.describe)('build phase file is not found', () => {
912
+ (0, vitest_1.it)('should return empty array', () => {
913
+ // -- Arrange --
914
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
915
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
916
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
917
+ nativeTarget.buildPhases = [
918
+ {
919
+ value: 'build-phase-key',
920
+ },
921
+ ];
922
+ xcodeProject.objects.PBXSourcesBuildPhase = {
923
+ 'build-phase-key': {
924
+ isa: 'PBXSourcesBuildPhase',
925
+ files: [],
926
+ },
927
+ };
928
+ // -- Act --
929
+ const files = xcodeProject.findFilesInSourceBuildPhase({
930
+ id: nativeTargetId,
931
+ obj: nativeTarget,
932
+ });
933
+ // -- Assert --
934
+ (0, vitest_1.expect)(files).toEqual([]);
935
+ });
655
936
  });
656
- });
657
- (0, vitest_1.describe)('group child is file reference', () => {
658
- const group = {
659
- isa: 'PBXGroup',
660
- children: [
661
- {
662
- value: 'D4E604CD2D50CEEC00CAB00F',
663
- },
664
- ],
665
- path: '',
666
- };
667
- (0, vitest_1.describe)('file references are undefined', () => {
937
+ (0, vitest_1.describe)('build phase file reference is a comment', () => {
668
938
  (0, vitest_1.it)('should return empty array', () => {
669
939
  // -- Arrange --
670
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
671
- xcodeProject.objects.PBXFileReference = undefined;
940
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
941
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
942
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
943
+ nativeTarget.buildPhases = [
944
+ {
945
+ value: 'build-phase-key',
946
+ },
947
+ ];
948
+ xcodeProject.objects.PBXSourcesBuildPhase = {
949
+ 'build-phase-key': {
950
+ isa: 'PBXSourcesBuildPhase',
951
+ files: [
952
+ {
953
+ value: 'file-key',
954
+ },
955
+ ],
956
+ },
957
+ };
958
+ xcodeProject.objects.PBXBuildFile = {
959
+ 'file-key': {
960
+ isa: 'PBXBuildFile',
961
+ fileRef: 'file-ref-key',
962
+ },
963
+ };
964
+ xcodeProject.objects.PBXFileReference = {
965
+ 'file-ref-key': 'this is a comment',
966
+ };
672
967
  // -- Act --
673
- const files = xcodeProject.buildGroup(group);
968
+ const files = xcodeProject.findFilesInSourceBuildPhase({
969
+ id: nativeTargetId,
970
+ obj: nativeTarget,
971
+ });
674
972
  // -- Assert --
675
973
  (0, vitest_1.expect)(files).toEqual([]);
676
974
  });
677
975
  });
678
- (0, vitest_1.describe)('file reference is string', () => {
976
+ (0, vitest_1.describe)('build phase file reference has no path', () => {
679
977
  (0, vitest_1.it)('should be ignored', () => {
680
978
  // -- Arrange --
681
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
682
- const group = {
683
- isa: 'PBXGroup',
684
- children: [
685
- {
686
- value: 'D4E604CD2D50CEEC00CAB00F_comment',
687
- },
688
- ],
689
- path: '',
979
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
980
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
981
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
982
+ nativeTarget.buildPhases = [
983
+ {
984
+ value: 'build-phase-key',
985
+ },
986
+ ];
987
+ xcodeProject.objects.PBXSourcesBuildPhase = {
988
+ 'build-phase-key': {
989
+ isa: 'PBXSourcesBuildPhase',
990
+ files: [
991
+ {
992
+ value: 'file-key',
993
+ },
994
+ ],
995
+ },
996
+ };
997
+ xcodeProject.objects.PBXBuildFile = {
998
+ 'file-key': {
999
+ isa: 'PBXBuildFile',
1000
+ fileRef: 'file-ref-key',
1001
+ },
1002
+ };
1003
+ xcodeProject.objects.PBXFileReference = {
1004
+ 'file-ref-key': {
1005
+ isa: 'PBXFileReference',
1006
+ path: undefined,
1007
+ sourceTree: 'SOURCE_ROOT',
1008
+ },
690
1009
  };
691
1010
  // -- Act --
692
- const files = xcodeProject.buildGroup(group);
1011
+ const files = xcodeProject.findFilesInSourceBuildPhase({
1012
+ id: nativeTargetId,
1013
+ obj: nativeTarget,
1014
+ });
693
1015
  // -- Assert --
694
1016
  (0, vitest_1.expect)(files).toEqual([]);
695
1017
  });
696
1018
  });
697
- (0, vitest_1.describe)('file reference is valid', () => {
698
- (0, vitest_1.it)('should return array of escaped paths', () => {
1019
+ (0, vitest_1.describe)('when file reference path contains doublequotes', () => {
1020
+ (0, vitest_1.it)('should be removed', () => {
699
1021
  // -- Arrange --
700
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
1022
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
1023
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1024
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1025
+ nativeTarget.buildPhases = [
1026
+ {
1027
+ value: 'build-phase-key',
1028
+ },
1029
+ ];
1030
+ xcodeProject.objects.PBXSourcesBuildPhase = {
1031
+ 'build-phase-key': {
1032
+ isa: 'PBXSourcesBuildPhase',
1033
+ files: [
1034
+ {
1035
+ value: 'file-key',
1036
+ },
1037
+ ],
1038
+ },
1039
+ };
1040
+ xcodeProject.objects.PBXBuildFile = {
1041
+ 'file-key': {
1042
+ isa: 'PBXBuildFile',
1043
+ fileRef: 'file-ref-key',
1044
+ },
1045
+ };
701
1046
  xcodeProject.objects.PBXFileReference = {
702
- D4E604CD2D50CEEC00CAB00F: {
1047
+ 'file-ref-key': {
703
1048
  isa: 'PBXFileReference',
704
- path: '"some/path/to/file.swift"',
1049
+ path: '"path/with/quotes.swift"',
705
1050
  sourceTree: 'SOURCE_ROOT',
706
1051
  },
707
1052
  };
708
- const group = {
709
- isa: 'PBXGroup',
710
- children: [
711
- {
712
- value: 'D4E604CD2D50CEEC00CAB00F',
713
- },
714
- ],
715
- path: '',
716
- };
717
1053
  // -- Act --
718
- const files = xcodeProject.buildGroup(group);
1054
+ const files = xcodeProject.findFilesInSourceBuildPhase({
1055
+ id: nativeTargetId,
1056
+ obj: nativeTarget,
1057
+ });
719
1058
  // -- Assert --
720
1059
  (0, vitest_1.expect)(files).toEqual([
721
- {
722
- key: 'D4E604CD2D50CEEC00CAB00F',
723
- path: 'some/path/to/file.swift',
724
- },
1060
+ path.join(xcodeProject.baseDir, 'path/with/quotes.swift'),
725
1061
  ]);
726
1062
  });
727
1063
  });
1064
+ (0, vitest_1.it)('should return all files in build phase', () => {
1065
+ // -- Arrange --
1066
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
1067
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1068
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1069
+ // -- Act --
1070
+ const files = xcodeProject.findFilesInSourceBuildPhase({
1071
+ id: nativeTargetId,
1072
+ obj: nativeTarget,
1073
+ });
1074
+ // -- Assert --
1075
+ // The list should reflect exactly the list of `files` in the `PBXSourcesBuildPhase` in the project.pbxproj file
1076
+ (0, vitest_1.expect)(files).toEqual([
1077
+ // Absolute paths
1078
+ '/System/Library/CoreServices/SystemVersion.plist',
1079
+ // Path relative to the build directory
1080
+ // NOT SUPPORTED YET
1081
+ // Path relative to the SDK
1082
+ '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/SDKSettings.plist',
1083
+ // Path relative to the developer directory
1084
+ '/Applications/Xcode.app/Contents/Developer/usr/bin/git',
1085
+ path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-2', 'File-1-2-2.swift'),
1086
+ path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-2', 'File-1-2-3--relative-to-group.swift'),
1087
+ path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-2', 'File-1-2-1.swift'),
1088
+ path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-1', 'Subgroup 1-1-2', 'File-1-1-2-1.swift'),
1089
+ path.join(xcodeProject.baseDir, 'Group Reference 1-3', 'File-1-3-1.swift'),
1090
+ path.join(xcodeProject.baseDir, 'Group 1', 'Subgroup 1-2', 'File-1-2-3--relative-to-project.swift'),
1091
+ ]);
1092
+ });
728
1093
  });
729
- (0, vitest_1.describe)('group child is group reference', () => {
730
- const group = {
731
- isa: 'PBXGroup',
732
- children: [
733
- {
734
- value: 'D4E604C42D50CEEC00CAB00F',
735
- },
736
- ],
737
- path: '',
738
- };
739
- (0, vitest_1.describe)('groups are undefined', () => {
740
- (0, vitest_1.it)('should return empty array', () => {
1094
+ (0, vitest_1.describe)('findSourceBuildPhaseInTarget', () => {
1095
+ (0, vitest_1.describe)('when build phases are undefined', () => {
1096
+ (0, vitest_1.it)('should return undefined', () => {
741
1097
  // -- Arrange --
742
1098
  const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
743
- xcodeProject.objects.PBXGroup = undefined;
1099
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1100
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1101
+ nativeTarget.buildPhases = undefined;
744
1102
  // -- Act --
745
- const files = xcodeProject.buildGroup(group);
1103
+ const buildPhase = xcodeProject.findSourceBuildPhaseInTarget(nativeTarget);
746
1104
  // -- Assert --
747
- (0, vitest_1.expect)(files).toEqual([]);
1105
+ (0, vitest_1.expect)(buildPhase).toBeUndefined();
748
1106
  });
749
1107
  });
750
- (0, vitest_1.describe)('group reference is string', () => {
751
- (0, vitest_1.it)('should return array of file paths', () => {
1108
+ (0, vitest_1.describe)('when build phases are empty', () => {
1109
+ (0, vitest_1.it)('should return undefined', () => {
752
1110
  // -- Arrange --
753
1111
  const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
754
- const group = {
755
- isa: 'PBXGroup',
756
- children: [
757
- {
758
- value: 'D4E604CE2D50CEEC00CAB00F_comment',
759
- },
760
- ],
761
- path: '',
762
- };
1112
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1113
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1114
+ nativeTarget.buildPhases = [];
763
1115
  // -- Act --
764
- const files = xcodeProject.buildGroup(group);
1116
+ const buildPhase = xcodeProject.findSourceBuildPhaseInTarget(nativeTarget);
765
1117
  // -- Assert --
766
- (0, vitest_1.expect)(files).toEqual([]);
1118
+ (0, vitest_1.expect)(buildPhase).toBeUndefined();
767
1119
  });
768
1120
  });
769
- (0, vitest_1.describe)('group reference is valid', () => {
770
- (0, vitest_1.it)('should return array of file paths', () => {
1121
+ (0, vitest_1.describe)('when referenced build phase is not found', () => {
1122
+ (0, vitest_1.it)('should ignore it', () => {
771
1123
  // -- Arrange --
772
1124
  const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
773
- // -- Act --
774
- const files = xcodeProject.buildGroup(group);
775
- // -- Assert --
776
- (0, vitest_1.expect)(files).toEqual([
1125
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1126
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1127
+ nativeTarget.buildPhases = [
777
1128
  {
778
- key: 'D4E604CD2D50CEEC00CAB00F',
779
- path: 'Project.app',
1129
+ value: 'build-phase-key',
780
1130
  },
781
- ]);
1131
+ ];
1132
+ xcodeProject.objects.PBXSourcesBuildPhase = {};
1133
+ // -- Act --
1134
+ const buildPhase = xcodeProject.findSourceBuildPhaseInTarget(nativeTarget);
1135
+ // -- Assert --
1136
+ (0, vitest_1.expect)(buildPhase).toBeUndefined();
782
1137
  });
783
1138
  });
784
- (0, vitest_1.describe)('group reference has path', () => {
785
- (0, vitest_1.it)('should append the path to the file paths', () => {
1139
+ (0, vitest_1.describe)('when referenced build phase is found', () => {
1140
+ (0, vitest_1.it)('should return the build phase', () => {
786
1141
  // -- Arrange --
787
1142
  const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
788
- const group = {
789
- isa: 'PBXGroup',
790
- children: [
791
- {
792
- value: 'sub-group',
793
- },
794
- ],
795
- path: '"some/path/to/group"',
796
- };
797
- const subgroup = {
798
- isa: 'PBXGroup',
799
- children: [
800
- {
801
- value: 'file-at-path',
802
- },
803
- ],
804
- };
805
- const file = {
806
- isa: 'PBXFileReference',
807
- path: '"some/file/at/path.swift"',
808
- sourceTree: '<group>',
809
- };
810
- xcodeProject.objects.PBXGroup = {
811
- 'main-group': group,
812
- 'sub-group': subgroup,
813
- };
814
- xcodeProject.objects.PBXFileReference = {
815
- 'file-at-path': file,
816
- };
1143
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1144
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
817
1145
  // -- Act --
818
- const files = xcodeProject.buildGroup(group);
1146
+ const buildPhase = xcodeProject.findSourceBuildPhaseInTarget(nativeTarget);
819
1147
  // -- Assert --
820
- (0, vitest_1.expect)(files).toEqual([
821
- {
822
- key: 'file-at-path',
823
- path: 'some/file/at/path.swift',
1148
+ (0, vitest_1.expect)(buildPhase).toEqual({
1149
+ id: 'D4E604C92D50CEEC00CAB00F',
1150
+ obj: {
1151
+ isa: 'PBXSourcesBuildPhase',
1152
+ files: [],
1153
+ buildActionMask: 2147483647,
1154
+ runOnlyForDeploymentPostprocessing: 0,
824
1155
  },
825
- ]);
1156
+ });
826
1157
  });
827
1158
  });
828
1159
  });
829
- (0, vitest_1.describe)('group child is not a file reference or group', () => {
830
- (0, vitest_1.it)('should be ignored', () => {
831
- // -- Arrange --
832
- const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
833
- xcodeProject.objects.PBXGroup = {};
834
- xcodeProject.objects.PBXFileReference = {};
835
- const group = {
836
- isa: 'PBXGroup',
837
- children: [
1160
+ (0, vitest_1.describe)('findFilesInSynchronizedRootGroups', () => {
1161
+ (0, vitest_1.describe)('when synchronized root groups are undefined', () => {
1162
+ (0, vitest_1.it)('should return empty array', () => {
1163
+ // -- Arrange --
1164
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
1165
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1166
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1167
+ nativeTarget.fileSystemSynchronizedGroups = undefined;
1168
+ // -- Act --
1169
+ const files = xcodeProject.findFilesInSynchronizedRootGroups({
1170
+ id: nativeTargetId,
1171
+ obj: nativeTarget,
1172
+ });
1173
+ // -- Assert --
1174
+ (0, vitest_1.expect)(files).toEqual([]);
1175
+ });
1176
+ });
1177
+ (0, vitest_1.describe)('when synchronized root groups are empty', () => {
1178
+ (0, vitest_1.it)('should return empty array', () => {
1179
+ // -- Arrange --
1180
+ const xcodeProject = new xcode_manager_1.XcodeProject(singleTargetProjectPath);
1181
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1182
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1183
+ nativeTarget.fileSystemSynchronizedGroups = [];
1184
+ // -- Act --
1185
+ const files = xcodeProject.findFilesInSynchronizedRootGroups({
1186
+ id: nativeTargetId,
1187
+ obj: nativeTarget,
1188
+ });
1189
+ // -- Assert --
1190
+ (0, vitest_1.expect)(files).toEqual([]);
1191
+ });
1192
+ });
1193
+ (0, vitest_1.describe)('when synchronized root groups are not found', () => {
1194
+ (0, vitest_1.it)('should ignore files in them', () => {
1195
+ // -- Arrange --
1196
+ const xcodeProject = new xcode_manager_1.XcodeProject(projectWithSynchronizedFolders);
1197
+ const nativeTargetId = 'D4E604CC2D50CEEC00CAB00F';
1198
+ const nativeTarget = xcodeProject.objects.PBXNativeTarget?.[nativeTargetId];
1199
+ // Add an invalid group reference to the native target
1200
+ nativeTarget.fileSystemSynchronizedGroups = [
1201
+ ...(nativeTarget.fileSystemSynchronizedGroups || []),
838
1202
  {
839
- value: 'random-key',
1203
+ value: 'invalid-group-key',
840
1204
  },
841
- ],
842
- path: '',
843
- };
844
- // -- Act --
845
- const files = xcodeProject.buildGroup(group);
846
- // -- Assert --
847
- (0, vitest_1.expect)(files).toEqual([]);
1205
+ ];
1206
+ // -- Act --
1207
+ const files = xcodeProject.findFilesInSynchronizedRootGroups({
1208
+ id: nativeTargetId,
1209
+ obj: nativeTarget,
1210
+ });
1211
+ // -- Assert --
1212
+ (0, vitest_1.expect)(files).not.toContain(path.join(xcodeProject.baseDir, 'Sources', 'Subfolder 1', 'Excluded-File.swift'));
1213
+ });
848
1214
  });
849
1215
  });
850
1216
  });