mage-obsidian 1.1.2 → 2.0.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 (111) hide show
  1. package/.github/workflows/ci.yml +38 -0
  2. package/.github/workflows/publish.yml +26 -25
  3. package/.oxlintrc.json +19 -0
  4. package/.prettierignore +7 -0
  5. package/.prettierrc.json +7 -0
  6. package/LICENSE +1 -1
  7. package/README.md +1 -0
  8. package/eslint.config.js +24 -0
  9. package/package.json +39 -13
  10. package/pnpm-workspace.yaml +4 -0
  11. package/src/cli/buildThemes.ts +263 -0
  12. package/src/config/default.ts +31 -0
  13. package/src/config/eslint.js +60 -0
  14. package/src/core/configResolver.ts +141 -0
  15. package/src/core/contractValidator.ts +56 -0
  16. package/src/core/cssResolver.ts +153 -0
  17. package/src/{service/generateInterceptors.js → core/generateInterceptors.ts} +79 -46
  18. package/src/core/generateJsconfig.ts +168 -0
  19. package/src/{service/moduleResolver.js → core/moduleResolver.ts} +79 -46
  20. package/src/core/preCompileFiles.ts +105 -0
  21. package/src/core/preCompileMagentoFiles.ts +34 -0
  22. package/src/core/themeResolverSync.ts +66 -0
  23. package/src/runtime/i18nCore.ts +113 -0
  24. package/src/runtime/interceptorManager.ts +186 -0
  25. package/src/runtime/islands.ts +84 -0
  26. package/src/runtime/sectionStoreCore.ts +259 -0
  27. package/src/utils/{findComponents.js → findComponents.ts} +29 -16
  28. package/src/utils/runWithConcurrency.ts +35 -0
  29. package/src/vite/defaultNodeResolver.ts +17 -0
  30. package/src/{service/inheritAssetsModuleResolver.js → vite/inheritAssetsModuleResolver.ts} +15 -11
  31. package/src/{service/inheritModuleResolver.js → vite/inheritModuleResolver.ts} +6 -10
  32. package/src/{service/interceptorsPlugin.js → vite/interceptorsPlugin.ts} +25 -19
  33. package/src/vite/magentoHrmRewrite.ts +44 -0
  34. package/src/vite/sharedPlugins.ts +54 -0
  35. package/src/vite/themeSourceWatcher.ts +96 -0
  36. package/src/vite/unresolvedModuleGuard.ts +87 -0
  37. package/tsconfig.json +34 -0
  38. package/vitest.config.js +18 -0
  39. package/jest.config.js +0 -5
  40. package/src/__tests__/__mocks__/configResolver.js +0 -35
  41. package/src/__tests__/fixtures/interceptors/emptyTarget.js +0 -2
  42. package/src/__tests__/fixtures/interceptors/pluginForNonFunction.js +0 -7
  43. package/src/__tests__/fixtures/interceptors/pluginModule.js +0 -13
  44. package/src/__tests__/fixtures/interceptors/targetModule.js +0 -12
  45. package/src/__tests__/fixtures/interceptors/targetNonFunction.js +0 -7
  46. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/components/ComponentA.vue +0 -0
  47. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/components/ComponentB.vue +0 -0
  48. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/css/module.extend.css +0 -0
  49. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/js/main.js +0 -0
  50. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/main.js +0 -0
  51. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/module.config.js +0 -9
  52. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/components/ComponentA.vue +0 -0
  53. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/components/ComponentB.vue +0 -0
  54. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/css/module.extend.css +0 -2
  55. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/js/main.js +0 -0
  56. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/module.config.js +0 -7
  57. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/components/ComponentA.vue +0 -0
  58. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/components/ComponentB.vue +0 -0
  59. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/css/module.extend.css +0 -2
  60. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/js/main.js +0 -0
  61. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/module.config.js +0 -7
  62. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/components/ComponentA.vue +0 -0
  63. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/components/ComponentB.vue +0 -0
  64. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/css/module.extend.css +0 -0
  65. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/js/main.js +0 -0
  66. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/module.config.js +0 -2
  67. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/components/ComponentA.vue +0 -0
  68. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/components/ComponentB.vue +0 -0
  69. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/css/module.extend.css +0 -0
  70. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/js/main.js +0 -0
  71. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/module.config.js +0 -2
  72. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/components/ComponentA.vue +0 -0
  73. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/components/ComponentB.vue +0 -0
  74. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/css/module.extend.css +0 -0
  75. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/js/main.js +0 -0
  76. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/module.config.js +0 -2
  77. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/components/ComponentA.vue +0 -0
  78. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/components/ComponentB.vue +0 -0
  79. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/css/theme.source.css +0 -6
  80. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/js/main.js +0 -0
  81. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/theme.config.js +0 -5
  82. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-b/web/css/theme.source.css +0 -6
  83. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-b/web/theme.config.js +0 -5
  84. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/components/ComponentA.vue +0 -0
  85. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/components/ComponentB.vue +0 -0
  86. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/css/module.extend.css +0 -0
  87. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/js/main.js +0 -0
  88. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/module.config.js +0 -2
  89. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/web/css/theme.source.css +0 -6
  90. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/web/theme.config.js +0 -2
  91. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-d/web/css/theme.source.css +0 -6
  92. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-d/web/theme.config.js +0 -3
  93. package/src/__tests__/magento_scenarios/app/etc/mage_obsidian_frontend_modules_a.json +0 -53
  94. package/src/__tests__/magento_scenarios/app/etc/mage_obsidian_frontend_modules_b.json +0 -50
  95. package/src/__tests__/service/generateInterceptors.test.js +0 -196
  96. package/src/__tests__/service/inheritModuleResolver.test.js +0 -61
  97. package/src/__tests__/service/interceptorManager_magento_behavior.test.js +0 -137
  98. package/src/__tests__/service/moduleResolver.test.js +0 -194
  99. package/src/__tests__/service/themeResolverSync.test.js +0 -97
  100. package/src/__tests__/vite-plugins/interceptorsPlugin.test.js +0 -121
  101. package/src/config/default.js +0 -27
  102. package/src/scripts/buildThemes.js +0 -132
  103. package/src/service/configResolver.js +0 -63
  104. package/src/service/cssResolver.js +0 -73
  105. package/src/service/defaultNodeResolver.js +0 -16
  106. package/src/service/interceptorManager.js +0 -137
  107. package/src/service/magentoHrmRewrite.js +0 -43
  108. package/src/service/preCompileFiles.js +0 -37
  109. package/src/service/preCompileMagentoFiles.js +0 -16
  110. package/src/service/setupGlobals.js +0 -19
  111. package/src/service/themeResolverSync.js +0 -67
package/jest.config.js DELETED
@@ -1,5 +0,0 @@
1
- export default {
2
- testEnvironment: 'node',
3
- transform: {},
4
- testPathIgnorePatterns: ['/__tests__/magento_scenarios/','/node_modules/', '/__tests__/__mocks__/', '/__tests__/fixtures/'],
5
- };
@@ -1,35 +0,0 @@
1
- import path from "path";
2
- import fs from "fs";
3
- import { jest } from '@jest/globals';
4
- import { fileURLToPath } from 'url';
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
-
9
- const createMockConfigResolver = (scenario) => {
10
- const configPath = path.resolve(__dirname, `../magento_scenarios/app/etc/mage_obsidian_frontend_modules_${scenario}.json`);
11
- const magentoConfigJson = fs.readFileSync(configPath, 'utf-8');
12
- const mockMagentoConfig = JSON.parse(magentoConfigJson);
13
- for (const key in mockMagentoConfig.modules) {
14
- let module = mockMagentoConfig.modules[key];
15
- module.src = path.resolve(__dirname, '..', module.src);
16
- }
17
- for (const key in mockMagentoConfig.themes) {
18
- let theme = mockMagentoConfig.themes[key];
19
- theme.src = path.resolve(__dirname, '..', theme.src);
20
- }
21
- return {
22
- default: {
23
- getMagentoConfig: jest.fn(() => mockMagentoConfig),
24
- getModulesConfigArray: jest.fn(() => Object.entries(mockMagentoConfig.modules)),
25
- getThemesConfigArray: jest.fn(() => Object.entries(mockMagentoConfig.themes)),
26
- getAllMagentoModulesEnabled: jest.fn(() => mockMagentoConfig.allModules),
27
- isDev: jest.fn(() => mockMagentoConfig.mode === 'development'),
28
- getOutputDirFromTheme: jest.fn((themePath) => `${themePath}/output`),
29
- getThemeDefinition: jest.fn((themeName) => mockMagentoConfig.themes[themeName]),
30
- getModuleDefinition: jest.fn((moduleName) => mockMagentoConfig.modules[moduleName]),
31
- }
32
- }
33
- };
34
-
35
- export default createMockConfigResolver;
@@ -1,2 +0,0 @@
1
-
2
- export const someOtherFunction = () => {};
@@ -1,7 +0,0 @@
1
-
2
- export function beforeConfig() {
3
- console.log('Should not run');
4
- }
5
- export function beforeDefault() {
6
- console.log('Should not run');
7
- }
@@ -1,13 +0,0 @@
1
-
2
- export function beforeTargetFunction(arg) {
3
- return [`Modified: ${arg}`];
4
- }
5
-
6
- export function afterAnotherFunction(result) {
7
- return `${result} - Modified`;
8
- }
9
-
10
- export function beforeDefault() {
11
- return ['Default Modified'];
12
- }
13
-
@@ -1,12 +0,0 @@
1
-
2
- export function targetFunction(arg) {
3
- return `Original: ${arg}`;
4
- }
5
-
6
- export function anotherFunction() {
7
- return 'Another';
8
- }
9
-
10
- export default function defaultExport() {
11
- return 'Default';
12
- }
@@ -1,7 +0,0 @@
1
-
2
- export const config = {
3
- some: 'value'
4
- };
5
- export default {
6
- main: 'config'
7
- };
@@ -1,9 +0,0 @@
1
- export default {
2
- tailwind: {
3
- theme: { extend: {} },
4
- plugins: [],
5
- content: [
6
- '../templates/**/*.phtml'
7
- ]
8
- }
9
- };
@@ -1,7 +0,0 @@
1
- export default {
2
- tailwind: {
3
- content: [
4
- '../templates/**/*.phtml'
5
- ]
6
- }
7
- };
@@ -1,7 +0,0 @@
1
- export default {
2
- tailwind: {
3
- content: [
4
- '../templates/**/*.phtml'
5
- ]
6
- }
7
- };
@@ -1,6 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- body {
6
- }
@@ -1,5 +0,0 @@
1
- export default {
2
- ignoredCssFromModules: [
3
- 'Vendor_ModuleNameA',
4
- ],
5
- };
@@ -1,6 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- body {
6
- }
@@ -1,5 +0,0 @@
1
- export default {
2
- ignoredCssFromModules: [
3
- 'Vendor_ModuleNameNoConfig'
4
- ]
5
- }
@@ -1,6 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- body {
6
- }
@@ -1,6 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- body {
6
- }
@@ -1,3 +0,0 @@
1
- export default {
2
- includeCssSourceFromParentThemes: false,
3
- }
@@ -1,53 +0,0 @@
1
- {
2
- "modules": {
3
- "Vendor_ModuleNameA": {
4
- "src": "magento_scenarios\/app\/code\/Vendor\/ModuleNameA"
5
- },
6
- "Vendor_ModuleNameB": {
7
- "src": "magento_scenarios\/app\/code\/Vendor\/ModuleNameB"
8
- },
9
- "Vendor_ModuleNameC": {
10
- "src": "magento_scenarios\/app\/code\/Vendor\/ModuleNameC"
11
- }
12
- },
13
- "themes": {
14
- "Vendor\/theme-a": {
15
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-a",
16
- "parent": null
17
- },
18
- "Vendor\/theme-b": {
19
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-b",
20
- "parent": "Vendor\/theme-a"
21
- },
22
- "Vendor\/theme-c": {
23
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-c",
24
- "parent": "Vendor\/theme-b"
25
- },
26
- "Vendor\/theme-d": {
27
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-d",
28
- "parent": null
29
- }
30
- },
31
- "allModules": [
32
- "Vendor_ModuleNameA",
33
- "Vendor_ModuleNameB",
34
- "Vendor_ModuleNameC"
35
- ],
36
- "VUE_COMPONENTS_PATH": "components",
37
- "JS_PATH": "js",
38
- "FOLDERS_TO_WATCH": [
39
- "components",
40
- "js"
41
- ],
42
- "ALLOWED_EXTENSIONS": [
43
- "js",
44
- "vue",
45
- "cjs",
46
- "ts"
47
- ],
48
- "MODULE_CSS_EXTEND_FILE": "module.extend.css",
49
- "MODULE_CONFIG_FILE": "module.config.js",
50
- "THEME_CONFIG_FILE": "theme.config.js",
51
- "THEME_CSS_SOURCE_FILE": "theme.source.css",
52
- "LIB_PATH": "lib"
53
- }
@@ -1,50 +0,0 @@
1
- {
2
- "modules": {
3
- "Vendor_ModuleNameA": {
4
- "src": "magento_scenarios\/app\/code\/Vendor\/ModuleNameA"
5
- },
6
- "Vendor_ModuleNameC": {
7
- "src": "magento_scenarios\/app\/code\/Vendor\/ModuleNameC"
8
- }
9
- },
10
- "themes": {
11
- "Vendor\/theme-a": {
12
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-a",
13
- "parent": null
14
- },
15
- "Vendor\/theme-b": {
16
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-b",
17
- "parent": "Vendor\/theme-a"
18
- },
19
- "Vendor\/theme-c": {
20
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-c",
21
- "parent": "Vendor\/theme-b"
22
- },
23
- "Vendor\/theme-d": {
24
- "src": "magento_scenarios\/app\/design\/frontend\/Vendor\/theme-d",
25
- "parent": null
26
- }
27
- },
28
- "allModules": [
29
- "Vendor_ModuleNameA",
30
- "Vendor_ModuleNameB",
31
- "Vendor_ModuleNameNoConfig"
32
- ],
33
- "VUE_COMPONENTS_PATH": "components",
34
- "JS_PATH": "js",
35
- "FOLDERS_TO_WATCH": [
36
- "components",
37
- "js"
38
- ],
39
- "ALLOWED_EXTENSIONS": [
40
- "js",
41
- "vue",
42
- "cjs",
43
- "ts"
44
- ],
45
- "MODULE_CSS_EXTEND_FILE": "module.extend.css",
46
- "MODULE_CONFIG_FILE": "module.config.js",
47
- "THEME_CONFIG_FILE": "theme.config.js",
48
- "THEME_CSS_SOURCE_FILE": "theme.source.css",
49
- "LIB_PATH": "lib"
50
- }
@@ -1,196 +0,0 @@
1
-
2
- import { jest } from '@jest/globals';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
-
6
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
- const fixturesDir = path.resolve(__dirname, '../fixtures/interceptors');
8
- const targetModulePath = path.join(fixturesDir, 'targetModule.js');
9
- const pluginModulePath = path.join(fixturesDir, 'pluginModule.js');
10
- const targetNonFunctionPath = path.join(fixturesDir, 'targetNonFunction.js');
11
- const pluginForNonFunctionPath = path.join(fixturesDir, 'pluginForNonFunction.js');
12
-
13
- describe('generateInterceptors', () => {
14
- let generateInterceptorsService;
15
- let themeResolverMock;
16
- let moduleResolverMock;
17
- let interceptorManager;
18
-
19
- beforeEach(async () => {
20
- jest.resetModules();
21
-
22
- themeResolverMock = {
23
- getThemeConfig: jest.fn(),
24
- };
25
-
26
- moduleResolverMock = {
27
- getModuleConfigByThemeConfig: jest.fn(),
28
- getAllJsVueFilesWithInheritanceCached: jest.fn(),
29
- getAllJsVueFilesWithInheritance: jest.fn(),
30
- };
31
-
32
- jest.unstable_mockModule('../../service/themeResolverSync.js', () => ({
33
- default: themeResolverMock
34
- }));
35
-
36
- jest.unstable_mockModule('../../service/moduleResolver.js', () => ({
37
- default: moduleResolverMock
38
- }));
39
-
40
- jest.unstable_mockModule('../../service/configResolver.js', () => ({
41
- default: {
42
- resolveLibRealPath: jest.fn().mockReturnValue('/mocked/path/to/interceptorManager')
43
- }
44
- }));
45
-
46
- // Import real interceptorManager to reset state
47
- interceptorManager = (await import('../../service/interceptorManager.js')).default;
48
- interceptorManager.interceptors = {};
49
-
50
- generateInterceptorsService = (await import('../../service/generateInterceptors.js')).default;
51
- });
52
-
53
- test('should generate interceptors correctly', async () => {
54
- const themeName = 'Vendor/theme-test';
55
-
56
- themeResolverMock.getThemeConfig.mockReturnValue({
57
- src: '/path/to/theme'
58
- });
59
-
60
- moduleResolverMock.getModuleConfigByThemeConfig.mockResolvedValue({
61
- interceptors: {
62
- 'TestPlugin': {
63
- name: 'TestPlugin',
64
- target: 'Vendor_TargetModule::js/target.js',
65
- interceptor: 'Vendor_PluginModule::js/plugin.js',
66
- sortOrder: 10,
67
- active: true
68
- }
69
- }
70
- });
71
-
72
- const allFilesMap = {
73
- 'Vendor_TargetModule/js/target': targetModulePath,
74
- 'Vendor_PluginModule/js/plugin': pluginModulePath
75
- };
76
-
77
- moduleResolverMock.getAllJsVueFilesWithInheritanceCached.mockReturnValue(allFilesMap);
78
-
79
- const result = await generateInterceptorsService.generateInterceptors(themeName);
80
-
81
- const targetIdentifier = 'Vendor_TargetModule::js/target.js';
82
- // Use bracket access check to avoid Jest treating '.' as nested property
83
- expect(result[targetIdentifier]).toBeDefined();
84
-
85
- const interceptorData = result[targetIdentifier];
86
- expect(interceptorData).toHaveProperty('proxy');
87
- expect(interceptorData).toHaveProperty('source');
88
- expect(interceptorData).toHaveProperty('targetPath', targetModulePath);
89
- expect(interceptorData.interceptors).toHaveLength(1);
90
- expect(interceptorData.interceptors[0].name).toBe('TestPlugin');
91
-
92
- // Verify Source Code Generation
93
- const source = interceptorData.source;
94
- expect(source).toContain(`import * as originalModule from '/@fs${targetModulePath}?originalIntercepted';`);
95
- expect(source).toContain(`import * as interceptor_0 from '/@fs${pluginModulePath}';`);
96
- expect(source).toContain(`interceptorManager.addInterceptor('${targetIdentifier}::targetFunction', 'TestPlugin', 'before', interceptor_0.beforeTargetFunction, 10);`);
97
- expect(source).toContain(`interceptorManager.addInterceptor('${targetIdentifier}::default', 'TestPlugin', 'before', interceptor_0.beforeDefault, 10);`);
98
- expect(source).toContain(`export const targetFunction = proxy.targetFunction;`);
99
-
100
- // Verify Proxy Behavior
101
- const proxy = interceptorData.proxy;
102
- const resultFunc = await proxy.targetFunction('test');
103
- expect(resultFunc).toBe('Original: Modified: test');
104
-
105
- const resultAnother = await proxy.anotherFunction();
106
- expect(resultAnother).toBe('Another - Modified');
107
-
108
- const resultDefault = await proxy.default();
109
- expect(resultDefault).toBe('Default'); // The mock plugin returns ['Default Modified'] but the original function ignores args and returns 'Default'.
110
- // Wait, before interceptor modifies arguments.
111
- // targetModule.js: export default function defaultExport() { return 'Default'; }
112
- // It doesn't take arguments, so modifying arguments won't change output unless we check arguments.
113
- // But we just want to verify it was registered.
114
-
115
- });
116
-
117
- test('should handle missing target module gracefully', async () => {
118
- themeResolverMock.getThemeConfig.mockReturnValue({});
119
- moduleResolverMock.getModuleConfigByThemeConfig.mockResolvedValue({
120
- 'Vendor_TargetModule': { interceptors: [] }
121
- });
122
- moduleResolverMock.getAllJsVueFilesWithInheritanceCached.mockReturnValue({});
123
-
124
- const result = await generateInterceptorsService.generateInterceptors('Vendor/theme-missing');
125
- expect(result).toEqual({});
126
- });
127
-
128
- test('should throw error if plugin targets non-existent method', async () => {
129
- const themeName = 'Vendor/theme-test';
130
- themeResolverMock.getThemeConfig.mockReturnValue({});
131
- moduleResolverMock.getModuleConfigByThemeConfig.mockResolvedValue({
132
- interceptors: {
133
- 'BadPlugin': {
134
- name: 'BadPlugin',
135
- target: 'Vendor_TargetModule::js/target.js',
136
- interceptor: 'Vendor_PluginModule::js/plugin.js',
137
- sortOrder: 10
138
- }
139
- }
140
- });
141
-
142
- const emptyTargetModulePath = path.join(fixturesDir, 'emptyTarget.js');
143
-
144
- const allFilesMap = {
145
- 'Vendor_TargetModule/js/target': emptyTargetModulePath,
146
- 'Vendor_PluginModule/js/plugin': pluginModulePath
147
- };
148
-
149
- moduleResolverMock.getAllJsVueFilesWithInheritanceCached.mockReturnValue(allFilesMap);
150
-
151
- // We expect the promise to reject because generateInterceptors throws on invalid target method
152
- await expect(generateInterceptorsService.generateInterceptors(themeName))
153
- .rejects
154
- .toThrow(/does not export/);
155
- });
156
-
157
- test('should skip interception for non-function exports', async () => {
158
- const themeName = 'Vendor/theme-test';
159
-
160
- themeResolverMock.getThemeConfig.mockReturnValue({
161
- src: '/path/to/theme'
162
- });
163
-
164
- moduleResolverMock.getModuleConfigByThemeConfig.mockResolvedValue({
165
- interceptors: {
166
- 'TestPlugin': {
167
- name: 'TestPlugin',
168
- target: 'Vendor_TargetModule::js/targetNonFunction.js',
169
- interceptor: 'Vendor_PluginModule::js/pluginForNonFunction.js',
170
- sortOrder: 10,
171
- active: true
172
- }
173
- }
174
- });
175
-
176
- const allFilesMap = {
177
- 'Vendor_TargetModule/js/targetNonFunction': targetNonFunctionPath,
178
- 'Vendor_PluginModule/js/pluginForNonFunction': pluginForNonFunctionPath
179
- };
180
-
181
- moduleResolverMock.getAllJsVueFilesWithInheritanceCached.mockReturnValue(allFilesMap);
182
-
183
- const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
184
-
185
- const result = await generateInterceptorsService.generateInterceptors(themeName);
186
-
187
- const targetIdentifier = 'Vendor_TargetModule::js/targetNonFunction.js';
188
-
189
- // Since both 'config' and 'default' are objects, and we are trying to intercept them,
190
- // they should be skipped. If all are skipped, the targetIdentifier should not be in result.
191
- expect(result[targetIdentifier]).toBeUndefined();
192
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('is not a function'));
193
-
194
- consoleSpy.mockRestore();
195
- });
196
- });
@@ -1,61 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import createMockConfigResolver from '../__mocks__/configResolver.js';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
-
9
- let scenarios = [
10
- {
11
- scenario: 'a',
12
- themes: [
13
- { code: 'Vendor/theme-a', codeImport: 'Vendor_ModuleNameA::js/test', expected: '/TEST/web/js/test.js' },
14
- { code: 'Vendor/theme-a', codeImport: 'Vendor_ModuleNameA::js/test.vue', expected: '/TEST/web/js/test.js' },
15
- { code: 'Vendor/theme-a', codeImport: 'Vendor_ModuleNameA::js/test.css', expected: undefined },
16
- { code: 'Vendor/theme-a', codeImport: 'Vendor_ModuleNameB::js/test', expected: undefined },
17
- { code: 'Vendor/theme-a', codeImport: null, expected: undefined },
18
- { code: 'Vendor/theme-b', codeImport: 'Vendor_ModuleNameA::js/unknown', expected: undefined }
19
- ]
20
- }
21
- ];
22
-
23
- function mockConfigAndModules(scenario) {
24
- jest.unstable_mockModule('#service/configResolver.js', () => ({
25
- __esModule: true,
26
- default: createMockConfigResolver(scenario).default,
27
- }));
28
-
29
- jest.unstable_mockModule('#service/moduleResolver.js', () => ({
30
- __esModule: true,
31
- default: {
32
- getAllJsVueFilesWithInheritanceCached: jest.fn(() => ({
33
- 'Vendor_ModuleNameA/js/test': '/TEST/web/js/test.js',
34
- })),
35
- }
36
- }));
37
- }
38
-
39
- async function setupInheritModuleResolver(scenario) {
40
- mockConfigAndModules(scenario);
41
- const { default: inheritModuleResolverFactory } = await import('#service/inheritModuleResolver.js');
42
- return inheritModuleResolverFactory();
43
- }
44
-
45
- describe('inherit-resolver', () => {
46
- let inheritModuleResolver;
47
-
48
- beforeEach(() => {
49
- jest.resetModules();
50
- });
51
-
52
- test.each(scenarios.flatMap(({ scenario, themes }) =>
53
- themes.map(({ code, codeImport, expected }) => ([scenario, code, codeImport, expected]))
54
- ))('Scenario "%s", Theme "%s", Import "%s"', async (scenario, code, codeImport, expected) => {
55
- process.env.CURRENT_THEME = code;
56
- inheritModuleResolver = await setupInheritModuleResolver(scenario);
57
- const result = await inheritModuleResolver.resolveId.handler(codeImport);
58
-
59
- expect(result).toEqual(expected);
60
- });
61
- });