shakapacker 7.2.3 → 8.0.0.pre.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -1
  3. data/.eslintrc.js +29 -8
  4. data/.github/PULL_REQUEST_TEMPLATE.md +10 -3
  5. data/.github/workflows/dummy.yml +5 -1
  6. data/.github/workflows/generator.yml +13 -18
  7. data/.github/workflows/node.yml +56 -0
  8. data/.github/workflows/ruby.yml +28 -17
  9. data/.rubocop.yml +1 -0
  10. data/CHANGELOG.md +52 -1
  11. data/README.md +88 -50
  12. data/Rakefile +1 -7
  13. data/docs/customizing_babel_config.md +2 -2
  14. data/docs/deployment.md +13 -6
  15. data/docs/react.md +6 -12
  16. data/docs/troubleshooting.md +4 -4
  17. data/docs/using_esbuild_loader.md +1 -1
  18. data/docs/using_swc_loader.md +1 -1
  19. data/docs/v8_upgrade.md +148 -0
  20. data/gemfiles/Gemfile-rails.7.1.x +12 -0
  21. data/jest.config.js +4 -0
  22. data/lib/install/config/shakapacker.yml +2 -2
  23. data/lib/install/template.rb +36 -30
  24. data/lib/shakapacker/base_strategy.rb +2 -1
  25. data/lib/shakapacker/compiler.rb +5 -20
  26. data/lib/shakapacker/configuration.rb +2 -46
  27. data/lib/shakapacker/deprecation_helper.rb +0 -78
  28. data/lib/shakapacker/dev_server.rb +1 -16
  29. data/lib/shakapacker/dev_server_runner.rb +2 -21
  30. data/lib/shakapacker/env.rb +1 -1
  31. data/lib/shakapacker/instance.rb +1 -3
  32. data/lib/shakapacker/manifest.rb +1 -1
  33. data/lib/shakapacker/railtie.rb +7 -0
  34. data/lib/shakapacker/runner.rb +4 -18
  35. data/lib/shakapacker/utils/manager.rb +58 -0
  36. data/lib/shakapacker/utils/misc.rb +0 -12
  37. data/lib/shakapacker/version.rb +1 -1
  38. data/lib/shakapacker/version_checker.rb +9 -30
  39. data/lib/shakapacker/webpack_runner.rb +2 -21
  40. data/lib/shakapacker.rb +0 -2
  41. data/lib/tasks/shakapacker/check_binstubs.rake +12 -26
  42. data/lib/tasks/shakapacker/check_manager.rake +3 -8
  43. data/lib/tasks/shakapacker/info.rake +6 -15
  44. data/package/babel/preset.js +15 -15
  45. data/package/config.js +15 -17
  46. data/package/dev_server.js +4 -4
  47. data/package/env.js +19 -17
  48. data/package/environments/base.js +41 -24
  49. data/package/environments/development.js +6 -6
  50. data/package/environments/production.js +16 -16
  51. data/package/environments/test.js +1 -1
  52. data/package/esbuild/index.js +6 -6
  53. data/package/index.d.ts +0 -1
  54. data/package/index.js +17 -46
  55. data/package/rules/babel.js +6 -8
  56. data/package/rules/coffee.js +2 -2
  57. data/package/rules/css.js +1 -1
  58. data/package/rules/erb.js +4 -4
  59. data/package/rules/esbuild.js +5 -7
  60. data/package/rules/file.js +17 -7
  61. data/package/rules/index.js +11 -11
  62. data/package/rules/jscommon.js +5 -5
  63. data/package/rules/less.js +6 -6
  64. data/package/rules/raw.js +1 -1
  65. data/package/rules/sass.js +4 -4
  66. data/package/rules/stylus.js +6 -6
  67. data/package/rules/swc.js +5 -7
  68. data/package/swc/index.js +10 -10
  69. data/package/utils/configPath.js +3 -18
  70. data/package/utils/defaultConfigPath.js +1 -1
  71. data/package/utils/{get_style_rule.js → getStyleRule.js} +6 -6
  72. data/package/utils/helpers.js +2 -43
  73. data/package/utils/inliningCss.js +4 -3
  74. data/package/utils/snakeToCamelCase.js +5 -0
  75. data/package/webpackDevServerConfig.js +28 -25
  76. data/package.json +11 -17
  77. data/prettier.config.js +4 -0
  78. data/shakapacker.gemspec +1 -1
  79. data/spec/dummy/app/javascript/packs/application.js +1 -1
  80. data/spec/dummy/config/application.rb +3 -0
  81. data/spec/dummy/config/initializers/react_on_rails.rb +2 -2
  82. data/spec/dummy/config/shakapacker.yml +3 -4
  83. data/spec/dummy/config/webpack/commonWebpackConfig.js +0 -1
  84. data/spec/dummy/config/webpack/webpack.config.js +1 -1
  85. data/spec/dummy/package.json +2 -1
  86. data/spec/dummy/yarn.lock +2 -3
  87. data/spec/generator_specs/e2e_template/template.rb +15 -28
  88. data/spec/generator_specs/generator_spec.rb +6 -136
  89. data/spec/mounted_app/test/dummy/config/webpacker.yml +0 -1
  90. data/spec/shakapacker/compiler_spec.rb +1 -3
  91. data/spec/shakapacker/configuration_spec.rb +4 -56
  92. data/spec/shakapacker/dev_server_runner_spec.rb +19 -102
  93. data/spec/shakapacker/dev_server_spec.rb +1 -16
  94. data/spec/shakapacker/engine_rake_tasks_spec.rb +1 -16
  95. data/spec/shakapacker/instance_spec.rb +1 -3
  96. data/spec/shakapacker/rake_tasks_spec.rb +2 -14
  97. data/spec/shakapacker/shakapacker_spec.rb +0 -1
  98. data/spec/shakapacker/test_app/config/shakapacker_css_extract_ignore_order_warnings.yml +0 -1
  99. data/spec/shakapacker/test_app/config/shakapacker_manifest_path.yml +0 -1
  100. data/spec/shakapacker/test_app/config/shakapacker_nested_entries.yml +0 -1
  101. data/spec/shakapacker/test_app/config/shakapacker_other_location.yml +0 -1
  102. data/spec/shakapacker/test_app/package.json +2 -1
  103. data/spec/shakapacker/utils_manager_spec.rb +125 -0
  104. data/spec/shakapacker/version_checker_spec.rb +4 -4
  105. data/spec/shakapacker/webpack_runner_spec.rb +19 -28
  106. data/spec/support/package_json_helpers.rb +7 -4
  107. data/test/helpers.js +67 -0
  108. data/test/package/config.test.js +50 -0
  109. data/test/package/dev_server.test.js +44 -0
  110. data/test/package/development.test.js +43 -0
  111. data/test/package/env.test.js +57 -0
  112. data/test/package/environments/base.test.js +105 -0
  113. data/test/package/environments/development.test.js +50 -0
  114. data/test/package/environments/production.test.js +106 -0
  115. data/test/package/index.test.js +45 -0
  116. data/test/package/production.test.js +32 -0
  117. data/test/package/rules/babel.test.js +58 -0
  118. data/test/package/rules/esbuild.test.js +59 -0
  119. data/test/package/rules/file.test.js +81 -0
  120. data/test/package/rules/index.test.js +7 -0
  121. data/test/package/rules/raw.test.js +12 -0
  122. data/test/package/rules/swc.test.js +59 -0
  123. data/test/package/staging.test.js +31 -0
  124. data/test/package/test.test.js +28 -0
  125. data/yarn.lock +1278 -421
  126. metadata +52 -102
  127. data/.github/workflows/jest.yml +0 -34
  128. data/.github/workflows/js-lint.yml +0 -34
  129. data/.github/workflows/rubocop.yml +0 -29
  130. data/.github/workflows/ruby-backward-compatibility.yml +0 -52
  131. data/lib/install/package.json +0 -15
  132. data/lib/tasks/shakapacker/check_yarn.rake +0 -34
  133. data/lib/tasks/shakapacker/yarn_install.rake +0 -24
  134. data/lib/tasks/webpacker/binstubs.rake +0 -9
  135. data/lib/tasks/webpacker/check_binstubs.rake +0 -9
  136. data/lib/tasks/webpacker/check_node.rake +0 -9
  137. data/lib/tasks/webpacker/check_yarn.rake +0 -9
  138. data/lib/tasks/webpacker/clean.rake +0 -9
  139. data/lib/tasks/webpacker/clobber.rake +0 -11
  140. data/lib/tasks/webpacker/compile.rake +0 -9
  141. data/lib/tasks/webpacker/info.rake +0 -9
  142. data/lib/tasks/webpacker/install.rake +0 -9
  143. data/lib/tasks/webpacker/verify_config.rake +0 -9
  144. data/lib/tasks/webpacker/verify_install.rake +0 -9
  145. data/lib/tasks/webpacker/yarn_install.rake +0 -9
  146. data/lib/tasks/webpacker.rake +0 -20
  147. data/lib/webpacker/dev_server_runner.rb +0 -9
  148. data/lib/webpacker/webpack_runner.rb +0 -9
  149. data/lib/webpacker.rb +0 -4
  150. data/package/__tests__/config-bc.js +0 -27
  151. data/package/__tests__/config.js +0 -46
  152. data/package/__tests__/dev_server-bc.js +0 -46
  153. data/package/__tests__/dev_server.js +0 -46
  154. data/package/__tests__/development-bc.js +0 -66
  155. data/package/__tests__/development.js +0 -66
  156. data/package/__tests__/env-bc.js +0 -59
  157. data/package/__tests__/env.js +0 -59
  158. data/package/__tests__/index-bc.js +0 -22
  159. data/package/__tests__/index.js +0 -46
  160. data/package/__tests__/production-bc.js +0 -51
  161. data/package/__tests__/production.js +0 -51
  162. data/package/__tests__/staging-bc.js +0 -53
  163. data/package/__tests__/staging.js +0 -53
  164. data/package/__tests__/test-bc.js +0 -43
  165. data/package/__tests__/test.js +0 -43
  166. data/package/environments/__tests__/base-bc.js +0 -107
  167. data/package/environments/__tests__/base.js +0 -107
  168. data/package/environments/__tests__/development.js +0 -53
  169. data/package/environments/__tests__/production.js +0 -92
  170. data/package/rules/__tests__/__utils__/webpack.js +0 -50
  171. data/package/rules/__tests__/babel.js +0 -63
  172. data/package/rules/__tests__/esbuild.js +0 -64
  173. data/package/rules/__tests__/file.js +0 -62
  174. data/package/rules/__tests__/index.js +0 -7
  175. data/package/rules/__tests__/raw.js +0 -18
  176. data/package/rules/__tests__/swc.js +0 -63
  177. data/package/utils/snakeToCamelCase +0 -7
  178. data/spec/backward_compatibility_specs/command_spec.rb +0 -116
  179. data/spec/backward_compatibility_specs/compiler_spec.rb +0 -59
  180. data/spec/backward_compatibility_specs/compiler_strategy_spec.rb +0 -24
  181. data/spec/backward_compatibility_specs/configuration_spec.rb +0 -294
  182. data/spec/backward_compatibility_specs/dev_server_runner_spec.rb +0 -206
  183. data/spec/backward_compatibility_specs/dev_server_spec.rb +0 -47
  184. data/spec/backward_compatibility_specs/digest_strategy_spec.rb +0 -38
  185. data/spec/backward_compatibility_specs/engine_rake_tasks_spec.rb +0 -67
  186. data/spec/backward_compatibility_specs/env_spec.rb +0 -23
  187. data/spec/backward_compatibility_specs/helper_spec.rb +0 -243
  188. data/spec/backward_compatibility_specs/instance_spec.rb +0 -31
  189. data/spec/backward_compatibility_specs/manifest_spec.rb +0 -100
  190. data/spec/backward_compatibility_specs/mtime_strategy_spec.rb +0 -55
  191. data/spec/backward_compatibility_specs/rake_tasks_spec.rb +0 -41
  192. data/spec/backward_compatibility_specs/spec_helper_initializer.rb +0 -24
  193. data/spec/backward_compatibility_specs/webpack_runner_spec.rb +0 -86
  194. data/spec/backward_compatibility_specs/webpacker_spec.rb +0 -41
  195. data/spec/backward_compatibility_specs/webpacker_test_app/.gitignore +0 -2
  196. data/spec/backward_compatibility_specs/webpacker_test_app/Rakefile +0 -3
  197. data/spec/backward_compatibility_specs/webpacker_test_app/app/packs/entrypoints/application.js +0 -10
  198. data/spec/backward_compatibility_specs/webpacker_test_app/app/packs/entrypoints/generated/something.js +0 -2
  199. data/spec/backward_compatibility_specs/webpacker_test_app/app/packs/entrypoints/multi_entry.css +0 -4
  200. data/spec/backward_compatibility_specs/webpacker_test_app/app/packs/entrypoints/multi_entry.js +0 -4
  201. data/spec/backward_compatibility_specs/webpacker_test_app/bin/webpacker +0 -13
  202. data/spec/backward_compatibility_specs/webpacker_test_app/bin/webpacker-dev-server +0 -13
  203. data/spec/backward_compatibility_specs/webpacker_test_app/config/application.rb +0 -11
  204. data/spec/backward_compatibility_specs/webpacker_test_app/config/environment.rb +0 -4
  205. data/spec/backward_compatibility_specs/webpacker_test_app/config/initializers/inspect_autoload_paths.rb +0 -1
  206. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpack/webpack.config.js +0 -0
  207. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker.yml +0 -83
  208. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_css_extract_ignore_order_warnings.yml +0 -84
  209. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_defaults_fallback.yml +0 -11
  210. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_manifest_path.yml +0 -80
  211. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_nested_entries.yml +0 -83
  212. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_no_precompile.yml +0 -7
  213. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_other_location.yml +0 -85
  214. data/spec/backward_compatibility_specs/webpacker_test_app/config/webpacker_public_root.yml +0 -18
  215. data/spec/backward_compatibility_specs/webpacker_test_app/config.ru +0 -5
  216. data/spec/backward_compatibility_specs/webpacker_test_app/package.json +0 -13
  217. data/spec/backward_compatibility_specs/webpacker_test_app/public/packs/manifest.json +0 -58
  218. data/spec/backward_compatibility_specs/webpacker_test_app/some.config.js +0 -0
  219. data/spec/backward_compatibility_specs/webpacker_test_app/tmp/shakapacker/last-compilation-digest-production +0 -1
  220. data/spec/backward_compatibility_specs/webpacker_test_app/yarn.lock +0 -11
@@ -0,0 +1,125 @@
1
+ require_relative "spec_helper_initializer"
2
+ require "shakapacker/utils/manager"
3
+
4
+ Struct.new("Status", :exit_code) do
5
+ def success?
6
+ exit_code.zero?
7
+ end
8
+
9
+ def exitstatus
10
+ exit_code
11
+ end
12
+ end
13
+
14
+ describe "Shakapacker::Utils::Manager" do
15
+ around do |example|
16
+ within_temp_directory { example.run }
17
+ end
18
+
19
+ describe "~error_unless_package_manager_is_obvious!" do
20
+ before do
21
+ allow(Shakapacker).to receive(:puts_deprecation_message)
22
+ end
23
+
24
+ context "when 'packageManager' is set in the package.json" do
25
+ before do
26
+ File.write("package.json", { "packageManager" => "pnpm" }.to_json)
27
+ end
28
+
29
+ it "does nothing" do
30
+ Shakapacker::Utils::Manager.error_unless_package_manager_is_obvious!
31
+
32
+ expect(Shakapacker).not_to have_received(:puts_deprecation_message)
33
+ end
34
+ end
35
+
36
+ context "when the guessed manager is npm" do
37
+ it "does nothing" do
38
+ File.write("package.json", {}.to_json)
39
+ FileUtils.touch("package-lock.json")
40
+
41
+ Shakapacker::Utils::Manager.error_unless_package_manager_is_obvious!
42
+
43
+ expect(Shakapacker).not_to have_received(:puts_deprecation_message)
44
+ end
45
+ end
46
+
47
+ Shakapacker::Utils::Manager::MANAGER_LOCKS.reject { |manager| manager == "npm" }.each do |manager, lock|
48
+ context "when there is a #{lock}" do
49
+ before do
50
+ allow(Open3).to receive(:capture3).and_return(["1.2.3\n", "", Struct::Status.new(0)])
51
+ end
52
+
53
+ it "raises an error about setting 'packageManager' for #{manager}" do
54
+ File.write("package.json", {}.to_json)
55
+ FileUtils.touch(lock)
56
+
57
+ expect { Shakapacker::Utils::Manager.error_unless_package_manager_is_obvious! }.to raise_error(Shakapacker::Utils::Manager::Error, <<~MSG)
58
+ You don't have "packageManager" set in your package.json
59
+ meaning that Shakapacker will use npm but you've got a #{lock}
60
+ file meaning you probably want to be using #{manager} instead.
61
+
62
+ To make this happen, set "packageManager" in your package.json to #{manager}@1.2.3
63
+ MSG
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "~guess_binary" do
70
+ Shakapacker::Utils::Manager::MANAGER_LOCKS.each do |manager, lock|
71
+ context "when a #{lock} exists" do
72
+ before { FileUtils.touch(lock) }
73
+
74
+ it "guesses #{manager}" do
75
+ expect(Shakapacker::Utils::Manager.guess_binary).to eq manager
76
+ end
77
+ end
78
+ end
79
+
80
+ context "when there is no lockfile" do
81
+ it "returns npm" do
82
+ expect(Shakapacker::Utils::Manager.guess_binary).to eq "npm"
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "~guess_version" do
88
+ before do
89
+ allow(Open3).to receive(:capture3).and_return(["1.2.3\n", "", Struct::Status.new(0)])
90
+ end
91
+
92
+ Shakapacker::Utils::Manager::MANAGER_LOCKS.each do |manager, lock|
93
+ context "when a #{lock} exists" do
94
+ before { FileUtils.touch(lock) }
95
+
96
+ it "calls #{manager} with --version" do
97
+ Shakapacker::Utils::Manager.guess_version
98
+
99
+ expect(Open3).to have_received(:capture3).with("#{manager} --version")
100
+ end
101
+ end
102
+ end
103
+
104
+ it "returns the output without a trailing newline" do
105
+ FileUtils.touch("package-lock.json")
106
+
107
+ expect(Shakapacker::Utils::Manager.guess_version).to eq("1.2.3")
108
+ end
109
+
110
+ context "when the command errors" do
111
+ before do
112
+ allow(Open3).to receive(:capture3).and_return(["", "oh noes!", Struct::Status.new(1)])
113
+ end
114
+
115
+ it "raises an error" do
116
+ FileUtils.touch("package-lock.json")
117
+
118
+ expect { Shakapacker::Utils::Manager.guess_version }.to raise_error(
119
+ Shakapacker::Utils::Manager::Error,
120
+ "npm --version failed with exit code 1: oh noes!"
121
+ )
122
+ end
123
+ end
124
+ end
125
+ end
@@ -29,19 +29,19 @@ describe "VersionChecker" do
29
29
  version_checker.raise_if_gem_and_node_package_versions_differ
30
30
  end
31
31
 
32
- it "prints error in stderr if consistency check is disabled and version mismatch" do
32
+ it "does nothing if consistency check is disabled and version mismatch" do
33
33
  node_package_version = NodePackageVersionDouble.new(raw: "6.1.0", major_minor_patch: ["6", "1", "0"])
34
34
 
35
35
  expect { check_version(node_package_version, "6.0.0", false) }
36
- .to output(/Shakapacker::VersionChecker - Version mismatch/)
36
+ .not_to output
37
37
  .to_stderr
38
38
  end
39
39
 
40
- it "prints error in stderr if consistency check is disabled and we have semver" do
40
+ it "does nothing if consistency check is disabled and we have semver" do
41
41
  node_package_version = NodePackageVersionDouble.new(raw: "^6.1.0", major_minor_patch: ["6", "1", "0"], semver_wildcard: true)
42
42
 
43
43
  expect { check_version(node_package_version, "6.0.0", false) }
44
- .to output(/Shakapacker::VersionChecker - Semver wildcard without a lockfile detected/)
44
+ .not_to output
45
45
  .to_stderr
46
46
  end
47
47
 
@@ -2,6 +2,13 @@ require_relative "spec_helper_initializer"
2
2
  require "shakapacker/webpack_runner"
3
3
 
4
4
  describe "WebpackRunner" do
5
+ around do |example|
6
+ within_temp_directory do
7
+ FileUtils.cp_r(File.expand_path("./test_app", __dir__), Dir.pwd)
8
+ Dir.chdir("test_app") { example.run }
9
+ end
10
+ end
11
+
5
12
  before :all do
6
13
  @original_node_env, ENV["NODE_ENV"] = ENV["NODE_ENV"], "development"
7
14
  @original_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "development"
@@ -12,15 +19,21 @@ describe "WebpackRunner" do
12
19
  ENV["RAILS_ENV"] = @original_rails_env
13
20
  end
14
21
 
15
- let(:test_app_path) { File.expand_path("./test_app", __dir__) }
22
+ let(:test_app_path) { Dir.pwd }
16
23
 
17
24
  NODE_PACKAGE_MANAGERS.each do |fallback_manager|
18
25
  context "when using package_json with #{fallback_manager} as the manager" do
19
- with_use_package_json_gem(enabled: true, fallback_manager: fallback_manager)
26
+ before do
27
+ manager_name = fallback_manager.split("_")[0]
28
+ manager_version = "1.2.3"
29
+ manager_version = "4.5.6" if fallback_manager == "yarn_berry"
20
30
 
21
- let(:package_json) { PackageJson.read(test_app_path) }
31
+ PackageJson.read.merge! { { "packageManager" => "#{manager_name}@#{manager_version}" } }
22
32
 
23
- require "package_json"
33
+ allow(Shakapacker::Utils::Manager).to receive(:error_unless_package_manager_is_obvious!)
34
+ end
35
+
36
+ let(:package_json) { PackageJson.read(test_app_path) }
24
37
 
25
38
  it "uses the expected package manager", unless: fallback_manager == "yarn_classic" do
26
39
  cmd = package_json.manager.native_exec_command("webpack", ["--config", "#{test_app_path}/config/webpack/webpack.config.js"])
@@ -44,42 +57,20 @@ describe "WebpackRunner" do
44
57
  end
45
58
  end
46
59
 
47
- context "when not using package_json" do
48
- with_use_package_json_gem(enabled: false)
49
-
50
- it "supports running via node_modules" do
51
- cmd = ["#{test_app_path}/node_modules/.bin/webpack", "--config", "#{test_app_path}/config/webpack/webpack.config.js"]
52
-
53
- verify_command(cmd, use_node_modules: true)
54
- end
55
-
56
- it "supports running via yarn" do
57
- cmd = ["yarn", "webpack", "--config", "#{test_app_path}/config/webpack/webpack.config.js"]
58
-
59
- verify_command(cmd, use_node_modules: false)
60
- end
61
-
62
- it "passes on arguments" do
63
- cmd = ["#{test_app_path}/node_modules/.bin/webpack", "--config", "#{test_app_path}/config/webpack/webpack.config.js", "--watch"]
64
-
65
- verify_command(cmd, argv: ["--watch"])
66
- end
67
- end
68
-
69
60
  private
70
61
 
71
- def verify_command(cmd, use_node_modules: true, argv: [])
62
+ def verify_command(cmd, argv: [])
72
63
  Dir.chdir(test_app_path) do
73
64
  klass = Shakapacker::WebpackRunner
74
65
  instance = klass.new(argv)
75
66
 
76
67
  allow(klass).to receive(:new).and_return(instance)
77
- allow(instance).to receive(:node_modules_bin_exist?).and_return(use_node_modules)
78
68
  allow(Kernel).to receive(:exec)
79
69
 
80
70
  klass.run(argv)
81
71
 
82
72
  expect(Kernel).to have_received(:exec).with(Shakapacker::Compiler.env, *cmd)
73
+ expect(Shakapacker::Utils::Manager).to have_received(:error_unless_package_manager_is_obvious!)
83
74
  end
84
75
  end
85
76
  end
@@ -1,16 +1,19 @@
1
1
  NODE_PACKAGE_MANAGERS = ["npm", "yarn_classic", "yarn_berry", "pnpm", "bun"]
2
2
 
3
- def with_use_package_json_gem(enabled:, fallback_manager: nil)
3
+ def with_package_json_fallback_manager(fallback_manager)
4
4
  around do |example|
5
- old_use_package_json_gem_value = ENV["SHAKAPACKER_USE_PACKAGE_JSON_GEM"]
6
5
  old_package_json_fallback_manager_value = ENV["PACKAGE_JSON_FALLBACK_MANAGER"]
7
6
 
8
- ENV["SHAKAPACKER_USE_PACKAGE_JSON_GEM"] = enabled.to_s
9
7
  ENV["PACKAGE_JSON_FALLBACK_MANAGER"] = fallback_manager.to_s
10
8
 
11
9
  example.run
12
10
 
13
- ENV["SHAKAPACKER_USE_PACKAGE_JSON_GEM"] = old_use_package_json_gem_value
14
11
  ENV["PACKAGE_JSON_FALLBACK_MANAGER"] = old_package_json_fallback_manager_value
15
12
  end
16
13
  end
14
+
15
+ def within_temp_directory(tmpdir = nil, &block)
16
+ Dir.mktmpdir("shakapacker-", tmpdir) do |dir|
17
+ Dir.chdir(dir, &block)
18
+ end
19
+ end
data/test/helpers.js ADDED
@@ -0,0 +1,67 @@
1
+ const webpack = require("webpack")
2
+ const MemoryFS = require("memory-fs")
3
+ const thenify = require("thenify")
4
+ const path = require("path")
5
+
6
+ const createTrackLoader = () => {
7
+ const filesTracked = {}
8
+ return [
9
+ filesTracked,
10
+ (source) => {
11
+ filesTracked[source.resource] = true
12
+ return source
13
+ }
14
+ ]
15
+ }
16
+
17
+ const pathToNodeModules = path.resolve("node_modules")
18
+ const pathToNodeModulesIncluded = path.resolve("node_modules/included")
19
+ const pathToAppJavascript = path.resolve("app/javascript")
20
+
21
+ const createInMemoryFs = () => {
22
+ const fs = new MemoryFS()
23
+
24
+ fs.mkdirpSync(pathToNodeModules)
25
+ fs.mkdirpSync(pathToNodeModulesIncluded)
26
+ fs.mkdirpSync(pathToAppJavascript)
27
+
28
+ return fs
29
+ }
30
+
31
+ const createTestCompiler = (config, fs = createInMemoryFs()) => {
32
+ Object.values(config.entry).forEach((file) => {
33
+ fs.writeFileSync(file, "console.log(1);")
34
+ })
35
+
36
+ const compiler = webpack(config)
37
+ compiler.run = thenify(compiler.run)
38
+ compiler.inputFileSystem = fs
39
+ compiler.outputFileSystem = fs
40
+ return compiler
41
+ }
42
+
43
+ const chdirTestApp = () => {
44
+ try {
45
+ return process.chdir("spec/shakapacker/test_app")
46
+ } catch (e) {
47
+ return null
48
+ }
49
+ }
50
+
51
+ const chdirCwd = () => process.chdir(process.cwd())
52
+
53
+ const resetEnv = () => {
54
+ process.env = {}
55
+ }
56
+
57
+ module.exports = {
58
+ chdirTestApp,
59
+ chdirCwd,
60
+ resetEnv,
61
+ createTrackLoader,
62
+ pathToNodeModules,
63
+ pathToNodeModulesIncluded,
64
+ pathToAppJavascript,
65
+ createInMemoryFs,
66
+ createTestCompiler
67
+ }
@@ -0,0 +1,50 @@
1
+ const { resolve } = require("path")
2
+ const { chdirTestApp, resetEnv } = require("../helpers")
3
+
4
+ const rootPath = process.cwd()
5
+ chdirTestApp()
6
+
7
+ describe("Config", () => {
8
+ beforeEach(() => jest.resetModules() && resetEnv())
9
+ afterAll(() => process.chdir(rootPath))
10
+
11
+ test("public path", () => {
12
+ process.env.RAILS_ENV = "development"
13
+ const config = require("../../package/config")
14
+ expect(config.publicPath).toBe("/packs/")
15
+ })
16
+
17
+ test("public path with asset host", () => {
18
+ process.env.RAILS_ENV = "development"
19
+ process.env.SHAKAPACKER_ASSET_HOST = "http://foo.com/"
20
+ const config = require("../../package/config")
21
+ expect(config.publicPath).toBe("http://foo.com/packs/")
22
+ })
23
+
24
+ test("should return additional paths as listed in app config, with resolved paths", () => {
25
+ const config = require("../../package/config")
26
+
27
+ expect(config.additional_paths).toStrictEqual([
28
+ "app/assets",
29
+ "/etc/yarn",
30
+ "some.config.js",
31
+ "app/elm"
32
+ ])
33
+ })
34
+
35
+ test("should default manifestPath to the public dir", () => {
36
+ const config = require("../../package/config")
37
+
38
+ expect(config.manifestPath).toStrictEqual(
39
+ resolve("public/packs/manifest.json")
40
+ )
41
+ })
42
+
43
+ test("should allow overriding manifestPath", () => {
44
+ process.env.SHAKAPACKER_CONFIG = "config/shakapacker_manifest_path.yml"
45
+ const config = require("../../package/config")
46
+ expect(config.manifestPath).toStrictEqual(
47
+ resolve("app/javascript/manifest.json")
48
+ )
49
+ })
50
+ })
@@ -0,0 +1,44 @@
1
+ const { chdirTestApp } = require("../helpers")
2
+
3
+ const rootPath = process.cwd()
4
+ chdirTestApp()
5
+
6
+ describe("DevServer", () => {
7
+ beforeEach(() => jest.resetModules())
8
+ afterAll(() => process.chdir(rootPath))
9
+
10
+ test("with NODE_ENV and RAILS_ENV set to development", () => {
11
+ process.env.NODE_ENV = "development"
12
+ process.env.RAILS_ENV = "development"
13
+ process.env.SHAKAPACKER_DEV_SERVER_HOST = "0.0.0.0"
14
+ process.env.SHAKAPACKER_DEV_SERVER_PORT = 5000
15
+ process.env.SHAKAPACKER_DEV_SERVER_DISABLE_HOST_CHECK = false
16
+
17
+ const devServer = require("../../package/dev_server")
18
+ expect(devServer).toBeDefined()
19
+ expect(devServer.host).toBe("0.0.0.0")
20
+ expect(devServer.port).toBe("5000")
21
+ expect(devServer.disable_host_check).toBe(false)
22
+ })
23
+
24
+ test("with custom env prefix", () => {
25
+ const config = require("../../package/config")
26
+ config.dev_server.env_prefix = "TEST_SHAKAPACKER_DEV_SERVER"
27
+
28
+ process.env.NODE_ENV = "development"
29
+ process.env.RAILS_ENV = "development"
30
+ process.env.TEST_SHAKAPACKER_DEV_SERVER_HOST = "0.0.0.0"
31
+ process.env.TEST_SHAKAPACKER_DEV_SERVER_PORT = 5000
32
+
33
+ const devServer = require("../../package/dev_server")
34
+ expect(devServer).toBeDefined()
35
+ expect(devServer.host).toBe("0.0.0.0")
36
+ expect(devServer.port).toBe("5000")
37
+ })
38
+
39
+ test("with NODE_ENV and RAILS_ENV set to production", () => {
40
+ process.env.RAILS_ENV = "production"
41
+ process.env.NODE_ENV = "production"
42
+ expect(require("../../package/dev_server")).toStrictEqual({})
43
+ })
44
+ })
@@ -0,0 +1,43 @@
1
+ const { resolve } = require("path")
2
+ const { chdirTestApp, resetEnv } = require("../helpers")
3
+
4
+ const rootPath = process.cwd()
5
+ chdirTestApp()
6
+
7
+ describe("Development environment", () => {
8
+ beforeEach(() => jest.resetModules() && resetEnv())
9
+ afterAll(() => process.chdir(rootPath))
10
+
11
+ describe("generateWebpackConfig", () => {
12
+ beforeEach(() => jest.resetModules())
13
+
14
+ test("should use development config and environment including devServer if WEBPACK_SERVE", () => {
15
+ process.env.RAILS_ENV = "development"
16
+ process.env.NODE_ENV = "development"
17
+ process.env.WEBPACK_SERVE = "true"
18
+ const { generateWebpackConfig } = require("../../package/index")
19
+
20
+ const webpackConfig = generateWebpackConfig()
21
+
22
+ expect(webpackConfig.output.path).toStrictEqual(
23
+ resolve("public", "packs")
24
+ )
25
+ expect(webpackConfig.output.publicPath).toBe("/packs/")
26
+ })
27
+
28
+ test("should use development config and environment if WEBPACK_SERVE", () => {
29
+ process.env.RAILS_ENV = "development"
30
+ process.env.NODE_ENV = "development"
31
+ process.env.WEBPACK_SERVE = undefined
32
+ const { generateWebpackConfig } = require("../../package/index")
33
+
34
+ const webpackConfig = generateWebpackConfig()
35
+
36
+ expect(webpackConfig.output.path).toStrictEqual(
37
+ resolve("public", "packs")
38
+ )
39
+ expect(webpackConfig.output.publicPath).toBe("/packs/")
40
+ expect(webpackConfig.devServer).toBeUndefined()
41
+ })
42
+ })
43
+ })
@@ -0,0 +1,57 @@
1
+ const { chdirTestApp } = require("../helpers")
2
+
3
+ const rootPath = process.cwd()
4
+ chdirTestApp()
5
+
6
+ describe("Env", () => {
7
+ beforeEach(() => jest.resetModules())
8
+ afterAll(() => process.chdir(rootPath))
9
+
10
+ test("with NODE_ENV and RAILS_ENV set to development", () => {
11
+ process.env.RAILS_ENV = "development"
12
+ process.env.NODE_ENV = "development"
13
+ expect(require("../../package/env")).toStrictEqual({
14
+ railsEnv: "development",
15
+ nodeEnv: "development",
16
+ isProduction: false,
17
+ isDevelopment: true,
18
+ runningWebpackDevServer: false
19
+ })
20
+ })
21
+
22
+ test("with undefined NODE_ENV and RAILS_ENV set to development", () => {
23
+ process.env.RAILS_ENV = "development"
24
+ delete process.env.NODE_ENV
25
+ expect(require("../../package/env")).toStrictEqual({
26
+ railsEnv: "development",
27
+ nodeEnv: "production",
28
+ isProduction: true,
29
+ isDevelopment: false,
30
+ runningWebpackDevServer: false
31
+ })
32
+ })
33
+
34
+ test("with undefined NODE_ENV and RAILS_ENV", () => {
35
+ delete process.env.NODE_ENV
36
+ delete process.env.RAILS_ENV
37
+ expect(require("../../package/env")).toStrictEqual({
38
+ railsEnv: "production",
39
+ nodeEnv: "production",
40
+ isProduction: true,
41
+ isDevelopment: false,
42
+ runningWebpackDevServer: false
43
+ })
44
+ })
45
+
46
+ test("with a non-standard environment", () => {
47
+ process.env.RAILS_ENV = "staging"
48
+ process.env.NODE_ENV = "staging"
49
+ expect(require("../../package/env")).toStrictEqual({
50
+ railsEnv: "staging",
51
+ nodeEnv: "production",
52
+ isProduction: true,
53
+ isDevelopment: false,
54
+ runningWebpackDevServer: false
55
+ })
56
+ })
57
+ })
@@ -0,0 +1,105 @@
1
+ // environment.js expects to find config/shakapacker.yml and resolved modules from
2
+ // the root of a Rails project
3
+
4
+ const { resolve } = require("path")
5
+ const { chdirTestApp, resetEnv } = require("../../helpers")
6
+
7
+ const rootPath = process.cwd()
8
+ chdirTestApp()
9
+
10
+ const baseConfig = require("../../../package/environments/base")
11
+ const config = require("../../../package/config")
12
+
13
+ describe("Base config", () => {
14
+ beforeEach(() => jest.resetModules() && resetEnv())
15
+ afterAll(() => process.chdir(rootPath))
16
+
17
+ describe("config", () => {
18
+ test("should return entry", () => {
19
+ expect(baseConfig.entry.application).toStrictEqual(
20
+ resolve("app", "javascript", "entrypoints", "application.js")
21
+ )
22
+ })
23
+
24
+ test("should return false for css_extract_ignore_order_warnings when using default config", () => {
25
+ expect(config.css_extract_ignore_order_warnings).toBe(false)
26
+ })
27
+
28
+ test("should return true for css_extract_ignore_order_warnings when configured", () => {
29
+ process.env.SHAKAPACKER_CONFIG =
30
+ "config/shakapacker_css_extract_ignore_order_warnings.yml"
31
+ const config2 = require("../../../package/config")
32
+
33
+ expect(config2.css_extract_ignore_order_warnings).toBe(true)
34
+ })
35
+
36
+ test("should return only 2 entry points with config.nested_entries == false", () => {
37
+ expect(config.nested_entries).toBe(false)
38
+
39
+ expect(baseConfig.entry.multi_entry.sort()).toStrictEqual([
40
+ resolve("app", "javascript", "entrypoints", "multi_entry.css"),
41
+ resolve("app", "javascript", "entrypoints", "multi_entry.js")
42
+ ])
43
+ expect(baseConfig.entry["generated/something"]).toBeUndefined()
44
+ })
45
+
46
+ test("should returns top level and nested entry points with config.nested_entries == true", () => {
47
+ process.env.SHAKAPACKER_CONFIG = "config/shakapacker_nested_entries.yml"
48
+ const config2 = require("../../../package/config")
49
+ const baseConfig2 = require("../../../package/environments/base")
50
+
51
+ expect(config2.nested_entries).toBe(true)
52
+
53
+ expect(baseConfig2.entry.application).toStrictEqual(
54
+ resolve("app", "javascript", "entrypoints", "application.js")
55
+ )
56
+ expect(baseConfig2.entry.multi_entry.sort()).toStrictEqual([
57
+ resolve("app", "javascript", "entrypoints", "multi_entry.css"),
58
+ resolve("app", "javascript", "entrypoints", "multi_entry.js")
59
+ ])
60
+ expect(baseConfig2.entry["generated/something"]).toStrictEqual(
61
+ resolve("app", "javascript", "entrypoints", "generated", "something.js")
62
+ )
63
+ })
64
+
65
+ test("should return output", () => {
66
+ expect(baseConfig.output.filename).toBe("js/[name]-[contenthash].js")
67
+ expect(baseConfig.output.chunkFilename).toBe(
68
+ "js/[name]-[contenthash].chunk.js"
69
+ )
70
+ })
71
+
72
+ test("should return default loader rules for each file in config/loaders", () => {
73
+ const rules = require("../../../package/rules")
74
+
75
+ const defaultRules = Object.keys(rules)
76
+ const configRules = baseConfig.module.rules
77
+
78
+ expect(defaultRules).toHaveLength(3)
79
+ expect(configRules).toHaveLength(3)
80
+ })
81
+
82
+ test("should return default plugins", () => {
83
+ expect(baseConfig.plugins).toHaveLength(2)
84
+ })
85
+
86
+ test("should return default resolveLoader", () => {
87
+ expect(baseConfig.resolveLoader.modules).toStrictEqual(["node_modules"])
88
+ })
89
+
90
+ test("should return default resolve.modules with additions", () => {
91
+ expect(baseConfig.resolve.modules).toStrictEqual([
92
+ resolve("app", "javascript"),
93
+ resolve("app/assets"),
94
+ resolve("/etc/yarn"),
95
+ resolve("some.config.js"),
96
+ resolve("app/elm"),
97
+ "node_modules"
98
+ ])
99
+ })
100
+
101
+ test("returns plugins property as Array", () => {
102
+ expect(baseConfig.plugins).toBeInstanceOf(Array)
103
+ })
104
+ })
105
+ })
@@ -0,0 +1,50 @@
1
+ const { chdirTestApp, resetEnv } = require("../../helpers")
2
+
3
+ const rootPath = process.cwd()
4
+ chdirTestApp()
5
+
6
+ describe("Development specific config", () => {
7
+ beforeEach(() => {
8
+ jest.resetModules()
9
+ resetEnv()
10
+ process.env.NODE_ENV = "development"
11
+ })
12
+ afterAll(() => process.chdir(rootPath))
13
+
14
+ describe("with config.useContentHash = true", () => {
15
+ test("sets filename to use contentHash", () => {
16
+ const config = require("../../../package/config")
17
+ config.useContentHash = true
18
+ const environmentConfig = require("../../../package/environments/development")
19
+
20
+ expect(environmentConfig.output.filename).toBe(
21
+ "js/[name]-[contenthash].js"
22
+ )
23
+ expect(environmentConfig.output.chunkFilename).toBe(
24
+ "js/[name]-[contenthash].chunk.js"
25
+ )
26
+ })
27
+ })
28
+
29
+ describe("with config.useContentHash = false", () => {
30
+ test("sets filename without using contentHash", () => {
31
+ const config = require("../../../package/config")
32
+ config.useContentHash = false
33
+ const environmentConfig = require("../../../package/environments/development")
34
+
35
+ expect(environmentConfig.output.filename).toBe("js/[name].js")
36
+ expect(environmentConfig.output.chunkFilename).toBe("js/[name].chunk.js")
37
+ })
38
+ })
39
+
40
+ describe("with unset config.useContentHash", () => {
41
+ test("sets filename without using contentHash", () => {
42
+ const config = require("../../../package/config")
43
+ delete config.useContentHash
44
+ const environmentConfig = require("../../../package/environments/development")
45
+
46
+ expect(environmentConfig.output.filename).toBe("js/[name].js")
47
+ expect(environmentConfig.output.chunkFilename).toBe("js/[name].chunk.js")
48
+ })
49
+ })
50
+ })