ti2 1.0.122 → 1.0.124

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/index.js CHANGED
@@ -60,6 +60,7 @@ const axiosSafeResponse = response => {
60
60
 
61
61
  module.exports = async ({
62
62
  apiDocs = true,
63
+ pluginCapabilities: pluginCapabilitiesParam = {},
63
64
  plugins: pluginsParam = {},
64
65
  pluginsInstantiated = false,
65
66
  port: portParam,
@@ -83,7 +84,7 @@ module.exports = async ({
83
84
  // Create a new axios instance for this plugin and configure SSL if needed
84
85
  const pluginAxios = axios.create();
85
86
  configureAxiosSSL(pluginAxios, process.env.SSL_INSECURE_ALLOWED_DOMAINS);
86
-
87
+
87
88
  const pluginInstance = await new Plugin({
88
89
  cache: {
89
90
  drop: args => cache.drop({ ...args, pluginName }),
@@ -99,9 +100,18 @@ module.exports = async ({
99
100
  events: ti2Events,
100
101
  name: pluginName,
101
102
  ...params,
103
+ capabilities: R.pathOr({}, [pluginName], pluginCapabilitiesParam),
102
104
  });
103
105
  return pluginInstance;
104
106
  });
107
+ plugins.forEach(plugin => {
108
+ const configuredCapabilities = R.path([plugin.name], pluginCapabilitiesParam);
109
+ Object.assign(plugin, {
110
+ capabilities: configuredCapabilities === undefined
111
+ ? plugin.capabilities || {}
112
+ : configuredCapabilities,
113
+ });
114
+ });
105
115
  if (worker) {
106
116
  return require('./worker/index')({ plugins });
107
117
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ti2",
3
- "version": "1.0.122",
3
+ "version": "1.0.124",
4
4
  "description": "Tourist Industry Exchange (TI2)",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -52,12 +52,17 @@ jest.mock('../queue', () => {
52
52
  })
53
53
  },
54
54
  addJob: jest.fn().mockResolvedValue('test-job-id'),
55
- allDone: jest.fn().mockResolvedValue(true)
55
+ allDone: jest.fn().mockResolvedValue(true),
56
+ saveResult: jest.fn().mockResolvedValue(undefined),
56
57
  };
57
58
  });
58
59
 
59
60
  // Import the mocked queue and the actual worker module
60
- const { addJob, queue, allDone } = require('../queue');
61
+ const {
62
+ addJob,
63
+ queue,
64
+ saveResult,
65
+ } = require('../queue');
61
66
  const actualWorkerModule = require('../index'); // Actual worker module
62
67
 
63
68
  describe('worker: API job handling', () => {
@@ -86,7 +91,10 @@ describe('worker: API job handling', () => {
86
91
  axios.mockImplementation(config => {
87
92
  // This mock is for the internal axios call made by the worker
88
93
  if (config.url && config.url.includes('/products/testAppKey/testUserId/testTokenHint/search')) {
89
- return Promise.resolve({ status: 200, data: { success: true, message: 'Mocked internal success' } });
94
+ return Promise.resolve({
95
+ status: 200,
96
+ data: { success: true, products: [{ productId: 'incidental-product' }] },
97
+ });
90
98
  }
91
99
  console.error('Unexpected axios call to mock:', config);
92
100
  return Promise.reject(new Error(`Unexpected axios call in mock for URL: ${config.url}`));
@@ -117,6 +125,10 @@ describe('worker: API job handling', () => {
117
125
  actualJobHandler = null; // Clear captured handler
118
126
  });
119
127
 
128
+ beforeEach(() => {
129
+ saveResult.mockClear();
130
+ });
131
+
120
132
  it('should create a job of type "api" for the product search endpoint and send it to the API server', async () => {
121
133
 
122
134
  // 1. Test that we can create a job
@@ -169,5 +181,45 @@ describe('worker: API job handling', () => {
169
181
  }),
170
182
  })
171
183
  );
184
+ expect(saveResult).toHaveBeenCalledWith({
185
+ id: jobId,
186
+ resultValue: expect.objectContaining({
187
+ ti2CatalogProductCount: null,
188
+ ti2ReturnedProductCount: null,
189
+ }),
190
+ });
191
+ });
192
+
193
+ it('reports committed and returned counts for a full catalog refresh', async () => {
194
+ axios.mockResolvedValueOnce({
195
+ status: 200,
196
+ data: {
197
+ products: [],
198
+ catalogRefreshOutcome: 'empty_result_preserved_cache',
199
+ cacheUpdated: false,
200
+ cachePreserved: true,
201
+ cachedProductCount: 7,
202
+ },
203
+ });
204
+ const job = {
205
+ id: 'catalog-refresh-job',
206
+ data: {
207
+ type: 'api',
208
+ method: 'POST',
209
+ url: '/products/testAppKey/testUserId/testTokenHint/search',
210
+ headers: { 'content-type': 'application/json' },
211
+ payload: { forceRefresh: true, backgroundJob: true },
212
+ },
213
+ };
214
+
215
+ await actualJobHandler(job);
216
+
217
+ expect(saveResult).toHaveBeenCalledWith({
218
+ id: job.id,
219
+ resultValue: expect.objectContaining({
220
+ ti2CatalogProductCount: 7,
221
+ ti2ReturnedProductCount: 0,
222
+ }),
223
+ });
172
224
  });
173
225
  });
@@ -27,7 +27,7 @@ const mockBookingsPostProcessAction = jest.fn();
27
27
  jest.mock('../../controllers/bookings', () => {
28
28
  return jest.fn(() => ({
29
29
  // This action name must match what's in job.data.postProcess.action
30
- $updateProductSearchCache: mockBookingsPostProcessAction,
30
+ $postProcessAction: mockBookingsPostProcessAction,
31
31
  // Add other methods if the worker's initialization of bookingsCtrl calls them
32
32
  }));
33
33
  });
@@ -111,7 +111,7 @@ describe('worker: Plugin job handling', () => {
111
111
  inTesting: true,
112
112
  postProcess: {
113
113
  controller: 'bookings',
114
- action: '$updateProductSearchCache', // Must match the mocked action name in bookings mock
114
+ action: '$postProcessAction',
115
115
  args: { staticArg1: 'value1', appKey: mockPluginName }, // Static args for postProcess
116
116
  },
117
117
  };
@@ -192,7 +192,7 @@ describe('worker: Plugin job handling', () => {
192
192
  inTesting: true,
193
193
  postProcess: {
194
194
  controller: 'bookings',
195
- action: '$updateProductSearchCache',
195
+ action: '$postProcessAction',
196
196
  args: { appKey: mockPluginName },
197
197
  },
198
198
  };
package/worker/index.js CHANGED
@@ -100,7 +100,22 @@ const worker = ({ plugins: pluginsParam }) => { // pluginsParam are instantiated
100
100
  jobLog(`Worker internal server for job ${jobId} closed.`);
101
101
  }
102
102
  }
103
- resultValue = { code, result, success: code >= 200 && code < 300 };
103
+ const isCatalogRefreshResult = Boolean(
104
+ result && typeof result.catalogRefreshOutcome === 'string',
105
+ );
106
+ const returnedProducts = isCatalogRefreshResult && result.products;
107
+ resultValue = {
108
+ code,
109
+ result,
110
+ success: code >= 200 && code < 300,
111
+ ti2CatalogProductCount: isCatalogRefreshResult
112
+ && Number.isInteger(result.cachedProductCount)
113
+ ? result.cachedProductCount
114
+ : null,
115
+ ti2ReturnedProductCount: Array.isArray(returnedProducts)
116
+ ? returnedProducts.length
117
+ : null,
118
+ };
104
119
 
105
120
  } else if (type === 'callback') {
106
121
  const { callbackUrl, request, result } = jobDataPayload; // jobDataPayload is job.data.payload