haori 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +157 -0
  3. package/README.md +158 -0
  4. package/dist/haori.cjs.js +13 -0
  5. package/dist/haori.cjs.js.map +1 -0
  6. package/dist/haori.es.js +2929 -0
  7. package/dist/haori.es.js.map +1 -0
  8. package/dist/haori.iife.js +13 -0
  9. package/dist/haori.iife.js.map +1 -0
  10. package/dist/index.d.ts +824 -0
  11. package/dist/src/core.d.ts +144 -0
  12. package/dist/src/core.d.ts.map +1 -0
  13. package/dist/src/core.js +605 -0
  14. package/dist/src/core.js.map +1 -0
  15. package/dist/src/dev.d.ts +35 -0
  16. package/dist/src/dev.d.ts.map +1 -0
  17. package/dist/src/dev.js +44 -0
  18. package/dist/src/dev.js.map +1 -0
  19. package/dist/src/env.d.ts +25 -0
  20. package/dist/src/env.d.ts.map +1 -0
  21. package/dist/src/env.js +64 -0
  22. package/dist/src/env.js.map +1 -0
  23. package/dist/src/event.d.ts +144 -0
  24. package/dist/src/event.d.ts.map +1 -0
  25. package/dist/src/event.js +221 -0
  26. package/dist/src/event.js.map +1 -0
  27. package/dist/src/event_dispatcher.d.ts +50 -0
  28. package/dist/src/event_dispatcher.d.ts.map +1 -0
  29. package/dist/src/event_dispatcher.js +99 -0
  30. package/dist/src/event_dispatcher.js.map +1 -0
  31. package/dist/src/expression.d.ts +39 -0
  32. package/dist/src/expression.d.ts.map +1 -0
  33. package/dist/src/expression.js +148 -0
  34. package/dist/src/expression.js.map +1 -0
  35. package/dist/src/form.d.ts +113 -0
  36. package/dist/src/form.d.ts.map +1 -0
  37. package/dist/src/form.js +361 -0
  38. package/dist/src/form.js.map +1 -0
  39. package/dist/src/fragment.d.ts +427 -0
  40. package/dist/src/fragment.d.ts.map +1 -0
  41. package/dist/src/fragment.js +1168 -0
  42. package/dist/src/fragment.js.map +1 -0
  43. package/dist/src/haori.d.ts +54 -0
  44. package/dist/src/haori.d.ts.map +1 -0
  45. package/dist/src/haori.js +120 -0
  46. package/dist/src/haori.js.map +1 -0
  47. package/dist/src/import.d.ts +19 -0
  48. package/dist/src/import.d.ts.map +1 -0
  49. package/dist/src/import.js +64 -0
  50. package/dist/src/import.js.map +1 -0
  51. package/dist/src/index.d.ts +17 -0
  52. package/dist/src/index.d.ts.map +1 -0
  53. package/dist/src/index.js +21 -0
  54. package/dist/src/index.js.map +1 -0
  55. package/dist/src/log.d.ts +32 -0
  56. package/dist/src/log.d.ts.map +1 -0
  57. package/dist/src/log.js +43 -0
  58. package/dist/src/log.js.map +1 -0
  59. package/dist/src/observer.d.ts +17 -0
  60. package/dist/src/observer.d.ts.map +1 -0
  61. package/dist/src/observer.js +102 -0
  62. package/dist/src/observer.js.map +1 -0
  63. package/dist/src/procedure.d.ts +203 -0
  64. package/dist/src/procedure.d.ts.map +1 -0
  65. package/dist/src/procedure.js +1040 -0
  66. package/dist/src/procedure.js.map +1 -0
  67. package/dist/src/queue.d.ts +28 -0
  68. package/dist/src/queue.d.ts.map +1 -0
  69. package/dist/src/queue.js +150 -0
  70. package/dist/src/queue.js.map +1 -0
  71. package/dist/src/url.d.ts +14 -0
  72. package/dist/src/url.d.ts.map +1 -0
  73. package/dist/src/url.js +22 -0
  74. package/dist/src/url.js.map +1 -0
  75. package/dist/tests/click-attributes.test.d.ts +2 -0
  76. package/dist/tests/click-attributes.test.d.ts.map +1 -0
  77. package/dist/tests/click-attributes.test.js +95 -0
  78. package/dist/tests/click-attributes.test.js.map +1 -0
  79. package/dist/tests/core.test.d.ts +5 -0
  80. package/dist/tests/core.test.d.ts.map +1 -0
  81. package/dist/tests/core.test.js +158 -0
  82. package/dist/tests/core.test.js.map +1 -0
  83. package/dist/tests/data-each-browserlike.test.d.ts +2 -0
  84. package/dist/tests/data-each-browserlike.test.d.ts.map +1 -0
  85. package/dist/tests/data-each-browserlike.test.js +48 -0
  86. package/dist/tests/data-each-browserlike.test.js.map +1 -0
  87. package/dist/tests/data-each-fragment-debug.test.d.ts +2 -0
  88. package/dist/tests/data-each-fragment-debug.test.d.ts.map +1 -0
  89. package/dist/tests/data-each-fragment-debug.test.js +119 -0
  90. package/dist/tests/data-each-fragment-debug.test.js.map +1 -0
  91. package/dist/tests/data-each-table.test.d.ts +2 -0
  92. package/dist/tests/data-each-table.test.d.ts.map +1 -0
  93. package/dist/tests/data-each-table.test.js +63 -0
  94. package/dist/tests/data-each-table.test.js.map +1 -0
  95. package/dist/tests/dev.test.d.ts +2 -0
  96. package/dist/tests/dev.test.d.ts.map +1 -0
  97. package/dist/tests/dev.test.js +51 -0
  98. package/dist/tests/dev.test.js.map +1 -0
  99. package/dist/tests/each_arg.test.d.ts +2 -0
  100. package/dist/tests/each_arg.test.d.ts.map +1 -0
  101. package/dist/tests/each_arg.test.js +41 -0
  102. package/dist/tests/each_arg.test.js.map +1 -0
  103. package/dist/tests/env.test.d.ts +2 -0
  104. package/dist/tests/env.test.d.ts.map +1 -0
  105. package/dist/tests/env.test.js +96 -0
  106. package/dist/tests/env.test.js.map +1 -0
  107. package/dist/tests/event.test.d.ts +2 -0
  108. package/dist/tests/event.test.d.ts.map +1 -0
  109. package/dist/tests/event.test.js +287 -0
  110. package/dist/tests/event.test.js.map +1 -0
  111. package/dist/tests/expression.test.d.ts +2 -0
  112. package/dist/tests/expression.test.d.ts.map +1 -0
  113. package/dist/tests/expression.test.js +281 -0
  114. package/dist/tests/expression.test.js.map +1 -0
  115. package/dist/tests/fetch-and-procedure-scenarios.test.d.ts +2 -0
  116. package/dist/tests/fetch-and-procedure-scenarios.test.d.ts.map +1 -0
  117. package/dist/tests/fetch-and-procedure-scenarios.test.js +133 -0
  118. package/dist/tests/fetch-and-procedure-scenarios.test.js.map +1 -0
  119. package/dist/tests/form.test.d.ts +2 -0
  120. package/dist/tests/form.test.d.ts.map +1 -0
  121. package/dist/tests/form.test.js +607 -0
  122. package/dist/tests/form.test.js.map +1 -0
  123. package/dist/tests/fragment.test.d.ts +2 -0
  124. package/dist/tests/fragment.test.d.ts.map +1 -0
  125. package/dist/tests/fragment.test.js +164 -0
  126. package/dist/tests/fragment.test.js.map +1 -0
  127. package/dist/tests/import.test.d.ts +2 -0
  128. package/dist/tests/import.test.d.ts.map +1 -0
  129. package/dist/tests/import.test.js +148 -0
  130. package/dist/tests/import.test.js.map +1 -0
  131. package/dist/tests/log.test.d.ts +2 -0
  132. package/dist/tests/log.test.d.ts.map +1 -0
  133. package/dist/tests/log.test.js +58 -0
  134. package/dist/tests/log.test.js.map +1 -0
  135. package/dist/tests/procedure-action-operations.test.d.ts +2 -0
  136. package/dist/tests/procedure-action-operations.test.d.ts.map +1 -0
  137. package/dist/tests/procedure-action-operations.test.js +148 -0
  138. package/dist/tests/procedure-action-operations.test.js.map +1 -0
  139. package/dist/tests/procedure-fetch-options.test.d.ts +2 -0
  140. package/dist/tests/procedure-fetch-options.test.d.ts.map +1 -0
  141. package/dist/tests/procedure-fetch-options.test.js +131 -0
  142. package/dist/tests/procedure-fetch-options.test.js.map +1 -0
  143. package/dist/tests/procedure.test.d.ts +2 -0
  144. package/dist/tests/procedure.test.d.ts.map +1 -0
  145. package/dist/tests/procedure.test.js +136 -0
  146. package/dist/tests/procedure.test.js.map +1 -0
  147. package/dist/tests/procedure_events.test.d.ts +7 -0
  148. package/dist/tests/procedure_events.test.d.ts.map +1 -0
  149. package/dist/tests/procedure_events.test.js +96 -0
  150. package/dist/tests/procedure_events.test.js.map +1 -0
  151. package/dist/tests/reset_each.test.d.ts +2 -0
  152. package/dist/tests/reset_each.test.d.ts.map +1 -0
  153. package/dist/tests/reset_each.test.js +215 -0
  154. package/dist/tests/reset_each.test.js.map +1 -0
  155. package/dist/tests/row-move.test.d.ts +2 -0
  156. package/dist/tests/row-move.test.d.ts.map +1 -0
  157. package/dist/tests/row-move.test.js +197 -0
  158. package/dist/tests/row-move.test.js.map +1 -0
  159. package/dist/tests/row-operations.test.d.ts +2 -0
  160. package/dist/tests/row-operations.test.d.ts.map +1 -0
  161. package/dist/tests/row-operations.test.js +238 -0
  162. package/dist/tests/row-operations.test.js.map +1 -0
  163. package/dist/tests/url.test.d.ts +2 -0
  164. package/dist/tests/url.test.d.ts.map +1 -0
  165. package/dist/tests/url.test.js +150 -0
  166. package/dist/tests/url.test.js.map +1 -0
  167. package/dist/vite.config.d.ts +3 -0
  168. package/dist/vite.config.d.ts.map +1 -0
  169. package/dist/vite.config.js +28 -0
  170. package/dist/vite.config.js.map +1 -0
  171. package/dist/vitest.config.d.ts +3 -0
  172. package/dist/vitest.config.d.ts.map +1 -0
  173. package/dist/vitest.config.js +19 -0
  174. package/dist/vitest.config.js.map +1 -0
  175. package/package.json +68 -0
@@ -0,0 +1,131 @@
1
+ /* @vitest-environment jsdom */
2
+ /**
3
+ * Procedure の fetch オプションと前後フックに関するテスト
4
+ */
5
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
6
+ import Core from '../src/core';
7
+ describe('Procedure fetch options and hooks', () => {
8
+ beforeEach(async () => {
9
+ vi.restoreAllMocks();
10
+ await import('../src/observer');
11
+ });
12
+ it('sends JSON body for POST when method is POST', async () => {
13
+ const fetchSpy = vi.spyOn(globalThis, 'fetch').mockImplementation(() => {
14
+ return Promise.resolve(new Response('{}', { headers: { 'Content-Type': 'application/json' } }));
15
+ });
16
+ const container = document.createElement('div');
17
+ document.body.appendChild(container);
18
+ // 非イベント fetch 属性を使って POST を要求
19
+ const src = document.createElement('div');
20
+ src.setAttribute('data-fetch', 'http://api.test/post');
21
+ src.setAttribute('data-fetch-method', 'POST');
22
+ src.setAttribute('data-fetch-data', 'x=1');
23
+ container.appendChild(src);
24
+ await new Promise(resolve => setTimeout(resolve, 50));
25
+ expect(fetchSpy).toHaveBeenCalled();
26
+ const called = fetchSpy.mock.calls.slice(-1)[0];
27
+ const options = called[1];
28
+ if (options) {
29
+ expect(String(options.method).toUpperCase()).toBe('POST');
30
+ }
31
+ container.remove();
32
+ });
33
+ it('handles multipart headers and FormData', async () => {
34
+ const fetchSpy = vi.spyOn(globalThis, 'fetch').mockImplementation(() => {
35
+ return Promise.resolve(new Response('{}', { headers: { 'Content-Type': 'application/json' } }));
36
+ });
37
+ const container = document.createElement('div');
38
+ document.body.appendChild(container);
39
+ const src = document.createElement('div');
40
+ src.setAttribute('data-fetch', 'http://api.test/upload');
41
+ src.setAttribute('data-fetch-method', 'POST');
42
+ const headersObj = { 'Content-Type': 'multipart/form-data', 'X-Test': '1' };
43
+ src.setAttribute('data-fetch-headers', JSON.stringify(headersObj));
44
+ src.setAttribute('data-fetch-data', JSON.stringify({ a: 'b' }));
45
+ container.appendChild(src);
46
+ await new Promise(resolve => setTimeout(resolve, 50));
47
+ expect(fetchSpy).toHaveBeenCalled();
48
+ const called = fetchSpy.mock.calls.slice(-1)[0];
49
+ const options = called[1];
50
+ if (options) {
51
+ const headers = new Headers(options.headers || undefined);
52
+ // multipart の場合ライブラリは Content-Type を削除し FormData を body に設定する
53
+ expect(headers.get('Content-Type')).toBeNull();
54
+ expect(options.body).toBeInstanceOf(FormData);
55
+ }
56
+ container.remove();
57
+ });
58
+ it('bindArg binds response under key', async () => {
59
+ vi.spyOn(globalThis, 'fetch').mockImplementation(() => {
60
+ return Promise.resolve(new Response(JSON.stringify({ got: true }), {
61
+ headers: { 'Content-Type': 'application/json' },
62
+ }));
63
+ });
64
+ const sbd = vi.spyOn(Core, 'setBindingData').mockResolvedValue(undefined);
65
+ const container = document.createElement('div');
66
+ document.body.appendChild(container);
67
+ const target = document.createElement('div');
68
+ target.id = 'bind-target';
69
+ const src = document.createElement('div');
70
+ src.setAttribute('data-fetch', 'http://api.test/resp');
71
+ src.setAttribute('data-fetch-bind', '#bind-target');
72
+ src.setAttribute('data-fetch-bind-arg', 'result');
73
+ container.appendChild(target);
74
+ container.appendChild(src);
75
+ await new Promise(resolve => setTimeout(resolve, 50));
76
+ expect(sbd).toHaveBeenCalled();
77
+ const calls = sbd.mock.calls;
78
+ const last = calls[calls.length - 1];
79
+ const binding = last[1];
80
+ expect(binding).toHaveProperty('result');
81
+ container.remove();
82
+ });
83
+ it('beforeCallback can stop or modify options', async () => {
84
+ const fetchSpy = vi.spyOn(globalThis, 'fetch').mockImplementation(() => {
85
+ return Promise.resolve(new Response('{}', { headers: { 'Content-Type': 'application/json' } }));
86
+ });
87
+ // Case: beforeCallback returns false -> use data-click-before-run to return false
88
+ const container = document.createElement('div');
89
+ document.body.appendChild(container);
90
+ const btnStop = document.createElement('button');
91
+ btnStop.setAttribute('data-click-before-run', 'return false;');
92
+ btnStop.setAttribute('data-click-fetch', 'http://api.test/stop');
93
+ container.appendChild(btnStop);
94
+ await new Promise(resolve => setTimeout(resolve, 50));
95
+ btnStop.click();
96
+ await new Promise(resolve => setTimeout(resolve, 50));
97
+ expect(fetchSpy).not.toHaveBeenCalled();
98
+ // Case: beforeCallback modifies fetchOptions
99
+ const btnModify = document.createElement('button');
100
+ const modifyScript = 'return {fetchOptions:{headers:{"X-From-Before":"yes"}}};';
101
+ btnModify.setAttribute('data-click-before-run', modifyScript);
102
+ btnModify.setAttribute('data-click-fetch', 'http://api.test/modify');
103
+ container.appendChild(btnModify);
104
+ await new Promise(resolve => setTimeout(resolve, 50));
105
+ btnModify.click();
106
+ await new Promise(resolve => setTimeout(resolve, 50));
107
+ const called = fetchSpy.mock.calls.slice(-1)[0];
108
+ const headers = new Headers(called[1].headers || undefined);
109
+ expect(headers.get('X-From-Before')).toBe('yes');
110
+ container.remove();
111
+ });
112
+ it('afterCallback can stop further processing', async () => {
113
+ vi.spyOn(globalThis, 'fetch').mockImplementation(() => {
114
+ return Promise.resolve(new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }));
115
+ });
116
+ const sbd = vi.spyOn(Core, 'setBindingData').mockResolvedValue(undefined);
117
+ const container = document.createElement('div');
118
+ document.body.appendChild(container);
119
+ const btn = document.createElement('button');
120
+ btn.setAttribute('data-click-fetch', 'http://api.test/stop');
121
+ btn.setAttribute('data-click-after-run', 'return {stop:true};');
122
+ container.appendChild(btn);
123
+ await new Promise(resolve => setTimeout(resolve, 50));
124
+ btn.click();
125
+ await new Promise(resolve => setTimeout(resolve, 50));
126
+ // setBindingData should not be called because afterCallback returned stop
127
+ expect(sbd).not.toHaveBeenCalled();
128
+ container.remove();
129
+ });
130
+ });
131
+ //# sourceMappingURL=procedure-fetch-options.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedure-fetch-options.test.js","sourceRoot":"","sources":["../../tests/procedure-fetch-options.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=procedure.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedure.test.d.ts","sourceRoot":"","sources":["../../tests/procedure.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,136 @@
1
+ import { describe, it, beforeEach, expect, vi } from 'vitest';
2
+ import Procedure from '../src/procedure';
3
+ import Core from '../src/core';
4
+ import Haori from '../src/haori';
5
+ import Fragment from '../src/fragment';
6
+ vi.mock('../src/core');
7
+ vi.mock('../src/haori');
8
+ class MockFragment {
9
+ constructor() {
10
+ this.value = '';
11
+ this.target = document.createElement('div');
12
+ this.getTarget = () => this.target;
13
+ this.getChildElementFragments = vi.fn(() => []);
14
+ this.getValue = vi.fn(() => this.value);
15
+ this.setValue = vi.fn(async (v) => {
16
+ this.value = v;
17
+ });
18
+ this.getBindingData = vi.fn(() => ({}));
19
+ }
20
+ setTarget(target) {
21
+ this.target = target;
22
+ }
23
+ }
24
+ describe('Procedureクラス', () => {
25
+ beforeEach(() => {
26
+ vi.clearAllMocks();
27
+ });
28
+ it('バリデーションに失敗した場合は即resolveされる', async () => {
29
+ const fragment = new MockFragment();
30
+ const input = document.createElement('input');
31
+ vi.spyOn(input, 'reportValidity').mockReturnValue(false);
32
+ vi.spyOn(input, 'focus').mockImplementation(() => { });
33
+ fragment.setTarget(input);
34
+ const proc = new Procedure({
35
+ targetFragment: fragment,
36
+ formFragment: fragment,
37
+ valid: true,
38
+ });
39
+ await expect(proc.run()).resolves.toBeUndefined();
40
+ expect(input.focus).toHaveBeenCalled();
41
+ });
42
+ it('confirmがfalseの場合は即resolveされる', async () => {
43
+ vi.spyOn(Haori, 'confirm').mockResolvedValue(false);
44
+ const proc = new Procedure({ confirmMessage: 'Are you sure?' });
45
+ await expect(proc.run()).resolves.toBeUndefined();
46
+ expect(Haori.confirm).toHaveBeenCalledWith('Are you sure?');
47
+ });
48
+ it('beforeCallbackでstopが返った場合は停止する', async () => {
49
+ const beforeCallback = vi.fn(() => ({ stop: true }));
50
+ const proc = new Procedure({ beforeCallback });
51
+ await expect(proc.run()).resolves.toBeUndefined();
52
+ expect(beforeCallback).toHaveBeenCalled();
53
+ });
54
+ it('afterCallbackでstopが返った場合は停止する', async () => {
55
+ global.fetch = vi
56
+ .fn()
57
+ .mockResolvedValue(new Response('{}', { headers: { 'Content-Type': 'application/json' } }));
58
+ const afterCallback = vi.fn(() => ({ stop: true }));
59
+ const proc = new Procedure({
60
+ fetchUrl: 'http://test',
61
+ afterCallback,
62
+ });
63
+ await expect(proc.run()).resolves.toBeUndefined();
64
+ expect(afterCallback).toHaveBeenCalled();
65
+ });
66
+ it('bindFragmentsにバインドされる', async () => {
67
+ vi.spyOn(Core, 'setBindingData').mockResolvedValue(undefined);
68
+ global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ foo: 'bar' }), {
69
+ headers: { 'Content-Type': 'application/json' },
70
+ }));
71
+ const fragment = new MockFragment();
72
+ const proc = new Procedure({
73
+ fetchUrl: 'http://test',
74
+ bindFragments: [fragment],
75
+ });
76
+ await expect(proc.run()).resolves.toBeUndefined();
77
+ expect(Core.setBindingData).toHaveBeenCalled();
78
+ });
79
+ it('非イベント: data-fetch-arg で bindArg が適用される', async () => {
80
+ // 準備: ターゲットとソース要素
81
+ const container = document.createElement('div');
82
+ document.body.appendChild(container);
83
+ const target = document.createElement('div');
84
+ target.id = 'tgt';
85
+ const source = document.createElement('div');
86
+ source.setAttribute('data-fetch', 'http://test');
87
+ source.setAttribute('data-fetch-bind', '#tgt');
88
+ source.setAttribute('data-fetch-arg', 'wrapped');
89
+ container.append(target, source);
90
+ // fetch のモック
91
+ global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ x: 1 }), {
92
+ headers: { 'Content-Type': 'application/json' },
93
+ }));
94
+ // setBindingData のスパイ
95
+ const sbd = vi
96
+ .spyOn(Core, 'setBindingData')
97
+ .mockResolvedValue(undefined);
98
+ // Procedure 実行(非イベント)
99
+ const frag = Fragment.get(source);
100
+ const proc = new (await import('../src/procedure')).default(frag, null);
101
+ await expect(proc.run()).resolves.toBeUndefined();
102
+ // 呼び出し検証
103
+ expect(sbd).toHaveBeenCalled();
104
+ const calls = sbd.mock.calls;
105
+ // 最後の呼び出しのデータを確認
106
+ const last = calls[calls.length - 1];
107
+ expect(last[0].id).toBe('tgt');
108
+ const bound = last[1];
109
+ expect(bound).toHaveProperty('wrapped');
110
+ expect(bound['wrapped']).toEqual({ x: 1 });
111
+ // クリーンアップ
112
+ container.remove();
113
+ });
114
+ it('adjustFragmentsで値が増減される', async () => {
115
+ const fragment = new MockFragment();
116
+ fragment.getValue = vi.fn(() => '10');
117
+ fragment.setValue = vi.fn(() => Promise.resolve());
118
+ const proc = new Procedure({
119
+ adjustFragments: [fragment],
120
+ adjustValue: 5,
121
+ });
122
+ await expect(proc.run()).resolves.toBeUndefined();
123
+ expect(fragment.setValue).toHaveBeenCalledWith('15');
124
+ });
125
+ it('validateOneは非input要素でtrueを返す', () => {
126
+ const fragment = new MockFragment();
127
+ fragment.setTarget(document.createElement('div'));
128
+ const proc = new Procedure({});
129
+ expect(proc['validateOne'](fragment)).toBe(true);
130
+ });
131
+ it('confirmはメッセージがなければtrueを返す', async () => {
132
+ const proc = new Procedure({});
133
+ await expect(proc['confirm']()).resolves.toBe(true);
134
+ });
135
+ });
136
+ //# sourceMappingURL=procedure.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedure.test.js","sourceRoot":"","sources":["../../tests/procedure.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ declare global {
2
+ interface Window {
3
+ __afterRan: boolean;
4
+ }
5
+ }
6
+ export {};
7
+ //# sourceMappingURL=procedure_events.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedure_events.test.d.ts","sourceRoot":"","sources":["../../tests/procedure_events.test.ts"],"names":[],"mappings":"AAwHA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
@@ -0,0 +1,96 @@
1
+ import { describe, it, beforeEach, expect, vi, afterEach } from 'vitest';
2
+ import Procedure from '../src/procedure';
3
+ import Fragment from '../src/fragment';
4
+ import Haori from '../src/haori';
5
+ describe('イベント属性: before-run / after-run', () => {
6
+ let container;
7
+ beforeEach(() => {
8
+ container = document.createElement('div');
9
+ document.body.appendChild(container);
10
+ // Reset global flag if used
11
+ // 型安全のために Window 拡張を使用
12
+ window.__afterRan = false;
13
+ });
14
+ afterEach(() => {
15
+ container.remove();
16
+ vi.restoreAllMocks();
17
+ });
18
+ const createFragmentWith = (attrs) => {
19
+ const el = document.createElement('button');
20
+ for (const [k, v] of Object.entries(attrs)) {
21
+ el.setAttribute(k, v);
22
+ }
23
+ container.appendChild(el);
24
+ const frag = Fragment.get(el);
25
+ return frag;
26
+ };
27
+ it('data-???-before-run が false を返すと以後の処理を停止する(dialog が呼ばれない)', async () => {
28
+ const frag = createFragmentWith({
29
+ 'data-click-before-run': 'return false;',
30
+ 'data-click-dialog': 'OK',
31
+ });
32
+ const dialogSpy = vi.spyOn(Haori, 'dialog').mockResolvedValue();
33
+ const proc = new Procedure(frag, 'click');
34
+ await expect(proc.run()).resolves.toBeUndefined();
35
+ expect(dialogSpy).not.toHaveBeenCalled();
36
+ });
37
+ it('data-???-after-run が false を返すと後続(dialog)が実行されない', async () => {
38
+ const frag = createFragmentWith({
39
+ 'data-click-fetch': 'https://example.com/api',
40
+ 'data-click-after-run': 'return false;',
41
+ 'data-click-dialog': 'OK',
42
+ });
43
+ global.fetch = vi.fn().mockResolvedValue(new Response('{}', {
44
+ headers: { 'Content-Type': 'application/json' },
45
+ }));
46
+ const dialogSpy = vi.spyOn(Haori, 'dialog').mockResolvedValue();
47
+ const proc = new Procedure(frag, 'click');
48
+ await expect(proc.run()).resolves.toBeUndefined();
49
+ expect(dialogSpy).not.toHaveBeenCalled();
50
+ });
51
+ it('フェッチエラー時は after-run が実行されない', async () => {
52
+ const frag = createFragmentWith({
53
+ 'data-click-fetch': 'https://example.com/api',
54
+ 'data-click-after-run': 'window.__afterRan = true;',
55
+ });
56
+ global.fetch = vi
57
+ .fn()
58
+ .mockResolvedValue(new Response('bad', { status: 400 }));
59
+ vi.spyOn(Haori, 'addErrorMessage').mockResolvedValue();
60
+ const proc = new Procedure(frag, 'click');
61
+ await expect(proc.run()).resolves.toBeUndefined();
62
+ expect(window.__afterRan).toBe(false);
63
+ });
64
+ it('baseline: fetch が呼ばれる(URL は元の値)', async () => {
65
+ const frag = createFragmentWith({
66
+ 'data-click-fetch': 'https://example.com/original',
67
+ 'data-click-after-run': 'return;',
68
+ });
69
+ const fetchMock = (global.fetch = vi.fn().mockResolvedValue(new Response('{}', {
70
+ headers: { 'Content-Type': 'application/json' },
71
+ })));
72
+ const proc = new Procedure(frag, 'click');
73
+ await expect(proc.run()).resolves.toBeUndefined();
74
+ const calls = fetchMock.mock
75
+ .calls;
76
+ expect(calls.length).toBe(1);
77
+ expect(String(calls[0][0])).toBe('https://example.com/original');
78
+ });
79
+ it('before-run で fetchUrl を上書きできる', async () => {
80
+ const frag = createFragmentWith({
81
+ 'data-click-fetch': 'https://example.com/original',
82
+ 'data-click-before-run': 'return { fetchUrl: \'https://example.com/override\' };',
83
+ 'data-click-after-run': 'return;',
84
+ });
85
+ const fetchMock = (global.fetch = vi.fn().mockResolvedValue(new Response('{}', {
86
+ headers: { 'Content-Type': 'application/json' },
87
+ })));
88
+ const proc = new Procedure(frag, 'click');
89
+ await expect(proc.run()).resolves.toBeUndefined();
90
+ const calls = fetchMock.mock
91
+ .calls;
92
+ expect(calls.length).toBe(1);
93
+ expect(String(calls[0][0])).toBe('https://example.com/override');
94
+ });
95
+ });
96
+ //# sourceMappingURL=procedure_events.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedure_events.test.js","sourceRoot":"","sources":["../../tests/procedure_events.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=reset_each.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reset_each.test.d.ts","sourceRoot":"","sources":["../../tests/reset_each.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,215 @@
1
+ import { describe, it, beforeEach, afterEach, expect, vi } from 'vitest';
2
+ import Fragment from '../src/fragment';
3
+ import Form from '../src/form';
4
+ import Core from '../src/core';
5
+ import Haori from '../src/haori';
6
+ describe('Form.reset と data-each 複製の境界ケース', () => {
7
+ let container;
8
+ beforeEach(() => {
9
+ container = document.createElement('div');
10
+ document.body.appendChild(container);
11
+ vi.spyOn(Core, 'evaluateAll').mockResolvedValue();
12
+ vi.spyOn(Haori, 'clearMessages').mockResolvedValue();
13
+ });
14
+ afterEach(() => {
15
+ vi.restoreAllMocks();
16
+ container.remove();
17
+ });
18
+ const getFrag = (el) => {
19
+ const f = Fragment.get(el);
20
+ return f;
21
+ };
22
+ const markMounted = (f) => {
23
+ f.setMounted(true);
24
+ f.getChildElementFragments().forEach(child => markMounted(child));
25
+ };
26
+ it('data-each 配下で before/after を残し、それ以外の複製を削除する', async () => {
27
+ const each = document.createElement('div');
28
+ each.setAttribute('data-each', '[]');
29
+ const before = document.createElement('div');
30
+ before.setAttribute('data-each-before', '');
31
+ const c1 = document.createElement('div');
32
+ c1.className = 'clone1';
33
+ const c2 = document.createElement('div');
34
+ c2.className = 'clone2';
35
+ const after = document.createElement('div');
36
+ after.setAttribute('data-each-after', '');
37
+ each.append(before, c1, c2, after);
38
+ container.appendChild(each);
39
+ const frag = getFrag(each);
40
+ markMounted(frag);
41
+ await expect(Form.reset(frag)).resolves.toBeUndefined();
42
+ // before/after は残る
43
+ expect(each.querySelector('[data-each-before]')).not.toBeNull();
44
+ expect(each.querySelector('[data-each-after]')).not.toBeNull();
45
+ // クローンは削除される
46
+ expect(each.querySelector('.clone1')).toBeNull();
47
+ expect(each.querySelector('.clone2')).toBeNull();
48
+ expect(Core.evaluateAll).toHaveBeenCalledTimes(1);
49
+ expect(Haori.clearMessages).toHaveBeenCalled();
50
+ });
51
+ it('ネスト: before 内の内側 each の複製も削除される(再帰)', async () => {
52
+ const outer = document.createElement('section');
53
+ outer.setAttribute('data-each', '[]');
54
+ const before = document.createElement('div');
55
+ before.setAttribute('data-each-before', '');
56
+ const inner = document.createElement('div');
57
+ inner.setAttribute('data-each', '[]');
58
+ const ib = document.createElement('span');
59
+ ib.setAttribute('data-each-before', '');
60
+ const ic1 = document.createElement('span');
61
+ ic1.className = 'inner-clone1';
62
+ const ic2 = document.createElement('span');
63
+ ic2.className = 'inner-clone2';
64
+ const ia = document.createElement('span');
65
+ ia.setAttribute('data-each-after', '');
66
+ inner.append(ib, ic1, ic2, ia);
67
+ before.appendChild(inner);
68
+ const after = document.createElement('div');
69
+ after.setAttribute('data-each-after', '');
70
+ outer.append(before, after);
71
+ container.appendChild(outer);
72
+ const frag = getFrag(outer);
73
+ markMounted(frag);
74
+ await expect(Form.reset(frag)).resolves.toBeUndefined();
75
+ // 外側 before/after は残る
76
+ expect(outer.querySelector('[data-each-before]')).not.toBeNull();
77
+ expect(outer.querySelector('[data-each-after]')).not.toBeNull();
78
+ // 内側 each のクローンは削除される(before/after は残る)
79
+ expect(inner.querySelector('.inner-clone1')).toBeNull();
80
+ expect(inner.querySelector('.inner-clone2')).toBeNull();
81
+ expect(inner.querySelector('[data-each-before]')).not.toBeNull();
82
+ expect(inner.querySelector('[data-each-after]')).not.toBeNull();
83
+ });
84
+ it('大量の複製(100)でも全て削除され before/after のみ残る', async () => {
85
+ const each = document.createElement('ul');
86
+ each.setAttribute('data-each', '[]');
87
+ const before = document.createElement('li');
88
+ before.setAttribute('data-each-before', '');
89
+ each.appendChild(before);
90
+ for (let i = 0; i < 100; i++) {
91
+ const li = document.createElement('li');
92
+ li.className = `item-${i}`;
93
+ each.appendChild(li);
94
+ }
95
+ const after = document.createElement('li');
96
+ after.setAttribute('data-each-after', '');
97
+ each.appendChild(after);
98
+ container.appendChild(each);
99
+ const frag = getFrag(each);
100
+ markMounted(frag);
101
+ await expect(Form.reset(frag)).resolves.toBeUndefined();
102
+ // 100個のクローンが削除済み
103
+ let found = false;
104
+ for (let i = 0; i < 100; i++) {
105
+ if (each.querySelector(`.item-${i}`)) {
106
+ found = true;
107
+ break;
108
+ }
109
+ }
110
+ expect(found).toBe(false);
111
+ // before/after は残る
112
+ expect(each.querySelector('[data-each-before]')).not.toBeNull();
113
+ expect(each.querySelector('[data-each-after]')).not.toBeNull();
114
+ });
115
+ it('3段の深い入れ子でも各階層の複製が削除され before/after は保持される', async () => {
116
+ // outer -> middle -> inner と3段の each
117
+ const outer = document.createElement('div');
118
+ outer.setAttribute('data-each', '[]');
119
+ const ob = document.createElement('div');
120
+ ob.setAttribute('data-each-before', '');
121
+ const oa = document.createElement('div');
122
+ oa.setAttribute('data-each-after', '');
123
+ const middle = document.createElement('section');
124
+ middle.setAttribute('data-each', '[]');
125
+ const mb = document.createElement('div');
126
+ mb.setAttribute('data-each-before', '');
127
+ const mc1 = document.createElement('div');
128
+ mc1.className = 'm-clone1';
129
+ const mc2 = document.createElement('div');
130
+ mc2.className = 'm-clone2';
131
+ const ma = document.createElement('div');
132
+ ma.setAttribute('data-each-after', '');
133
+ const inner = document.createElement('article');
134
+ inner.setAttribute('data-each', '[]');
135
+ const ib = document.createElement('span');
136
+ ib.setAttribute('data-each-before', '');
137
+ const ic1 = document.createElement('span');
138
+ ic1.className = 'i-clone1';
139
+ const ic2 = document.createElement('span');
140
+ ic2.className = 'i-clone2';
141
+ const ia = document.createElement('span');
142
+ ia.setAttribute('data-each-after', '');
143
+ inner.append(ib, ic1, ic2, ia);
144
+ middle.append(mb, mc1, mc2, inner, ma);
145
+ // middle は outer の before 内に配置(outer の each で本体は保持される想定)
146
+ ob.appendChild(middle);
147
+ outer.append(ob, oa);
148
+ container.appendChild(outer);
149
+ const frag = getFrag(outer);
150
+ markMounted(frag);
151
+ await expect(Form.reset(frag)).resolves.toBeUndefined();
152
+ // outer 層: before/after 残存
153
+ expect(outer.querySelector('[data-each-before]')).not.toBeNull();
154
+ expect(outer.querySelector('[data-each-after]')).not.toBeNull();
155
+ // middle 層のクローンは削除(DOM 上からも消える)
156
+ expect(outer.querySelector('.m-clone1')).toBeNull();
157
+ expect(outer.querySelector('.m-clone2')).toBeNull();
158
+ // inner 層は本体ごと削除され、クローンも DOM 上に存在しない
159
+ expect(outer.querySelector('article[data-each]')).toBeNull();
160
+ expect(outer.querySelector('.i-clone1')).toBeNull();
161
+ expect(outer.querySelector('.i-clone2')).toBeNull();
162
+ });
163
+ it('複数フォーム混在時に selector 指定の reset で対象フォームのみ each 複製が削除される', async () => {
164
+ // form1 と form2 を用意し、どちらにも each の複製を配置
165
+ const form1 = document.createElement('form');
166
+ form1.id = 'f1';
167
+ const e1 = document.createElement('div');
168
+ e1.setAttribute('data-each', '[]');
169
+ const e1b = document.createElement('div');
170
+ e1b.setAttribute('data-each-before', '');
171
+ const e1c = document.createElement('div');
172
+ e1c.className = 'f1-clone';
173
+ const e1a = document.createElement('div');
174
+ e1a.setAttribute('data-each-after', '');
175
+ e1.append(e1b, e1c, e1a);
176
+ form1.appendChild(e1);
177
+ const form2 = document.createElement('form');
178
+ form2.id = 'f2';
179
+ const e2 = document.createElement('div');
180
+ e2.setAttribute('data-each', '[]');
181
+ const e2b = document.createElement('div');
182
+ e2b.setAttribute('data-each-before', '');
183
+ const e2c = document.createElement('div');
184
+ e2c.className = 'f2-clone';
185
+ const e2a = document.createElement('div');
186
+ e2a.setAttribute('data-each-after', '');
187
+ e2.append(e2b, e2c, e2a);
188
+ form2.appendChild(e2);
189
+ container.append(form1, form2);
190
+ // reset を発火させるボタン
191
+ const button = document.createElement('button');
192
+ button.setAttribute('data-click-reset', '#f1');
193
+ container.appendChild(button);
194
+ const f1 = getFrag(form1);
195
+ const f2 = getFrag(form2);
196
+ const btnFrag = getFrag(button);
197
+ // マウント状態にする(remove() が DOM から除去できるように)
198
+ markMounted(f1);
199
+ markMounted(f2);
200
+ markMounted(btnFrag);
201
+ // Procedure を実行(fetch 無し→成功系フローで reset 実行)
202
+ const Procedure = (await import('../src/procedure')).default;
203
+ const proc = new Procedure(btnFrag, 'click');
204
+ await expect(proc.run()).resolves.toBeUndefined();
205
+ // form1 側の each 複製は削除され、before/after は残る
206
+ expect(form1.querySelector('.f1-clone')).toBeNull();
207
+ expect(form1.querySelector('[data-each-before]')).not.toBeNull();
208
+ expect(form1.querySelector('[data-each-after]')).not.toBeNull();
209
+ // form2 側は影響を受けない(クローンは残存)
210
+ expect(form2.querySelector('.f2-clone')).not.toBeNull();
211
+ expect(form2.querySelector('[data-each-before]')).not.toBeNull();
212
+ expect(form2.querySelector('[data-each-after]')).not.toBeNull();
213
+ });
214
+ });
215
+ //# sourceMappingURL=reset_each.test.js.map