@osdk/client 2.2.0-beta.12 → 2.2.0-beta.13
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/CHANGELOG.md +17 -0
- package/build/browser/actions/actions.test.js +1 -1
- package/build/browser/actions/actions.test.js.map +1 -1
- package/build/browser/index.js +1 -1
- package/build/browser/index.js.map +1 -1
- package/build/browser/logger/TestLogger.js +59 -0
- package/build/browser/logger/TestLogger.js.map +1 -0
- package/build/browser/object/attachment.test.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js +4 -0
- package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js +44 -33
- package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects.js +4 -9
- package/build/browser/object/convertWireToOsdkObjects.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects.test.js +29 -25
- package/build/browser/object/convertWireToOsdkObjects.test.js.map +1 -1
- package/build/browser/object/fetchPage.js +4 -3
- package/build/browser/object/fetchPage.js.map +1 -1
- package/build/browser/object/object.test.js +17 -1
- package/build/browser/object/object.test.js.map +1 -1
- package/build/browser/object/timeseries.test.js.map +1 -1
- package/build/browser/objectSet/ObjectSet.test.js +98 -1
- package/build/browser/objectSet/ObjectSet.test.js.map +1 -1
- package/build/browser/objectSet/ObjectSetListenerWebsocket.js +2 -2
- package/build/browser/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
- package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js +2 -3
- package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
- package/build/browser/objectSet/createObjectSet.js +1 -0
- package/build/browser/objectSet/createObjectSet.js.map +1 -1
- package/build/browser/observable/internal/ActionApplication.js +4 -4
- package/build/browser/observable/internal/ActionApplication.js.map +1 -1
- package/build/browser/observable/internal/ObjectQuery.js +1 -1
- package/build/browser/observable/internal/ObjectQuery.js.map +1 -1
- package/build/browser/observable/internal/OptimisticJob.js +1 -1
- package/build/browser/observable/internal/OptimisticJob.js.map +1 -1
- package/build/browser/observable/internal/Store.js +2 -2
- package/build/browser/observable/internal/Store.js.map +1 -1
- package/build/browser/observable/internal/Store.test.js +173 -216
- package/build/browser/observable/internal/Store.test.js.map +1 -1
- package/build/browser/queries/applyQuery.js +3 -3
- package/build/browser/queries/applyQuery.js.map +1 -1
- package/build/browser/util/UserAgent.js +1 -1
- package/build/browser/util/extractRdpDefinition.js +87 -0
- package/build/browser/util/extractRdpDefinition.js.map +1 -0
- package/build/browser/util/extractRdpDefinition.test.js +144 -0
- package/build/browser/util/extractRdpDefinition.test.js.map +1 -0
- package/build/browser/util/objectSpecifierUtils.js +48 -0
- package/build/browser/util/objectSpecifierUtils.js.map +1 -0
- package/build/browser/util/objectSpecifierUtils.test.js +42 -0
- package/build/browser/util/objectSpecifierUtils.test.js.map +1 -0
- package/build/browser/util/toDataValueQueries.js +2 -4
- package/build/browser/util/toDataValueQueries.js.map +1 -1
- package/build/cjs/{chunk-EY52J5Z4.cjs → chunk-USHAX4EP.cjs} +89 -17
- package/build/cjs/chunk-USHAX4EP.cjs.map +1 -0
- package/build/cjs/{chunk-MCQVHD2F.cjs → chunk-VT3UM6EP.cjs} +17 -16
- package/build/cjs/chunk-VT3UM6EP.cjs.map +1 -0
- package/build/cjs/index.cjs +104 -95
- package/build/cjs/index.cjs.map +1 -1
- package/build/cjs/index.d.cts +11 -3
- package/build/cjs/public/internal.cjs +6 -7
- package/build/cjs/public/internal.cjs.map +1 -1
- package/build/cjs/public/unstable-do-not-use.cjs +67 -66
- package/build/cjs/public/unstable-do-not-use.cjs.map +1 -1
- package/build/esm/actions/actions.test.js +1 -1
- package/build/esm/actions/actions.test.js.map +1 -1
- package/build/esm/index.js +1 -1
- package/build/esm/index.js.map +1 -1
- package/build/esm/logger/TestLogger.js +59 -0
- package/build/esm/logger/TestLogger.js.map +1 -0
- package/build/esm/object/attachment.test.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js +4 -0
- package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js +44 -33
- package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects.js +4 -9
- package/build/esm/object/convertWireToOsdkObjects.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects.test.js +29 -25
- package/build/esm/object/convertWireToOsdkObjects.test.js.map +1 -1
- package/build/esm/object/fetchPage.js +4 -3
- package/build/esm/object/fetchPage.js.map +1 -1
- package/build/esm/object/object.test.js +17 -1
- package/build/esm/object/object.test.js.map +1 -1
- package/build/esm/object/timeseries.test.js.map +1 -1
- package/build/esm/objectSet/ObjectSet.test.js +98 -1
- package/build/esm/objectSet/ObjectSet.test.js.map +1 -1
- package/build/esm/objectSet/ObjectSetListenerWebsocket.js +2 -2
- package/build/esm/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
- package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js +2 -3
- package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
- package/build/esm/objectSet/createObjectSet.js +1 -0
- package/build/esm/objectSet/createObjectSet.js.map +1 -1
- package/build/esm/observable/internal/ActionApplication.js +4 -4
- package/build/esm/observable/internal/ActionApplication.js.map +1 -1
- package/build/esm/observable/internal/ObjectQuery.js +1 -1
- package/build/esm/observable/internal/ObjectQuery.js.map +1 -1
- package/build/esm/observable/internal/OptimisticJob.js +1 -1
- package/build/esm/observable/internal/OptimisticJob.js.map +1 -1
- package/build/esm/observable/internal/Store.js +2 -2
- package/build/esm/observable/internal/Store.js.map +1 -1
- package/build/esm/observable/internal/Store.test.js +173 -216
- package/build/esm/observable/internal/Store.test.js.map +1 -1
- package/build/esm/queries/applyQuery.js +3 -3
- package/build/esm/queries/applyQuery.js.map +1 -1
- package/build/esm/util/UserAgent.js +1 -1
- package/build/esm/util/extractRdpDefinition.js +87 -0
- package/build/esm/util/extractRdpDefinition.js.map +1 -0
- package/build/esm/util/extractRdpDefinition.test.js +144 -0
- package/build/esm/util/extractRdpDefinition.test.js.map +1 -0
- package/build/esm/util/objectSpecifierUtils.js +48 -0
- package/build/esm/util/objectSpecifierUtils.js.map +1 -0
- package/build/esm/util/objectSpecifierUtils.test.js +42 -0
- package/build/esm/util/objectSpecifierUtils.test.js.map +1 -0
- package/build/esm/util/toDataValueQueries.js +2 -4
- package/build/esm/util/toDataValueQueries.js.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/logger/TestLogger.d.ts +14 -0
- package/build/types/logger/TestLogger.d.ts.map +1 -0
- package/build/types/object/convertWireToOsdkObjects.d.ts +4 -4
- package/build/types/object/convertWireToOsdkObjects.d.ts.map +1 -1
- package/build/types/object/fetchPage.d.ts.map +1 -1
- package/build/types/object/object.test.d.ts.map +1 -1
- package/build/types/objectSet/ObjectSet.test.d.ts.map +1 -1
- package/build/types/observable/internal/ActionApplication.d.ts +2 -2
- package/build/types/observable/internal/ActionApplication.d.ts.map +1 -1
- package/build/types/observable/internal/OptimisticJob.d.ts.map +1 -1
- package/build/types/observable/internal/Store.d.ts +2 -2
- package/build/types/observable/internal/Store.d.ts.map +1 -1
- package/build/types/queries/applyQuery.d.ts +2 -2
- package/build/types/queries/applyQuery.d.ts.map +1 -1
- package/build/types/util/extractRdpDefinition.d.ts +4 -0
- package/build/types/util/extractRdpDefinition.d.ts.map +1 -0
- package/build/types/util/extractRdpDefinition.test.d.ts +1 -0
- package/build/types/util/extractRdpDefinition.test.d.ts.map +1 -0
- package/build/types/util/objectSpecifierUtils.d.ts +24 -0
- package/build/types/util/objectSpecifierUtils.d.ts.map +1 -0
- package/build/types/util/objectSpecifierUtils.test.d.ts +1 -0
- package/build/types/util/objectSpecifierUtils.test.d.ts.map +1 -0
- package/package.json +11 -11
- package/build/browser/object/createObjectSpecifierFromPrimaryKey.js +0 -20
- package/build/browser/object/createObjectSpecifierFromPrimaryKey.js.map +0 -1
- package/build/cjs/chunk-EY52J5Z4.cjs.map +0 -1
- package/build/cjs/chunk-MCQVHD2F.cjs.map +0 -1
- package/build/cjs/chunk-Q7SFCCGT.cjs +0 -11
- package/build/cjs/chunk-Q7SFCCGT.cjs.map +0 -1
- package/build/cjs/graphql-RGM5SRWV.cjs +0 -10532
- package/build/cjs/graphql-RGM5SRWV.cjs.map +0 -1
- package/build/esm/object/createObjectSpecifierFromPrimaryKey.js +0 -20
- package/build/esm/object/createObjectSpecifierFromPrimaryKey.js.map +0 -1
- package/build/types/object/createObjectSpecifierFromPrimaryKey.d.ts +0 -2
- package/build/types/object/createObjectSpecifierFromPrimaryKey.d.ts.map +0 -1
|
@@ -14,21 +14,21 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { LegacyFauxFoundry, startNodeApiServer, stubData } from "@osdk/shared.test";
|
|
17
|
+
import { editTodo, Employee, FooInterface, Todo } from "@osdk/client.test.ontology";
|
|
18
|
+
import { ActionTypeBuilder, FauxFoundry, ontologies, startNodeApiServer, stubData } from "@osdk/shared.test";
|
|
20
19
|
import chalk from "chalk";
|
|
20
|
+
import invariant from "tiny-invariant";
|
|
21
21
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi, vitest } from "vitest";
|
|
22
|
+
import { ActionValidationError } from "../../actions/ActionValidationError.js";
|
|
22
23
|
import { createClient } from "../../createClient.js";
|
|
23
|
-
import {
|
|
24
|
-
import { createObjectSet } from "../../objectSet/createObjectSet.js";
|
|
25
|
-
import { InterfaceDefinitions } from "../../ontology/OntologyProvider.js";
|
|
24
|
+
import { TestLogger } from "../../logger/TestLogger.js";
|
|
26
25
|
import { createOptimisticId } from "./OptimisticId.js";
|
|
27
26
|
import { runOptimisticJob } from "./OptimisticJob.js";
|
|
28
27
|
import { invalidateList, Store } from "./Store.js";
|
|
29
|
-
import { applyCustomMatchers, createClientMockHelper, createDefer,
|
|
28
|
+
import { applyCustomMatchers, createClientMockHelper, createDefer, expectNoMoreCalls, expectSingleListCallAndClear, expectSingleObjectCallAndClear, getObject, mockListSubCallback, mockSingleSubCallback, objectPayloadContaining, updateList, updateObject, waitForCall } from "./testUtils.js";
|
|
29
|
+
const JOHN_DOE_ID = 50030;
|
|
30
30
|
const defer = createDefer();
|
|
31
|
-
const logger =
|
|
31
|
+
const logger = new TestLogger();
|
|
32
32
|
beforeAll(() => {
|
|
33
33
|
vi.setConfig({
|
|
34
34
|
fakeTimers: {
|
|
@@ -59,6 +59,42 @@ function testStage(s) {
|
|
|
59
59
|
console.log(chalk.bgYellow(`Test Stage: ${s}`));
|
|
60
60
|
}
|
|
61
61
|
applyCustomMatchers();
|
|
62
|
+
function setupOntology(fauxFoundry) {
|
|
63
|
+
const fauxOntology = fauxFoundry.getDefaultOntology();
|
|
64
|
+
ontologies.addEmployeeOntology(fauxOntology);
|
|
65
|
+
fauxFoundry.getDefaultOntology().registerObjectType(stubData.todoWithLinkTypes);
|
|
66
|
+
fauxFoundry.getDefaultOntology().registerActionType(stubData.editTodo.actionTypeV2, (b, payload) => {
|
|
67
|
+
const {
|
|
68
|
+
id,
|
|
69
|
+
...other
|
|
70
|
+
} = payload.parameters;
|
|
71
|
+
b.modifyObject(Todo.apiName, id, {
|
|
72
|
+
...other
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function setupSomeEmployees(fauxFoundry) {
|
|
77
|
+
const dataStore = fauxFoundry.getDefaultDataStore();
|
|
78
|
+
dataStore.registerObject(Employee, {
|
|
79
|
+
employeeId: 1
|
|
80
|
+
});
|
|
81
|
+
dataStore.registerObject(Employee, {
|
|
82
|
+
employeeId: 2
|
|
83
|
+
});
|
|
84
|
+
dataStore.registerObject(Employee, {
|
|
85
|
+
$apiName: "Employee",
|
|
86
|
+
employeeId: 3
|
|
87
|
+
});
|
|
88
|
+
dataStore.registerObject(Employee, {
|
|
89
|
+
$apiName: "Employee",
|
|
90
|
+
employeeId: 4
|
|
91
|
+
});
|
|
92
|
+
dataStore.registerObject(Employee, {
|
|
93
|
+
$apiName: "Employee",
|
|
94
|
+
employeeId: JOHN_DOE_ID,
|
|
95
|
+
fullName: "John Doe"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
62
98
|
describe(Store, () => {
|
|
63
99
|
describe("with mock server", () => {
|
|
64
100
|
let client;
|
|
@@ -66,12 +102,14 @@ describe(Store, () => {
|
|
|
66
102
|
let employeesAsServerReturns;
|
|
67
103
|
let mutatedEmployees;
|
|
68
104
|
beforeAll(async () => {
|
|
69
|
-
const testSetup = startNodeApiServer(new
|
|
105
|
+
const testSetup = startNodeApiServer(new FauxFoundry("https://stack.palantir.com/"), createClient, {
|
|
70
106
|
logger
|
|
71
107
|
});
|
|
72
108
|
({
|
|
73
109
|
client
|
|
74
110
|
} = testSetup);
|
|
111
|
+
setupOntology(testSetup.fauxFoundry);
|
|
112
|
+
setupSomeEmployees(testSetup.fauxFoundry);
|
|
75
113
|
employeesAsServerReturns = (await client(Employee).fetchPage()).data;
|
|
76
114
|
mutatedEmployees = [employeesAsServerReturns[0], employeesAsServerReturns[1].$clone({
|
|
77
115
|
fullName: "foo"
|
|
@@ -364,11 +402,11 @@ describe(Store, () => {
|
|
|
364
402
|
subFn2.error.mockClear();
|
|
365
403
|
});
|
|
366
404
|
const likeEmployee50030 = expect.objectContaining({
|
|
367
|
-
$primaryKey:
|
|
405
|
+
$primaryKey: JOHN_DOE_ID,
|
|
368
406
|
fullName: "John Doe"
|
|
369
407
|
});
|
|
370
408
|
it("fetches and updates twice", async () => {
|
|
371
|
-
defer(cache.observeObject(Employee,
|
|
409
|
+
defer(cache.observeObject(Employee, JOHN_DOE_ID, {
|
|
372
410
|
mode: "force"
|
|
373
411
|
}, subFn1));
|
|
374
412
|
expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
@@ -384,7 +422,7 @@ describe(Store, () => {
|
|
|
384
422
|
}));
|
|
385
423
|
const firstLoad = subFn1.next.mock.lastCall?.[0];
|
|
386
424
|
subFn1.next.mockClear();
|
|
387
|
-
defer(cache.observeObject(Employee,
|
|
425
|
+
defer(cache.observeObject(Employee, JOHN_DOE_ID, {
|
|
388
426
|
mode: "force"
|
|
389
427
|
}, subFn2));
|
|
390
428
|
expectSingleObjectCallAndClear(subFn1, likeEmployee50030, "loading");
|
|
@@ -411,13 +449,13 @@ describe(Store, () => {
|
|
|
411
449
|
subFn.complete.mockClear();
|
|
412
450
|
subFn.next.mockClear();
|
|
413
451
|
subFn.error.mockClear();
|
|
414
|
-
sub = defer(cache.observeObject(Employee,
|
|
452
|
+
sub = defer(cache.observeObject(Employee, JOHN_DOE_ID, {
|
|
415
453
|
mode: "offline"
|
|
416
454
|
}, subFn));
|
|
417
455
|
expectSingleObjectCallAndClear(subFn, undefined, "init");
|
|
418
456
|
});
|
|
419
457
|
it("does basic observation and unsubscribe", async () => {
|
|
420
|
-
const emp = employeesAsServerReturns
|
|
458
|
+
const emp = employeesAsServerReturns.find(x => x.$primaryKey === JOHN_DOE_ID);
|
|
421
459
|
|
|
422
460
|
// force an update
|
|
423
461
|
updateObject(cache, emp);
|
|
@@ -439,7 +477,7 @@ describe(Store, () => {
|
|
|
439
477
|
expect(subFn.next).not.toHaveBeenCalled();
|
|
440
478
|
});
|
|
441
479
|
it("observes with list update", async () => {
|
|
442
|
-
const emp = employeesAsServerReturns
|
|
480
|
+
const emp = employeesAsServerReturns.find(x => x.$primaryKey === JOHN_DOE_ID);
|
|
443
481
|
|
|
444
482
|
// force an update
|
|
445
483
|
updateObject(cache, emp.$clone({
|
|
@@ -632,20 +670,38 @@ describe(Store, () => {
|
|
|
632
670
|
});
|
|
633
671
|
describe("with mock client", () => {
|
|
634
672
|
let client;
|
|
635
|
-
let
|
|
673
|
+
let apiServer;
|
|
674
|
+
let fauxFoundry;
|
|
636
675
|
let store;
|
|
676
|
+
beforeAll(async () => {
|
|
677
|
+
const testSetup = startNodeApiServer(new FauxFoundry("https://stack.palantir.com/", undefined, {
|
|
678
|
+
logger
|
|
679
|
+
}), createClient, {
|
|
680
|
+
logger
|
|
681
|
+
});
|
|
682
|
+
({
|
|
683
|
+
client,
|
|
684
|
+
apiServer,
|
|
685
|
+
fauxFoundry
|
|
686
|
+
} = testSetup);
|
|
687
|
+
setupOntology(testSetup.fauxFoundry);
|
|
688
|
+
return () => {
|
|
689
|
+
testSetup.apiServer.close();
|
|
690
|
+
};
|
|
691
|
+
});
|
|
692
|
+
beforeEach(() => {
|
|
693
|
+
apiServer.resetHandlers();
|
|
694
|
+
});
|
|
637
695
|
beforeEach(async () => {
|
|
638
|
-
mockClient = createClientMockHelper();
|
|
639
|
-
client = mockClient.client;
|
|
640
696
|
store = new Store(client);
|
|
641
697
|
});
|
|
642
698
|
it("properly fires error handler for a list", async () => {
|
|
643
|
-
const error = new Error("A faux error");
|
|
644
|
-
mockClient.mockFetchPageOnce().reject(error);
|
|
645
699
|
const sub = mockListSubCallback();
|
|
646
700
|
store.observeList({
|
|
647
701
|
type: Employee,
|
|
648
|
-
where: {
|
|
702
|
+
where: {
|
|
703
|
+
aBadPropertyThatDoesNotExist: "aBadValue"
|
|
704
|
+
},
|
|
649
705
|
orderBy: {}
|
|
650
706
|
}, sub);
|
|
651
707
|
await waitForCall(sub.error, 1);
|
|
@@ -654,22 +710,14 @@ describe(Store, () => {
|
|
|
654
710
|
});
|
|
655
711
|
describe("batching", () => {
|
|
656
712
|
it("groups requests for single objects", async () => {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
$objectType: "Employee",
|
|
665
|
-
$primaryKey: 1
|
|
666
|
-
}],
|
|
667
|
-
nextPageToken: undefined,
|
|
668
|
-
totalCount: "2"
|
|
713
|
+
fauxFoundry.getDefaultDataStore().registerObject(Employee, {
|
|
714
|
+
$apiName: "Employee",
|
|
715
|
+
employeeId: 0
|
|
716
|
+
});
|
|
717
|
+
fauxFoundry.getDefaultDataStore().registerObject(Employee, {
|
|
718
|
+
$apiName: "Employee",
|
|
719
|
+
employeeId: 1
|
|
669
720
|
});
|
|
670
|
-
vi.mocked(client.fetchMetadata).mockReturnValue(Promise.resolve({
|
|
671
|
-
primaryKeyApiName: "id"
|
|
672
|
-
}));
|
|
673
721
|
const a = mockSingleSubCallback();
|
|
674
722
|
const b = mockSingleSubCallback();
|
|
675
723
|
defer(store.observeObject(Employee, 0, {}, a));
|
|
@@ -696,25 +744,17 @@ describe(Store, () => {
|
|
|
696
744
|
})
|
|
697
745
|
})
|
|
698
746
|
});
|
|
699
|
-
console.log(client.mock.calls);
|
|
700
747
|
});
|
|
701
748
|
});
|
|
702
749
|
describe("actions", () => {
|
|
703
750
|
beforeEach(() => {
|
|
704
|
-
|
|
705
|
-
primaryKeyApiName: "id"
|
|
706
|
-
}));
|
|
751
|
+
fauxFoundry.getDefaultDataStore().clear();
|
|
707
752
|
});
|
|
708
753
|
it("properly invalidates objects", async () => {
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
$apiName: "Todo",
|
|
714
|
-
$primaryKey: 0
|
|
715
|
-
}],
|
|
716
|
-
nextPageToken: undefined,
|
|
717
|
-
totalCount: "1"
|
|
754
|
+
fauxFoundry.getDefaultDataStore().registerObject(Todo, {
|
|
755
|
+
$apiName: "Todo",
|
|
756
|
+
id: 0,
|
|
757
|
+
text: "og title"
|
|
718
758
|
});
|
|
719
759
|
const todoSubFn = mockSingleSubCallback();
|
|
720
760
|
defer(store.observeObject(Todo, 0, {}, todoSubFn));
|
|
@@ -731,25 +771,9 @@ describe(Store, () => {
|
|
|
731
771
|
});
|
|
732
772
|
|
|
733
773
|
// at this point we have an observation properly set up
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
primaryKey: 0
|
|
738
|
-
}]
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
// after we apply the action, the object is invalidated and gets re-requested
|
|
742
|
-
mockClient.mockFetchPageOnce().resolve({
|
|
743
|
-
data: [{
|
|
744
|
-
$primaryKey: 0,
|
|
745
|
-
$apiName: "Todo",
|
|
746
|
-
text: "hello there kind sir"
|
|
747
|
-
}],
|
|
748
|
-
nextPageToken: undefined,
|
|
749
|
-
totalCount: "1"
|
|
750
|
-
});
|
|
751
|
-
await store.applyAction(createOffice, {
|
|
752
|
-
officeId: "whatever"
|
|
774
|
+
await store.applyAction(editTodo, {
|
|
775
|
+
id: 0,
|
|
776
|
+
text: "hello there kind sir"
|
|
753
777
|
});
|
|
754
778
|
await todoSubFn.expectLoadingAndLoaded({
|
|
755
779
|
loading: objectPayloadContaining({
|
|
@@ -763,18 +787,16 @@ describe(Store, () => {
|
|
|
763
787
|
});
|
|
764
788
|
});
|
|
765
789
|
it("rolls back optimistic updates on error", async () => {
|
|
766
|
-
const fauxObject = {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
$title: "does not matter"
|
|
771
|
-
};
|
|
790
|
+
const fauxObject = expect.objectContaining({
|
|
791
|
+
id: 0,
|
|
792
|
+
text: "does not matter"
|
|
793
|
+
});
|
|
772
794
|
|
|
773
|
-
//
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
795
|
+
// set the object in the "backend"
|
|
796
|
+
fauxFoundry.getDefaultDataStore().registerObject(Todo, {
|
|
797
|
+
$apiName: "Todo",
|
|
798
|
+
id: 0,
|
|
799
|
+
text: "does not matter"
|
|
778
800
|
});
|
|
779
801
|
const todoSubFn = mockSingleSubCallback();
|
|
780
802
|
defer(store.observeObject(Todo, 0, {}, todoSubFn));
|
|
@@ -790,94 +812,53 @@ describe(Store, () => {
|
|
|
790
812
|
isOptimistic: false
|
|
791
813
|
})
|
|
792
814
|
});
|
|
815
|
+
const object = store.getValue(store.getCacheKey("object", "Todo", 0))?.value;
|
|
816
|
+
!object ? process.env.NODE_ENV !== "production" ? invariant(false) : invariant(false) : void 0;
|
|
793
817
|
|
|
794
818
|
// at this point we have an observation properly set up
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
officeId: "whatever"
|
|
819
|
+
await expect(store.applyAction(editTodo, {
|
|
820
|
+
id: "not an id that exists"
|
|
798
821
|
}, {
|
|
799
822
|
optimisticUpdate: ctx => {
|
|
800
|
-
ctx.updateObject({
|
|
801
|
-
...fauxObject,
|
|
823
|
+
ctx.updateObject(object.$clone({
|
|
802
824
|
text: "optimistic"
|
|
803
|
-
});
|
|
825
|
+
}));
|
|
804
826
|
}
|
|
827
|
+
})).rejects.toThrow(ActionValidationError);
|
|
828
|
+
await waitForCall(todoSubFn, 2);
|
|
829
|
+
await todoSubFn.expectLoadingAndLoaded({
|
|
830
|
+
loading: objectPayloadContaining({
|
|
831
|
+
status: "loading",
|
|
832
|
+
object: expect.objectContaining({
|
|
833
|
+
id: 0,
|
|
834
|
+
text: "optimistic"
|
|
835
|
+
}),
|
|
836
|
+
isOptimistic: true
|
|
837
|
+
}),
|
|
838
|
+
loaded: objectPayloadContaining({
|
|
839
|
+
object: fauxObject,
|
|
840
|
+
status: "loaded",
|
|
841
|
+
isOptimistic: false
|
|
842
|
+
})
|
|
805
843
|
});
|
|
806
|
-
await waitForCall(todoSubFn, 1);
|
|
807
|
-
expect(todoSubFn.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
808
|
-
object: {
|
|
809
|
-
...fauxObject,
|
|
810
|
-
text: "optimistic"
|
|
811
|
-
},
|
|
812
|
-
status: "loading",
|
|
813
|
-
isOptimistic: true
|
|
814
|
-
}));
|
|
815
|
-
todoSubFn.next.mockClear();
|
|
816
|
-
|
|
817
|
-
// let the action error out
|
|
818
|
-
applyActionResult.reject("an error thrown");
|
|
819
|
-
await expect(actionPromise).rejects.toThrow("an error thrown");
|
|
820
|
-
|
|
821
|
-
// back to the original object
|
|
822
|
-
await waitForCall(todoSubFn, 1);
|
|
823
|
-
expect(todoSubFn.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
824
|
-
object: fauxObject,
|
|
825
|
-
status: "loaded",
|
|
826
|
-
isOptimistic: false
|
|
827
|
-
}));
|
|
828
844
|
});
|
|
829
845
|
});
|
|
830
846
|
describe("orderBy", async () => {
|
|
831
|
-
const ontologyProvider = {
|
|
832
|
-
getObjectDefinition: async () => {
|
|
833
|
-
return {
|
|
834
|
-
...wireObjectTypeFullMetadataToSdkObjectMetadata(stubData.todoWithLinkTypes, true),
|
|
835
|
-
[InterfaceDefinitions]: {}
|
|
836
|
-
};
|
|
837
|
-
},
|
|
838
|
-
getActionDefinition() {
|
|
839
|
-
throw new Error("not implemented");
|
|
840
|
-
},
|
|
841
|
-
getInterfaceDefinition() {
|
|
842
|
-
throw new Error("not implemented");
|
|
843
|
-
},
|
|
844
|
-
getQueryDefinition() {
|
|
845
|
-
throw new Error("not implemented");
|
|
846
|
-
}
|
|
847
|
-
};
|
|
848
|
-
const minimalClient = createMinimalClient({
|
|
849
|
-
ontologyRid: "ri.whatever"
|
|
850
|
-
}, "https://localhost:8080", () => Promise.resolve("token"), {
|
|
851
|
-
logger
|
|
852
|
-
}, fetch, createObjectSet, () => () => ontologyProvider);
|
|
853
|
-
async function createObject(type, x) {
|
|
854
|
-
return (await minimalClient.objectFactory2(minimalClient, [{
|
|
855
|
-
...x,
|
|
856
|
-
$apiName: type.apiName,
|
|
857
|
-
$objectType: type.apiName,
|
|
858
|
-
$objectSpecifier: `${type.apiName}:${x.$primaryKey}`
|
|
859
|
-
}], undefined))[0];
|
|
860
|
-
}
|
|
861
847
|
let nextPk = 0;
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
const fauxObjectC = await createObject(Todo, {
|
|
877
|
-
$primaryKey: nextPk,
|
|
878
|
-
$title: "c",
|
|
879
|
-
id: nextPk,
|
|
880
|
-
text: "c"
|
|
848
|
+
let fauxObjectA;
|
|
849
|
+
let fauxObjectB;
|
|
850
|
+
let fauxObjectC;
|
|
851
|
+
beforeAll(async () => {
|
|
852
|
+
fauxFoundry.getDefaultDataStore().clear();
|
|
853
|
+
[fauxObjectA, fauxObjectB, fauxObjectC] = await Promise.all(["a", "b", "c"].map(text => {
|
|
854
|
+
const id = nextPk++;
|
|
855
|
+
fauxFoundry.getDefaultDataStore().registerObject(Todo, {
|
|
856
|
+
$apiName: "Todo",
|
|
857
|
+
id,
|
|
858
|
+
text
|
|
859
|
+
});
|
|
860
|
+
return client(Todo).fetchOne(id);
|
|
861
|
+
}));
|
|
881
862
|
});
|
|
882
863
|
const noWhereNoOrderBy = {
|
|
883
864
|
type: Todo,
|
|
@@ -893,11 +874,6 @@ describe(Store, () => {
|
|
|
893
874
|
};
|
|
894
875
|
const subListUnordered = mockListSubCallback();
|
|
895
876
|
const subListOrdered = mockListSubCallback();
|
|
896
|
-
beforeEach(() => {
|
|
897
|
-
vi.mocked(client.fetchMetadata).mockReturnValue(Promise.resolve({
|
|
898
|
-
primaryKeyApiName: "id"
|
|
899
|
-
}));
|
|
900
|
-
});
|
|
901
877
|
beforeEach(() => {
|
|
902
878
|
defer(store.observeList({
|
|
903
879
|
...noWhereNoOrderBy,
|
|
@@ -937,14 +913,11 @@ describe(Store, () => {
|
|
|
937
913
|
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB, fauxObjectC]);
|
|
938
914
|
});
|
|
939
915
|
it("produces proper results with optimistic updates and successful action", async () => {
|
|
940
|
-
const optimisticallyMutatedA =
|
|
941
|
-
...fauxObjectA,
|
|
916
|
+
const optimisticallyMutatedA = fauxObjectA.$clone({
|
|
942
917
|
text: "optimistic"
|
|
943
918
|
});
|
|
944
919
|
const pkForOptimistic = nextPk++;
|
|
945
|
-
const optimisticallyCreatedObjectD =
|
|
946
|
-
"$primaryKey": pkForOptimistic,
|
|
947
|
-
"$title": "d",
|
|
920
|
+
const optimisticallyCreatedObjectD = expect.objectContaining({
|
|
948
921
|
"text": "d",
|
|
949
922
|
id: pkForOptimistic
|
|
950
923
|
});
|
|
@@ -960,10 +933,6 @@ describe(Store, () => {
|
|
|
960
933
|
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
|
|
961
934
|
testStage("Start");
|
|
962
935
|
|
|
963
|
-
// the optimistic job will call createObject which triggers the `objectFactory2` of the
|
|
964
|
-
// cache context.
|
|
965
|
-
mockClient.mockObjectFactory2Once().resolve([optimisticallyCreatedObjectD]);
|
|
966
|
-
|
|
967
936
|
// Perform something optimistic.
|
|
968
937
|
const removeOptimisticResult = runOptimisticJob(store, b => {
|
|
969
938
|
b.createObject(Todo, pkForOptimistic, {
|
|
@@ -1005,26 +974,18 @@ describe(Store, () => {
|
|
|
1005
974
|
// I think these are named backwards
|
|
1006
975
|
it("produces proper results with optimistic updates and rollback", async () => {
|
|
1007
976
|
const pkForOptimistic = nextPk++;
|
|
1008
|
-
const optimisticallyCreatedObjectD =
|
|
977
|
+
const optimisticallyCreatedObjectD = expect.objectContaining({
|
|
1009
978
|
"$primaryKey": pkForOptimistic,
|
|
1010
|
-
"$title":
|
|
1011
|
-
|
|
979
|
+
"$title": undefined,
|
|
980
|
+
// FIXME once this is calculated by optimistic then this needs to be the right value
|
|
981
|
+
"text": "d optimistic",
|
|
1012
982
|
id: pkForOptimistic
|
|
1013
983
|
});
|
|
1014
|
-
const optimisticallyMutatedA =
|
|
1015
|
-
...fauxObjectA,
|
|
984
|
+
const optimisticallyMutatedA = fauxObjectA.$clone({
|
|
1016
985
|
text: "optimistic"
|
|
1017
986
|
});
|
|
1018
987
|
testStage("Initial Setup");
|
|
1019
988
|
|
|
1020
|
-
// later we will "create" this object
|
|
1021
|
-
const createdObjectD = await createObject(Todo, {
|
|
1022
|
-
"$primaryKey": 9000,
|
|
1023
|
-
"$title": "d prime",
|
|
1024
|
-
"text": "d prime",
|
|
1025
|
-
id: 9000
|
|
1026
|
-
});
|
|
1027
|
-
|
|
1028
989
|
// for whatever reason, the first list is loaded as [B, A]
|
|
1029
990
|
updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
|
|
1030
991
|
await waitForCall(subListUnordered, 1);
|
|
@@ -1035,19 +996,33 @@ describe(Store, () => {
|
|
|
1035
996
|
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
|
|
1036
997
|
testStage("Optimistic Creation");
|
|
1037
998
|
|
|
999
|
+
// create the weirdest action ever. It always creates a Todo with
|
|
1000
|
+
// a new primary key and the text "d" and updates A
|
|
1001
|
+
const {
|
|
1002
|
+
actionDefinition: crazyAction,
|
|
1003
|
+
actionTypeV2: crazyActionTypeV2
|
|
1004
|
+
} = new ActionTypeBuilder("asdf").addParameter("foo", "string").build();
|
|
1005
|
+
fauxFoundry.getDefaultOntology().registerActionType(crazyActionTypeV2, batch => {
|
|
1006
|
+
const idForD = nextPk++;
|
|
1007
|
+
batch.addObject(Todo.apiName, idForD, {
|
|
1008
|
+
id: idForD,
|
|
1009
|
+
text: "d"
|
|
1010
|
+
});
|
|
1011
|
+
batch.modifyObject(fauxObjectA.$apiName, fauxObjectA.$primaryKey, {
|
|
1012
|
+
text: "a prime",
|
|
1013
|
+
$title: "a prime" // FIXME we shouldn't have to set this, it can be calculated
|
|
1014
|
+
});
|
|
1015
|
+
});
|
|
1016
|
+
|
|
1038
1017
|
// the optimistic job will call createObject which triggers the `objectFactory2` of the
|
|
1039
1018
|
// cache context.
|
|
1040
1019
|
|
|
1041
|
-
|
|
1042
|
-
const
|
|
1043
|
-
testStage("Apply Action");
|
|
1044
|
-
const actionPromise = store.applyAction(createOffice, {
|
|
1045
|
-
officeId: "5"
|
|
1046
|
-
}, {
|
|
1020
|
+
// Perform something optimistic.
|
|
1021
|
+
const pActionResult = store.applyAction(crazyAction, {}, {
|
|
1047
1022
|
optimisticUpdate: b => {
|
|
1048
|
-
b.createObject(Todo,
|
|
1049
|
-
id:
|
|
1050
|
-
text: "d"
|
|
1023
|
+
b.createObject(Todo, pkForOptimistic, {
|
|
1024
|
+
id: pkForOptimistic,
|
|
1025
|
+
text: "d optimistic"
|
|
1051
1026
|
});
|
|
1052
1027
|
b.updateObject(optimisticallyMutatedA);
|
|
1053
1028
|
}
|
|
@@ -1068,33 +1043,15 @@ describe(Store, () => {
|
|
|
1068
1043
|
isOptimistic: true
|
|
1069
1044
|
});
|
|
1070
1045
|
testStage("Resolve Action");
|
|
1071
|
-
const modifiedObjectA =
|
|
1072
|
-
...fauxObjectA,
|
|
1046
|
+
const modifiedObjectA = fauxObjectA.$clone({
|
|
1073
1047
|
text: "a prime"
|
|
1074
1048
|
});
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
nextPageToken: undefined,
|
|
1080
|
-
totalCount: "1"
|
|
1081
|
-
});
|
|
1082
|
-
mockedApplyAction.resolve({
|
|
1083
|
-
addedObjects: [{
|
|
1084
|
-
objectType: "Todo",
|
|
1085
|
-
primaryKey: createdObjectD.id
|
|
1086
|
-
}],
|
|
1087
|
-
modifiedObjects: [{
|
|
1088
|
-
objectType: "Todo",
|
|
1089
|
-
primaryKey: fauxObjectA.$primaryKey
|
|
1090
|
-
}]
|
|
1091
|
-
});
|
|
1092
|
-
await actionPromise;
|
|
1049
|
+
const pkForD = (await pActionResult).addedObjects?.[0].primaryKey;
|
|
1050
|
+
!(typeof pkForD === "number") ? process.env.NODE_ENV !== "production" ? invariant(false) : invariant(false) : void 0;
|
|
1051
|
+
// load this without the cache for comparisons
|
|
1052
|
+
const createdObjectD = await client(Todo).fetchOne(pkForD);
|
|
1093
1053
|
await waitForCall(subListUnordered, 1);
|
|
1094
|
-
|
|
1095
|
-
expectSingleListCallAndClear(subListUnordered, [fauxObjectB,
|
|
1096
|
-
// fauxObjectC,
|
|
1097
|
-
modifiedObjectA, createdObjectD], {
|
|
1054
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, modifiedObjectA, createdObjectD], {
|
|
1098
1055
|
isOptimistic: false
|
|
1099
1056
|
});
|
|
1100
1057
|
await waitForCall(subListOrdered, 1);
|