shakapacker 6.5.5 → 6.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +11 -7
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  4. data/.github/workflows/ruby.yml +3 -1
  5. data/.gitignore +3 -3
  6. data/.rspec +1 -0
  7. data/CHANGELOG.md +18 -2
  8. data/CONTRIBUTING.md +11 -1
  9. data/Gemfile.development_dependencies +3 -1
  10. data/README.md +41 -8
  11. data/Rakefile +4 -5
  12. data/gemfiles/Gemfile-rails-edge +1 -1
  13. data/gemfiles/Gemfile-rails.5.2.x +1 -1
  14. data/gemfiles/Gemfile-rails.6.0.x +1 -1
  15. data/gemfiles/Gemfile-rails.6.1.x +1 -1
  16. data/gemfiles/Gemfile-rails.7.0.x +1 -1
  17. data/lib/install/template.rb +21 -16
  18. data/lib/tasks/webpacker/compile.rake +5 -10
  19. data/lib/webpacker/helper.rb +20 -9
  20. data/lib/webpacker/version.rb +1 -1
  21. data/package/rules/__tests__/__utils__/webpack.js +50 -0
  22. data/package/rules/__tests__/babel.js +63 -0
  23. data/package/rules/__tests__/esbuild.js +64 -0
  24. data/package/rules/__tests__/index.js +0 -4
  25. data/package/rules/__tests__/swc.js +64 -0
  26. data/package/rules/babel.js +3 -14
  27. data/package/rules/esbuild.js +2 -13
  28. data/package/rules/jscommon.js +26 -0
  29. data/package/rules/swc.js +2 -13
  30. data/package/utils/helpers.js +1 -1
  31. data/package.json +8 -2
  32. data/spec/command_spec.rb +114 -0
  33. data/spec/compiler_spec.rb +57 -0
  34. data/spec/compiler_strategy_spec.rb +20 -0
  35. data/spec/configuration_spec.rb +281 -0
  36. data/{test/dev_server_runner_test.rb → spec/dev_server_runner_spec.rb} +30 -40
  37. data/spec/dev_server_spec.rb +45 -0
  38. data/spec/digest_strategy_spec.rb +33 -0
  39. data/{test/engine_rake_tasks_test.rb → spec/engine_rake_tasks_spec.rb} +17 -9
  40. data/spec/env_spec.rb +21 -0
  41. data/{test → spec}/fixtures/beta_package-lock.v1.json +0 -0
  42. data/{test → spec}/fixtures/beta_package-lock.v2.json +0 -0
  43. data/{test → spec}/fixtures/beta_package.json +0 -0
  44. data/{test → spec}/fixtures/beta_yarn.v1.lock +0 -0
  45. data/{test → spec}/fixtures/beta_yarn.v2.lock +0 -0
  46. data/{test → spec}/fixtures/git_url_package-lock.v1.json +0 -0
  47. data/{test → spec}/fixtures/git_url_package-lock.v2.json +0 -0
  48. data/{test → spec}/fixtures/git_url_package.json +0 -0
  49. data/{test → spec}/fixtures/git_url_yarn.v1.lock +0 -0
  50. data/{test → spec}/fixtures/git_url_yarn.v2.lock +0 -0
  51. data/{test → spec}/fixtures/github_url_package-lock.v1.json +0 -0
  52. data/{test → spec}/fixtures/github_url_package-lock.v2.json +0 -0
  53. data/{test → spec}/fixtures/github_url_package.json +0 -0
  54. data/{test → spec}/fixtures/github_url_yarn.v1.lock +0 -0
  55. data/{test → spec}/fixtures/github_url_yarn.v2.lock +0 -0
  56. data/{test → spec}/fixtures/relative_path_package-lock.v1.json +0 -0
  57. data/{test → spec}/fixtures/relative_path_package-lock.v2.json +0 -0
  58. data/{test → spec}/fixtures/relative_path_package.json +0 -0
  59. data/{test → spec}/fixtures/relative_path_yarn.v1.lock +0 -0
  60. data/{test → spec}/fixtures/relative_path_yarn.v2.lock +0 -0
  61. data/{test → spec}/fixtures/semver_caret_package-lock.v1.json +0 -0
  62. data/{test → spec}/fixtures/semver_caret_package-lock.v2.json +0 -0
  63. data/{test → spec}/fixtures/semver_caret_package.json +0 -0
  64. data/{test → spec}/fixtures/semver_caret_yarn.v1.lock +0 -0
  65. data/{test → spec}/fixtures/semver_caret_yarn.v2.lock +0 -0
  66. data/{test → spec}/fixtures/semver_exact_package-lock.v1.json +0 -0
  67. data/{test → spec}/fixtures/semver_exact_package-lock.v2.json +0 -0
  68. data/{test → spec}/fixtures/semver_exact_package.json +0 -0
  69. data/{test → spec}/fixtures/semver_exact_yarn.v1.lock +0 -0
  70. data/{test → spec}/fixtures/semver_exact_yarn.v2.lock +0 -0
  71. data/{test → spec}/fixtures/semver_tilde_package-lock.v1.json +0 -0
  72. data/{test → spec}/fixtures/semver_tilde_package-lock.v2.json +0 -0
  73. data/{test → spec}/fixtures/semver_tilde_package.json +0 -0
  74. data/{test → spec}/fixtures/semver_tilde_yarn.v1.lock +0 -0
  75. data/{test → spec}/fixtures/semver_tilde_yarn.v2.lock +0 -0
  76. data/{test → spec}/fixtures/without_package-lock.v1.json +0 -0
  77. data/{test → spec}/fixtures/without_package-lock.v2.json +0 -0
  78. data/{test → spec}/fixtures/without_package.json +0 -0
  79. data/{test → spec}/fixtures/without_yarn.v1.lock +0 -0
  80. data/{test → spec}/fixtures/without_yarn.v2.lock +0 -0
  81. data/spec/helper_spec.rb +241 -0
  82. data/spec/manifest_spec.rb +98 -0
  83. data/{test → spec}/mounted_app/Rakefile +0 -0
  84. data/{test → spec}/mounted_app/test/dummy/Rakefile +0 -0
  85. data/{test → spec}/mounted_app/test/dummy/bin/rails +0 -0
  86. data/{test → spec}/mounted_app/test/dummy/bin/rake +0 -0
  87. data/{test → spec}/mounted_app/test/dummy/config/application.rb +0 -0
  88. data/{test → spec}/mounted_app/test/dummy/config/environment.rb +0 -0
  89. data/{test → spec}/mounted_app/test/dummy/config/webpacker.yml +0 -0
  90. data/{test → spec}/mounted_app/test/dummy/config.ru +0 -0
  91. data/{test → spec}/mounted_app/test/dummy/package.json +0 -0
  92. data/spec/mtime_strategy_spec.rb +53 -0
  93. data/spec/rake_tasks_spec.rb +32 -0
  94. data/spec/spec_helper.rb +123 -0
  95. data/{test → spec}/test_app/Rakefile +0 -0
  96. data/{test → spec}/test_app/app/packs/entrypoints/application.js +0 -0
  97. data/{test → spec}/test_app/app/packs/entrypoints/generated/something.js +0 -0
  98. data/{test → spec}/test_app/app/packs/entrypoints/multi_entry.css +0 -0
  99. data/{test → spec}/test_app/app/packs/entrypoints/multi_entry.js +0 -0
  100. data/{test → spec}/test_app/bin/webpacker +0 -0
  101. data/{test → spec}/test_app/bin/webpacker-dev-server +0 -0
  102. data/{test → spec}/test_app/config/application.rb +0 -0
  103. data/{test → spec}/test_app/config/environment.rb +0 -0
  104. data/{test → spec}/test_app/config/initializers/inspect_autoload_paths.rb +0 -0
  105. data/{test → spec}/test_app/config/webpack/webpack.config.js +0 -0
  106. data/{test → spec}/test_app/config/webpacker.yml +0 -0
  107. data/{test → spec}/test_app/config/webpacker_css_extract_ignore_order_warnings.yml +0 -0
  108. data/{test → spec}/test_app/config/webpacker_defaults_fallback.yml +0 -0
  109. data/{test → spec}/test_app/config/webpacker_manifest_path.yml +0 -0
  110. data/{test → spec}/test_app/config/webpacker_nested_entries.yml +0 -0
  111. data/{test → spec}/test_app/config/webpacker_no_precompile.yml +0 -0
  112. data/{test → spec}/test_app/config/webpacker_other_location.yml +0 -0
  113. data/{test → spec}/test_app/config/webpacker_public_root.yml +0 -0
  114. data/{test → spec}/test_app/config.ru +0 -0
  115. data/{test → spec}/test_app/package.json +0 -0
  116. data/{test → spec}/test_app/public/packs/manifest.json +8 -0
  117. data/{test → spec}/test_app/some.config.js +0 -0
  118. data/{test → spec}/test_app/yarn.lock +0 -0
  119. data/spec/version_checker_spec.rb +950 -0
  120. data/{test/webpack_runner_test.rb → spec/webpack_runner_spec.rb} +12 -15
  121. data/spec/webpacker_spec.rb +39 -0
  122. data/yarn.lock +846 -844
  123. metadata +102 -187
  124. data/.github/ISSUE_TEMPLATE/feature-request.md +0 -18
  125. data/lib/tasks/yarn.rake +0 -44
  126. data/test/command_test.rb +0 -109
  127. data/test/compiler_strategy_test.rb +0 -27
  128. data/test/compiler_test.rb +0 -60
  129. data/test/configuration_test.rb +0 -186
  130. data/test/dev_server_test.rb +0 -47
  131. data/test/digest_strategy_test.rb +0 -33
  132. data/test/env_test.rb +0 -23
  133. data/test/helper_test.rb +0 -248
  134. data/test/manifest_test.rb +0 -89
  135. data/test/mtime_strategy_test.rb +0 -42
  136. data/test/rake_tasks_test.rb +0 -37
  137. data/test/test_helper.rb +0 -33
  138. data/test/version_checker_test.rb +0 -826
  139. data/test/webpacker_test.rb +0 -49
@@ -0,0 +1,64 @@
1
+ const path = require("path");
2
+ const {
3
+ app_javascript,
4
+ node_modules,
5
+ node_modules_included,
6
+ createTestCompiler,
7
+ createTrackLoader,
8
+ } = require("./__utils__/webpack");
9
+ const swcConfig = require("../swc");
10
+
11
+ jest.mock("../../config", () => {
12
+ const original = jest.requireActual("../../config");
13
+ return {
14
+ ...original,
15
+ webpack_loader: "swc",
16
+ additional_paths: [...original.additional_paths, "node_modules/included"],
17
+ };
18
+ });
19
+
20
+ const createWebpackConfig = (file, use) => {
21
+ return {
22
+ entry: { file },
23
+ module: {
24
+ rules: [
25
+ {
26
+ ...swcConfig,
27
+ use,
28
+ },
29
+ ],
30
+ },
31
+ output: {
32
+ path: "/",
33
+ filename: "scripts-bundled.js",
34
+ },
35
+ };
36
+ };
37
+
38
+ describe("swc", () => {
39
+ test("process source path", async () => {
40
+ const normalPath = `${app_javascript}/a.js`;
41
+ const [tracked, loader] = createTrackLoader();
42
+ const compiler = createTestCompiler(
43
+ createWebpackConfig(normalPath, loader)
44
+ );
45
+ await compiler.run();
46
+ expect(tracked[normalPath]).toBeTruthy();
47
+ });
48
+
49
+ test("exclude node_modules", async () => {
50
+ const ignored = `${node_modules}/a.js`;
51
+ const [tracked, loader] = createTrackLoader();
52
+ const compiler = createTestCompiler(createWebpackConfig(ignored, loader));
53
+ await compiler.run();
54
+ expect(tracked[ignored]).toBeUndefined();
55
+ });
56
+
57
+ test("explicitly included node_modules should be transpiled", async () => {
58
+ const included = `${node_modules_included}/a.js`;
59
+ const [tracked, loader] = createTrackLoader();
60
+ const compiler = createTestCompiler(createWebpackConfig(included, loader));
61
+ await compiler.run();
62
+ expect(tracked[included]).toBeTruthy();
63
+ });
64
+ });
@@ -1,24 +1,13 @@
1
- const { resolve } = require('path')
2
- const { realpathSync } = require('fs')
3
1
  const { loaderMatches } = require('../utils/helpers')
4
-
5
2
  const {
6
- source_path: sourcePath,
7
- additional_paths: additionalPaths,
8
3
  webpack_loader: webpackLoader
9
4
  } = require('../config')
10
5
  const { isProduction } = require('../env')
6
+ const jscommon = require('./jscommon')
11
7
 
12
8
  module.exports = loaderMatches(webpackLoader, 'babel', () => ({
13
9
  test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/,
14
- include: [sourcePath, ...additionalPaths].map((p) => {
15
- try {
16
- return realpathSync(p)
17
- } catch (e) {
18
- return resolve(p)
19
- }
20
- }),
21
- exclude: /node_modules/,
10
+ ...jscommon,
22
11
  use: [
23
12
  {
24
13
  loader: require.resolve('babel-loader'),
@@ -29,4 +18,4 @@ module.exports = loaderMatches(webpackLoader, 'babel', () => ({
29
18
  }
30
19
  }
31
20
  ]
32
- }))
21
+ }))
@@ -1,23 +1,12 @@
1
- const { resolve } = require('path')
2
- const { realpathSync } = require('fs')
3
1
  const { loaderMatches } = require('../utils/helpers')
4
2
  const { getEsbuildLoaderConfig } = require('../esbuild')
5
-
6
3
  const {
7
- source_path: sourcePath,
8
- additional_paths: additionalPaths,
9
4
  webpack_loader: webpackLoader
10
5
  } = require('../config')
6
+ const jscommon = require('./jscommon')
11
7
 
12
8
  module.exports = loaderMatches(webpackLoader, 'esbuild', () => ({
13
9
  test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
14
- include: [sourcePath, ...additionalPaths].map((p) => {
15
- try {
16
- return realpathSync(p)
17
- } catch (e) {
18
- return resolve(p)
19
- }
20
- }),
21
- exclude: /node_modules/,
10
+ ...jscommon,
22
11
  use: ({ resource }) => getEsbuildLoaderConfig(resource)
23
12
  }))
@@ -0,0 +1,26 @@
1
+ const { resolve } = require('path')
2
+ const { realpathSync } = require('fs')
3
+ const {
4
+ source_path: sourcePath,
5
+ additional_paths: additionalPaths
6
+ } = require('../config')
7
+
8
+ const inclusions = [sourcePath, ...additionalPaths].map(p => {
9
+ try {
10
+ return realpathSync(p)
11
+ } catch (e) {
12
+ return resolve(p)
13
+ }
14
+ })
15
+
16
+ module.exports = {
17
+ include: inclusions,
18
+ exclude: [
19
+ {
20
+ // exclude all node_modules from running through babel-loader
21
+ and: [resolve('node_modules')],
22
+ // Do not exclude inclusions, as otherwise these won't be transpiled
23
+ not: [...inclusions]
24
+ }
25
+ ]
26
+ }
data/package/rules/swc.js CHANGED
@@ -1,23 +1,12 @@
1
- const { resolve } = require('path')
2
- const { realpathSync } = require('fs')
3
1
  const { loaderMatches } = require('../utils/helpers')
4
2
  const { getSwcLoaderConfig } = require('../swc')
5
-
6
3
  const {
7
- source_path: sourcePath,
8
- additional_paths: additionalPaths,
9
4
  webpack_loader: webpackLoader
10
5
  } = require('../config')
6
+ const jscommon = require('./jscommon')
11
7
 
12
8
  module.exports = loaderMatches(webpackLoader, 'swc', () => ({
13
9
  test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
14
- include: [sourcePath, ...additionalPaths].map((p) => {
15
- try {
16
- return realpathSync(p)
17
- } catch (e) {
18
- return resolve(p)
19
- }
20
- }),
21
- exclude: /node_modules/,
10
+ ...jscommon,
22
11
  use: ({ resource }) => getSwcLoaderConfig(resource)
23
12
  }))
@@ -2,7 +2,7 @@ const isArray = (value) => Array.isArray(value)
2
2
  const isBoolean = (str) => /^true/.test(str) || /^false/.test(str)
3
3
  const chdirTestApp = () => {
4
4
  try {
5
- return process.chdir('test/test_app')
5
+ return process.chdir('spec/test_app')
6
6
  } catch (e) {
7
7
  return null
8
8
  }
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shakapacker",
3
- "version": "6.5.5",
3
+ "version": "6.5.6",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "main": "package/index.js",
6
6
  "files": [
@@ -40,14 +40,20 @@
40
40
  "eslint-plugin-import": "^2.24.2",
41
41
  "eslint-plugin-jsx-a11y": "^6.4.1",
42
42
  "eslint-plugin-react": "^7.26.0",
43
- "jest": "^27.2.1",
43
+ "jest": "^28.1.3",
44
+ "memory-fs": "^0.5.0",
44
45
  "swc-loader": "^0.1.15",
46
+ "thenify": "^3.3.1",
45
47
  "webpack": "^5.72.0",
46
48
  "webpack-assets-manifest": "^5.0.6",
47
49
  "webpack-merge": "^5.8.0"
48
50
  },
49
51
  "jest": {
50
52
  "testRegex": "(/__tests__/.*|(\\.|/))\\.jsx?$",
53
+ "testPathIgnorePatterns": [
54
+ "/__fixtures__/",
55
+ "/__utils__/"
56
+ ],
51
57
  "roots": [
52
58
  "<rootDir>/package"
53
59
  ]
@@ -0,0 +1,114 @@
1
+ describe "Command" do
2
+ before do
3
+ allow(Webpacker.logger).to receive(:info)
4
+ end
5
+
6
+ describe "#compile" do
7
+ it "returns success status when stale" do
8
+ expect(Webpacker.compiler).to receive(:stale?).and_return(true)
9
+ expect(Webpacker.compiler).to receive(:run_webpack).and_return(true)
10
+
11
+ expect(Webpacker.commands.compile).to be true
12
+ end
13
+
14
+ it "returns success status when fresh" do
15
+ expect(Webpacker.compiler).to receive(:stale?).and_return(false)
16
+
17
+ expect(Webpacker.commands.compile).to be true
18
+ end
19
+
20
+ it "returns failure status when stale" do
21
+ expect(Webpacker.compiler).to receive(:stale?).and_return(true)
22
+ expect(Webpacker.compiler).to receive(:run_webpack).and_return(false)
23
+
24
+ expect(Webpacker.commands.compile).to be false
25
+ end
26
+ end
27
+
28
+ describe "#clean" do
29
+ let(:now) { Time.parse("2021-01-01 12:34:56 UTC") }
30
+ let(:prev_files) do
31
+ # Test assets to be kept and deleted, path and mtime
32
+ {
33
+ # recent versions to be kept with Webpacker.commands.clean(count = 2)
34
+ "js/application-deadbeef.js" => now - 4000,
35
+ "js/common-deadbeee.js" => now - 4002,
36
+ "css/common-deadbeed.css" => now - 4004,
37
+ "media/images/logo-deadbeeb.css" => now - 4006,
38
+ "js/application-1eadbeef.js" => now - 8000,
39
+ "js/common-1eadbeee.js" => now - 8002,
40
+ "css/common-1eadbeed.css" => now - 8004,
41
+ "media/images/logo-1eadbeeb.css" => now - 8006,
42
+ # new files to be kept with Webpacker.commands.clean(age = 3600)
43
+ "js/brandnew-0001.js" => now,
44
+ "js/brandnew-0002.js" => now - 10,
45
+ "js/brandnew-0003.js" => now - 20,
46
+ "js/brandnew-0004.js" => now - 40,
47
+ }.transform_keys { |path| "#{Webpacker.config.public_output_path}/#{path}" }
48
+ end
49
+
50
+ let(:expired_files) do
51
+ {
52
+ # old files that are outside count = 2 or age = 3600 and to be deleted
53
+ "js/application-0eadbeef.js" => now - 9000,
54
+ "js/common-0eadbeee.js" => now - 9002,
55
+ "css/common-0eadbeed.css" => now - 9004,
56
+ "js/brandnew-0005.js" => now - 3640,
57
+ }.transform_keys { |path| "#{Webpacker.config.public_output_path}/#{path}" }
58
+ end
59
+
60
+ let(:all_files) { prev_files.merge(expired_files) }
61
+
62
+ let(:file_delete_mock) { double("File Delete") }
63
+ let(:file_mtime_stub) { Proc.new { |longpath| all_files[longpath] } }
64
+ let(:file_delete_stub) { Proc.new { |longpath| file_delete_mock.delete(longpath) } }
65
+
66
+ before :context do
67
+ @dir_glob_stub = Proc.new { |arg|
68
+ case arg
69
+ when "#{Webpacker.config.public_output_path}/**/*"
70
+ all_files.keys
71
+ else
72
+ []
73
+ end
74
+ }
75
+ end
76
+
77
+ it "works with nested hashes and without any compiled files" do
78
+ allow(File).to receive(:delete).and_return(true)
79
+ expect(Webpacker.commands.clean).to be true
80
+ end
81
+
82
+ it "deletes only and only expired versioned files if no parameter passed" do
83
+ all_files.keys.each do |longpath|
84
+ allow(file_delete_mock).to receive(:delete).with(longpath)
85
+ end
86
+
87
+ with_time_dir_and_files_stub do
88
+ expect(Webpacker.commands.clean).to be true
89
+
90
+ # Verify that only and only expired files are deleted
91
+ all_files.keys.each do |longpath|
92
+ if expired_files.has_key? longpath
93
+ expect(file_delete_mock).to have_received(:delete).with(longpath)
94
+ else
95
+ expect(file_delete_mock).to_not have_received(:delete).with(longpath)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def with_time_dir_and_files_stub(&proc)
104
+ allow(Time).to receive(:now).and_return(now)
105
+ allow(Dir).to receive(:glob) { |arg| @dir_glob_stub.call(arg) }
106
+ allow(File).to receive(:directory?).and_return(false)
107
+ allow(File).to receive(:file?).and_return(true)
108
+ allow(File).to receive(:mtime) { |arg| file_mtime_stub.call(arg) }
109
+ allow(File).to receive(:delete) { |arg| file_delete_stub.call(arg) }
110
+
111
+ yield proc
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,57 @@
1
+ describe "Webpacker::Compiler" do
2
+ it "accepts custom environment variables" do
3
+ expect(Webpacker.compiler.send(:webpack_env)["FOO"]).to be nil
4
+
5
+ Webpacker.compiler.env["FOO"] = "BAR"
6
+ expect(Webpacker.compiler.send(:webpack_env)["FOO"]).to eq "BAR"
7
+ ensure
8
+ Webpacker.compiler.env = {}
9
+ end
10
+
11
+ it "returns true when fresh" do
12
+ mocked_strategy = double("Strategy")
13
+ expect(mocked_strategy).to receive(:stale?).and_return(false)
14
+
15
+ expect(Webpacker.compiler).to receive(:strategy).and_return(mocked_strategy)
16
+
17
+ expect(Webpacker.compiler.compile).to be true
18
+ end
19
+
20
+ it "returns true and calls after_compile_hook on successful compile" do
21
+ mocked_strategy = spy("Strategy")
22
+ expect(mocked_strategy).to receive(:stale?).and_return(true)
23
+
24
+ allow(Webpacker.compiler).to receive(:strategy).and_return(mocked_strategy)
25
+
26
+ status = OpenStruct.new(success?: true)
27
+ allow(Open3).to receive(:capture3).and_return([:sterr, :stdout, status])
28
+
29
+ expect(Webpacker.compiler.compile).to be true
30
+ expect(mocked_strategy).to have_received(:after_compile_hook)
31
+ end
32
+
33
+ it "returns false and calls after_compile_hook on failed compile" do
34
+ mocked_strategy = spy("Strategy")
35
+ allow(mocked_strategy).to receive(:stale?).and_return(true)
36
+ allow(mocked_strategy).to receive(:after_compile_hook)
37
+
38
+ allow(Webpacker.compiler).to receive(:strategy).and_return(mocked_strategy)
39
+
40
+ status = OpenStruct.new(success?: false)
41
+ allow(Open3).to receive(:capture3).and_return([:sterr, :stdout, status])
42
+
43
+ expect(Webpacker.compiler.compile).to be false
44
+ expect(mocked_strategy).to have_received(:after_compile_hook)
45
+ end
46
+
47
+ it "accepts external env variables" do
48
+ expect(Webpacker.compiler.send(:webpack_env)["WEBPACKER_ASSET_HOST"]).to be nil
49
+ expect(Webpacker.compiler.send(:webpack_env)["WEBPACKER_RELATIVE_URL_ROOT"]).to be nil
50
+
51
+ ENV["WEBPACKER_ASSET_HOST"] = "foo.bar"
52
+ ENV["WEBPACKER_RELATIVE_URL_ROOT"] = "/baz"
53
+
54
+ expect(Webpacker.compiler.send(:webpack_env)["WEBPACKER_ASSET_HOST"]).to eq "foo.bar"
55
+ expect(Webpacker.compiler.send(:webpack_env)["WEBPACKER_RELATIVE_URL_ROOT"]).to eq "/baz"
56
+ end
57
+ end
@@ -0,0 +1,20 @@
1
+ describe "Webpacker::CompilerStrategy" do
2
+ describe "#from_config" do
3
+ it "returns and instance of MtimeStrategy when compiler_strategy is set to mtime" do
4
+ allow(Webpacker.config).to receive(:compiler_strategy).and_return("mtime")
5
+ expect(Webpacker::CompilerStrategy.from_config).to be_an_instance_of(Webpacker::MtimeStrategy)
6
+ end
7
+
8
+ it "returns and instance of DigestStrategy when compiler_strategy is set to digest" do
9
+ allow(Webpacker.config).to receive(:compiler_strategy).and_return("digest")
10
+ expect(Webpacker::CompilerStrategy.from_config).to be_an_instance_of(Webpacker::DigestStrategy)
11
+ end
12
+
13
+ it "raise exception for unknown compiler_strategy in the config file" do
14
+ expected_error_message = "Unknown strategy 'other'. Available options are 'mtime' and 'digest'."
15
+ allow(Webpacker.config).to receive(:compiler_strategy).and_return("other")
16
+
17
+ expect { Webpacker::CompilerStrategy.from_config }.to raise_error(expected_error_message)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,281 @@
1
+ describe "Webpacker::Configuration" do
2
+ ROOT_PATH = Pathname.new(File.expand_path("test_app", __dir__))
3
+
4
+ context "with standard webpacker.yml" do
5
+ let(:config) do
6
+ Webpacker::Configuration.new(
7
+ root_path: ROOT_PATH,
8
+ config_path: Pathname.new(File.expand_path("./test_app/config/webpacker.yml", __dir__)),
9
+ env: "production"
10
+ )
11
+ end
12
+
13
+ it "#source_path returns correct path" do
14
+ source_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/packs").to_s
15
+ expect(config.source_path.to_s).to eq source_path
16
+ end
17
+
18
+ it "#source_entry_path returns correct path" do
19
+ source_entry_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/packs", "entrypoints").to_s
20
+ expect(config.source_entry_path.to_s).to eq source_entry_path
21
+ end
22
+
23
+ it "#public_root_path returns correct path" do
24
+ public_root_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public").to_s
25
+ expect(config.public_path.to_s).to eq public_root_path
26
+ end
27
+
28
+ it "#public_output_path returns correct path" do
29
+ public_output_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs").to_s
30
+ expect(config.public_output_path.to_s).to eq public_output_path
31
+ end
32
+
33
+ it "#public_manifest_path returns correct path" do
34
+ public_manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s
35
+ expect(config.public_manifest_path.to_s).to eq public_manifest_path
36
+ end
37
+
38
+ it "#manifest_path returns correct path" do
39
+ manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s
40
+ expect(config.manifest_path.to_s).to eq manifest_path
41
+ end
42
+
43
+ it "#cache_path returns correct path" do
44
+ cache_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/tmp/webpacker").to_s
45
+ expect(config.cache_path.to_s).to eq cache_path
46
+ end
47
+
48
+ it "#additional_paths returns correct path" do
49
+ expect(config.additional_paths).to eq ["app/assets", "/etc/yarn", "some.config.js", "app/elm"]
50
+ end
51
+
52
+ describe "#cache_manifest?" do
53
+ it "returns true in production environment" do
54
+ expect(config.cache_manifest?).to be true
55
+ end
56
+
57
+ it "returns false in developemnt environemnt" do
58
+ with_rails_env("development") do
59
+ expect(Webpacker.config.cache_manifest?).to be false
60
+ end
61
+ end
62
+
63
+ it "returns false in test environment" do
64
+ with_rails_env("test") do
65
+ expect(Webpacker.config.cache_manifest?).to be false
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#compile?" do
71
+ it "returns false in production environment" do
72
+ expect(config.compile?).to be false
73
+ end
74
+
75
+ it "returns true in developemnt environemnt" do
76
+ with_rails_env("development") do
77
+ expect(Webpacker.config.compile?).to be true
78
+ end
79
+ end
80
+
81
+ it "returns true in test environemnt" do
82
+ with_rails_env("test") do
83
+ expect(Webpacker.config.compile?).to be true
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "#nested_entries?" do
89
+ it "returns false in production environment" do
90
+ expect(config.nested_entries?).to be false
91
+ end
92
+
93
+ it "returns false in development environment" do
94
+ with_rails_env("development") do
95
+ expect(Webpacker.config.nested_entries?).to be false
96
+ end
97
+ end
98
+
99
+ it "returns false in test environment" do
100
+ with_rails_env("test") do
101
+ expect(Webpacker.config.nested_entries?).to be false
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "#ensure_consistent_versioning?" do
107
+ it "returns false in production environment" do
108
+ expect(config.ensure_consistent_versioning?).to be false
109
+ end
110
+
111
+ it "returns true in development environment" do
112
+ with_rails_env("development") do
113
+ expect(Webpacker.config.ensure_consistent_versioning?).to be true
114
+ end
115
+ end
116
+
117
+ it "returns false in test environment" do
118
+ with_rails_env("test") do
119
+ expect(Webpacker.config.ensure_consistent_versioning?).to be false
120
+ end
121
+ end
122
+ end
123
+
124
+ describe "#webpacker_precompile?" do
125
+ before :each do
126
+ ENV["WEBPACKER_PRECOMPILE"] = nil
127
+ end
128
+
129
+ subject { config.webpacker_precompile? }
130
+
131
+ it "returns true when WEBPACKER_PRECOMPILE is unset" do
132
+ is_expected.to be true
133
+ end
134
+
135
+ it "returns false when WEBPACKER_PRECOMPILE sets to no" do
136
+ ENV["WEBPACKER_PRECOMPILE"] = "no"
137
+ is_expected.to be false
138
+ end
139
+
140
+ it "returns true when WEBPACKER_PRECOMPILE sets to yes" do
141
+ ENV["WEBPACKER_PRECOMPILE"] = "yes"
142
+ is_expected.to be true
143
+ end
144
+
145
+ it "returns false when WEBPACKER_PRECOMPILE sets to false" do
146
+ ENV["WEBPACKER_PRECOMPILE"] = "false"
147
+ is_expected.to be false
148
+ end
149
+
150
+ it "returns true when WEBPACKER_PRECOMPILE sets to true" do
151
+ ENV["WEBPACKER_PRECOMPILE"] = "true"
152
+ is_expected.to be true
153
+ end
154
+
155
+ it "returns false when WEBPACKER_PRECOMPILE sets to n" do
156
+ ENV["WEBPACKER_PRECOMPILE"] = "n"
157
+ is_expected.to be false
158
+ end
159
+
160
+ it "returns true when WEBPACKER_PRECOMPILE sets to y" do
161
+ ENV["WEBPACKER_PRECOMPILE"] = "y"
162
+ is_expected.to be true
163
+ end
164
+
165
+ it "returns false when WEBPACKER_PRECOMPILE sets to f" do
166
+ ENV["WEBPACKER_PRECOMPILE"] = "f"
167
+ is_expected.to be false
168
+ end
169
+
170
+ it "returns true when WEBPACKER_PRECOMPILE sets to t" do
171
+ ENV["WEBPACKER_PRECOMPILE"] = "t"
172
+ is_expected.to be true
173
+ end
174
+ end
175
+ end
176
+
177
+ context "with webpacker config file containing public_output_path entry" do
178
+ config = Webpacker::Configuration.new(
179
+ root_path: ROOT_PATH,
180
+ config_path: Pathname.new(File.expand_path("./test_app/config/webpacker_public_root.yml", __dir__)),
181
+ env: "production"
182
+ )
183
+
184
+ it "#public_output_path returns correct path" do
185
+ expected_public_output_path = File.expand_path File.join(File.dirname(__FILE__), "public/packs").to_s
186
+ expect(config.public_output_path.to_s).to eq expected_public_output_path
187
+ end
188
+ end
189
+
190
+ context "with webpacker config file containing manifext_path entry" do
191
+ config = Webpacker::Configuration.new(
192
+ root_path: ROOT_PATH,
193
+ config_path: Pathname.new(File.expand_path("./test_app/config/webpacker_manifest_path.yml", __dir__)),
194
+ env: "production"
195
+ )
196
+
197
+ it "#manifest_path returns correct expected value" do
198
+ expected_manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/packs", "manifest.json").to_s
199
+ expect(config.manifest_path.to_s).to eq expected_manifest_path
200
+ end
201
+ end
202
+
203
+ context "with webpacker_precompile entry set to false" do
204
+ describe "#webpacker_precompile?" do
205
+ before :each do
206
+ ENV["WEBPACKER_PRECOMPILE"] = nil
207
+ end
208
+
209
+ let(:config) {
210
+ Webpacker::Configuration.new(
211
+ root_path: ROOT_PATH,
212
+ config_path: Pathname.new(File.expand_path("./test_app/config/webpacker_no_precompile.yml", __dir__)),
213
+ env: "production"
214
+ )
215
+ }
216
+
217
+ subject { config.webpacker_precompile? }
218
+
219
+ it "returns false with unset WEBPACKER_PRECOMPILE" do
220
+ expect(subject).to be false
221
+ end
222
+
223
+ it "returns true with WEBPACKER_PRECOMPILE set to true" do
224
+ ENV["WEBPACKER_PRECOMPILE"] = "true"
225
+ expect(subject).to be true
226
+ end
227
+
228
+ it "returns false with WEBPACKER_PRECOMPILE set to nil" do
229
+ ENV["WEBPACKER_PRECOMPILE"] = nil
230
+ expect(subject).to be false
231
+ end
232
+ end
233
+ end
234
+
235
+ context "with webpacker config file containing invalid path" do
236
+ config = Webpacker::Configuration.new(
237
+ root_path: ROOT_PATH,
238
+ config_path: Pathname.new(File.expand_path("./test_app/config/invalid_path.yml", __dir__)),
239
+ env: "default"
240
+ )
241
+
242
+ it "#webpacker_precompile? returns false" do
243
+ expect(config.webpacker_precompile?).to be false
244
+ end
245
+ end
246
+
247
+ context "with webpacker config file with defaults fallback" do
248
+ let(:config) do
249
+ Webpacker::Configuration.new(
250
+ root_path: ROOT_PATH,
251
+ config_path: Pathname.new(File.expand_path("./test_app/config/webpacker_defaults_fallback.yml", __dir__)),
252
+ env: "default"
253
+ )
254
+ end
255
+
256
+ it "#cache_manifest? falls back to 'default' config from bundled file" do
257
+ expect(config.cache_manifest?).to be false
258
+ end
259
+
260
+ it "#webpacker_precompile? uses 'default' config from custom file" do
261
+ expect(config.webpacker_precompile?).to be false
262
+ end
263
+ end
264
+
265
+ context "falls back to bundled production config for custom environments" do
266
+ let(:config) do
267
+ Webpacker::Configuration.new(
268
+ root_path: ROOT_PATH,
269
+ config_path: Pathname.new(File.expand_path("./test_app/config/webpacker_defaults_fallback.yml", __dir__)),
270
+ env: "staging"
271
+ )
272
+ end
273
+
274
+ it "#cache_manifest? fall back to 'production' config from bundled file" do
275
+ expect(config.cache_manifest?).to be true
276
+ end
277
+ it "#webpacker_precompile? use 'staging' config from custom file" do
278
+ expect(config.webpacker_precompile?).to be false
279
+ end
280
+ end
281
+ end