@osdk/client 2.2.0-beta.2 → 2.2.0-beta.20
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 +269 -0
- package/build/browser/Client.js.map +1 -1
- package/build/browser/MinimalClientContext.js.map +1 -1
- package/build/browser/__unstable/ConjureSupport.js.map +1 -1
- package/build/browser/actions/ActionValidationError.js +1 -1
- package/build/browser/actions/ActionValidationError.js.map +1 -1
- package/build/browser/actions/actions.test.js +226 -87
- package/build/browser/actions/actions.test.js.map +1 -1
- package/build/browser/actions/applyAction.js +28 -16
- package/build/browser/actions/applyAction.js.map +1 -1
- package/build/browser/createClient.js +19 -8
- package/build/browser/createClient.js.map +1 -1
- package/build/browser/createClient.test.js +14 -6
- package/build/browser/createClient.test.js.map +1 -1
- package/build/browser/createMinimalClient.js +2 -2
- package/build/browser/createMinimalClient.js.map +1 -1
- package/build/browser/createMinimalClientHelper.js +25 -0
- package/build/browser/createMinimalClientHelper.js.map +1 -0
- package/build/browser/derivedProperties/createWithPropertiesObjectSet.js +36 -13
- package/build/browser/derivedProperties/createWithPropertiesObjectSet.js.map +1 -1
- package/build/browser/derivedProperties/createWithPropertiesObjectSet.test.js +133 -0
- package/build/browser/derivedProperties/createWithPropertiesObjectSet.test.js.map +1 -1
- package/build/browser/derivedProperties/derivedPropertyDefinitionFactory.js +94 -0
- package/build/browser/derivedProperties/derivedPropertyDefinitionFactory.js.map +1 -0
- package/build/browser/fetchMetadata.test.js +11 -9
- package/build/browser/fetchMetadata.test.js.map +1 -1
- package/build/browser/index.js +1 -0
- package/build/browser/index.js.map +1 -1
- package/build/browser/intellisense.test.helpers/showsObjectPropertyJsdoc.js +25 -0
- package/build/browser/intellisense.test.helpers/showsObjectPropertyJsdoc.js.map +1 -0
- package/build/browser/intellisense.test.js +17 -1
- package/build/browser/intellisense.test.js.map +1 -1
- package/build/browser/internal/conversions/modernToLegacyGroupByClause.js +7 -0
- package/build/browser/internal/conversions/modernToLegacyGroupByClause.js.map +1 -1
- package/build/browser/internal/conversions/modernToLegacyWhereClause.js +1 -1
- package/build/browser/internal/conversions/modernToLegacyWhereClause.js.map +1 -1
- package/build/browser/logger/BaseLogger.js +59 -0
- package/build/browser/logger/BaseLogger.js.map +1 -0
- package/build/browser/logger/BrowserLogger.js +67 -0
- package/build/browser/logger/BrowserLogger.js.map +1 -0
- package/build/browser/logger/MinimalLogger.js +39 -0
- package/build/browser/logger/MinimalLogger.js.map +1 -0
- package/build/browser/logger/MinimalLogger.test.js +60 -0
- package/build/browser/logger/MinimalLogger.test.js.map +1 -0
- package/build/browser/logger/TestLogger.js +56 -0
- package/build/browser/logger/TestLogger.js.map +1 -0
- package/build/browser/object/AttachmentUpload.js +3 -0
- package/build/browser/object/AttachmentUpload.js.map +1 -1
- package/build/browser/object/SimpleOsdkProperties.js +2 -0
- package/build/browser/object/SimpleOsdkProperties.js.map +1 -0
- package/build/browser/object/aggregate.test.js +12 -2
- package/build/browser/object/aggregate.test.js.map +1 -1
- package/build/browser/object/attachment.test.js +20 -7
- package/build/browser/object/attachment.test.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/BaseHolder.js +2 -0
- package/build/browser/object/convertWireToOsdkObjects/BaseHolder.js.map +1 -0
- package/build/browser/object/convertWireToOsdkObjects/InterfaceHolder.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/ObjectHolder.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js +29 -0
- package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js +53 -35
- package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/getDollarAs.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects/getDollarLink.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects.js +10 -11
- package/build/browser/object/convertWireToOsdkObjects.js.map +1 -1
- package/build/browser/object/convertWireToOsdkObjects.test.js +46 -36
- package/build/browser/object/convertWireToOsdkObjects.test.js.map +1 -1
- package/build/browser/object/fetchPage.js +17 -4
- package/build/browser/object/fetchPage.js.map +1 -1
- package/build/browser/object/fetchPage.test.js +56 -2
- package/build/browser/object/fetchPage.test.js.map +1 -1
- package/build/browser/object/geotimeseriesreference.test.js +56 -134
- package/build/browser/object/geotimeseriesreference.test.js.map +1 -1
- package/build/browser/object/media.test.js +19 -14
- package/build/browser/object/media.test.js.map +1 -1
- package/build/browser/object/object.test.js +182 -66
- package/build/browser/object/object.test.js.map +1 -1
- package/build/browser/object/timeseries.test.js +119 -85
- package/build/browser/object/timeseries.test.js.map +1 -1
- package/build/browser/objectSet/InterfaceObjectSet.test.js +37 -17
- package/build/browser/objectSet/InterfaceObjectSet.test.js.map +1 -1
- package/build/browser/objectSet/ObjectSet.test.js +212 -114
- package/build/browser/objectSet/ObjectSet.test.js.map +1 -1
- package/build/browser/objectSet/ObjectSetListenerWebsocket.js +20 -16
- package/build/browser/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
- package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js +21 -12
- package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
- package/build/browser/objectSet/createObjectSet.js +2 -1
- package/build/browser/objectSet/createObjectSet.js.map +1 -1
- package/build/browser/observable/ListPayload.js.map +1 -1
- package/build/browser/observable/ObjectPayload.js.map +1 -1
- package/build/browser/observable/ObservableClient.js.map +1 -1
- package/build/browser/observable/OptimisticBuilder.js.map +1 -1
- package/build/browser/observable/internal/ActionApplication.js +102 -0
- package/build/browser/observable/internal/ActionApplication.js.map +1 -0
- package/build/browser/observable/internal/BulkObjectLoader.js +93 -0
- package/build/browser/observable/internal/BulkObjectLoader.js.map +1 -0
- package/build/browser/observable/internal/BulkObjectLoader.test.js +112 -0
- package/build/browser/observable/internal/BulkObjectLoader.test.js.map +1 -0
- package/build/browser/observable/internal/CacheKey.js +38 -1
- package/build/browser/observable/internal/CacheKey.js.map +1 -1
- package/build/browser/observable/internal/CacheKeys.js +4 -4
- package/build/browser/observable/internal/CacheKeys.js.map +1 -1
- package/build/browser/observable/internal/Changes.js +58 -0
- package/build/browser/observable/internal/Changes.js.map +1 -0
- package/build/browser/observable/internal/Layer.js +6 -3
- package/build/browser/observable/internal/Layer.js.map +1 -1
- package/build/browser/observable/internal/ListQuery.js +495 -129
- package/build/browser/observable/internal/ListQuery.js.map +1 -1
- package/build/browser/observable/internal/ObjectQuery.js +40 -14
- package/build/browser/observable/internal/ObjectQuery.js.map +1 -1
- package/build/browser/observable/internal/ObservableClientImpl.js +4 -12
- package/build/browser/observable/internal/ObservableClientImpl.js.map +1 -1
- package/build/browser/observable/internal/OptimisticJob.js +30 -29
- package/build/browser/observable/internal/OptimisticJob.js.map +1 -1
- package/build/browser/observable/internal/OrderByCanonicalizer.js +73 -0
- package/build/browser/observable/internal/OrderByCanonicalizer.js.map +1 -0
- package/build/browser/observable/internal/OrderByCanonicalizer.test.js +78 -0
- package/build/browser/observable/internal/OrderByCanonicalizer.test.js.map +1 -0
- package/build/browser/observable/internal/Query.js +79 -6
- package/build/browser/observable/internal/Query.js.map +1 -1
- package/build/browser/observable/internal/RefCounts.js +7 -2
- package/build/browser/observable/internal/RefCounts.js.map +1 -1
- package/build/browser/observable/internal/SimpleWhereClause.js +2 -0
- package/build/browser/observable/internal/SimpleWhereClause.js.map +1 -0
- package/build/browser/observable/internal/Store.js +140 -190
- package/build/browser/observable/internal/Store.js.map +1 -1
- package/build/browser/observable/internal/Store.test.js +666 -300
- package/build/browser/observable/internal/Store.test.js.map +1 -1
- package/build/browser/observable/internal/WhereClauseCanonicalizer.js +11 -3
- package/build/browser/observable/internal/WhereClauseCanonicalizer.js.map +1 -1
- package/build/browser/observable/internal/objectMatchesWhereClause.js +0 -4
- package/build/browser/observable/internal/objectMatchesWhereClause.js.map +1 -1
- package/build/browser/observable/internal/objectMatchesWhereClause.test.js.map +1 -1
- package/build/browser/observable/internal/testUtils.js +222 -19
- package/build/browser/observable/internal/testUtils.js.map +1 -1
- package/build/browser/ontology/StandardOntologyProvider.test.js +17 -16
- package/build/browser/ontology/StandardOntologyProvider.test.js.map +1 -1
- package/build/browser/ontology/loadFullObjectMetadata.js +0 -1
- package/build/browser/ontology/loadFullObjectMetadata.js.map +1 -1
- package/build/browser/public/internal.js +2 -0
- package/build/browser/public/internal.js.map +1 -1
- package/build/browser/public/unstable-do-not-use.js +1 -0
- package/build/browser/public/unstable-do-not-use.js.map +1 -1
- package/build/browser/public-utils/osdkConfig.js +49 -0
- package/build/browser/public-utils/osdkConfig.js.map +1 -0
- package/build/{esm/observable/internal/ChangedObjects.js → browser/public-utils/vite-env.d.ts} +2 -7
- package/build/browser/queries/applyQuery.js +34 -2
- package/build/browser/queries/applyQuery.js.map +1 -1
- package/build/browser/queries/queries.test.js +36 -13
- package/build/browser/queries/queries.test.js.map +1 -1
- package/build/browser/queries/types.js.map +1 -1
- package/build/browser/tsserver.js.map +1 -1
- package/build/browser/util/UserAgent.js +1 -1
- package/build/browser/util/UserAgent.js.map +1 -1
- package/build/browser/util/extractRdpDefinition.js +140 -0
- package/build/browser/util/extractRdpDefinition.js.map +1 -0
- package/build/browser/util/extractRdpDefinition.test.js +233 -0
- package/build/browser/util/extractRdpDefinition.test.js.map +1 -0
- package/build/browser/{observable/internal/ChangedObjects.js → util/isPoint.js} +3 -7
- package/build/browser/util/isPoint.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/toDataValue.js +14 -2
- package/build/browser/util/toDataValue.js.map +1 -1
- package/build/browser/util/toDataValue.test.js +37 -16
- package/build/browser/util/toDataValue.test.js.map +1 -1
- package/build/browser/util/toDataValueQueries.js +25 -2
- package/build/browser/util/toDataValueQueries.js.map +1 -1
- package/build/cjs/{Client-C8K3E1vH.d.cts → Client-CgL2LKN9.d.cts} +7 -8
- package/build/cjs/{chunk-T5UE6BI7.cjs → chunk-33GHS3X4.cjs} +256 -80
- package/build/cjs/chunk-33GHS3X4.cjs.map +1 -0
- package/build/cjs/{chunk-X7WGNFZ4.cjs → chunk-37QC7LR3.cjs} +173 -34
- package/build/cjs/chunk-37QC7LR3.cjs.map +1 -0
- package/build/cjs/chunk-T4NIFYZS.cjs +14 -0
- package/build/cjs/chunk-T4NIFYZS.cjs.map +1 -0
- package/build/cjs/index.cjs +298 -177
- package/build/cjs/index.cjs.map +1 -1
- package/build/cjs/index.d.cts +14 -22
- package/build/cjs/public/internal.cjs +61 -7
- package/build/cjs/public/internal.cjs.map +1 -1
- package/build/cjs/public/internal.d.cts +50 -3
- package/build/cjs/public/unstable-do-not-use.cjs +1181 -527
- package/build/cjs/public/unstable-do-not-use.cjs.map +1 -1
- package/build/cjs/public/unstable-do-not-use.d.cts +44 -25
- package/build/esm/Client.js.map +1 -1
- package/build/esm/MinimalClientContext.js.map +1 -1
- package/build/esm/__unstable/ConjureSupport.js.map +1 -1
- package/build/esm/actions/ActionValidationError.js +1 -1
- package/build/esm/actions/ActionValidationError.js.map +1 -1
- package/build/esm/actions/actions.test.js +226 -87
- package/build/esm/actions/actions.test.js.map +1 -1
- package/build/esm/actions/applyAction.js +28 -16
- package/build/esm/actions/applyAction.js.map +1 -1
- package/build/esm/createClient.js +19 -8
- package/build/esm/createClient.js.map +1 -1
- package/build/esm/createClient.test.js +14 -6
- package/build/esm/createClient.test.js.map +1 -1
- package/build/esm/createMinimalClient.js +2 -2
- package/build/esm/createMinimalClient.js.map +1 -1
- package/build/esm/createMinimalClientHelper.js +25 -0
- package/build/esm/createMinimalClientHelper.js.map +1 -0
- package/build/esm/derivedProperties/createWithPropertiesObjectSet.js +36 -13
- package/build/esm/derivedProperties/createWithPropertiesObjectSet.js.map +1 -1
- package/build/esm/derivedProperties/createWithPropertiesObjectSet.test.js +133 -0
- package/build/esm/derivedProperties/createWithPropertiesObjectSet.test.js.map +1 -1
- package/build/esm/derivedProperties/derivedPropertyDefinitionFactory.js +94 -0
- package/build/esm/derivedProperties/derivedPropertyDefinitionFactory.js.map +1 -0
- package/build/esm/fetchMetadata.test.js +11 -9
- package/build/esm/fetchMetadata.test.js.map +1 -1
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/intellisense.test.helpers/showsObjectPropertyJsdoc.js +25 -0
- package/build/esm/intellisense.test.helpers/showsObjectPropertyJsdoc.js.map +1 -0
- package/build/esm/intellisense.test.js +17 -1
- package/build/esm/intellisense.test.js.map +1 -1
- package/build/esm/internal/conversions/modernToLegacyGroupByClause.js +7 -0
- package/build/esm/internal/conversions/modernToLegacyGroupByClause.js.map +1 -1
- package/build/esm/internal/conversions/modernToLegacyWhereClause.js +1 -1
- package/build/esm/internal/conversions/modernToLegacyWhereClause.js.map +1 -1
- package/build/esm/logger/BaseLogger.js +59 -0
- package/build/esm/logger/BaseLogger.js.map +1 -0
- package/build/esm/logger/BrowserLogger.js +67 -0
- package/build/esm/logger/BrowserLogger.js.map +1 -0
- package/build/esm/logger/MinimalLogger.js +39 -0
- package/build/esm/logger/MinimalLogger.js.map +1 -0
- package/build/esm/logger/MinimalLogger.test.js +60 -0
- package/build/esm/logger/MinimalLogger.test.js.map +1 -0
- package/build/esm/logger/TestLogger.js +56 -0
- package/build/esm/logger/TestLogger.js.map +1 -0
- package/build/esm/object/AttachmentUpload.js +3 -0
- package/build/esm/object/AttachmentUpload.js.map +1 -1
- package/build/esm/object/SimpleOsdkProperties.js +2 -0
- package/build/esm/object/SimpleOsdkProperties.js.map +1 -0
- package/build/esm/object/aggregate.test.js +12 -2
- package/build/esm/object/aggregate.test.js.map +1 -1
- package/build/esm/object/attachment.test.js +20 -7
- package/build/esm/object/attachment.test.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/BaseHolder.js +2 -0
- package/build/esm/object/convertWireToOsdkObjects/BaseHolder.js.map +1 -0
- package/build/esm/object/convertWireToOsdkObjects/InterfaceHolder.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/ObjectHolder.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js +29 -0
- package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js +53 -35
- package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/getDollarAs.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects/getDollarLink.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects.js +10 -11
- package/build/esm/object/convertWireToOsdkObjects.js.map +1 -1
- package/build/esm/object/convertWireToOsdkObjects.test.js +46 -36
- package/build/esm/object/convertWireToOsdkObjects.test.js.map +1 -1
- package/build/esm/object/fetchPage.js +17 -4
- package/build/esm/object/fetchPage.js.map +1 -1
- package/build/esm/object/fetchPage.test.js +56 -2
- package/build/esm/object/fetchPage.test.js.map +1 -1
- package/build/esm/object/geotimeseriesreference.test.js +56 -134
- package/build/esm/object/geotimeseriesreference.test.js.map +1 -1
- package/build/esm/object/media.test.js +19 -14
- package/build/esm/object/media.test.js.map +1 -1
- package/build/esm/object/object.test.js +182 -66
- package/build/esm/object/object.test.js.map +1 -1
- package/build/esm/object/timeseries.test.js +119 -85
- package/build/esm/object/timeseries.test.js.map +1 -1
- package/build/esm/objectSet/InterfaceObjectSet.test.js +37 -17
- package/build/esm/objectSet/InterfaceObjectSet.test.js.map +1 -1
- package/build/esm/objectSet/ObjectSet.test.js +212 -114
- package/build/esm/objectSet/ObjectSet.test.js.map +1 -1
- package/build/esm/objectSet/ObjectSetListenerWebsocket.js +20 -16
- package/build/esm/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
- package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js +21 -12
- package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
- package/build/esm/objectSet/createObjectSet.js +2 -1
- package/build/esm/objectSet/createObjectSet.js.map +1 -1
- package/build/esm/observable/ListPayload.js.map +1 -1
- package/build/esm/observable/ObjectPayload.js.map +1 -1
- package/build/esm/observable/ObservableClient.js.map +1 -1
- package/build/esm/observable/OptimisticBuilder.js.map +1 -1
- package/build/esm/observable/internal/ActionApplication.js +102 -0
- package/build/esm/observable/internal/ActionApplication.js.map +1 -0
- package/build/esm/observable/internal/BulkObjectLoader.js +93 -0
- package/build/esm/observable/internal/BulkObjectLoader.js.map +1 -0
- package/build/esm/observable/internal/BulkObjectLoader.test.js +112 -0
- package/build/esm/observable/internal/BulkObjectLoader.test.js.map +1 -0
- package/build/esm/observable/internal/CacheKey.js +38 -1
- package/build/esm/observable/internal/CacheKey.js.map +1 -1
- package/build/esm/observable/internal/CacheKeys.js +4 -4
- package/build/esm/observable/internal/CacheKeys.js.map +1 -1
- package/build/esm/observable/internal/Changes.js +58 -0
- package/build/esm/observable/internal/Changes.js.map +1 -0
- package/build/esm/observable/internal/Layer.js +6 -3
- package/build/esm/observable/internal/Layer.js.map +1 -1
- package/build/esm/observable/internal/ListQuery.js +495 -129
- package/build/esm/observable/internal/ListQuery.js.map +1 -1
- package/build/esm/observable/internal/ObjectQuery.js +40 -14
- package/build/esm/observable/internal/ObjectQuery.js.map +1 -1
- package/build/esm/observable/internal/ObservableClientImpl.js +4 -12
- package/build/esm/observable/internal/ObservableClientImpl.js.map +1 -1
- package/build/esm/observable/internal/OptimisticJob.js +30 -29
- package/build/esm/observable/internal/OptimisticJob.js.map +1 -1
- package/build/esm/observable/internal/OrderByCanonicalizer.js +73 -0
- package/build/esm/observable/internal/OrderByCanonicalizer.js.map +1 -0
- package/build/esm/observable/internal/OrderByCanonicalizer.test.js +78 -0
- package/build/esm/observable/internal/OrderByCanonicalizer.test.js.map +1 -0
- package/build/esm/observable/internal/Query.js +79 -6
- package/build/esm/observable/internal/Query.js.map +1 -1
- package/build/esm/observable/internal/RefCounts.js +7 -2
- package/build/esm/observable/internal/RefCounts.js.map +1 -1
- package/build/esm/observable/internal/SimpleWhereClause.js +2 -0
- package/build/esm/observable/internal/SimpleWhereClause.js.map +1 -0
- package/build/esm/observable/internal/Store.js +140 -190
- package/build/esm/observable/internal/Store.js.map +1 -1
- package/build/esm/observable/internal/Store.test.js +666 -300
- package/build/esm/observable/internal/Store.test.js.map +1 -1
- package/build/esm/observable/internal/WhereClauseCanonicalizer.js +11 -3
- package/build/esm/observable/internal/WhereClauseCanonicalizer.js.map +1 -1
- package/build/esm/observable/internal/objectMatchesWhereClause.js +0 -4
- package/build/esm/observable/internal/objectMatchesWhereClause.js.map +1 -1
- package/build/esm/observable/internal/objectMatchesWhereClause.test.js.map +1 -1
- package/build/esm/observable/internal/testUtils.js +222 -19
- package/build/esm/observable/internal/testUtils.js.map +1 -1
- package/build/esm/ontology/StandardOntologyProvider.test.js +17 -16
- package/build/esm/ontology/StandardOntologyProvider.test.js.map +1 -1
- package/build/esm/ontology/loadFullObjectMetadata.js +0 -1
- package/build/esm/ontology/loadFullObjectMetadata.js.map +1 -1
- package/build/esm/public/internal.js +2 -0
- package/build/esm/public/internal.js.map +1 -1
- package/build/esm/public/unstable-do-not-use.js +1 -0
- package/build/esm/public/unstable-do-not-use.js.map +1 -1
- package/build/esm/public-utils/osdkConfig.js +49 -0
- package/build/esm/public-utils/osdkConfig.js.map +1 -0
- package/build/esm/public-utils/vite-env.d.ts +19 -0
- package/build/esm/queries/applyQuery.js +34 -2
- package/build/esm/queries/applyQuery.js.map +1 -1
- package/build/esm/queries/queries.test.js +36 -13
- package/build/esm/queries/queries.test.js.map +1 -1
- package/build/esm/queries/types.js.map +1 -1
- package/build/esm/tsserver.js.map +1 -1
- package/build/esm/util/UserAgent.js +1 -1
- package/build/esm/util/UserAgent.js.map +1 -1
- package/build/esm/util/extractRdpDefinition.js +140 -0
- package/build/esm/util/extractRdpDefinition.js.map +1 -0
- package/build/esm/util/extractRdpDefinition.test.js +233 -0
- package/build/esm/util/extractRdpDefinition.test.js.map +1 -0
- package/build/esm/util/isPoint.js +20 -0
- package/build/esm/util/isPoint.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/toDataValue.js +14 -2
- package/build/esm/util/toDataValue.js.map +1 -1
- package/build/esm/util/toDataValue.test.js +37 -16
- package/build/esm/util/toDataValue.test.js.map +1 -1
- package/build/esm/util/toDataValueQueries.js +25 -2
- package/build/esm/util/toDataValueQueries.js.map +1 -1
- package/build/types/Client.d.ts +1 -1
- package/build/types/Client.d.ts.map +1 -1
- package/build/types/MinimalClientContext.d.ts +1 -1
- package/build/types/MinimalClientContext.d.ts.map +1 -1
- package/build/types/__unstable/ConjureSupport.d.ts +2 -2
- package/build/types/actions/applyAction.d.ts +1 -2
- package/build/types/actions/applyAction.d.ts.map +1 -1
- package/build/types/createClient.d.ts +1 -1
- package/build/types/createClient.d.ts.map +1 -1
- package/build/types/createClient.test.d.ts +2 -1
- package/build/types/createClient.test.d.ts.map +1 -1
- package/build/types/createMinimalClientHelper.d.ts +1 -0
- package/build/types/createMinimalClientHelper.d.ts.map +1 -0
- package/build/types/derivedProperties/derivedPropertyDefinitionFactory.d.ts +1 -0
- package/build/types/derivedProperties/derivedPropertyDefinitionFactory.d.ts.map +1 -0
- package/build/types/index.d.ts +5 -5
- package/build/types/index.d.ts.map +1 -1
- package/build/types/intellisense.test.helpers/showsObjectPropertyJsdoc.d.ts +1 -0
- package/build/types/intellisense.test.helpers/showsObjectPropertyJsdoc.d.ts.map +1 -0
- package/build/types/logger/BaseLogger.d.ts +33 -0
- package/build/types/logger/BaseLogger.d.ts.map +1 -0
- package/build/types/logger/BrowserLogger.d.ts +9 -0
- package/build/types/logger/BrowserLogger.d.ts.map +1 -0
- package/build/types/logger/MinimalLogger.d.ts +9 -0
- package/build/types/logger/MinimalLogger.d.ts.map +1 -0
- package/build/types/logger/MinimalLogger.test.d.ts +1 -0
- package/build/types/logger/MinimalLogger.test.d.ts.map +1 -0
- package/build/types/logger/TestLogger.d.ts +14 -0
- package/build/types/logger/TestLogger.d.ts.map +1 -0
- package/build/types/object/AttachmentUpload.d.ts +3 -0
- package/build/types/object/AttachmentUpload.d.ts.map +1 -1
- package/build/types/object/SimpleOsdkProperties.d.ts +1 -0
- package/build/types/object/SimpleOsdkProperties.d.ts.map +1 -0
- package/build/types/object/convertWireToOsdkObjects/BaseHolder.d.ts +1 -0
- package/build/types/object/convertWireToOsdkObjects/BaseHolder.d.ts.map +1 -0
- package/build/types/object/convertWireToOsdkObjects.d.ts +8 -1
- 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/ListPayload.d.ts +5 -9
- package/build/types/observable/ListPayload.d.ts.map +1 -1
- package/build/types/observable/ObjectPayload.d.ts +4 -7
- package/build/types/observable/ObjectPayload.d.ts.map +1 -1
- package/build/types/observable/ObservableClient.d.ts +33 -10
- package/build/types/observable/ObservableClient.d.ts.map +1 -1
- package/build/types/observable/OptimisticBuilder.d.ts +1 -1
- package/build/types/observable/OptimisticBuilder.d.ts.map +1 -1
- package/build/types/observable/internal/ActionApplication.d.ts +9 -0
- package/build/types/observable/internal/ActionApplication.d.ts.map +1 -0
- package/build/types/observable/internal/BulkObjectLoader.d.ts +8 -0
- package/build/types/observable/internal/BulkObjectLoader.d.ts.map +1 -0
- package/build/types/observable/internal/BulkObjectLoader.test.d.ts +1 -0
- package/build/types/observable/internal/BulkObjectLoader.test.d.ts.map +1 -0
- package/build/types/observable/internal/CacheKeys.d.ts +2 -1
- package/build/types/observable/internal/CacheKeys.d.ts.map +1 -1
- package/build/types/observable/internal/Changes.d.ts +15 -0
- package/build/types/observable/internal/Changes.d.ts.map +1 -0
- package/build/types/observable/internal/Layer.d.ts +2 -1
- package/build/types/observable/internal/Layer.d.ts.map +1 -1
- package/build/types/observable/internal/ListQuery.d.ts +69 -23
- package/build/types/observable/internal/ListQuery.d.ts.map +1 -1
- package/build/types/observable/internal/ObjectQuery.d.ts +8 -9
- package/build/types/observable/internal/ObjectQuery.d.ts.map +1 -1
- package/build/types/observable/internal/OptimisticJob.d.ts +2 -2
- package/build/types/observable/internal/OptimisticJob.d.ts.map +1 -1
- package/build/types/observable/internal/OrderByCanonicalizer.d.ts +12 -0
- package/build/types/observable/internal/OrderByCanonicalizer.d.ts.map +1 -0
- package/build/types/observable/internal/OrderByCanonicalizer.test.d.ts +1 -0
- package/build/types/observable/internal/OrderByCanonicalizer.test.d.ts.map +1 -0
- package/build/types/observable/internal/Query.d.ts +45 -9
- package/build/types/observable/internal/Query.d.ts.map +1 -1
- package/build/types/observable/internal/RefCounts.d.ts.map +1 -1
- package/build/types/observable/internal/SimpleWhereClause.d.ts +2 -0
- package/build/types/observable/internal/SimpleWhereClause.d.ts.map +1 -0
- package/build/types/observable/internal/Store.d.ts +34 -30
- package/build/types/observable/internal/Store.d.ts.map +1 -1
- package/build/types/observable/internal/WhereClauseCanonicalizer.d.ts +2 -1
- package/build/types/observable/internal/WhereClauseCanonicalizer.d.ts.map +1 -1
- package/build/types/observable/internal/objectMatchesWhereClause.d.ts +4 -2
- package/build/types/observable/internal/objectMatchesWhereClause.d.ts.map +1 -1
- package/build/types/observable/internal/testUtils.d.ts +48 -9
- package/build/types/observable/internal/testUtils.d.ts.map +1 -1
- package/build/types/public/internal.d.ts +2 -0
- package/build/types/public/internal.d.ts.map +1 -1
- package/build/types/public/unstable-do-not-use.d.ts +4 -5
- package/build/types/public/unstable-do-not-use.d.ts.map +1 -1
- package/build/types/public-utils/osdkConfig.d.ts +8 -0
- package/build/types/public-utils/osdkConfig.d.ts.map +1 -0
- package/build/types/public-utils/vite-env.d.d.ts +3 -0
- package/build/types/public-utils/vite-env.d.d.ts.map +1 -0
- package/build/types/queries/applyQuery.d.ts +4 -2
- package/build/types/queries/applyQuery.d.ts.map +1 -1
- package/build/types/queries/types.d.ts +1 -1
- package/build/types/queries/types.d.ts.map +1 -1
- package/build/types/tsserver.d.ts +1 -1
- package/build/types/tsserver.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/isPoint.d.ts +1 -0
- package/build/types/util/isPoint.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 +20 -16
- package/build/browser/Logger.js +0 -2
- package/build/browser/Logger.js.map +0 -1
- package/build/browser/observable/internal/ChangedObjects.js.map +0 -1
- package/build/cjs/chunk-Q7SFCCGT.cjs +0 -11
- package/build/cjs/chunk-Q7SFCCGT.cjs.map +0 -1
- package/build/cjs/chunk-T5UE6BI7.cjs.map +0 -1
- package/build/cjs/chunk-X7WGNFZ4.cjs.map +0 -1
- package/build/cjs/graphql-JJX5MZPQ.cjs +0 -10491
- package/build/cjs/graphql-JJX5MZPQ.cjs.map +0 -1
- package/build/esm/Logger.js +0 -2
- package/build/esm/Logger.js.map +0 -1
- package/build/esm/observable/internal/ChangedObjects.js.map +0 -1
- package/build/types/Logger.d.ts +0 -18
- package/build/types/Logger.d.ts.map +0 -1
- package/build/types/observable/internal/ChangedObjects.d.ts +0 -7
- package/build/types/observable/internal/ChangedObjects.d.ts.map +0 -1
|
@@ -14,14 +14,21 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { editTodo, Employee, FooInterface, Todo } from "@osdk/client.test.ontology";
|
|
18
|
+
import { ActionTypeBuilder, FauxFoundry, ontologies, startNodeApiServer, stubData } from "@osdk/shared.test";
|
|
19
|
+
import chalk from "chalk";
|
|
20
|
+
import invariant from "tiny-invariant";
|
|
19
21
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi, vitest } from "vitest";
|
|
22
|
+
import { ActionValidationError } from "../../actions/ActionValidationError.js";
|
|
20
23
|
import { createClient } from "../../createClient.js";
|
|
24
|
+
import { TestLogger } from "../../logger/TestLogger.js";
|
|
21
25
|
import { createOptimisticId } from "./OptimisticId.js";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
26
|
+
import { runOptimisticJob } from "./OptimisticJob.js";
|
|
27
|
+
import { invalidateList, Store } from "./Store.js";
|
|
28
|
+
import { applyCustomMatchers, createClientMockHelper, createDefer, expectNoMoreCalls, expectSingleListCallAndClear, expectSingleObjectCallAndClear, getObject, mockListSubCallback, mockSingleSubCallback, objectPayloadContaining, updateList, updateObject, waitForCall } from "./testUtils.js";
|
|
29
|
+
const JOHN_DOE_ID = 50030;
|
|
24
30
|
const defer = createDefer();
|
|
31
|
+
const logger = new TestLogger();
|
|
25
32
|
beforeAll(() => {
|
|
26
33
|
vi.setConfig({
|
|
27
34
|
fakeTimers: {
|
|
@@ -38,7 +45,56 @@ const ANY_INIT_ENTRY = {
|
|
|
38
45
|
lastUpdated: 0,
|
|
39
46
|
status: "init"
|
|
40
47
|
};
|
|
48
|
+
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
50
|
+
function fullTaskName(task) {
|
|
51
|
+
return task ? `${fullTaskName(task.suite)} > ${task.name}` : "";
|
|
52
|
+
}
|
|
53
|
+
beforeEach(x => {
|
|
54
|
+
console.log(chalk.bgRed(chalk.white(fullTaskName(x.task))));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// helper method to make debugging tests easier
|
|
58
|
+
function testStage(s) {
|
|
59
|
+
console.log(chalk.bgYellow(`Test Stage: ${s}`));
|
|
60
|
+
}
|
|
41
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
|
+
}
|
|
42
98
|
describe(Store, () => {
|
|
43
99
|
describe("with mock server", () => {
|
|
44
100
|
let client;
|
|
@@ -46,44 +102,51 @@ describe(Store, () => {
|
|
|
46
102
|
let employeesAsServerReturns;
|
|
47
103
|
let mutatedEmployees;
|
|
48
104
|
beforeAll(async () => {
|
|
49
|
-
|
|
50
|
-
|
|
105
|
+
const testSetup = startNodeApiServer(new FauxFoundry("https://stack.palantir.com/"), createClient, {
|
|
106
|
+
logger
|
|
107
|
+
});
|
|
108
|
+
({
|
|
109
|
+
client
|
|
110
|
+
} = testSetup);
|
|
111
|
+
setupOntology(testSetup.fauxFoundry);
|
|
112
|
+
setupSomeEmployees(testSetup.fauxFoundry);
|
|
51
113
|
employeesAsServerReturns = (await client(Employee).fetchPage()).data;
|
|
52
114
|
mutatedEmployees = [employeesAsServerReturns[0], employeesAsServerReturns[1].$clone({
|
|
53
115
|
fullName: "foo"
|
|
54
116
|
}), ...employeesAsServerReturns.slice(2)];
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
117
|
+
return () => {
|
|
118
|
+
testSetup.apiServer.close();
|
|
119
|
+
};
|
|
58
120
|
});
|
|
59
121
|
beforeEach(() => {
|
|
60
122
|
cache = new Store(client);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
123
|
+
return () => {
|
|
124
|
+
cache = undefined;
|
|
125
|
+
};
|
|
64
126
|
});
|
|
65
127
|
it("basic single object works", async () => {
|
|
66
128
|
const emp = employeesAsServerReturns[0];
|
|
129
|
+
const cacheKey = cache.getCacheKey("object", "Employee", emp.$primaryKey);
|
|
67
130
|
|
|
68
131
|
// starts empty
|
|
69
|
-
expect(cache.
|
|
70
|
-
const result =
|
|
132
|
+
expect(cache.getValue(cacheKey)?.value).toBeUndefined();
|
|
133
|
+
const result = updateObject(cache, emp);
|
|
71
134
|
expect(emp).toBe(result);
|
|
72
135
|
|
|
73
136
|
// getting the object now matches the result
|
|
74
|
-
expect(cache.
|
|
75
|
-
const updatedEmpFromCache =
|
|
137
|
+
expect(cache.getValue(cacheKey)?.value).toEqual(result);
|
|
138
|
+
const updatedEmpFromCache = updateObject(cache, emp.$clone({
|
|
76
139
|
fullName: "new name"
|
|
77
140
|
}));
|
|
78
141
|
expect(updatedEmpFromCache).not.toBe(emp);
|
|
79
142
|
|
|
80
143
|
// getting it again is the updated object
|
|
81
|
-
expect(cache.
|
|
144
|
+
expect(cache.getValue(cacheKey)?.value).toEqual(updatedEmpFromCache);
|
|
82
145
|
});
|
|
83
146
|
describe("optimistic updates", () => {
|
|
84
147
|
it("rolls back objects", async () => {
|
|
85
148
|
const emp = employeesAsServerReturns[0];
|
|
86
|
-
|
|
149
|
+
updateObject(cache, emp); // pre-seed the cache with the "real" value
|
|
87
150
|
|
|
88
151
|
const subFn = mockSingleSubCallback();
|
|
89
152
|
defer(cache.observeObject(Employee, emp.$primaryKey, {
|
|
@@ -92,7 +155,7 @@ describe(Store, () => {
|
|
|
92
155
|
expectSingleObjectCallAndClear(subFn, emp, "loaded");
|
|
93
156
|
const optimisticId = createOptimisticId();
|
|
94
157
|
// update with an optimistic write
|
|
95
|
-
|
|
158
|
+
updateObject(cache, emp.$clone({
|
|
96
159
|
fullName: "new name"
|
|
97
160
|
}), {
|
|
98
161
|
optimisticId
|
|
@@ -106,10 +169,12 @@ describe(Store, () => {
|
|
|
106
169
|
expectSingleObjectCallAndClear(subFn, emp, "loaded");
|
|
107
170
|
});
|
|
108
171
|
it("rolls back to an updated real value", async () => {
|
|
109
|
-
vi.useFakeTimers();
|
|
110
|
-
|
|
111
172
|
// pre-seed the cache with the "real" value
|
|
112
|
-
|
|
173
|
+
updateList(cache, {
|
|
174
|
+
type: Employee,
|
|
175
|
+
where: {},
|
|
176
|
+
orderBy: {}
|
|
177
|
+
}, employeesAsServerReturns);
|
|
113
178
|
const emp = employeesAsServerReturns[0];
|
|
114
179
|
const empSubFn = mockSingleSubCallback();
|
|
115
180
|
defer(cache.observeObject(Employee, emp.$primaryKey, {
|
|
@@ -117,88 +182,90 @@ describe(Store, () => {
|
|
|
117
182
|
}, empSubFn));
|
|
118
183
|
expectSingleObjectCallAndClear(empSubFn, emp, "loaded");
|
|
119
184
|
const listSubFn = mockListSubCallback();
|
|
120
|
-
defer(cache.observeList(
|
|
185
|
+
defer(cache.observeList({
|
|
186
|
+
type: Employee,
|
|
121
187
|
mode: "offline"
|
|
122
188
|
}, listSubFn));
|
|
189
|
+
await waitForCall(listSubFn, 1);
|
|
123
190
|
expectSingleListCallAndClear(listSubFn, employeesAsServerReturns);
|
|
124
191
|
const optimisticEmployee = emp.$clone({
|
|
125
192
|
fullName: "new name"
|
|
126
193
|
});
|
|
127
194
|
const optimisticId = createOptimisticId();
|
|
195
|
+
testStage("optimistic update");
|
|
196
|
+
expect(listSubFn.next).not.toHaveBeenCalled();
|
|
128
197
|
|
|
129
198
|
// update with an optimistic write
|
|
130
|
-
|
|
199
|
+
updateObject(cache, optimisticEmployee, {
|
|
131
200
|
optimisticId
|
|
132
201
|
});
|
|
202
|
+
testStage("after optimistic update");
|
|
133
203
|
|
|
134
204
|
// expect optimistic write
|
|
135
205
|
expectSingleObjectCallAndClear(empSubFn, optimisticEmployee);
|
|
136
206
|
|
|
137
207
|
// expect optimistic write to the list
|
|
138
|
-
|
|
208
|
+
await waitForCall(listSubFn, 1);
|
|
209
|
+
expectSingleListCallAndClear(listSubFn, [optimisticEmployee, ...employeesAsServerReturns.slice(1)], {
|
|
210
|
+
isOptimistic: true,
|
|
211
|
+
status: "loading"
|
|
212
|
+
});
|
|
139
213
|
|
|
140
214
|
// write the real update, via the earlier list definition
|
|
141
215
|
const truthUpdatedEmployee = emp.$clone({
|
|
142
216
|
fullName: "real update"
|
|
143
217
|
});
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// for the object
|
|
151
|
-
expectSingleListCallAndClear(listSubFn, [optimisticEmployee]);
|
|
218
|
+
testStage("write real update");
|
|
219
|
+
updateList(cache, {
|
|
220
|
+
type: Employee,
|
|
221
|
+
where: {},
|
|
222
|
+
orderBy: {}
|
|
223
|
+
}, [truthUpdatedEmployee]);
|
|
152
224
|
|
|
153
225
|
// remove the optimistic write
|
|
154
226
|
cache.removeLayer(optimisticId);
|
|
155
227
|
|
|
156
228
|
// see the object observation get updated
|
|
157
|
-
expectSingleObjectCallAndClear(empSubFn, truthUpdatedEmployee);
|
|
229
|
+
expectSingleObjectCallAndClear(empSubFn, truthUpdatedEmployee, "loaded");
|
|
158
230
|
|
|
159
231
|
// see the list get updated
|
|
160
|
-
|
|
161
|
-
|
|
232
|
+
await waitForCall(listSubFn, 1);
|
|
233
|
+
expectSingleListCallAndClear(listSubFn, [truthUpdatedEmployee], {
|
|
234
|
+
status: "loaded",
|
|
235
|
+
isOptimistic: false
|
|
236
|
+
});
|
|
162
237
|
});
|
|
163
238
|
it("rolls back to an updated real value via list", async () => {
|
|
164
239
|
const emp = employeesAsServerReturns[0];
|
|
165
|
-
|
|
240
|
+
updateObject(cache, emp); // pre-seed the cache with the "real" value
|
|
166
241
|
|
|
167
242
|
const subFn = mockSingleSubCallback();
|
|
168
243
|
defer(cache.observeObject(Employee, emp.$primaryKey, {
|
|
169
244
|
mode: "offline"
|
|
170
245
|
}, subFn));
|
|
171
|
-
|
|
172
|
-
object: emp,
|
|
173
|
-
status: "loaded"
|
|
174
|
-
}));
|
|
175
|
-
subFn.mockClear();
|
|
246
|
+
expectSingleObjectCallAndClear(subFn, emp, "loaded");
|
|
176
247
|
const optimisticEmployee = emp.$clone({
|
|
177
248
|
fullName: "new name"
|
|
178
249
|
});
|
|
179
250
|
|
|
180
251
|
// update with an optimistic write
|
|
181
252
|
const optimisticId = createOptimisticId();
|
|
182
|
-
|
|
253
|
+
updateObject(cache, optimisticEmployee, {
|
|
183
254
|
optimisticId
|
|
184
255
|
});
|
|
185
|
-
|
|
186
|
-
object: optimisticEmployee
|
|
187
|
-
}));
|
|
188
|
-
subFn.mockClear();
|
|
256
|
+
expectSingleObjectCallAndClear(subFn, optimisticEmployee);
|
|
189
257
|
const truthUpdatedEmployee = emp.$clone({
|
|
190
258
|
fullName: "real update"
|
|
191
259
|
});
|
|
192
|
-
|
|
260
|
+
updateObject(cache, truthUpdatedEmployee);
|
|
193
261
|
|
|
194
262
|
// we shouldn't expect an update because the top layer has a value
|
|
195
|
-
expect(subFn).not.toHaveBeenCalled();
|
|
263
|
+
expect(subFn.next).not.toHaveBeenCalled();
|
|
196
264
|
|
|
197
265
|
// remove the optimistic write
|
|
198
266
|
cache.removeLayer(optimisticId);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}));
|
|
267
|
+
expectSingleObjectCallAndClear(subFn, truthUpdatedEmployee);
|
|
268
|
+
expectNoMoreCalls(subFn);
|
|
202
269
|
});
|
|
203
270
|
});
|
|
204
271
|
describe(".invalidateObject", () => {
|
|
@@ -207,29 +274,20 @@ describe(Store, () => {
|
|
|
207
274
|
const staleEmp = emp.$clone({
|
|
208
275
|
fullName: "stale"
|
|
209
276
|
});
|
|
210
|
-
|
|
277
|
+
updateObject(cache, staleEmp);
|
|
211
278
|
const subFn = mockSingleSubCallback();
|
|
212
279
|
defer(cache.observeObject(Employee, emp.$primaryKey, {
|
|
213
280
|
mode: "offline"
|
|
214
281
|
}, subFn));
|
|
215
|
-
|
|
216
|
-
object: staleEmp,
|
|
217
|
-
status: "loaded"
|
|
218
|
-
}));
|
|
219
|
-
subFn.mockClear();
|
|
282
|
+
expectSingleObjectCallAndClear(subFn, staleEmp, "loaded");
|
|
220
283
|
|
|
221
284
|
// invalidate
|
|
222
285
|
void cache.invalidateObject(Employee, staleEmp.$primaryKey);
|
|
223
|
-
await
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
subFn.mockClear();
|
|
229
|
-
await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
|
|
230
|
-
expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
231
|
-
object: emp
|
|
232
|
-
}));
|
|
286
|
+
await waitForCall(subFn);
|
|
287
|
+
expectSingleObjectCallAndClear(subFn, staleEmp, "loading");
|
|
288
|
+
await waitForCall(subFn);
|
|
289
|
+
expectSingleObjectCallAndClear(subFn, emp, "loaded");
|
|
290
|
+
expectNoMoreCalls(subFn);
|
|
233
291
|
});
|
|
234
292
|
});
|
|
235
293
|
describe(".invalidateList", () => {
|
|
@@ -244,39 +302,43 @@ describe(Store, () => {
|
|
|
244
302
|
const staleEmp = emp.$clone({
|
|
245
303
|
fullName: "stale"
|
|
246
304
|
});
|
|
247
|
-
|
|
305
|
+
updateList(cache, {
|
|
306
|
+
type: Employee,
|
|
307
|
+
where: {},
|
|
308
|
+
orderBy: {}
|
|
309
|
+
}, [staleEmp]);
|
|
248
310
|
const subFn = mockSingleSubCallback();
|
|
249
311
|
defer(cache.observeObject(Employee, emp.$primaryKey, {
|
|
250
312
|
mode: "offline"
|
|
251
313
|
}, subFn));
|
|
252
314
|
expectSingleObjectCallAndClear(subFn, staleEmp);
|
|
253
315
|
const subListFn = mockListSubCallback();
|
|
254
|
-
defer(cache.observeList(
|
|
316
|
+
defer(cache.observeList({
|
|
317
|
+
type: Employee,
|
|
255
318
|
mode: "offline"
|
|
256
319
|
}, subListFn));
|
|
257
|
-
await
|
|
258
|
-
|
|
259
|
-
resolvedList: [staleEmp],
|
|
320
|
+
await waitForCall(subListFn, 1);
|
|
321
|
+
expectSingleListCallAndClear(subListFn, [staleEmp], {
|
|
260
322
|
status: "loaded"
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
323
|
+
});
|
|
324
|
+
testStage("invalidate");
|
|
325
|
+
const invalidateListPromise = invalidateList(cache, {
|
|
326
|
+
type: Employee
|
|
327
|
+
});
|
|
328
|
+
testStage("check invalidate");
|
|
329
|
+
await waitForCall(subListFn, 1);
|
|
330
|
+
expectSingleListCallAndClear(subListFn, [staleEmp], {
|
|
267
331
|
status: "loading"
|
|
268
|
-
})
|
|
269
|
-
subListFn
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
object: emp
|
|
279
|
-
}));
|
|
332
|
+
});
|
|
333
|
+
await waitForCall(subListFn, 1);
|
|
334
|
+
expectSingleListCallAndClear(subListFn, employeesAsServerReturns, {
|
|
335
|
+
status: "loaded"
|
|
336
|
+
});
|
|
337
|
+
await waitForCall(subFn, 1);
|
|
338
|
+
expectSingleObjectCallAndClear(subFn, emp, "loaded");
|
|
339
|
+
|
|
340
|
+
// don't leave promises dangling
|
|
341
|
+
await invalidateListPromise;
|
|
280
342
|
});
|
|
281
343
|
});
|
|
282
344
|
describe(".invalidateObjectType", () => {
|
|
@@ -291,92 +353,92 @@ describe(Store, () => {
|
|
|
291
353
|
const staleEmp = emp.$clone({
|
|
292
354
|
fullName: "stale"
|
|
293
355
|
});
|
|
294
|
-
|
|
356
|
+
updateList(cache, {
|
|
357
|
+
type: Employee,
|
|
358
|
+
where: {},
|
|
359
|
+
orderBy: {}
|
|
360
|
+
}, [staleEmp]);
|
|
295
361
|
const subFn = mockSingleSubCallback();
|
|
296
362
|
defer(cache.observeObject(Employee, emp.$primaryKey, {
|
|
297
363
|
mode: "offline"
|
|
298
364
|
}, subFn));
|
|
299
365
|
expectSingleObjectCallAndClear(subFn, staleEmp);
|
|
300
366
|
const subListFn = mockListSubCallback();
|
|
301
|
-
defer(cache.observeList(
|
|
367
|
+
defer(cache.observeList({
|
|
368
|
+
type: Employee,
|
|
369
|
+
where: {},
|
|
370
|
+
orderBy: {},
|
|
302
371
|
mode: "offline"
|
|
303
372
|
}, subListFn));
|
|
304
|
-
await
|
|
305
|
-
|
|
306
|
-
resolvedList: [staleEmp],
|
|
373
|
+
await waitForCall(subListFn, 1);
|
|
374
|
+
expectSingleListCallAndClear(subListFn, [staleEmp], {
|
|
307
375
|
status: "loaded"
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
cache.invalidateObjectType(Employee);
|
|
311
|
-
await
|
|
312
|
-
|
|
313
|
-
resolvedList: [staleEmp],
|
|
376
|
+
});
|
|
377
|
+
testStage("invalidate");
|
|
378
|
+
const pInvalidateComplete = cache.invalidateObjectType(Employee, undefined);
|
|
379
|
+
await waitForCall(subListFn, 1);
|
|
380
|
+
expectSingleListCallAndClear(subListFn, [staleEmp], {
|
|
314
381
|
status: "loading"
|
|
315
|
-
})
|
|
316
|
-
subListFn
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
status: "loaded",
|
|
325
|
-
object: emp
|
|
326
|
-
}));
|
|
382
|
+
});
|
|
383
|
+
await waitForCall(subListFn, 1);
|
|
384
|
+
expectSingleListCallAndClear(subListFn, employeesAsServerReturns);
|
|
385
|
+
await waitForCall(subFn, 1);
|
|
386
|
+
expectSingleObjectCallAndClear(subFn, emp, "loaded");
|
|
387
|
+
|
|
388
|
+
// we don't need this value to control the test but we want to make sure we don't have
|
|
389
|
+
// any unhandled exceptions upon test completion
|
|
390
|
+
await pInvalidateComplete;
|
|
327
391
|
});
|
|
328
392
|
});
|
|
329
393
|
describe(".observeObject (force)", () => {
|
|
330
394
|
const subFn1 = mockSingleSubCallback();
|
|
331
395
|
const subFn2 = mockSingleSubCallback();
|
|
332
396
|
beforeEach(async () => {
|
|
333
|
-
subFn1.mockClear();
|
|
334
|
-
|
|
397
|
+
subFn1.complete.mockClear();
|
|
398
|
+
subFn1.next.mockClear();
|
|
399
|
+
subFn1.error.mockClear();
|
|
400
|
+
subFn2.complete.mockClear();
|
|
401
|
+
subFn2.next.mockClear();
|
|
402
|
+
subFn2.error.mockClear();
|
|
335
403
|
});
|
|
336
404
|
const likeEmployee50030 = expect.objectContaining({
|
|
337
|
-
$primaryKey:
|
|
405
|
+
$primaryKey: JOHN_DOE_ID,
|
|
338
406
|
fullName: "John Doe"
|
|
339
407
|
});
|
|
340
408
|
it("fetches and updates twice", async () => {
|
|
341
|
-
defer(cache.observeObject(Employee,
|
|
409
|
+
defer(cache.observeObject(Employee, JOHN_DOE_ID, {
|
|
342
410
|
mode: "force"
|
|
343
411
|
}, subFn1));
|
|
344
|
-
expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
412
|
+
expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
345
413
|
status: "loading",
|
|
346
414
|
object: undefined,
|
|
347
415
|
isOptimistic: false
|
|
348
416
|
}));
|
|
349
|
-
subFn1.mockClear();
|
|
350
|
-
await
|
|
351
|
-
expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
417
|
+
subFn1.next.mockClear();
|
|
418
|
+
await waitForCall(subFn1);
|
|
419
|
+
expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
352
420
|
object: likeEmployee50030,
|
|
353
421
|
isOptimistic: false
|
|
354
422
|
}));
|
|
355
|
-
const firstLoad = subFn1.mock.lastCall?.[0];
|
|
356
|
-
subFn1.mockClear();
|
|
357
|
-
defer(cache.observeObject(Employee,
|
|
423
|
+
const firstLoad = subFn1.next.mock.lastCall?.[0];
|
|
424
|
+
subFn1.next.mockClear();
|
|
425
|
+
defer(cache.observeObject(Employee, JOHN_DOE_ID, {
|
|
358
426
|
mode: "force"
|
|
359
427
|
}, subFn2));
|
|
360
|
-
|
|
361
|
-
status: "loading"
|
|
362
|
-
}));
|
|
363
|
-
subFn1.mockClear();
|
|
428
|
+
expectSingleObjectCallAndClear(subFn1, likeEmployee50030, "loading");
|
|
364
429
|
|
|
365
430
|
// should be the earlier results
|
|
366
|
-
|
|
367
|
-
status: "loading"
|
|
368
|
-
}));
|
|
369
|
-
subFn2.mockClear();
|
|
431
|
+
expectSingleObjectCallAndClear(subFn2, likeEmployee50030, "loading");
|
|
370
432
|
|
|
371
433
|
// both will be updated
|
|
372
434
|
for (const s of [subFn1, subFn2]) {
|
|
373
435
|
// wait for the result to come in
|
|
374
|
-
await
|
|
375
|
-
expect(s).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
436
|
+
await waitForCall(s, 1);
|
|
437
|
+
expect(s.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
|
|
376
438
|
...firstLoad,
|
|
377
439
|
lastUpdated: expect.toBeGreaterThan(firstLoad.lastUpdated)
|
|
378
440
|
}));
|
|
379
|
-
s.mockClear();
|
|
441
|
+
s.next.mockClear();
|
|
380
442
|
}
|
|
381
443
|
});
|
|
382
444
|
});
|
|
@@ -384,152 +446,185 @@ describe(Store, () => {
|
|
|
384
446
|
const subFn = mockSingleSubCallback();
|
|
385
447
|
let sub;
|
|
386
448
|
beforeEach(() => {
|
|
387
|
-
subFn.mockClear();
|
|
388
|
-
|
|
449
|
+
subFn.complete.mockClear();
|
|
450
|
+
subFn.next.mockClear();
|
|
451
|
+
subFn.error.mockClear();
|
|
452
|
+
sub = defer(cache.observeObject(Employee, JOHN_DOE_ID, {
|
|
389
453
|
mode: "offline"
|
|
390
454
|
}, subFn));
|
|
391
|
-
|
|
392
|
-
status: "init",
|
|
393
|
-
object: undefined
|
|
394
|
-
}));
|
|
395
|
-
subFn.mockClear();
|
|
455
|
+
expectSingleObjectCallAndClear(subFn, undefined, "init");
|
|
396
456
|
});
|
|
397
457
|
it("does basic observation and unsubscribe", async () => {
|
|
398
|
-
const emp = employeesAsServerReturns
|
|
458
|
+
const emp = employeesAsServerReturns.find(x => x.$primaryKey === JOHN_DOE_ID);
|
|
399
459
|
|
|
400
460
|
// force an update
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
object: emp
|
|
404
|
-
}));
|
|
405
|
-
subFn.mockClear();
|
|
461
|
+
updateObject(cache, emp);
|
|
462
|
+
expectSingleObjectCallAndClear(subFn, emp);
|
|
406
463
|
|
|
407
464
|
// force again
|
|
408
|
-
|
|
465
|
+
updateObject(cache, emp.$clone({
|
|
409
466
|
fullName: "new name"
|
|
410
467
|
}));
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
fullName: "new name"
|
|
414
|
-
})
|
|
468
|
+
expectSingleObjectCallAndClear(subFn, emp.$clone({
|
|
469
|
+
fullName: "new name"
|
|
415
470
|
}));
|
|
416
|
-
subFn.mockClear();
|
|
417
471
|
sub.unsubscribe();
|
|
418
472
|
|
|
419
473
|
// force again but no subscription update
|
|
420
|
-
|
|
474
|
+
updateObject(cache, emp.$clone({
|
|
421
475
|
fullName: "new name 2"
|
|
422
476
|
}));
|
|
423
|
-
expect(subFn).not.toHaveBeenCalled();
|
|
477
|
+
expect(subFn.next).not.toHaveBeenCalled();
|
|
424
478
|
});
|
|
425
479
|
it("observes with list update", async () => {
|
|
426
|
-
const emp = employeesAsServerReturns
|
|
480
|
+
const emp = employeesAsServerReturns.find(x => x.$primaryKey === JOHN_DOE_ID);
|
|
427
481
|
|
|
428
482
|
// force an update
|
|
429
|
-
|
|
483
|
+
updateObject(cache, emp.$clone({
|
|
430
484
|
fullName: "not the name"
|
|
431
485
|
}));
|
|
432
|
-
expect(subFn).toHaveBeenCalledTimes(1);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
486
|
+
expect(subFn.next).toHaveBeenCalledTimes(1);
|
|
487
|
+
updateList(cache, {
|
|
488
|
+
type: Employee,
|
|
489
|
+
where: {},
|
|
490
|
+
orderBy: {}
|
|
491
|
+
}, employeesAsServerReturns);
|
|
492
|
+
expect(subFn.next).toHaveBeenCalledTimes(2);
|
|
493
|
+
expect(subFn.next.mock.calls[1][0]).toEqual(objectPayloadContaining({
|
|
436
494
|
object: emp
|
|
437
495
|
}));
|
|
438
496
|
});
|
|
439
497
|
});
|
|
440
498
|
describe(".observeList", () => {
|
|
441
499
|
const listSub1 = mockListSubCallback();
|
|
500
|
+
const ifaceSub = mockListSubCallback();
|
|
442
501
|
beforeEach(() => {
|
|
443
502
|
vi.useFakeTimers({});
|
|
444
|
-
listSub1.mockReset();
|
|
503
|
+
vi.mocked(listSub1.next).mockReset();
|
|
504
|
+
vi.mocked(listSub1.error).mockReset();
|
|
505
|
+
vi.mocked(listSub1.complete).mockReset();
|
|
506
|
+
vi.mocked(ifaceSub.next).mockReset();
|
|
507
|
+
vi.mocked(ifaceSub.error).mockReset();
|
|
508
|
+
vi.mocked(ifaceSub.complete).mockReset();
|
|
445
509
|
});
|
|
446
510
|
afterEach(() => {
|
|
447
511
|
vi.useRealTimers();
|
|
448
512
|
});
|
|
449
513
|
describe("mode=force", () => {
|
|
450
514
|
it("initial load", async () => {
|
|
451
|
-
defer(cache.observeList(
|
|
515
|
+
defer(cache.observeList({
|
|
516
|
+
type: Employee,
|
|
517
|
+
orderBy: {},
|
|
452
518
|
mode: "force"
|
|
453
519
|
}, listSub1));
|
|
520
|
+
defer(cache.observeList({
|
|
521
|
+
type: FooInterface,
|
|
522
|
+
orderBy: {},
|
|
523
|
+
mode: "force"
|
|
524
|
+
}, ifaceSub));
|
|
454
525
|
vitest.runOnlyPendingTimers();
|
|
455
|
-
await
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
})
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
526
|
+
await waitForCall(listSub1);
|
|
527
|
+
await waitForCall(ifaceSub);
|
|
528
|
+
expectSingleListCallAndClear(listSub1, [], {
|
|
529
|
+
status: "loading"
|
|
530
|
+
});
|
|
531
|
+
expectSingleListCallAndClear(ifaceSub, [], {
|
|
532
|
+
status: "loading"
|
|
533
|
+
});
|
|
534
|
+
await waitForCall(listSub1);
|
|
535
|
+
expectSingleListCallAndClear(listSub1, employeesAsServerReturns, {
|
|
464
536
|
status: "loaded"
|
|
465
|
-
})
|
|
537
|
+
});
|
|
538
|
+
await waitForCall(ifaceSub);
|
|
539
|
+
expectSingleListCallAndClear(ifaceSub, employeesAsServerReturns, {
|
|
540
|
+
status: "loaded"
|
|
541
|
+
});
|
|
542
|
+
expectNoMoreCalls(listSub1);
|
|
543
|
+
expectNoMoreCalls(ifaceSub);
|
|
544
|
+
expect(listSub1.next).not.toHaveBeenCalled();
|
|
545
|
+
expect(listSub1.error).not.toHaveBeenCalled();
|
|
546
|
+
expect(ifaceSub.next).not.toHaveBeenCalled();
|
|
547
|
+
expect(ifaceSub.error).not.toHaveBeenCalled();
|
|
466
548
|
});
|
|
467
549
|
it("subsequent load", async () => {
|
|
468
550
|
// Pre-seed with data the server doesn't return
|
|
469
|
-
|
|
470
|
-
|
|
551
|
+
updateList(cache, {
|
|
552
|
+
type: Employee,
|
|
553
|
+
where: {},
|
|
554
|
+
orderBy: {}
|
|
555
|
+
}, mutatedEmployees);
|
|
556
|
+
defer(cache.observeList({
|
|
557
|
+
type: Employee,
|
|
471
558
|
mode: "force"
|
|
472
559
|
}, listSub1));
|
|
473
|
-
await
|
|
474
|
-
|
|
475
|
-
|
|
560
|
+
await waitForCall(listSub1, 1);
|
|
561
|
+
const firstLoad = listSub1.next.mock.calls[0][0];
|
|
562
|
+
expectSingleListCallAndClear(listSub1, mutatedEmployees, {
|
|
476
563
|
status: "loading"
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
listSub1
|
|
480
|
-
await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
|
|
481
|
-
expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
|
|
482
|
-
resolvedList: employeesAsServerReturns,
|
|
564
|
+
});
|
|
565
|
+
await waitForCall(listSub1, 1);
|
|
566
|
+
expectSingleListCallAndClear(listSub1, employeesAsServerReturns, {
|
|
483
567
|
status: "loaded",
|
|
484
568
|
lastUpdated: expect.toBeGreaterThan(firstLoad.lastUpdated)
|
|
485
|
-
})
|
|
486
|
-
listSub1.mockClear();
|
|
569
|
+
});
|
|
487
570
|
});
|
|
488
571
|
});
|
|
489
572
|
describe("mode = offline", () => {
|
|
490
573
|
it("updates with list updates", async () => {
|
|
491
|
-
defer(cache.observeList(
|
|
574
|
+
defer(cache.observeList({
|
|
575
|
+
type: Employee,
|
|
576
|
+
where: {},
|
|
577
|
+
orderBy: {},
|
|
492
578
|
mode: "offline"
|
|
493
579
|
}, listSub1));
|
|
494
|
-
expect(listSub1).toHaveBeenCalledTimes(0);
|
|
495
|
-
|
|
580
|
+
expect(listSub1.next).toHaveBeenCalledTimes(0);
|
|
581
|
+
updateList(cache, {
|
|
582
|
+
type: Employee,
|
|
583
|
+
where: {},
|
|
584
|
+
orderBy: {}
|
|
585
|
+
}, employeesAsServerReturns);
|
|
496
586
|
vitest.runOnlyPendingTimers();
|
|
497
|
-
|
|
498
|
-
resolvedList: employeesAsServerReturns
|
|
499
|
-
}));
|
|
500
|
-
listSub1.mockClear();
|
|
587
|
+
expectSingleListCallAndClear(listSub1, employeesAsServerReturns);
|
|
501
588
|
|
|
502
589
|
// list is just now one object
|
|
503
|
-
|
|
590
|
+
updateList(cache, {
|
|
591
|
+
type: Employee,
|
|
592
|
+
where: {},
|
|
593
|
+
orderBy: {}
|
|
594
|
+
}, [employeesAsServerReturns[0]]);
|
|
504
595
|
vitest.runOnlyPendingTimers();
|
|
505
|
-
|
|
506
|
-
resolvedList: [employeesAsServerReturns[0]]
|
|
507
|
-
}));
|
|
596
|
+
expectSingleListCallAndClear(listSub1, [employeesAsServerReturns[0]]);
|
|
508
597
|
});
|
|
509
598
|
it("updates with different list updates", async () => {
|
|
510
|
-
defer(cache.observeList(
|
|
599
|
+
defer(cache.observeList({
|
|
600
|
+
type: Employee,
|
|
601
|
+
where: {},
|
|
602
|
+
orderBy: {},
|
|
511
603
|
mode: "offline"
|
|
512
604
|
}, listSub1));
|
|
513
|
-
expect(listSub1).toHaveBeenCalledTimes(0);
|
|
514
|
-
|
|
605
|
+
expect(listSub1.next).toHaveBeenCalledTimes(0);
|
|
606
|
+
updateList(cache, {
|
|
607
|
+
type: Employee,
|
|
608
|
+
where: {},
|
|
609
|
+
orderBy: {}
|
|
610
|
+
}, employeesAsServerReturns);
|
|
515
611
|
vitest.runOnlyPendingTimers();
|
|
516
|
-
|
|
517
|
-
resolvedList: employeesAsServerReturns
|
|
518
|
-
}));
|
|
519
|
-
listSub1.mockClear();
|
|
612
|
+
expectSingleListCallAndClear(listSub1, employeesAsServerReturns);
|
|
520
613
|
|
|
521
614
|
// new where === different list
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
615
|
+
updateList(cache, {
|
|
616
|
+
type: Employee,
|
|
617
|
+
where: {
|
|
618
|
+
employeeId: {
|
|
619
|
+
$gt: 0
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
orderBy: {}
|
|
526
623
|
}, mutatedEmployees);
|
|
527
624
|
vitest.runOnlyPendingTimers();
|
|
528
625
|
|
|
529
626
|
// original list updates still
|
|
530
|
-
|
|
531
|
-
resolvedList: mutatedEmployees
|
|
532
|
-
}));
|
|
627
|
+
expectSingleListCallAndClear(listSub1, mutatedEmployees);
|
|
533
628
|
});
|
|
534
629
|
});
|
|
535
630
|
});
|
|
@@ -542,57 +637,127 @@ describe(Store, () => {
|
|
|
542
637
|
});
|
|
543
638
|
it("works in the solo case", async () => {
|
|
544
639
|
const listSub = mockListSubCallback();
|
|
545
|
-
defer(cache.observeList(
|
|
640
|
+
defer(cache.observeList({
|
|
641
|
+
type: Employee,
|
|
642
|
+
where: {},
|
|
643
|
+
orderBy: {},
|
|
546
644
|
mode: "force",
|
|
547
645
|
pageSize: 1
|
|
548
646
|
}, listSub));
|
|
549
|
-
expect(listSub).not.toHaveBeenCalled();
|
|
550
|
-
await
|
|
551
|
-
|
|
647
|
+
expect(listSub.next).not.toHaveBeenCalled();
|
|
648
|
+
await waitForCall(listSub, 1);
|
|
649
|
+
expectSingleListCallAndClear(listSub, [], {
|
|
552
650
|
status: "loading"
|
|
553
|
-
})
|
|
554
|
-
listSub
|
|
555
|
-
await vi.waitFor(() => expect(listSub).toHaveBeenCalled());
|
|
556
|
-
expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
|
|
557
|
-
resolvedList: employeesAsServerReturns.slice(0, 1),
|
|
558
|
-
status: "loaded"
|
|
559
|
-
}));
|
|
651
|
+
});
|
|
652
|
+
await waitForCall(listSub, 1);
|
|
560
653
|
const {
|
|
561
654
|
fetchMore
|
|
562
|
-
} = listSub.mock.calls[0][0];
|
|
563
|
-
listSub.
|
|
655
|
+
} = listSub.next.mock.calls[0][0];
|
|
656
|
+
expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 1), {
|
|
657
|
+
status: "loaded"
|
|
658
|
+
});
|
|
564
659
|
void fetchMore();
|
|
565
|
-
await
|
|
566
|
-
|
|
567
|
-
resolvedList: employeesAsServerReturns.slice(0, 1),
|
|
660
|
+
await waitForCall(listSub, 1);
|
|
661
|
+
expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 1), {
|
|
568
662
|
status: "loading"
|
|
569
|
-
})
|
|
570
|
-
listSub
|
|
571
|
-
|
|
572
|
-
expect(listSub).toHaveBeenCalledWith(listPayloadContaining({
|
|
573
|
-
resolvedList: employeesAsServerReturns.slice(0, 2),
|
|
663
|
+
});
|
|
664
|
+
await waitForCall(listSub, 1);
|
|
665
|
+
expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 2), {
|
|
574
666
|
status: "loaded"
|
|
575
|
-
})
|
|
667
|
+
});
|
|
576
668
|
});
|
|
577
669
|
});
|
|
578
670
|
});
|
|
579
671
|
describe("with mock client", () => {
|
|
580
672
|
let client;
|
|
581
|
-
let
|
|
582
|
-
let
|
|
673
|
+
let apiServer;
|
|
674
|
+
let fauxFoundry;
|
|
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
|
+
});
|
|
583
695
|
beforeEach(async () => {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
696
|
+
store = new Store(client);
|
|
697
|
+
});
|
|
698
|
+
it("properly fires error handler for a list", async () => {
|
|
699
|
+
const sub = mockListSubCallback();
|
|
700
|
+
store.observeList({
|
|
701
|
+
type: Employee,
|
|
702
|
+
where: {
|
|
703
|
+
aBadPropertyThatDoesNotExist: "aBadValue"
|
|
704
|
+
},
|
|
705
|
+
orderBy: {}
|
|
706
|
+
}, sub);
|
|
707
|
+
await waitForCall(sub.error, 1);
|
|
708
|
+
expect(sub.error).toHaveBeenCalled();
|
|
709
|
+
expect(sub.next).not.toHaveBeenCalled();
|
|
710
|
+
});
|
|
711
|
+
describe("batching", () => {
|
|
712
|
+
it("groups requests for single objects", async () => {
|
|
713
|
+
fauxFoundry.getDefaultDataStore().registerObject(Employee, {
|
|
714
|
+
$apiName: "Employee",
|
|
715
|
+
employeeId: 0
|
|
716
|
+
});
|
|
717
|
+
fauxFoundry.getDefaultDataStore().registerObject(Employee, {
|
|
718
|
+
$apiName: "Employee",
|
|
719
|
+
employeeId: 1
|
|
720
|
+
});
|
|
721
|
+
const a = mockSingleSubCallback();
|
|
722
|
+
const b = mockSingleSubCallback();
|
|
723
|
+
defer(store.observeObject(Employee, 0, {}, a));
|
|
724
|
+
defer(store.observeObject(Employee, 1, {}, b));
|
|
725
|
+
await a.expectLoadingAndLoaded({
|
|
726
|
+
loading: objectPayloadContaining({
|
|
727
|
+
status: "loading",
|
|
728
|
+
object: undefined
|
|
729
|
+
}),
|
|
730
|
+
loaded: objectPayloadContaining({
|
|
731
|
+
object: expect.objectContaining({
|
|
732
|
+
$primaryKey: 0
|
|
733
|
+
})
|
|
734
|
+
})
|
|
735
|
+
});
|
|
736
|
+
await b.expectLoadingAndLoaded({
|
|
737
|
+
loading: objectPayloadContaining({
|
|
738
|
+
status: "loading",
|
|
739
|
+
object: undefined
|
|
740
|
+
}),
|
|
741
|
+
loaded: objectPayloadContaining({
|
|
742
|
+
object: expect.objectContaining({
|
|
743
|
+
$primaryKey: 1
|
|
744
|
+
})
|
|
745
|
+
})
|
|
746
|
+
});
|
|
747
|
+
});
|
|
587
748
|
});
|
|
588
749
|
describe("actions", () => {
|
|
750
|
+
beforeEach(() => {
|
|
751
|
+
fauxFoundry.getDefaultDataStore().clear();
|
|
752
|
+
});
|
|
589
753
|
it("properly invalidates objects", async () => {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
754
|
+
fauxFoundry.getDefaultDataStore().registerObject(Todo, {
|
|
755
|
+
$apiName: "Todo",
|
|
756
|
+
id: 0,
|
|
757
|
+
text: "og title"
|
|
593
758
|
});
|
|
594
759
|
const todoSubFn = mockSingleSubCallback();
|
|
595
|
-
defer(
|
|
760
|
+
defer(store.observeObject(Todo, 0, {}, todoSubFn));
|
|
596
761
|
await todoSubFn.expectLoadingAndLoaded({
|
|
597
762
|
loading: objectPayloadContaining({
|
|
598
763
|
status: "loading",
|
|
@@ -606,23 +771,10 @@ describe(Store, () => {
|
|
|
606
771
|
});
|
|
607
772
|
|
|
608
773
|
// at this point we have an observation properly set up
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
objectType: "Todo",
|
|
612
|
-
primaryKey: 0
|
|
613
|
-
}]
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
// after we apply the action, the object is invalidated and gets re-requested
|
|
617
|
-
|
|
618
|
-
mockClient.mockFetchOneOnce().resolve({
|
|
619
|
-
$apiName: "Todo",
|
|
774
|
+
await store.applyAction(editTodo, {
|
|
775
|
+
id: 0,
|
|
620
776
|
text: "hello there kind sir"
|
|
621
777
|
});
|
|
622
|
-
const actionPromise = cache.applyAction(createOffice, {
|
|
623
|
-
officeId: "whatever"
|
|
624
|
-
});
|
|
625
|
-
await actionPromise;
|
|
626
778
|
await todoSubFn.expectLoadingAndLoaded({
|
|
627
779
|
loading: objectPayloadContaining({
|
|
628
780
|
status: "loading"
|
|
@@ -635,17 +787,19 @@ describe(Store, () => {
|
|
|
635
787
|
});
|
|
636
788
|
});
|
|
637
789
|
it("rolls back optimistic updates on error", async () => {
|
|
638
|
-
const fauxObject = {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
$title: "does not matter"
|
|
643
|
-
};
|
|
790
|
+
const fauxObject = expect.objectContaining({
|
|
791
|
+
id: 0,
|
|
792
|
+
text: "does not matter"
|
|
793
|
+
});
|
|
644
794
|
|
|
645
|
-
//
|
|
646
|
-
|
|
795
|
+
// set the object in the "backend"
|
|
796
|
+
fauxFoundry.getDefaultDataStore().registerObject(Todo, {
|
|
797
|
+
$apiName: "Todo",
|
|
798
|
+
id: 0,
|
|
799
|
+
text: "does not matter"
|
|
800
|
+
});
|
|
647
801
|
const todoSubFn = mockSingleSubCallback();
|
|
648
|
-
defer(
|
|
802
|
+
defer(store.observeObject(Todo, 0, {}, todoSubFn));
|
|
649
803
|
await todoSubFn.expectLoadingAndLoaded({
|
|
650
804
|
loading: objectPayloadContaining({
|
|
651
805
|
status: "loading",
|
|
@@ -658,47 +812,259 @@ describe(Store, () => {
|
|
|
658
812
|
isOptimistic: false
|
|
659
813
|
})
|
|
660
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;
|
|
661
817
|
|
|
662
818
|
// at this point we have an observation properly set up
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
officeId: "whatever"
|
|
819
|
+
await expect(store.applyAction(editTodo, {
|
|
820
|
+
id: "not an id that exists"
|
|
666
821
|
}, {
|
|
667
822
|
optimisticUpdate: ctx => {
|
|
668
|
-
ctx.updateObject({
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
});
|
|
823
|
+
ctx.updateObject(object.$clone({
|
|
824
|
+
text: "optimistic"
|
|
825
|
+
}));
|
|
672
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
|
+
})
|
|
673
843
|
});
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
844
|
+
});
|
|
845
|
+
});
|
|
846
|
+
describe("orderBy", async () => {
|
|
847
|
+
let nextPk = 0;
|
|
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);
|
|
682
861
|
}));
|
|
683
|
-
|
|
862
|
+
});
|
|
863
|
+
const noWhereNoOrderBy = {
|
|
864
|
+
type: Todo,
|
|
865
|
+
where: {},
|
|
866
|
+
orderBy: {}
|
|
867
|
+
};
|
|
868
|
+
const noWhereOrderByText = {
|
|
869
|
+
type: Todo,
|
|
870
|
+
where: {},
|
|
871
|
+
orderBy: {
|
|
872
|
+
text: "asc"
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
const subListUnordered = mockListSubCallback();
|
|
876
|
+
const subListOrdered = mockListSubCallback();
|
|
877
|
+
beforeEach(() => {
|
|
878
|
+
defer(store.observeList({
|
|
879
|
+
...noWhereNoOrderBy,
|
|
880
|
+
mode: "offline"
|
|
881
|
+
}, subListUnordered));
|
|
882
|
+
expect(subListUnordered.next).toHaveBeenCalledTimes(0);
|
|
883
|
+
defer(store.observeList({
|
|
884
|
+
...noWhereOrderByText,
|
|
885
|
+
mode: "offline"
|
|
886
|
+
}, subListOrdered));
|
|
887
|
+
expect(subListOrdered.next).toHaveBeenCalledTimes(0);
|
|
888
|
+
});
|
|
889
|
+
it("invalidates the correct lists", async () => {
|
|
890
|
+
// for whatever reason, the first list is loaded as [B, A]
|
|
891
|
+
updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
|
|
892
|
+
await waitForCall(subListUnordered, 1);
|
|
893
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
|
|
684
894
|
|
|
685
|
-
//
|
|
686
|
-
|
|
687
|
-
await
|
|
895
|
+
// The other list definitely matches on the where clause and we can insert
|
|
896
|
+
// orderBy properly. So this is [A, B]
|
|
897
|
+
await waitForCall(subListOrdered, 1);
|
|
898
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
|
|
688
899
|
|
|
689
|
-
//
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
900
|
+
// For whatever reason, object B is no longer in the first set (use your imagination)
|
|
901
|
+
// but we have added a C before A. So the first list is [C, A]
|
|
902
|
+
updateList(store, {
|
|
903
|
+
type: Todo,
|
|
904
|
+
where: {},
|
|
905
|
+
orderBy: {}
|
|
906
|
+
}, [fauxObjectC, fauxObjectA]);
|
|
907
|
+
await waitForCall(subListUnordered, 1);
|
|
908
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectC, fauxObjectA]);
|
|
909
|
+
|
|
910
|
+
// Nothing told the system that B was deleted so we can presume it still exists
|
|
911
|
+
// and therefore the second list is now [A, B, C]
|
|
912
|
+
await waitForCall(subListOrdered, 1);
|
|
913
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB, fauxObjectC]);
|
|
914
|
+
});
|
|
915
|
+
it("produces proper results with optimistic updates and successful action", async () => {
|
|
916
|
+
const optimisticallyMutatedA = fauxObjectA.$clone({
|
|
917
|
+
text: "optimistic"
|
|
918
|
+
});
|
|
919
|
+
const pkForOptimistic = nextPk++;
|
|
920
|
+
const optimisticallyCreatedObjectD = expect.objectContaining({
|
|
921
|
+
"text": "d",
|
|
922
|
+
id: pkForOptimistic
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
// for whatever reason, the first list is loaded as [B, A]
|
|
926
|
+
updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
|
|
927
|
+
await waitForCall(subListUnordered, 1);
|
|
928
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
|
|
929
|
+
|
|
930
|
+
// The other list definitely matches on the where clause and we can insert
|
|
931
|
+
// orderBy properly. So this is [A, B]
|
|
932
|
+
await waitForCall(subListOrdered, 1);
|
|
933
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
|
|
934
|
+
testStage("Start");
|
|
935
|
+
|
|
936
|
+
// Perform something optimistic.
|
|
937
|
+
const removeOptimisticResult = runOptimisticJob(store, b => {
|
|
938
|
+
b.createObject(Todo, pkForOptimistic, {
|
|
939
|
+
id: pkForOptimistic,
|
|
940
|
+
text: "d"
|
|
941
|
+
});
|
|
942
|
+
b.updateObject(optimisticallyMutatedA);
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
// The first list is now [B, A, optimistic]
|
|
946
|
+
await waitForCall(subListUnordered, 1);
|
|
947
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, optimisticallyMutatedA,
|
|
948
|
+
// same position, new values
|
|
949
|
+
optimisticallyCreatedObjectD], {
|
|
950
|
+
isOptimistic: true
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
// the second list is now [A, B, optimistic]
|
|
954
|
+
await waitForCall(subListOrdered, 1);
|
|
955
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectB, optimisticallyCreatedObjectD, optimisticallyMutatedA], {
|
|
956
|
+
isOptimistic: true
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
// Roll back the optimistic update
|
|
960
|
+
await removeOptimisticResult();
|
|
961
|
+
|
|
962
|
+
// The first list is now [B, A]
|
|
963
|
+
await waitForCall(subListUnordered, 1);
|
|
964
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA], {
|
|
694
965
|
isOptimistic: false
|
|
695
|
-
})
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
// the second list is now [A, B]
|
|
969
|
+
await waitForCall(subListOrdered, 1);
|
|
970
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB], {
|
|
971
|
+
isOptimistic: false
|
|
972
|
+
});
|
|
973
|
+
});
|
|
974
|
+
// I think these are named backwards
|
|
975
|
+
it("produces proper results with optimistic updates and rollback", async () => {
|
|
976
|
+
const pkForOptimistic = nextPk++;
|
|
977
|
+
const optimisticallyCreatedObjectD = expect.objectContaining({
|
|
978
|
+
"$primaryKey": pkForOptimistic,
|
|
979
|
+
"$title": undefined,
|
|
980
|
+
// FIXME once this is calculated by optimistic then this needs to be the right value
|
|
981
|
+
"text": "d optimistic",
|
|
982
|
+
id: pkForOptimistic
|
|
983
|
+
});
|
|
984
|
+
const optimisticallyMutatedA = fauxObjectA.$clone({
|
|
985
|
+
text: "optimistic"
|
|
986
|
+
});
|
|
987
|
+
testStage("Initial Setup");
|
|
988
|
+
|
|
989
|
+
// for whatever reason, the first list is loaded as [B, A]
|
|
990
|
+
updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
|
|
991
|
+
await waitForCall(subListUnordered, 1);
|
|
992
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
|
|
993
|
+
|
|
994
|
+
// The other list definitely matches on the where clause and we can insert
|
|
995
|
+
// orderBy properly. So this is [A, B]
|
|
996
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
|
|
997
|
+
testStage("Optimistic Creation");
|
|
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
|
+
|
|
1017
|
+
// the optimistic job will call createObject which triggers the `objectFactory2` of the
|
|
1018
|
+
// cache context.
|
|
1019
|
+
|
|
1020
|
+
// Perform something optimistic.
|
|
1021
|
+
const pActionResult = store.applyAction(crazyAction, {}, {
|
|
1022
|
+
optimisticUpdate: b => {
|
|
1023
|
+
b.createObject(Todo, pkForOptimistic, {
|
|
1024
|
+
id: pkForOptimistic,
|
|
1025
|
+
text: "d optimistic"
|
|
1026
|
+
});
|
|
1027
|
+
b.updateObject(optimisticallyMutatedA);
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
testStage("Optimistic Updates");
|
|
1031
|
+
|
|
1032
|
+
// The first list is now [B, A, optimistic]
|
|
1033
|
+
await waitForCall(subListUnordered, 1);
|
|
1034
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, optimisticallyMutatedA,
|
|
1035
|
+
// same position, new values
|
|
1036
|
+
optimisticallyCreatedObjectD], {
|
|
1037
|
+
isOptimistic: true
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
// the second list is now [B, optimistic, optimistic a]
|
|
1041
|
+
await waitForCall(subListOrdered, 1);
|
|
1042
|
+
expectSingleListCallAndClear(subListOrdered, [fauxObjectB, optimisticallyCreatedObjectD, optimisticallyMutatedA], {
|
|
1043
|
+
isOptimistic: true
|
|
1044
|
+
});
|
|
1045
|
+
testStage("Resolve Action");
|
|
1046
|
+
const modifiedObjectA = fauxObjectA.$clone({
|
|
1047
|
+
text: "a prime"
|
|
1048
|
+
});
|
|
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);
|
|
1053
|
+
await waitForCall(subListUnordered, 1);
|
|
1054
|
+
expectSingleListCallAndClear(subListUnordered, [fauxObjectB, modifiedObjectA, createdObjectD], {
|
|
1055
|
+
isOptimistic: false
|
|
1056
|
+
});
|
|
1057
|
+
await waitForCall(subListOrdered, 1);
|
|
1058
|
+
expectSingleListCallAndClear(subListOrdered, [modifiedObjectA, fauxObjectB, createdObjectD], {
|
|
1059
|
+
isOptimistic: false
|
|
1060
|
+
});
|
|
696
1061
|
});
|
|
697
1062
|
});
|
|
698
1063
|
});
|
|
699
1064
|
describe("layers", () => {
|
|
700
1065
|
it("properly remove", () => {
|
|
701
|
-
const
|
|
1066
|
+
const clientHelper = createClientMockHelper();
|
|
1067
|
+
const store = new Store(clientHelper.client);
|
|
702
1068
|
const baseObjects = [1, 2].map(i => ({
|
|
703
1069
|
$primaryKey: i,
|
|
704
1070
|
$objectType: "Employee",
|
|
@@ -709,12 +1075,12 @@ describe(Store, () => {
|
|
|
709
1075
|
|
|
710
1076
|
// set the truth
|
|
711
1077
|
for (const obj of baseObjects) {
|
|
712
|
-
|
|
1078
|
+
updateObject(store, obj);
|
|
713
1079
|
}
|
|
714
1080
|
|
|
715
1081
|
// expect the truth
|
|
716
1082
|
for (const obj of baseObjects) {
|
|
717
|
-
expect(
|
|
1083
|
+
expect(getObject(store, "Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
|
|
718
1084
|
$title: `truth ${obj.$primaryKey}`
|
|
719
1085
|
}));
|
|
720
1086
|
}
|
|
@@ -734,7 +1100,7 @@ describe(Store, () => {
|
|
|
734
1100
|
|
|
735
1101
|
// expect the optimistic values
|
|
736
1102
|
for (let i = 0; i < 2; i++) {
|
|
737
|
-
expect(
|
|
1103
|
+
expect(getObject(store, "Employee", baseObjects[i].$primaryKey)).toEqual(expect.objectContaining({
|
|
738
1104
|
$title: `optimistic ${baseObjects[i].$primaryKey}`
|
|
739
1105
|
}));
|
|
740
1106
|
}
|
|
@@ -743,10 +1109,10 @@ describe(Store, () => {
|
|
|
743
1109
|
store.removeLayer(layerIds[0]);
|
|
744
1110
|
|
|
745
1111
|
// should have truth object 1 and optimistic object 2
|
|
746
|
-
expect(
|
|
1112
|
+
expect(getObject(store, "Employee", 1)).toEqual(expect.objectContaining({
|
|
747
1113
|
$title: "truth 1"
|
|
748
1114
|
}));
|
|
749
|
-
expect(
|
|
1115
|
+
expect(getObject(store, "Employee", 2)).toEqual(expect.objectContaining({
|
|
750
1116
|
$title: "optimistic 2"
|
|
751
1117
|
}));
|
|
752
1118
|
|
|
@@ -755,7 +1121,7 @@ describe(Store, () => {
|
|
|
755
1121
|
|
|
756
1122
|
// should have truth objects
|
|
757
1123
|
for (const obj of baseObjects) {
|
|
758
|
-
expect(
|
|
1124
|
+
expect(getObject(store, "Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
|
|
759
1125
|
$title: `truth ${obj.$primaryKey}`
|
|
760
1126
|
}));
|
|
761
1127
|
}
|