@jskit-ai/http-web 0.1.1
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/fixtures/crud-list-date-filters/App.vue +107 -0
- package/fixtures/crud-list-date-filters/index.html +12 -0
- package/fixtures/crud-list-date-filters/main.js +24 -0
- package/fixtures/crud-list-date-filters/vite.config.mjs +18 -0
- package/package.json +150 -0
- package/src/client/bulkActions.js +47 -0
- package/src/client/components/CrudAddEditScreen.vue +186 -0
- package/src/client/components/CrudDeleteAction.vue +93 -0
- package/src/client/components/CrudListBulkActionSurface.vue +126 -0
- package/src/client/components/CrudListDateFilterControl.vue +188 -0
- package/src/client/components/CrudListFilterSurface.vue +388 -0
- package/src/client/components/CrudListRecordActionMenu.vue +120 -0
- package/src/client/components/CrudListScreen.vue +501 -0
- package/src/client/components/CrudViewScreen.vue +197 -0
- package/src/client/composables/crud/crudBindingSupport.js +75 -0
- package/src/client/composables/crud/crudHttpClientSupport.js +57 -0
- package/src/client/composables/crud/crudJsonApiTransportSupport.js +145 -0
- package/src/client/composables/crud/crudLookupFieldLabelSupport.js +151 -0
- package/src/client/composables/crud/crudLookupFieldRuntime.js +251 -0
- package/src/client/composables/crud/crudSchemaFormHelpers.js +464 -0
- package/src/client/composables/internal/crudListFilterLookupSupport.js +161 -0
- package/src/client/composables/internal/crudListParentTitleSupport.js +171 -0
- package/src/client/composables/internal/useOperationScope.js +144 -0
- package/src/client/composables/records/useAddEdit.js +224 -0
- package/src/client/composables/records/useCrudAddEdit.js +227 -0
- package/src/client/composables/records/useCrudList.js +101 -0
- package/src/client/composables/records/useCrudView.js +47 -0
- package/src/client/composables/records/useList.js +500 -0
- package/src/client/composables/records/useView.js +164 -0
- package/src/client/composables/runtime/addEditUiRuntime.js +130 -0
- package/src/client/composables/runtime/listUiRuntime.js +123 -0
- package/src/client/composables/runtime/modelStateHelpers.js +90 -0
- package/src/client/composables/runtime/operationAdapters.js +34 -0
- package/src/client/composables/runtime/operationUiHelpers.js +125 -0
- package/src/client/composables/runtime/operationValidationHelpers.js +51 -0
- package/src/client/composables/runtime/useAddEditCore.js +112 -0
- package/src/client/composables/runtime/useCommandCore.js +123 -0
- package/src/client/composables/runtime/useEndpointResource.js +199 -0
- package/src/client/composables/runtime/useFieldErrorBag.js +61 -0
- package/src/client/composables/runtime/useListCore.js +112 -0
- package/src/client/composables/runtime/useUiFeedback.js +98 -0
- package/src/client/composables/runtime/useViewCore.js +93 -0
- package/src/client/composables/runtime/viewUiRuntime.js +96 -0
- package/src/client/composables/support/errorMessageHelpers.js +66 -0
- package/src/client/composables/support/listQueryParamSupport.js +473 -0
- package/src/client/composables/support/listSearchSupport.js +70 -0
- package/src/client/composables/support/refValueHelpers.js +19 -0
- package/src/client/composables/support/requestQueryRuntimeSupport.js +141 -0
- package/src/client/composables/support/resourceLoadStateHelpers.js +208 -0
- package/src/client/composables/support/routeTemplateHelpers.js +285 -0
- package/src/client/composables/support/scopeHelpers.js +145 -0
- package/src/client/composables/useAccess.js +109 -0
- package/src/client/composables/useCommand.js +118 -0
- package/src/client/composables/useCrudAddEditScreen.js +88 -0
- package/src/client/composables/useCrudDeleteAction.js +160 -0
- package/src/client/composables/useCrudListBulkActions.js +147 -0
- package/src/client/composables/useCrudListFilterLookups.js +146 -0
- package/src/client/composables/useCrudListFilters.js +339 -0
- package/src/client/composables/useCrudListParentTitle.js +151 -0
- package/src/client/composables/useCrudListRowActions.js +144 -0
- package/src/client/composables/useCrudListScreen.js +237 -0
- package/src/client/composables/useCrudViewScreen.js +77 -0
- package/src/client/composables/usePagedCollection.js +181 -0
- package/src/client/composables/useRealtimeQueryInvalidation.js +156 -0
- package/src/client/composables/useScopeRuntime.js +135 -0
- package/src/client/filters.js +15 -0
- package/src/client/index.js +24 -0
- package/src/client/lib/httpClient.js +47 -0
- package/src/client/lib/permissions.js +34 -0
- package/src/client/rowActions.js +47 -0
- package/src/client/support/contractGuards.js +34 -0
- package/src/client/support/crudListDateFilterSupport.js +91 -0
- package/test/addEditUiRuntime.test.js +110 -0
- package/test/crudBindingSupport.test.js +110 -0
- package/test/crudHttpClientSupport.test.js +77 -0
- package/test/crudJsonApiTransportSupport.test.js +179 -0
- package/test/crudListBulkActionSurface.test.js +27 -0
- package/test/crudListDateFilterSupport.test.js +92 -0
- package/test/crudListDateFilterSurface.browser.test.js +182 -0
- package/test/crudListFilterSurface.test.js +90 -0
- package/test/crudLookupFieldRuntime.test.js +264 -0
- package/test/crudScreenComponents.test.js +110 -0
- package/test/errorIntentContract.test.js +31 -0
- package/test/errorMessageHelpers.test.js +28 -0
- package/test/exportsContract.test.js +68 -0
- package/test/listQueryParamSupport.test.js +223 -0
- package/test/listUiRuntime.test.js +102 -0
- package/test/operationValidationHelpers.test.js +64 -0
- package/test/packageBoundary.test.js +31 -0
- package/test/permissions.test.js +35 -0
- package/test/refValueHelpers.test.js +14 -0
- package/test/requestTransportOptions.test.js +457 -0
- package/test/resourceLoadStateHelpers.test.js +189 -0
- package/test/routeTemplateHelpers.test.js +85 -0
- package/test/scopeHelpers.test.js +57 -0
- package/test/useAddEditCore.test.js +124 -0
- package/test/useAddEditRequestQueryParams.test.js +190 -0
- package/test/useCrudAddEdit.test.js +415 -0
- package/test/useCrudDeleteAction.test.js +139 -0
- package/test/useCrudListBulkActions.test.js +65 -0
- package/test/useCrudListFilterLookups.test.js +114 -0
- package/test/useCrudListFilters.test.js +293 -0
- package/test/useCrudListParentTitle.test.js +262 -0
- package/test/useCrudListRowActions.test.js +77 -0
- package/test/useListRouteInitialization.test.js +337 -0
- package/test/useListSearchSupport.test.js +61 -0
- package/test/usePagedCollection.test.js +53 -0
- package/test/useViewRequestQueryParams.test.js +20 -0
- package/test/viewCoreLoading.test.js +44 -0
- package/test/viewUiRuntime.test.js +95 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { computed } from "vue";
|
|
4
|
+
import {
|
|
5
|
+
isScopedOwnershipFilter,
|
|
6
|
+
normalizeOwnershipFilter,
|
|
7
|
+
resolveApiSuffix,
|
|
8
|
+
resolveResourceMessages
|
|
9
|
+
} from "../src/client/composables/support/scopeHelpers.js";
|
|
10
|
+
|
|
11
|
+
test("resolveResourceMessages merges defaults with resource messages", () => {
|
|
12
|
+
const messages = resolveResourceMessages(
|
|
13
|
+
{
|
|
14
|
+
messages: {
|
|
15
|
+
saveError: "Unable to update workspace settings.",
|
|
16
|
+
saveSuccess: "Workspace settings updated."
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
validation: "Fix invalid values and try again.",
|
|
21
|
+
saveSuccess: "Saved.",
|
|
22
|
+
saveError: "Unable to save."
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
assert.deepEqual(messages, {
|
|
27
|
+
validation: "Fix invalid values and try again.",
|
|
28
|
+
saveSuccess: "Workspace settings updated.",
|
|
29
|
+
saveError: "Unable to update workspace settings."
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("resolveApiSuffix unwraps computed refs", () => {
|
|
34
|
+
const suffix = computed(() => "/customers/42");
|
|
35
|
+
|
|
36
|
+
assert.equal(resolveApiSuffix(suffix), "/customers/42");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("resolveApiSuffix unwraps function-returned computed refs", () => {
|
|
40
|
+
const suffix = computed(() => "/customers/42");
|
|
41
|
+
|
|
42
|
+
assert.equal(resolveApiSuffix(() => suffix), "/customers/42");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("normalizeOwnershipFilter accepts route visibility levels", () => {
|
|
46
|
+
assert.equal(normalizeOwnershipFilter("public"), "public");
|
|
47
|
+
assert.equal(normalizeOwnershipFilter("workspace"), "workspace");
|
|
48
|
+
assert.equal(normalizeOwnershipFilter("user"), "user");
|
|
49
|
+
assert.equal(normalizeOwnershipFilter("workspace_user"), "workspace_user");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("isScopedOwnershipFilter only matches scoped ownership levels", () => {
|
|
53
|
+
assert.equal(isScopedOwnershipFilter("workspace"), true);
|
|
54
|
+
assert.equal(isScopedOwnershipFilter("workspace_user"), true);
|
|
55
|
+
assert.equal(isScopedOwnershipFilter("public"), false);
|
|
56
|
+
assert.equal(isScopedOwnershipFilter("user"), false);
|
|
57
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { QueryClient, VueQueryPlugin } from "@tanstack/vue-query";
|
|
4
|
+
import { computed, createSSRApp, effectScope, h, reactive, ref } from "vue";
|
|
5
|
+
import { useAddEditCore } from "../src/client/composables/runtime/useAddEditCore.js";
|
|
6
|
+
|
|
7
|
+
test("useAddEditCore writes saved payloads to the submit-time query key", async () => {
|
|
8
|
+
const queryClient = new QueryClient();
|
|
9
|
+
const model = reactive({
|
|
10
|
+
status: "draft"
|
|
11
|
+
});
|
|
12
|
+
const payload = {
|
|
13
|
+
id: 42,
|
|
14
|
+
status: "published"
|
|
15
|
+
};
|
|
16
|
+
const resource = {
|
|
17
|
+
isSaving: ref(false),
|
|
18
|
+
async save() {
|
|
19
|
+
return payload;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
let runtime = null;
|
|
23
|
+
const app = createSSRApp({
|
|
24
|
+
render() {
|
|
25
|
+
return h("div");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
app.use(VueQueryPlugin, {
|
|
29
|
+
queryClient
|
|
30
|
+
});
|
|
31
|
+
const scope = effectScope();
|
|
32
|
+
|
|
33
|
+
app.runWithContext(() => {
|
|
34
|
+
scope.run(() => {
|
|
35
|
+
runtime = useAddEditCore({
|
|
36
|
+
model,
|
|
37
|
+
resource,
|
|
38
|
+
queryKey: computed(() => ["products", model.status]),
|
|
39
|
+
canSave: ref(true),
|
|
40
|
+
fieldBag: {
|
|
41
|
+
clear() {},
|
|
42
|
+
apply() {}
|
|
43
|
+
},
|
|
44
|
+
feedback: {
|
|
45
|
+
clear() {},
|
|
46
|
+
success() {},
|
|
47
|
+
error() {}
|
|
48
|
+
},
|
|
49
|
+
mapLoadedToModel(target = {}, loaded = {}) {
|
|
50
|
+
target.status = loaded.status;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await runtime.submit();
|
|
57
|
+
scope.stop();
|
|
58
|
+
|
|
59
|
+
assert.equal(model.status, "published");
|
|
60
|
+
assert.deepEqual(queryClient.getQueryData(["products", "draft"]), payload);
|
|
61
|
+
assert.equal(queryClient.getQueryData(["products", "published"]), undefined);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("useAddEditCore snapshots the cache key after payload normalization", async () => {
|
|
65
|
+
const queryClient = new QueryClient();
|
|
66
|
+
const model = reactive({
|
|
67
|
+
status: "draft"
|
|
68
|
+
});
|
|
69
|
+
const payload = {
|
|
70
|
+
id: 42,
|
|
71
|
+
status: "published"
|
|
72
|
+
};
|
|
73
|
+
const resource = {
|
|
74
|
+
isSaving: ref(false),
|
|
75
|
+
async save() {
|
|
76
|
+
return payload;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
let runtime = null;
|
|
80
|
+
const app = createSSRApp({
|
|
81
|
+
render() {
|
|
82
|
+
return h("div");
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
app.use(VueQueryPlugin, {
|
|
86
|
+
queryClient
|
|
87
|
+
});
|
|
88
|
+
const scope = effectScope();
|
|
89
|
+
|
|
90
|
+
app.runWithContext(() => {
|
|
91
|
+
scope.run(() => {
|
|
92
|
+
runtime = useAddEditCore({
|
|
93
|
+
model,
|
|
94
|
+
resource,
|
|
95
|
+
queryKey: computed(() => ["products", model.status]),
|
|
96
|
+
canSave: ref(true),
|
|
97
|
+
fieldBag: {
|
|
98
|
+
clear() {},
|
|
99
|
+
apply() {}
|
|
100
|
+
},
|
|
101
|
+
feedback: {
|
|
102
|
+
clear() {},
|
|
103
|
+
success() {},
|
|
104
|
+
error() {}
|
|
105
|
+
},
|
|
106
|
+
buildRawPayload() {
|
|
107
|
+
model.status = "normalized";
|
|
108
|
+
return {};
|
|
109
|
+
},
|
|
110
|
+
mapLoadedToModel(target = {}, loaded = {}) {
|
|
111
|
+
target.status = loaded.status;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await runtime.submit();
|
|
118
|
+
scope.stop();
|
|
119
|
+
|
|
120
|
+
assert.equal(model.status, "published");
|
|
121
|
+
assert.equal(queryClient.getQueryData(["products", "draft"]), undefined);
|
|
122
|
+
assert.deepEqual(queryClient.getQueryData(["products", "normalized"]), payload);
|
|
123
|
+
assert.equal(queryClient.getQueryData(["products", "published"]), undefined);
|
|
124
|
+
});
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { computed, reactive, ref, shallowRef } from "vue";
|
|
4
|
+
import { createRequestQueryRuntime } from "../src/client/composables/support/requestQueryRuntimeSupport.js";
|
|
5
|
+
|
|
6
|
+
test("add/edit request query params resolve stable cache tokens and request query objects", () => {
|
|
7
|
+
const sourceQueryKey = ref(["products", "dev-admin"]);
|
|
8
|
+
const context = ref(Object.freeze({
|
|
9
|
+
surfaceId: "admin",
|
|
10
|
+
scopeParamValue: "dev-admin",
|
|
11
|
+
ownershipFilter: "workspace",
|
|
12
|
+
recordId: "product-42",
|
|
13
|
+
model: {
|
|
14
|
+
status: "draft"
|
|
15
|
+
}
|
|
16
|
+
}));
|
|
17
|
+
const runtime = createRequestQueryRuntime({
|
|
18
|
+
requestQueryParams(callbackContext = {}) {
|
|
19
|
+
assert.deepEqual(callbackContext, context.value);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
include: "serviceId,bookingSteps,bookingSteps.requiredRoleId",
|
|
23
|
+
preview: callbackContext.model.status === "draft"
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
context,
|
|
27
|
+
sourceQueryKey
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
assert.deepEqual(runtime.activeRequestQueryParamEntries.value, [
|
|
31
|
+
{
|
|
32
|
+
key: "include",
|
|
33
|
+
values: ["serviceId,bookingSteps,bookingSteps.requiredRoleId"]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
key: "preview",
|
|
37
|
+
values: ["1"]
|
|
38
|
+
}
|
|
39
|
+
]);
|
|
40
|
+
assert.equal(
|
|
41
|
+
runtime.activeRequestQueryParamsToken.value,
|
|
42
|
+
"include=serviceId,bookingSteps,bookingSteps.requiredRoleId&preview=1"
|
|
43
|
+
);
|
|
44
|
+
assert.deepEqual(
|
|
45
|
+
runtime.queryKey.value,
|
|
46
|
+
[
|
|
47
|
+
"products",
|
|
48
|
+
"dev-admin",
|
|
49
|
+
"__request_query__",
|
|
50
|
+
"include=serviceId,bookingSteps,bookingSteps.requiredRoleId&preview=1"
|
|
51
|
+
]
|
|
52
|
+
);
|
|
53
|
+
assert.deepEqual(runtime.requestQuery.value, {
|
|
54
|
+
include: "serviceId,bookingSteps,bookingSteps.requiredRoleId",
|
|
55
|
+
preview: "1"
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("add/edit request query params react to callback context changes", () => {
|
|
60
|
+
const recordId = ref("product-42");
|
|
61
|
+
const model = reactive({
|
|
62
|
+
status: "draft"
|
|
63
|
+
});
|
|
64
|
+
const context = computed(() => Object.freeze({
|
|
65
|
+
surfaceId: "admin",
|
|
66
|
+
scopeParamValue: "dev-admin",
|
|
67
|
+
ownershipFilter: "workspace",
|
|
68
|
+
recordId: recordId.value,
|
|
69
|
+
model
|
|
70
|
+
}));
|
|
71
|
+
const runtime = createRequestQueryRuntime({
|
|
72
|
+
requestQueryParams(callbackContext = {}) {
|
|
73
|
+
return {
|
|
74
|
+
include: "bookingSteps",
|
|
75
|
+
preview: callbackContext.model.status === "draft",
|
|
76
|
+
recordId: callbackContext.recordId
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
context,
|
|
80
|
+
sourceQueryKey: computed(() => ["products", context.value.scopeParamValue])
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
assert.deepEqual(
|
|
84
|
+
runtime.queryKey.value,
|
|
85
|
+
[
|
|
86
|
+
"products",
|
|
87
|
+
"dev-admin",
|
|
88
|
+
"__request_query__",
|
|
89
|
+
"include=bookingSteps&preview=1&recordId=product-42"
|
|
90
|
+
]
|
|
91
|
+
);
|
|
92
|
+
assert.deepEqual(runtime.requestQuery.value, {
|
|
93
|
+
include: "bookingSteps",
|
|
94
|
+
preview: "1",
|
|
95
|
+
recordId: "product-42"
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
model.status = "published";
|
|
99
|
+
recordId.value = "product-99";
|
|
100
|
+
|
|
101
|
+
assert.deepEqual(
|
|
102
|
+
runtime.queryKey.value,
|
|
103
|
+
[
|
|
104
|
+
"products",
|
|
105
|
+
"dev-admin",
|
|
106
|
+
"__request_query__",
|
|
107
|
+
"include=bookingSteps&recordId=product-99"
|
|
108
|
+
]
|
|
109
|
+
);
|
|
110
|
+
assert.deepEqual(runtime.requestQuery.value, {
|
|
111
|
+
include: "bookingSteps",
|
|
112
|
+
recordId: "product-99"
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("request query runtime preserves scalar base query keys", () => {
|
|
117
|
+
const runtime = createRequestQueryRuntime({
|
|
118
|
+
requestQueryParams: {
|
|
119
|
+
include: "bookingSteps"
|
|
120
|
+
},
|
|
121
|
+
sourceQueryKey: ref("products"),
|
|
122
|
+
sourcePath: "/api/products/42"
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
assert.deepEqual(
|
|
126
|
+
runtime.queryKey.value,
|
|
127
|
+
[
|
|
128
|
+
"products",
|
|
129
|
+
"__request_query__",
|
|
130
|
+
"include=bookingSteps"
|
|
131
|
+
]
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("request query runtime leaves keys and paths unchanged without active request params", () => {
|
|
136
|
+
const sourceQueryKey = ["products"];
|
|
137
|
+
const runtime = createRequestQueryRuntime({
|
|
138
|
+
requestQueryParams: {
|
|
139
|
+
include: "",
|
|
140
|
+
archived: false
|
|
141
|
+
},
|
|
142
|
+
sourceQueryKey: shallowRef(sourceQueryKey)
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
assert.deepEqual(runtime.activeRequestQueryParamEntries.value, []);
|
|
146
|
+
assert.equal(runtime.activeRequestQueryParamsToken.value, "");
|
|
147
|
+
assert.deepEqual(runtime.queryKey.value, ["products"]);
|
|
148
|
+
assert.equal(runtime.queryKey.value, sourceQueryKey);
|
|
149
|
+
assert.equal(runtime.requestQuery.value, null);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("request query runtime preserves inactive scalar query keys", () => {
|
|
153
|
+
const runtime = createRequestQueryRuntime({
|
|
154
|
+
requestQueryParams: {
|
|
155
|
+
include: ""
|
|
156
|
+
},
|
|
157
|
+
sourceQueryKey: ref("products")
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
assert.equal(runtime.queryKey.value, "products");
|
|
161
|
+
assert.equal(runtime.requestQuery.value, null);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("request query runtime carries typed fieldsets as a first-class query and cache-key dimension", () => {
|
|
165
|
+
const runtime = createRequestQueryRuntime({
|
|
166
|
+
requestQueryParams: {
|
|
167
|
+
include: "operator"
|
|
168
|
+
},
|
|
169
|
+
requestFieldsets: {
|
|
170
|
+
jobs: ["status", "id"],
|
|
171
|
+
contacts: ["displayName", "id"]
|
|
172
|
+
},
|
|
173
|
+
sourceQueryKey: ref(["jobs"])
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
assert.deepEqual(runtime.requestQuery.value, {
|
|
177
|
+
include: "operator",
|
|
178
|
+
fields: {
|
|
179
|
+
contacts: ["displayName", "id"],
|
|
180
|
+
jobs: ["id", "status"]
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
assert.deepEqual(runtime.queryKey.value, [
|
|
184
|
+
"jobs",
|
|
185
|
+
"__request_query__",
|
|
186
|
+
"include=operator",
|
|
187
|
+
"__request_fieldsets__",
|
|
188
|
+
'{"contacts":["displayName","id"],"jobs":["id","status"]}'
|
|
189
|
+
]);
|
|
190
|
+
});
|