@centreon/js-config 24.10.16 → 24.10.18

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.
@@ -65,8 +65,14 @@ module.exports = ({
65
65
  }
66
66
 
67
67
  // Save the testRetries object to a file in the e2e/results directory
68
+ const projectRoot = path.resolve(process.cwd());
69
+ const resolvedFolder = path.resolve(mainCypressFolder);
70
+ if (resolvedFolder !== projectRoot && !resolvedFolder.startsWith(projectRoot + path.sep)) {
71
+ throw new Error('mainCypressFolder is outside of the project directory');
72
+ }
73
+
68
74
  const resultFilePath = path.join(
69
- mainCypressFolder,
75
+ resolvedFolder,
70
76
  'results',
71
77
  'retries.json'
72
78
  );
@@ -32,12 +32,11 @@ Cypress.Commands.add(
32
32
  host,
33
33
  isForced = true
34
34
  }: ServiceCheck): Cypress.Chainable => {
35
- let query = `SELECT id FROM resources WHERE name = '${host}' AND type = 1`;
36
-
37
35
  return cy
38
36
  .requestOnDatabase({
39
37
  database: 'centreon_storage',
40
- query
38
+ query: 'SELECT id FROM resources WHERE name = ? AND type = 1',
39
+ params: [host]
41
40
  })
42
41
  .then(([rows]) => {
43
42
  if (rows.length === 0) {
@@ -84,12 +83,11 @@ Cypress.Commands.add(
84
83
  isForced = true,
85
84
  service
86
85
  }: ServiceCheck): Cypress.Chainable => {
87
- let query = `SELECT parent_id, id FROM resources WHERE parent_name = '${host}' AND name = '${service}'`;
88
-
89
86
  return cy
90
87
  .requestOnDatabase({
91
88
  database: 'centreon_storage',
92
- query
89
+ query: 'SELECT parent_id, id FROM resources WHERE parent_name = ? AND name = ?',
90
+ params: [host, service]
93
91
  })
94
92
  .then(([rows]) => {
95
93
  if (rows.length === 0) {
@@ -181,22 +179,23 @@ Cypress.Commands.add(
181
179
  cy.log('Checking hosts in database');
182
180
 
183
181
  let query = `SELECT COUNT(d.downtime_id) AS count_downtimes FROM downtimes as d
184
- INNER JOIN hosts as h ON h.host_id = d.host_id AND h.name = '${downtime.host}'`;
182
+ INNER JOIN hosts as h ON h.host_id = d.host_id AND h.name = ?`;
183
+ const params: Array<string> = [downtime.host];
185
184
  if (downtime.service) {
186
- query += ` INNER JOIN services as s ON s.service_id = d.service_id AND s.description = '${downtime.service}'`;
185
+ query += ` INNER JOIN services as s ON s.service_id = d.service_id AND s.description = ?`;
186
+ params.push(downtime.service);
187
187
  }
188
188
  query += ` WHERE d.started=1`;
189
189
  if (!downtime.service) {
190
190
  query += ` AND d.service_id = 0`;
191
191
  }
192
192
 
193
- cy.log(query);
194
-
195
193
  cy.waitUntil(() => {
196
194
  return cy
197
195
  .requestOnDatabase({
198
196
  database: 'centreon_storage',
199
- query
197
+ query,
198
+ params
200
199
  })
201
200
  .then(([rows]) => {
202
201
  const foundDowntimesCount = rows.length ? rows[0].count_downtimes : 0;
@@ -377,13 +377,14 @@ Output:\n${displayedOutput}`);
377
377
 
378
378
  interface RequestOnDatabaseProps {
379
379
  database: string;
380
+ params?: Array<string | number>;
380
381
  query: string;
381
382
  }
382
383
 
383
384
  Cypress.Commands.add(
384
385
  'requestOnDatabase',
385
- ({ database, query }: RequestOnDatabaseProps): Cypress.Chainable => {
386
- return cy.task('requestOnDatabase', { database, query });
386
+ ({ database, query, params }: RequestOnDatabaseProps): Cypress.Chainable => {
387
+ return cy.task('requestOnDatabase', { database, query, params });
387
388
  }
388
389
  );
389
390
 
@@ -553,8 +554,8 @@ Cypress.Commands.add(
553
554
  cy.log(`Getting logs from container ${name} ...`);
554
555
 
555
556
  return cy.getLogDirectory().then((logDirectory) => {
556
- let sourcePhpLogs = '/var/log/php8.2-fpm-centreon-error.log';
557
- let targetPhpLogs = `${logDirectory}/php8.2-fpm-centreon-error.log`;
557
+ let sourcePhpLogs = '/var/log/centreon/prod.web.log';
558
+ let targetPhpLogs = `${logDirectory}/prod.web.log`;
558
559
  let sourceApacheLogs = '/var/log/apache2';
559
560
  let targetApacheLogs = `${logDirectory}/apache2`;
560
561
  if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
@@ -957,7 +958,8 @@ declare global {
957
958
  }: NavigateToProps) => Cypress.Chainable;
958
959
  requestOnDatabase: ({
959
960
  database,
960
- query
961
+ query,
962
+ params
961
963
  }: RequestOnDatabaseProps) => Cypress.Chainable;
962
964
  setUserTokenApiV1: ({
963
965
  login,
@@ -2,6 +2,7 @@
2
2
  import { execSync } from 'child_process';
3
3
  import { existsSync, mkdirSync } from 'fs';
4
4
  import path from 'path';
5
+ import fs from "fs";
5
6
 
6
7
  import tar from 'tar-fs';
7
8
  import {
@@ -154,7 +155,7 @@ export default (on: Cypress.PluginEvents): void => {
154
155
 
155
156
  return container.getMappedPort(containerPort);
156
157
  },
157
- requestOnDatabase: async ({ database, query }) => {
158
+ requestOnDatabase: async ({ database, query, params }) => {
158
159
  let container: StartedTestContainer | null = null;
159
160
 
160
161
  if (dockerEnvironment !== null) {
@@ -171,11 +172,15 @@ export default (on: Cypress.PluginEvents): void => {
171
172
  user: 'centreon'
172
173
  });
173
174
 
174
- const [rows, fields] = await client.query(query);
175
-
176
- await client.end();
175
+ try {
176
+ const [rows, fields] = params
177
+ ? await client.execute(query, params)
178
+ : await client.query(query);
177
179
 
178
- return [rows, fields];
180
+ return [rows, fields];
181
+ } finally {
182
+ await client.end();
183
+ }
179
184
  },
180
185
  startContainer: async ({
181
186
  command,
@@ -241,6 +246,15 @@ export default (on: Cypress.PluginEvents): void => {
241
246
  console.error(error.message);
242
247
  }
243
248
 
249
+ // Best-effort teardown: keep the original startup error if cleanup fails.
250
+ try {
251
+ await dockerEnvironment?.down();
252
+ } catch (teardownError) {
253
+ console.error(teardownError);
254
+ } finally {
255
+ dockerEnvironment = null;
256
+ }
257
+
244
258
  throw error;
245
259
  }
246
260
  },
@@ -268,6 +282,83 @@ export default (on: Cypress.PluginEvents): void => {
268
282
  execSync(`npx wait-on ${url}`);
269
283
 
270
284
  return null;
271
- }
285
+ },
286
+ listFilesInDirectory: async ( directoryPath ) => {
287
+ return new Promise((resolve, reject) => {
288
+ fs.readdir(directoryPath, (err, files) => {
289
+ if (err) {
290
+ reject(err);
291
+ } else {
292
+ resolve(files);
293
+ }
294
+ });
295
+ });
296
+ },
297
+ fileExists: async ( filePath ) => {
298
+ return fs.existsSync(filePath);
299
+ },
300
+ getExportedFile({ downloadsFolder }: { downloadsFolder: string }): string {
301
+ const files = fs
302
+ .readdirSync(downloadsFolder)
303
+ .filter((name) => name.startsWith("ResourceStatusExport_all") && name.endsWith(".csv"))
304
+ .map((name) => ({
305
+ name,
306
+ time: fs.statSync(path.join(downloadsFolder, name)).mtime.getTime()
307
+ }))
308
+ .sort((a, b) => b.time - a.time);
309
+
310
+ if (files.length === 0) {
311
+ throw new Error("No exported file found");
312
+ }
313
+
314
+ return path.join(downloadsFolder, files[0].name);
315
+ },
316
+ readCsvFile({ filePath }: { filePath: string }): Promise<string> {
317
+ const projectRoot = path.resolve(process.cwd());
318
+ const resolvedPath = path.resolve(filePath);
319
+ if (resolvedPath !== projectRoot && !resolvedPath.startsWith(projectRoot + path.sep)) {
320
+ return Promise.reject(new Error("Path is outside of the project directory"));
321
+ }
322
+
323
+ return new Promise((resolve, reject) => {
324
+ fs.readFile(resolvedPath, "utf8", (err, data) => {
325
+ if (err) return reject(err);
326
+ resolve(data);
327
+ });
328
+ });
329
+ },
330
+ clearDownloadsFolder({ downloadsFolder }: { downloadsFolder: string }): null {
331
+ const projectRoot = path.resolve(process.cwd());
332
+ const resolvedFolder = path.resolve(downloadsFolder);
333
+ if (resolvedFolder !== projectRoot && !resolvedFolder.startsWith(projectRoot + path.sep)) {
334
+ throw new Error("Path is outside of the project directory");
335
+ }
336
+
337
+ if (!fs.existsSync(resolvedFolder)) {
338
+ return null;
339
+ }
340
+
341
+ const files = fs.readdirSync(resolvedFolder);
342
+ for (const file of files) {
343
+ const filePath = path.join(resolvedFolder, file);
344
+ if (!filePath.startsWith(resolvedFolder + path.sep)) {
345
+ continue;
346
+ }
347
+ fs.unlinkSync(filePath);
348
+ }
349
+
350
+ return null;
351
+ },
352
+ isDownloadComplete({ downloadsFolder }: { downloadsFolder: string }): boolean {
353
+ if (!fs.existsSync(downloadsFolder)) return false;
354
+
355
+ const files = fs
356
+ .readdirSync(downloadsFolder)
357
+ .filter(
358
+ (name) => !name.endsWith(".crdownload") && !name.endsWith(".tmp")
359
+ );
360
+
361
+ return files.length > 0;
362
+ },
272
363
  });
273
364
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@centreon/js-config",
3
3
  "description": "Centreon Frontend shared build configuration",
4
- "version": "24.10.16",
4
+ "version": "24.10.18",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/centreon/centreon.git"