@gravity-ui/data-source
Version:
A wrapper around data fetching
1,138 lines (1,131 loc) • 51.5 kB
JavaScript
"use strict";
var _regeneratorRuntime2 = _interopRequireDefault(require("@babel/runtime/helpers/regeneratorRuntime"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _react = _interopRequireDefault(require("react"));
var _reactQuery = require("@tanstack/react-query");
var _react2 = require("@testing-library/react");
var _ClientDataManager = require("../ClientDataManager");
var _DataSourceProvider = require("../DataSourceProvider");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
describe('subscriptions', function () {
var dataManager;
beforeEach(function () {
dataManager = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false
}
});
});
afterEach(function () {
var _dataManager$queryNor;
(_dataManager$queryNor = dataManager.queryNormalizer) === null || _dataManager$queryNor === void 0 || _dataManager$queryNor.unsubscribe();
dataManager.queryClient.clear();
});
describe('QueryCache subscription', function () {
it('should add query to normalizer when added to QueryCache', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee2() {
var normalized;
return (0, _regeneratorRuntime2.default)().wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
expect(dataManager.queryNormalizer).toBeDefined();
dataManager.queryNormalizer.subscribe();
// Add query with normalize: true option
_context2.next = 4;
return dataManager.queryClient.fetchQuery({
queryKey: ['users'],
queryFn: function () {
var _queryFn = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
return _context.abrupt("return", [{
id: '1',
name: 'User 1'
}]);
case 1:
case "end":
return _context.stop();
}
}, _callee);
}));
function queryFn() {
return _queryFn.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 4:
normalized = dataManager.queryNormalizer.getNormalizedData();
expect(normalized.objects['@@1']).toBeDefined();
case 6:
case "end":
return _context2.stop();
}
}, _callee2);
})));
it('should update query in normalizer on update', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee5() {
var queryKey, normalizedBefore, objectCountBefore, normalizedAfter;
return (0, _regeneratorRuntime2.default)().wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
expect(dataManager.queryNormalizer).toBeDefined();
dataManager.queryNormalizer.subscribe();
queryKey = ['users']; // Initial data with normalize: true
_context5.next = 5;
return dataManager.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn2 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee3() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
return _context3.abrupt("return", [{
id: '1',
name: 'Old'
}]);
case 1:
case "end":
return _context3.stop();
}
}, _callee3);
}));
function queryFn() {
return _queryFn2.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
normalizedBefore = dataManager.queryNormalizer.getNormalizedData();
objectCountBefore = Object.keys(normalizedBefore.objects).length; // Update data
_context5.next = 9;
return dataManager.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn3 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee4() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
return _context4.abrupt("return", [{
id: '1',
name: 'New'
}]);
case 1:
case "end":
return _context4.stop();
}
}, _callee4);
}));
function queryFn() {
return _queryFn3.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 9:
// Verify that normalized data was updated
normalizedAfter = dataManager.queryNormalizer.getNormalizedData();
expect(Object.keys(normalizedAfter.objects).length).toBe(objectCountBefore);
expect(normalizedAfter.queries[JSON.stringify(queryKey)]).toBeDefined();
case 12:
case "end":
return _context5.stop();
}
}, _callee5);
})));
it('should remove query from normalizer when removed from QueryCache', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee7() {
var queryKey, normalized;
return (0, _regeneratorRuntime2.default)().wrap(function _callee7$(_context7) {
while (1) switch (_context7.prev = _context7.next) {
case 0:
expect(dataManager.queryNormalizer).toBeDefined();
dataManager.queryNormalizer.subscribe();
queryKey = ['users']; // Add query
_context7.next = 5;
return dataManager.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn4 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee6() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee6$(_context6) {
while (1) switch (_context6.prev = _context6.next) {
case 0:
return _context6.abrupt("return", [{
id: '1',
name: 'User 1'
}]);
case 1:
case "end":
return _context6.stop();
}
}, _callee6);
}));
function queryFn() {
return _queryFn4.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
// Remove query
dataManager.queryClient.removeQueries({
queryKey: queryKey
});
// Give time to process event
_context7.next = 8;
return new Promise(function (resolve) {
return setTimeout(resolve, 10);
});
case 8:
normalized = dataManager.queryNormalizer.getNormalizedData(); // Query should be removed from queries
expect(normalized.queries[JSON.stringify(queryKey)]).toBeUndefined();
case 10:
case "end":
return _context7.stop();
}
}, _callee7);
})));
it('should support meta configuration for queries', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee8() {
var normalized;
return (0, _regeneratorRuntime2.default)().wrap(function _callee8$(_context8) {
while (1) switch (_context8.prev = _context8.next) {
case 0:
expect(dataManager.queryNormalizer).toBeDefined();
dataManager.queryNormalizer.subscribe();
// Check that we can use meta for configuration
// Real check for disabling via meta is already tested in integration tests
normalized = dataManager.queryNormalizer.getNormalizedData();
expect(normalized).toBeDefined();
expect(normalized.objects).toBeDefined();
expect(normalized.queries).toBeDefined();
case 6:
case "end":
return _context8.stop();
}
}, _callee8);
})));
it('should unsubscribe correctly', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee10() {
var normalized;
return (0, _regeneratorRuntime2.default)().wrap(function _callee10$(_context10) {
while (1) switch (_context10.prev = _context10.next) {
case 0:
expect(dataManager.queryNormalizer).toBeDefined();
dataManager.queryNormalizer.subscribe();
dataManager.queryNormalizer.unsubscribe();
// After unsubscribing, adding query should not affect normalizer
_context10.next = 5;
return dataManager.queryClient.fetchQuery({
queryKey: ['users'],
queryFn: function () {
var _queryFn5 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee9() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee9$(_context9) {
while (1) switch (_context9.prev = _context9.next) {
case 0:
return _context9.abrupt("return", [{
id: '1',
name: 'User 1'
}]);
case 1:
case "end":
return _context9.stop();
}
}, _callee9);
}));
function queryFn() {
return _queryFn5.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
normalized = dataManager.queryNormalizer.getNormalizedData();
expect(Object.keys(normalized.objects)).toHaveLength(0);
case 7:
case "end":
return _context10.stop();
}
}, _callee10);
})));
it('should allow multiple unsubscribe calls', function () {
expect(dataManager.queryNormalizer).toBeDefined();
dataManager.queryNormalizer.subscribe();
dataManager.queryNormalizer.unsubscribe();
// Repeated call should not throw error
expect(function () {
return dataManager.queryNormalizer.unsubscribe();
}).not.toThrow();
});
});
describe('MutationCache subscription', function () {
var dataManagerWithOptimistic;
beforeEach(function () {
dataManagerWithOptimistic = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false,
optimistic: {
autoCalculateRollback: true
}
}
});
});
afterEach(function () {
var _dataManagerWithOptim;
(_dataManagerWithOptim = dataManagerWithOptimistic.queryNormalizer) === null || _dataManagerWithOptim === void 0 || _dataManagerWithOptim.unsubscribe();
dataManagerWithOptimistic.queryClient.clear();
});
it('should update queries on successful mutation', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee13() {
var queryKey, wrapper, _renderHook, mutationResult, data;
return (0, _regeneratorRuntime2.default)().wrap(function _callee13$(_context13) {
while (1) switch (_context13.prev = _context13.next) {
case 0:
expect(dataManagerWithOptimistic.queryNormalizer).toBeDefined();
dataManagerWithOptimistic.queryNormalizer.subscribe();
queryKey = ['users']; // Initial data
_context13.next = 5;
return dataManagerWithOptimistic.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn6 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee11() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee11$(_context11) {
while (1) switch (_context11.prev = _context11.next) {
case 0:
return _context11.abrupt("return", [{
id: '1',
name: 'Old'
}]);
case 1:
case "end":
return _context11.stop();
}
}, _callee11);
}));
function queryFn() {
return _queryFn6.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
// Create wrapper for hooks
wrapper = function wrapper(_ref7) {
var children = _ref7.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dataManagerWithOptimistic,
children: children
});
}; // Mutation via useMutation
_renderHook = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee12() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee12$(_context12) {
while (1) switch (_context12.prev = _context12.next) {
case 0:
return _context12.abrupt("return", {
id: '1',
name: 'New'
});
case 1:
case "end":
return _context12.stop();
}
}, _callee12);
}));
function mutationFn() {
return _mutationFn.apply(this, arguments);
}
return mutationFn;
}(),
normalize: true,
optimistic: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook.result;
mutationResult.current.mutate(undefined);
_context13.next = 10;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isSuccess).toBe(true);
});
case 10:
data = dataManagerWithOptimistic.queryClient.getQueryData(queryKey);
expect(data[0].name).toBe('New');
case 12:
case "end":
return _context13.stop();
}
}, _callee13);
})));
it('should apply optimistic updates', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee16() {
var queryKey, wrapper, _renderHook2, mutationResult, dataFinal;
return (0, _regeneratorRuntime2.default)().wrap(function _callee16$(_context16) {
while (1) switch (_context16.prev = _context16.next) {
case 0:
expect(dataManagerWithOptimistic.queryNormalizer).toBeDefined();
dataManagerWithOptimistic.queryNormalizer.subscribe();
queryKey = ['users']; // Initial data
_context16.next = 5;
return dataManagerWithOptimistic.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn7 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee14() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee14$(_context14) {
while (1) switch (_context14.prev = _context14.next) {
case 0:
return _context14.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context14.stop();
}
}, _callee14);
}));
function queryFn() {
return _queryFn7.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
wrapper = function wrapper(_ref9) {
var children = _ref9.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dataManagerWithOptimistic,
children: children
});
}; // Mutation with optimistic data
_renderHook2 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn2 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee15() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee15$(_context15) {
while (1) switch (_context15.prev = _context15.next) {
case 0:
_context15.next = 2;
return new Promise(function (resolve) {
return setTimeout(resolve, 50);
});
case 2:
return _context15.abrupt("return", {
id: '1',
name: 'Final'
});
case 3:
case "end":
return _context15.stop();
}
}, _callee15);
}));
function mutationFn() {
return _mutationFn2.apply(this, arguments);
}
return mutationFn;
}(),
onMutate: function onMutate() {
return {
optimisticData: {
id: '1',
name: 'Optimistic'
}
};
},
normalize: true,
optimistic: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook2.result;
mutationResult.current.mutate(undefined);
// Check optimistic data
_context16.next = 10;
return (0, _react2.waitFor)(function () {
var data = dataManagerWithOptimistic.queryClient.getQueryData(queryKey);
expect(data[0].name).toBe('Optimistic');
});
case 10:
_context16.next = 12;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isSuccess).toBe(true);
});
case 12:
dataFinal = dataManagerWithOptimistic.queryClient.getQueryData(queryKey);
expect(dataFinal[0].name).toBe('Final');
case 14:
case "end":
return _context16.stop();
}
}, _callee16);
})));
it('should automatically calculate rollbackData', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee19() {
var queryKey, wrapper, _renderHook3, mutationResult, data;
return (0, _regeneratorRuntime2.default)().wrap(function _callee19$(_context19) {
while (1) switch (_context19.prev = _context19.next) {
case 0:
expect(dataManagerWithOptimistic.queryNormalizer).toBeDefined();
dataManagerWithOptimistic.queryNormalizer.subscribe();
queryKey = ['users']; // Initial data
_context19.next = 5;
return dataManagerWithOptimistic.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn8 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee17() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee17$(_context17) {
while (1) switch (_context17.prev = _context17.next) {
case 0:
return _context17.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context17.stop();
}
}, _callee17);
}));
function queryFn() {
return _queryFn8.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
wrapper = function wrapper(_ref11) {
var children = _ref11.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dataManagerWithOptimistic,
children: children
});
}; // Mutation with optimistic data that will fail
_renderHook3 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn3 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee18() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee18$(_context18) {
while (1) switch (_context18.prev = _context18.next) {
case 0:
_context18.next = 2;
return new Promise(function (resolve) {
return setTimeout(resolve, 50);
});
case 2:
throw new Error('Mutation failed');
case 3:
case "end":
return _context18.stop();
}
}, _callee18);
}));
function mutationFn() {
return _mutationFn3.apply(this, arguments);
}
return mutationFn;
}(),
onMutate: function onMutate() {
return {
optimisticData: {
id: '1',
name: 'Optimistic'
}
};
},
normalize: true,
optimistic: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook3.result;
mutationResult.current.mutate(undefined);
_context19.next = 10;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isError).toBe(true);
});
case 10:
// Data should be rolled back to original
data = dataManagerWithOptimistic.queryClient.getQueryData(queryKey);
expect(data[0].name).toBe('Original');
case 12:
case "end":
return _context19.stop();
}
}, _callee19);
})));
it('should rollback changes on mutation error', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee22() {
var queryKey, wrapper, _renderHook4, mutationResult, data;
return (0, _regeneratorRuntime2.default)().wrap(function _callee22$(_context22) {
while (1) switch (_context22.prev = _context22.next) {
case 0:
expect(dataManagerWithOptimistic.queryNormalizer).toBeDefined();
dataManagerWithOptimistic.queryNormalizer.subscribe();
queryKey = ['users']; // Initial data
_context22.next = 5;
return dataManagerWithOptimistic.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn9 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee20() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee20$(_context20) {
while (1) switch (_context20.prev = _context20.next) {
case 0:
return _context20.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context20.stop();
}
}, _callee20);
}));
function queryFn() {
return _queryFn9.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 5:
wrapper = function wrapper(_ref13) {
var children = _ref13.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dataManagerWithOptimistic,
children: children
});
}; // Mutation with error
_renderHook4 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn4 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee21() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee21$(_context21) {
while (1) switch (_context21.prev = _context21.next) {
case 0:
_context21.next = 2;
return new Promise(function (resolve) {
return setTimeout(resolve, 50);
});
case 2:
throw new Error('Failed');
case 3:
case "end":
return _context21.stop();
}
}, _callee21);
}));
function mutationFn() {
return _mutationFn4.apply(this, arguments);
}
return mutationFn;
}(),
onMutate: function onMutate() {
return {
optimisticData: {
id: '1',
name: 'Optimistic'
}
};
},
normalize: true,
optimistic: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook4.result;
mutationResult.current.mutate(undefined);
_context22.next = 10;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isError).toBe(true);
});
case 10:
data = dataManagerWithOptimistic.queryClient.getQueryData(queryKey);
expect(data[0].name).toBe('Original');
case 12:
case "end":
return _context22.stop();
}
}, _callee22);
})));
it('should ignore mutations with normalize: false', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee24() {
var dmNoNormalize, queryKey, wrapper, _renderHook5, mutationResult, data;
return (0, _regeneratorRuntime2.default)().wrap(function _callee24$(_context24) {
while (1) switch (_context24.prev = _context24.next) {
case 0:
dmNoNormalize = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false
}
});
expect(dmNoNormalize.queryNormalizer).toBeDefined();
queryKey = ['users'];
dmNoNormalize.queryClient.setQueryData(queryKey, [{
id: '1',
name: 'Original'
}]);
wrapper = function wrapper(_ref15) {
var children = _ref15.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dmNoNormalize,
children: children
});
}; // Mutation should not update data automatically (no normalize option)
_renderHook5 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn5 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee23() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee23$(_context23) {
while (1) switch (_context23.prev = _context23.next) {
case 0:
return _context23.abrupt("return", {
id: '1',
name: 'New'
});
case 1:
case "end":
return _context23.stop();
}
}, _callee23);
}));
function mutationFn() {
return _mutationFn5.apply(this, arguments);
}
return mutationFn;
}()
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook5.result;
mutationResult.current.mutate(undefined);
_context24.next = 9;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isSuccess).toBe(true);
});
case 9:
data = dmNoNormalize.queryClient.getQueryData(queryKey);
expect(data[0].name).toBe('Original');
// Not changed
case 11:
case "end":
return _context24.stop();
}
}, _callee24);
})));
it('should support devLogging for optimistic updates', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee27() {
var dmWithLogging, consoleSpy, queryKey, wrapper, _renderHook6, mutationResult;
return (0, _regeneratorRuntime2.default)().wrap(function _callee27$(_context27) {
while (1) switch (_context27.prev = _context27.next) {
case 0:
dmWithLogging = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false,
optimistic: {
autoCalculateRollback: true,
devLogging: true
}
}
});
expect(dmWithLogging.queryNormalizer).toBeDefined();
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
dmWithLogging.queryNormalizer.subscribe();
queryKey = ['users'];
_context27.next = 7;
return dmWithLogging.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn10 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee25() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee25$(_context25) {
while (1) switch (_context25.prev = _context25.next) {
case 0:
return _context25.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context25.stop();
}
}, _callee25);
}));
function queryFn() {
return _queryFn10.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 7:
wrapper = function wrapper(_ref17) {
var children = _ref17.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dmWithLogging,
children: children
});
};
_renderHook6 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn6 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee26() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee26$(_context26) {
while (1) switch (_context26.prev = _context26.next) {
case 0:
_context26.next = 2;
return new Promise(function (resolve) {
return setTimeout(resolve, 50);
});
case 2:
throw new Error('Failed');
case 3:
case "end":
return _context26.stop();
}
}, _callee26);
}));
function mutationFn() {
return _mutationFn6.apply(this, arguments);
}
return mutationFn;
}(),
onMutate: function onMutate() {
return {
optimisticData: {
id: '1',
name: 'Optimistic'
}
};
},
normalize: true,
optimistic: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook6.result;
mutationResult.current.mutate(undefined);
_context27.next = 12;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isError).toBe(true);
});
case 12:
// Verify that logging was called
expect(consoleSpy).toHaveBeenCalledWith('[OptimisticUpdate] Auto-calculated rollbackData:', expect.any(Object));
expect(consoleSpy).toHaveBeenCalledWith('[OptimisticUpdate] Rolling back changes');
consoleSpy.mockRestore();
case 15:
case "end":
return _context27.stop();
}
}, _callee27);
})));
it('should support manual rollbackData', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee30() {
var dmNoAutoRollback, queryKey, wrapper, _renderHook7, mutationResult, data;
return (0, _regeneratorRuntime2.default)().wrap(function _callee30$(_context30) {
while (1) switch (_context30.prev = _context30.next) {
case 0:
dmNoAutoRollback = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false,
optimistic: {
autoCalculateRollback: false
}
}
});
expect(dmNoAutoRollback.queryNormalizer).toBeDefined();
dmNoAutoRollback.queryNormalizer.subscribe();
queryKey = ['users'];
_context30.next = 6;
return dmNoAutoRollback.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn11 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee28() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee28$(_context28) {
while (1) switch (_context28.prev = _context28.next) {
case 0:
return _context28.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context28.stop();
}
}, _callee28);
}));
function queryFn() {
return _queryFn11.apply(this, arguments);
}
return queryFn;
}(),
normalize: true
});
case 6:
wrapper = function wrapper(_ref19) {
var children = _ref19.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dmNoAutoRollback,
children: children
});
};
_renderHook7 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn7 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee29() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee29$(_context29) {
while (1) switch (_context29.prev = _context29.next) {
case 0:
_context29.next = 2;
return new Promise(function (resolve) {
return setTimeout(resolve, 50);
});
case 2:
throw new Error('Failed');
case 3:
case "end":
return _context29.stop();
}
}, _callee29);
}));
function mutationFn() {
return _mutationFn7.apply(this, arguments);
}
return mutationFn;
}(),
onMutate: function onMutate() {
return {
optimisticData: {
id: '1',
name: 'Optimistic'
},
rollbackData: {
id: '1',
name: 'Manual Rollback'
}
};
},
normalize: true,
optimistic: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook7.result;
mutationResult.current.mutate(undefined);
_context30.next = 11;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isError).toBe(true);
});
case 11:
data = dmNoAutoRollback.queryClient.getQueryData(queryKey);
expect(data[0].name).toBe('Manual Rollback');
dmNoAutoRollback.queryNormalizer.unsubscribe();
dmNoAutoRollback.queryClient.clear();
case 15:
case "end":
return _context30.stop();
}
}, _callee30);
})));
it('should invalidate queries when invalidate option is enabled', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee33() {
var dmWithInvalidate, queryKey, invalidateSpy, wrapper, _renderHook8, mutationResult;
return (0, _regeneratorRuntime2.default)().wrap(function _callee33$(_context33) {
while (1) switch (_context33.prev = _context33.next) {
case 0:
dmWithInvalidate = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false,
invalidate: true
}
});
expect(dmWithInvalidate.queryNormalizer).toBeDefined();
dmWithInvalidate.queryNormalizer.subscribe();
queryKey = ['users']; // Initial data
_context33.next = 6;
return dmWithInvalidate.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn12 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee31() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee31$(_context31) {
while (1) switch (_context31.prev = _context31.next) {
case 0:
return _context31.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context31.stop();
}
}, _callee31);
}));
function queryFn() {
return _queryFn12.apply(this, arguments);
}
return queryFn;
}()
});
case 6:
// Spy on invalidateQueries
invalidateSpy = jest.spyOn(dmWithInvalidate.queryClient, 'invalidateQueries');
wrapper = function wrapper(_ref21) {
var children = _ref21.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dmWithInvalidate,
children: children
});
};
_renderHook8 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn8 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee32() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee32$(_context32) {
while (1) switch (_context32.prev = _context32.next) {
case 0:
return _context32.abrupt("return", {
id: '1',
name: 'Updated'
});
case 1:
case "end":
return _context32.stop();
}
}, _callee32);
}));
function mutationFn() {
return _mutationFn8.apply(this, arguments);
}
return mutationFn;
}(),
normalize: true
});
}, {
wrapper: wrapper
}), mutationResult = _renderHook8.result;
mutationResult.current.mutate(undefined);
_context33.next = 12;
return (0, _react2.waitFor)(function () {
return expect(mutationResult.current.isSuccess).toBe(true);
});
case 12:
// Verify that invalidateQueries was called
expect(invalidateSpy).toHaveBeenCalled();
invalidateSpy.mockRestore();
dmWithInvalidate.queryNormalizer.unsubscribe();
dmWithInvalidate.queryClient.clear();
case 16:
case "end":
return _context33.stop();
}
}, _callee33);
})));
it('should not invalidate queries when invalidate: false is set on mutation', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee36() {
var dmWithInvalidate, queryKey, invalidateSpy, wrapper, _renderHook9, mutationResult;
return (0, _regeneratorRuntime2.default)().wrap(function _callee36$(_context36) {
while (1) switch (_context36.prev = _context36.next) {
case 0:
dmWithInvalidate = new _ClientDataManager.ClientDataManager({
defaultOptions: {
queries: {
retry: false
},
mutations: {
retry: false
}
},
normalizerConfig: {
devLogging: false,
invalidate: true // Globally enabled
}
});
expect(dmWithInvalidate.queryNormalizer).toBeDefined();
dmWithInvalidate.queryNormalizer.subscribe();
queryKey = ['users'];
_context36.next = 6;
return dmWithInvalidate.queryClient.fetchQuery({
queryKey: queryKey,
queryFn: function () {
var _queryFn13 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee34() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee34$(_context34) {
while (1) switch (_context34.prev = _context34.next) {
case 0:
return _context34.abrupt("return", [{
id: '1',
name: 'Original'
}]);
case 1:
case "end":
return _context34.stop();
}
}, _callee34);
}));
function queryFn() {
return _queryFn13.apply(this, arguments);
}
return queryFn;
}()
});
case 6:
invalidateSpy = jest.spyOn(dmWithInvalidate.queryClient, 'invalidateQueries');
wrapper = function wrapper(_ref23) {
var children = _ref23.children;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataSourceProvider.DataSourceProvider, {
dataManager: dmWithInvalidate,
children: children
});
};
_renderHook9 = (0, _react2.renderHook)(function () {
return (0, _reactQuery.useMutation)({
mutationFn: function () {
var _mutationFn9 = (0, _asyncToGenerator2.default)(/*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee35() {
return (0, _regeneratorRuntime2.default)().wrap(function _callee35$(_context35) {
while (1) switch (_context35.pr