@supersoniks/concorde 4.7.3 → 4.8.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.
- package/README.md +1 -1
- package/ai/AGENTS.md +4 -0
- package/ai/cursor/rules/concorde.mdc +11 -1
- package/ai/jetbrains/rules/concorde.md +8 -0
- package/ai/skills/concorde/SKILL.md +29 -2
- package/ai/skills/concorde-scope/SKILL.md +2 -2
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +289 -289
- package/concorde-core.es.js +4839 -4546
- package/dist/concorde-core.bundle.js +289 -289
- package/dist/concorde-core.es.js +4839 -4546
- package/dist/docs-mock-api-sw.js +19 -0
- package/dist/docs-mock-api-sw.js.map +2 -2
- package/dist/robots.txt +2 -0
- package/docs/assets/index-wyNMyWT9.js +11196 -0
- package/docs/docs-mock-api-sw.js +19 -0
- package/docs/docs-mock-api-sw.js.map +2 -2
- package/docs/index.html +1 -1
- package/docs/robots.txt +2 -0
- package/package.json +9 -1
- package/public/docs-mock-api-sw.js +19 -0
- package/public/docs-mock-api-sw.js.map +2 -2
- package/public/robots.txt +2 -0
- package/src/core/components/functional/example/example.ts +3 -3
- package/src/core/components/ui/captcha/captcha.md +0 -12
- package/src/core/components/ui/icon/icon.ts +17 -2
- package/src/core/components/ui/menu/menu.ts +12 -3
- package/src/core/decorators/api.post.spec.ts +293 -0
- package/src/core/decorators/api.spec.ts +7 -14
- package/src/core/decorators/api.ts +648 -15
- package/src/core/decorators/subscriber/bind.ts +13 -5
- package/src/core/decorators/subscriber/dynamicPath.spec.ts +53 -0
- package/src/core/decorators/subscriber/dynamicPath.ts +23 -1
- package/src/core/decorators/subscriber/handle.ts +3 -1
- package/src/core/decorators/subscriber/onAssign.ts +10 -2
- package/src/core/decorators/subscriber/publish.ts +12 -2
- package/src/core/utils/PublisherProxy.ts +95 -11
- package/src/core/utils/api.ts +72 -3
- package/src/core/utils/dpOptions.spec.ts +56 -0
- package/src/core/utils/endpoint.ts +3 -3
- package/src/decorators.ts +17 -1
- package/src/docs/_core-concept/dataFlow.md +9 -3
- package/src/docs/_decorators/bind.md +2 -2
- package/src/docs/_decorators/get.md +13 -4
- package/src/docs/_decorators/handle.md +5 -1
- package/src/docs/_decorators/on-assign.md +2 -0
- package/src/docs/_decorators/patch.md +45 -0
- package/src/docs/_decorators/post.md +93 -0
- package/src/docs/_decorators/publish.md +1 -1
- package/src/docs/_decorators/put.md +43 -0
- package/src/docs/_decorators/subscribe.md +4 -1
- package/src/docs/_directives/sub.md +1 -1
- package/src/docs/_getting-started/my-first-component.md +1 -1
- package/src/docs/_misc/api-configuration.md +3 -1
- package/src/docs/_misc/dataProviderKey.md +2 -2
- package/src/docs/_misc/dynamic-path.md +71 -0
- package/src/docs/_misc/endpoint.md +5 -3
- package/src/docs/components/docs-demo-sources.ts +102 -3
- package/src/docs/components/docs-lit-demo-raw.ts +2 -26
- package/src/docs/components/docs-lit-demo.ts +9 -42
- package/src/docs/components/docs-source-excerpt.ts +53 -0
- package/src/docs/components/docs-source-link.ts +24 -8
- package/src/docs/components/docs-source-raw.ts +34 -0
- package/src/docs/example/decorators-demo-geo.ts +2 -2
- package/src/docs/example/decorators-demo-post.ts +249 -0
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +5 -5
- package/src/docs/example/decorators-demo.ts +1 -0
- package/src/docs/example/docs-api-config-demos.ts +5 -5
- package/src/docs/mock-api/router.ts +20 -0
- package/src/docs/navigation/navigation.ts +16 -0
- package/src/docs/search/docs-search.json +540 -15
- package/src/tsconfig.json +24 -0
- package/src/tsconfig.tsbuildinfo +1 -1
- package/vite.config.mts +1 -1
- package/docs/assets/index-D9pxaQYK.js +0 -7508
- package/docs/src/core/components/functional/date/date.md +0 -290
- package/docs/src/core/components/functional/fetch/fetch.md +0 -125
- package/docs/src/core/components/functional/if/if.md +0 -9
- package/docs/src/core/components/functional/list/list.md +0 -65
- package/docs/src/core/components/functional/mix/mix.md +0 -41
- package/docs/src/core/components/functional/queue/queue.md +0 -72
- package/docs/src/core/components/functional/router/router.md +0 -94
- package/docs/src/core/components/functional/sdui/default-library.json +0 -108
- package/docs/src/core/components/functional/sdui/example.json +0 -99
- package/docs/src/core/components/functional/sdui/sdui.md +0 -356
- package/docs/src/core/components/functional/states/states.md +0 -87
- package/docs/src/core/components/functional/submit/submit.md +0 -114
- package/docs/src/core/components/functional/subscriber/subscriber.md +0 -91
- package/docs/src/core/components/functional/value/value.md +0 -35
- package/docs/src/core/components/ui/alert/alert.md +0 -121
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/docs/src/core/components/ui/badge/badge.md +0 -127
- package/docs/src/core/components/ui/button/button.md +0 -182
- package/docs/src/core/components/ui/captcha/captcha.md +0 -24
- package/docs/src/core/components/ui/card/card.md +0 -97
- package/docs/src/core/components/ui/divider/divider.md +0 -35
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +0 -77
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +0 -129
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +0 -77
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +0 -44
- package/docs/src/core/components/ui/form/input/input.md +0 -142
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +0 -133
- package/docs/src/core/components/ui/form/radio/radio.md +0 -57
- package/docs/src/core/components/ui/form/select/select.md +0 -71
- package/docs/src/core/components/ui/form/switch/switch.md +0 -57
- package/docs/src/core/components/ui/form/textarea/textarea.md +0 -65
- package/docs/src/core/components/ui/group/group.md +0 -75
- package/docs/src/core/components/ui/icon/icon.md +0 -125
- package/docs/src/core/components/ui/icon/icons.json +0 -1
- package/docs/src/core/components/ui/image/image.md +0 -107
- package/docs/src/core/components/ui/link/link.md +0 -43
- package/docs/src/core/components/ui/loader/loader.md +0 -55
- package/docs/src/core/components/ui/menu/menu.md +0 -329
- package/docs/src/core/components/ui/modal/modal.md +0 -119
- package/docs/src/core/components/ui/pop/pop.md +0 -96
- package/docs/src/core/components/ui/progress/progress.md +0 -63
- package/docs/src/core/components/ui/table/table.md +0 -455
- package/docs/src/core/components/ui/toast/toast.md +0 -166
- package/docs/src/core/components/ui/tooltip/tooltip.md +0 -82
- package/docs/src/docs/_core-concept/dataFlow.md +0 -73
- package/docs/src/docs/_core-concept/overview.md +0 -57
- package/docs/src/docs/_core-concept/subscriber.md +0 -75
- package/docs/src/docs/_decorators/ancestor-attribute.md +0 -79
- package/docs/src/docs/_decorators/auto-subscribe.md +0 -202
- package/docs/src/docs/_decorators/bind.md +0 -167
- package/docs/src/docs/_decorators/get.md +0 -68
- package/docs/src/docs/_decorators/handle.md +0 -171
- package/docs/src/docs/_decorators/on-assign.md +0 -388
- package/docs/src/docs/_decorators/publish.md +0 -55
- package/docs/src/docs/_decorators/subscribe.md +0 -97
- package/docs/src/docs/_decorators/wait-for-ancestors.md +0 -163
- package/docs/src/docs/_directives/sub.md +0 -91
- package/docs/src/docs/_getting-started/ai-agents.md +0 -56
- package/docs/src/docs/_getting-started/concorde-manual-install.md +0 -133
- package/docs/src/docs/_getting-started/concorde-outside.md +0 -33
- package/docs/src/docs/_getting-started/create-a-component.md +0 -139
- package/docs/src/docs/_getting-started/my-first-component.md +0 -236
- package/docs/src/docs/_getting-started/my-first-subscriber.md +0 -120
- package/docs/src/docs/_getting-started/pubsub.md +0 -37
- package/docs/src/docs/_getting-started/start.md +0 -47
- package/docs/src/docs/_getting-started/theming.md +0 -91
- package/docs/src/docs/_misc/api-configuration.md +0 -79
- package/docs/src/docs/_misc/dataProviderKey.md +0 -168
- package/docs/src/docs/_misc/docs-mock-api.md +0 -60
- package/docs/src/docs/_misc/endpoint.md +0 -43
- package/docs/src/docs/_misc/html-integration.md +0 -13
- package/docs/src/docs/search/docs-search.json +0 -8532
- package/docs/src/tag-list.json +0 -1
- package/docs/src/tsconfig-model.json +0 -23
- package/docs/src/tsconfig.json +0 -1050
- package/php/get-challenge.php +0 -34
- package/php/some-service.php +0 -42
|
@@ -3,13 +3,21 @@ import { styleMap } from "lit/directives/style-map.js";
|
|
|
3
3
|
import {
|
|
4
4
|
customElement,
|
|
5
5
|
property,
|
|
6
|
-
queryAssignedElements,
|
|
6
|
+
queryAssignedElements as queryAssignedElementsDecorator,
|
|
7
7
|
state,
|
|
8
8
|
query,
|
|
9
|
+
QueryAssignedElementsDecorator,
|
|
10
|
+
QueryAssignedElementsOptions,
|
|
9
11
|
} from "lit/decorators.js";
|
|
10
12
|
import "@supersoniks/concorde/core/components/ui/menu/menu-item";
|
|
11
13
|
import { Size } from "../_css/size";
|
|
12
14
|
import { Shadow, shadowable } from "../_css/shadow";
|
|
15
|
+
|
|
16
|
+
const queryAssignedElements = (
|
|
17
|
+
options?: QueryAssignedElementsOptions,
|
|
18
|
+
): QueryAssignedElementsDecorator => {
|
|
19
|
+
return queryAssignedElementsDecorator(options);
|
|
20
|
+
};
|
|
13
21
|
const tagName = "sonic-menu";
|
|
14
22
|
|
|
15
23
|
@customElement(tagName)
|
|
@@ -107,7 +115,7 @@ export class MenuItems extends LitElement {
|
|
|
107
115
|
to bottom,
|
|
108
116
|
rgba(0, 0, 0, 0),
|
|
109
117
|
rgba(0, 0, 0, 1) 10%
|
|
110
|
-
);
|
|
118
|
+
);queryAssignedElements
|
|
111
119
|
mask-image: linear-gradient(
|
|
112
120
|
to bottom,
|
|
113
121
|
rgba(0, 0, 0, 0),
|
|
@@ -246,7 +254,8 @@ export class MenuItems extends LitElement {
|
|
|
246
254
|
if (this.scrollable) {
|
|
247
255
|
const activeItems = this.menuChildren.filter(
|
|
248
256
|
(item) =>
|
|
249
|
-
item.hasAttribute("active") &&
|
|
257
|
+
item.hasAttribute("active") &&
|
|
258
|
+
item.getAttribute("active") !== "false",
|
|
250
259
|
);
|
|
251
260
|
|
|
252
261
|
if (activeItems.length === 1) {
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { Endpoint } from "../utils/endpoint";
|
|
3
|
+
import { DataProviderKey } from "../utils/dataProviderKey";
|
|
4
|
+
import API, {
|
|
5
|
+
type ApiResult,
|
|
6
|
+
} from "@supersoniks/concorde/core/utils/api";
|
|
7
|
+
import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
8
|
+
import { patch, post, put } from "./api";
|
|
9
|
+
|
|
10
|
+
async function flushSendFrames() {
|
|
11
|
+
await new Promise<void>((resolve) => {
|
|
12
|
+
requestAnimationFrame(() => {
|
|
13
|
+
requestAnimationFrame(() => resolve());
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
await Promise.resolve();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function mockPayload<T>(result: T, method = "POST") {
|
|
20
|
+
return {
|
|
21
|
+
request: new Request("https://api.example.test/items/1", { method }),
|
|
22
|
+
response: new Response(JSON.stringify(result), {
|
|
23
|
+
status: 200,
|
|
24
|
+
headers: { "Content-Type": "application/json" },
|
|
25
|
+
}),
|
|
26
|
+
result,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe("post", () => {
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
vi.spyOn(API.prototype, "postDetailed").mockResolvedValue(
|
|
33
|
+
mockPayload({ ok: true }) as never,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
vi.restoreAllMocks();
|
|
39
|
+
document.body.replaceChildren();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("assigne ApiResult avec body publisher", async () => {
|
|
43
|
+
const bodyPubId = "postSpecBody1";
|
|
44
|
+
PublisherManager.get(bodyPubId).set({ value: "payload" });
|
|
45
|
+
const bodyKey = new DataProviderKey<{ value: string }>(bodyPubId);
|
|
46
|
+
const syncEp = new Endpoint<{ ok: boolean }>("items/1/sync");
|
|
47
|
+
const tag = "test-api-post-body";
|
|
48
|
+
|
|
49
|
+
class C extends HTMLElement {
|
|
50
|
+
@post(syncEp, bodyKey)
|
|
51
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
52
|
+
}
|
|
53
|
+
if (!customElements.get(tag)) {
|
|
54
|
+
customElements.define(tag, C);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const wrap = document.createElement("div");
|
|
58
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
59
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
60
|
+
wrap.appendChild(el);
|
|
61
|
+
document.body.appendChild(wrap);
|
|
62
|
+
|
|
63
|
+
await flushSendFrames();
|
|
64
|
+
|
|
65
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledWith("items/1/sync", {
|
|
66
|
+
value: "payload",
|
|
67
|
+
});
|
|
68
|
+
expect(el.payload?.result).toEqual({ ok: true });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("endpoint dynamique et relance quand le body publisher mute", async () => {
|
|
72
|
+
const bodyPubId = "postSpecBody2";
|
|
73
|
+
const pub = PublisherManager.get(bodyPubId);
|
|
74
|
+
pub.set({ id: "a" });
|
|
75
|
+
const bodyKey = new DataProviderKey<{ id: string }>(bodyPubId);
|
|
76
|
+
const syncEp = new Endpoint<{ ok: boolean }, { sessionId: string }>(
|
|
77
|
+
"sessions/${sessionId}/sync",
|
|
78
|
+
);
|
|
79
|
+
const tag = "test-api-post-dynamic";
|
|
80
|
+
|
|
81
|
+
class C extends HTMLElement {
|
|
82
|
+
sessionId = "99";
|
|
83
|
+
|
|
84
|
+
@post(syncEp, bodyKey)
|
|
85
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
86
|
+
}
|
|
87
|
+
if (!customElements.get(tag)) {
|
|
88
|
+
customElements.define(tag, C);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const wrap = document.createElement("div");
|
|
92
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
93
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
94
|
+
wrap.appendChild(el);
|
|
95
|
+
document.body.appendChild(wrap);
|
|
96
|
+
|
|
97
|
+
await flushSendFrames();
|
|
98
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledWith(
|
|
99
|
+
"sessions/99/sync",
|
|
100
|
+
{ id: "a" },
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
pub.set({ id: "b" });
|
|
104
|
+
await flushSendFrames();
|
|
105
|
+
expect(API.prototype.postDetailed).toHaveBeenCalled();
|
|
106
|
+
expect(API.prototype.postDetailed).toHaveBeenLastCalledWith(
|
|
107
|
+
"sessions/99/sync",
|
|
108
|
+
{ id: "b" },
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("n'envoie qu'une fois par frame quand le body mute en cascade", async () => {
|
|
113
|
+
const bodyPubId = "postSpecBodyCoalesce";
|
|
114
|
+
const pub = PublisherManager.get(bodyPubId);
|
|
115
|
+
pub.set({ a: 1, b: 2 });
|
|
116
|
+
const bodyKey = new DataProviderKey<{ a: number; b: number }>(bodyPubId);
|
|
117
|
+
const syncEp = new Endpoint<{ ok: boolean }>("sync");
|
|
118
|
+
const tag = "test-api-post-coalesce";
|
|
119
|
+
|
|
120
|
+
class C extends HTMLElement {
|
|
121
|
+
@post(syncEp, bodyKey)
|
|
122
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
123
|
+
}
|
|
124
|
+
if (!customElements.get(tag)) {
|
|
125
|
+
customElements.define(tag, C);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const wrap = document.createElement("div");
|
|
129
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
130
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
131
|
+
wrap.appendChild(el);
|
|
132
|
+
document.body.appendChild(wrap);
|
|
133
|
+
|
|
134
|
+
await flushSendFrames();
|
|
135
|
+
vi.mocked(API.prototype.postDetailed).mockClear();
|
|
136
|
+
|
|
137
|
+
pub.a.set(10);
|
|
138
|
+
pub.b.set(20);
|
|
139
|
+
await flushSendFrames();
|
|
140
|
+
|
|
141
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledTimes(1);
|
|
142
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledWith("sync", {
|
|
143
|
+
a: 10,
|
|
144
|
+
b: 20,
|
|
145
|
+
});
|
|
146
|
+
expect(el.payload?.result).toEqual({ ok: true });
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("ne poste pas sur mutation body si autoPostOnBodyMutation est false", async () => {
|
|
150
|
+
const bodyPubId = "postSpecBodyManual";
|
|
151
|
+
const triggerPubId = "postSpecTriggerManual";
|
|
152
|
+
const pub = PublisherManager.get(bodyPubId);
|
|
153
|
+
pub.set({ tick: 1 });
|
|
154
|
+
const bodyKey = new DataProviderKey<{ tick: number }>(bodyPubId);
|
|
155
|
+
const triggerKey = new DataProviderKey<number>(triggerPubId);
|
|
156
|
+
const syncEp = new Endpoint<{ ok: boolean }>("sync");
|
|
157
|
+
const tag = "test-api-post-manual";
|
|
158
|
+
|
|
159
|
+
class C extends HTMLElement {
|
|
160
|
+
@post(syncEp, bodyKey, {
|
|
161
|
+
autoPostOnBodyMutation: false,
|
|
162
|
+
triggerKey,
|
|
163
|
+
})
|
|
164
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
165
|
+
}
|
|
166
|
+
if (!customElements.get(tag)) {
|
|
167
|
+
customElements.define(tag, C);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const wrap = document.createElement("div");
|
|
171
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
172
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
173
|
+
wrap.appendChild(el);
|
|
174
|
+
document.body.appendChild(wrap);
|
|
175
|
+
|
|
176
|
+
await flushSendFrames();
|
|
177
|
+
const callsAfterConnect = vi.mocked(API.prototype.postDetailed).mock.calls
|
|
178
|
+
.length;
|
|
179
|
+
expect(callsAfterConnect).toBe(0);
|
|
180
|
+
|
|
181
|
+
pub.set({ tick: 2 });
|
|
182
|
+
await flushSendFrames();
|
|
183
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledTimes(0);
|
|
184
|
+
|
|
185
|
+
PublisherManager.get(triggerPubId).invalidate();
|
|
186
|
+
await flushSendFrames();
|
|
187
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledTimes(1);
|
|
188
|
+
expect(API.prototype.postDetailed).toHaveBeenCalledWith("sync", {
|
|
189
|
+
tick: 2,
|
|
190
|
+
});
|
|
191
|
+
expect(el.payload?.result).toEqual({ ok: true });
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("relance le POST quand le publisher trigger est invalidé", async () => {
|
|
195
|
+
const bodyPubId = "postSpecBody3";
|
|
196
|
+
const triggerPubId = "postSpecTrigger3";
|
|
197
|
+
PublisherManager.get(bodyPubId).set({ tick: 1 });
|
|
198
|
+
const bodyKey = new DataProviderKey<{ tick: number }>(bodyPubId);
|
|
199
|
+
const triggerKey = new DataProviderKey<number>(triggerPubId);
|
|
200
|
+
const syncEp = new Endpoint<{ ok: boolean }>("sync");
|
|
201
|
+
const tag = "test-api-post-trigger";
|
|
202
|
+
|
|
203
|
+
class C extends HTMLElement {
|
|
204
|
+
@post(syncEp, bodyKey, { triggerKey })
|
|
205
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
206
|
+
}
|
|
207
|
+
if (!customElements.get(tag)) {
|
|
208
|
+
customElements.define(tag, C);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const wrap = document.createElement("div");
|
|
212
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
213
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
214
|
+
wrap.appendChild(el);
|
|
215
|
+
document.body.appendChild(wrap);
|
|
216
|
+
|
|
217
|
+
await flushSendFrames();
|
|
218
|
+
const callsBeforeInvalidate = vi.mocked(API.prototype.postDetailed).mock.calls.length;
|
|
219
|
+
expect(callsBeforeInvalidate).toBeGreaterThanOrEqual(1);
|
|
220
|
+
|
|
221
|
+
PublisherManager.get(triggerPubId).invalidate();
|
|
222
|
+
await flushSendFrames();
|
|
223
|
+
expect(vi.mocked(API.prototype.postDetailed).mock.calls.length).toBeGreaterThan(
|
|
224
|
+
callsBeforeInvalidate,
|
|
225
|
+
);
|
|
226
|
+
expect(el.payload?.result).toEqual({ ok: true });
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe("put / patch", () => {
|
|
231
|
+
afterEach(() => {
|
|
232
|
+
vi.restoreAllMocks();
|
|
233
|
+
document.body.replaceChildren();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("@put appelle putDetailed", async () => {
|
|
237
|
+
vi.spyOn(API.prototype, "putDetailed").mockResolvedValue(
|
|
238
|
+
mockPayload({ ok: true }, "PUT") as never,
|
|
239
|
+
);
|
|
240
|
+
const bodyPubId = "putSpecBody1";
|
|
241
|
+
PublisherManager.get(bodyPubId).set({ name: "x" });
|
|
242
|
+
const bodyKey = new DataProviderKey<{ name: string }>(bodyPubId);
|
|
243
|
+
const ep = new Endpoint<{ ok: boolean }>("items/1");
|
|
244
|
+
const tag = "test-api-put";
|
|
245
|
+
|
|
246
|
+
class C extends HTMLElement {
|
|
247
|
+
@put(ep, bodyKey)
|
|
248
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
249
|
+
}
|
|
250
|
+
if (!customElements.get(tag)) {
|
|
251
|
+
customElements.define(tag, C);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const wrap = document.createElement("div");
|
|
255
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
256
|
+
wrap.appendChild(document.createElement(tag));
|
|
257
|
+
document.body.appendChild(wrap);
|
|
258
|
+
|
|
259
|
+
await flushSendFrames();
|
|
260
|
+
expect(API.prototype.putDetailed).toHaveBeenCalledWith("items/1", {
|
|
261
|
+
name: "x",
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("@patch appelle patchDetailed", async () => {
|
|
266
|
+
vi.spyOn(API.prototype, "patchDetailed").mockResolvedValue(
|
|
267
|
+
mockPayload({ ok: true }, "PATCH") as never,
|
|
268
|
+
);
|
|
269
|
+
const bodyPubId = "patchSpecBody1";
|
|
270
|
+
PublisherManager.get(bodyPubId).set({ name: "y" });
|
|
271
|
+
const bodyKey = new DataProviderKey<{ name: string }>(bodyPubId);
|
|
272
|
+
const ep = new Endpoint<{ ok: boolean }>("items/1");
|
|
273
|
+
const tag = "test-api-patch";
|
|
274
|
+
|
|
275
|
+
class C extends HTMLElement {
|
|
276
|
+
@patch(ep, bodyKey)
|
|
277
|
+
payload: ApiResult<{ ok: boolean }> | null = null;
|
|
278
|
+
}
|
|
279
|
+
if (!customElements.get(tag)) {
|
|
280
|
+
customElements.define(tag, C);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const wrap = document.createElement("div");
|
|
284
|
+
wrap.setAttribute("serviceURL", "https://api.example.test");
|
|
285
|
+
wrap.appendChild(document.createElement(tag));
|
|
286
|
+
document.body.appendChild(wrap);
|
|
287
|
+
|
|
288
|
+
await flushSendFrames();
|
|
289
|
+
expect(API.prototype.patchDetailed).toHaveBeenCalledWith("items/1", {
|
|
290
|
+
name: "y",
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
});
|
|
@@ -3,7 +3,7 @@ import { Endpoint } from "../utils/endpoint";
|
|
|
3
3
|
import { DataProviderKey } from "../utils/dataProviderKey";
|
|
4
4
|
import API, {
|
|
5
5
|
APIConfiguration,
|
|
6
|
-
type
|
|
6
|
+
type ApiResult,
|
|
7
7
|
} from "@supersoniks/concorde/core/utils/api";
|
|
8
8
|
import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
9
9
|
import { get } from "./api";
|
|
@@ -22,13 +22,6 @@ async function flushGetMicrotasks() {
|
|
|
22
22
|
await Promise.resolve();
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/** @get scoped : scheduleAfterHostReady diffère le fetch (rAF ou updateComplete Lit). */
|
|
26
|
-
async function flushScopedGet() {
|
|
27
|
-
await flushGetMicrotasks();
|
|
28
|
-
await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));
|
|
29
|
-
await flushGetMicrotasks();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
25
|
function mockPayload<T>(result: T) {
|
|
33
26
|
return {
|
|
34
27
|
request: new Request("https://api.example.test/items/1"),
|
|
@@ -52,7 +45,7 @@ describe("get", () => {
|
|
|
52
45
|
document.body.replaceChildren();
|
|
53
46
|
});
|
|
54
47
|
|
|
55
|
-
it("assigne
|
|
48
|
+
it("assigne ApiResult avec configurationKey (publisher)", async () => {
|
|
56
49
|
const pubId = "getSpecPub1";
|
|
57
50
|
PublisherManager.get(pubId).set(staticConfig);
|
|
58
51
|
const confKey = new DataProviderKey<APIConfiguration>(pubId);
|
|
@@ -61,7 +54,7 @@ describe("get", () => {
|
|
|
61
54
|
const tag = "test-api-get-config-key";
|
|
62
55
|
class C extends HTMLElement {
|
|
63
56
|
@get(itemEp, confKey)
|
|
64
|
-
payload:
|
|
57
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
65
58
|
}
|
|
66
59
|
if (!customElements.get(tag)) {
|
|
67
60
|
customElements.define(tag, C);
|
|
@@ -85,7 +78,7 @@ describe("get", () => {
|
|
|
85
78
|
rowId = "42";
|
|
86
79
|
|
|
87
80
|
@get(rowEp, confKey)
|
|
88
|
-
payload:
|
|
81
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
89
82
|
}
|
|
90
83
|
|
|
91
84
|
const tag = "test-api-get-row";
|
|
@@ -106,7 +99,7 @@ describe("get", () => {
|
|
|
106
99
|
|
|
107
100
|
class TestScoped extends HTMLElement {
|
|
108
101
|
@get(dataEp)
|
|
109
|
-
payload:
|
|
102
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
110
103
|
}
|
|
111
104
|
|
|
112
105
|
const tag = "test-api-get-scoped";
|
|
@@ -120,7 +113,7 @@ describe("get", () => {
|
|
|
120
113
|
wrap.appendChild(el);
|
|
121
114
|
document.body.appendChild(wrap);
|
|
122
115
|
|
|
123
|
-
await
|
|
116
|
+
await flushGetMicrotasks();
|
|
124
117
|
|
|
125
118
|
expect(API.prototype.getDetailed).toHaveBeenCalledWith("scoped-endpoint");
|
|
126
119
|
expect(el.payload?.result).toEqual({ id: "loaded" });
|
|
@@ -136,7 +129,7 @@ describe("get", () => {
|
|
|
136
129
|
|
|
137
130
|
class C extends HTMLElement {
|
|
138
131
|
@get(itemEp, confKey)
|
|
139
|
-
payload:
|
|
132
|
+
payload: ApiResult<{ id: string }> | null = null;
|
|
140
133
|
}
|
|
141
134
|
if (!customElements.get(tag)) {
|
|
142
135
|
customElements.define(tag, C);
|