• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GrottoCenter / grottocenter-api / 10511865220

22 Aug 2024 04:19PM UTC coverage: 47.822% (-1.1%) from 48.96%
10511865220

push

github

vmarseguerra
feat(entities): adds delete / restore for entrance sub entities

711 of 2020 branches covered (35.2%)

Branch coverage included in aggregate %.

193 of 432 new or added lines in 35 files covered. (44.68%)

4 existing lines in 4 files now uncovered.

2528 of 4753 relevant lines covered (53.19%)

4.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.98
/api/services/CommentService.js
1
const moment = require('moment');
2✔
2
const momentDurationFormatSetup = require('moment-duration-format');
2✔
3

4
const { isNil } = require('ramda');
2✔
5
const CommonService = require('./CommonService');
2✔
6

7
momentDurationFormatSetup(moment);
2✔
8

9
function average(arr) {
10
  if (arr.length === 0) return 0;
3!
11
  return arr.reduce((a, b) => a + b, 0) / arr.length;
5✔
12
}
13

14
module.exports = {
2✔
15
  /**
16
   * @param {integer} entranceId - id of the entrance for which stats are needed
17
   *
18
   * @returns {Promise} which resolves to the succesfully getStats
19
   */
20
  getStatsFromComments: (comments) => {
21
    const filterFn = (e) => e && e > 0;
9✔
22
    return {
1✔
23
      aestheticism: average(
24
        comments.map((c) => c.aestheticism).filter(filterFn)
3✔
25
      ),
26
      caving: average(comments.map((c) => c.caving).filter(filterFn)),
3✔
27
      approach: average(comments.map((c) => c.approach).filter(filterFn)),
3✔
28
    };
29
  },
30

31
  getStatsFromId: async (entranceId) => {
32
    const [aestheticism, caving, approach] = await Promise.all([
1✔
33
      TComment.avg('aestheticism').where({
34
        entrance: entranceId,
35
        aestheticism: { '>': 0 },
36
      }),
37
      TComment.avg('caving').where({
38
        entrance: entranceId,
39
        caving: { '>': 0 },
40
      }),
41
      TComment.avg('approach').where({
42
        entrance: entranceId,
43
        approach: { '>': 0 },
44
      }),
45
    ]);
46

47
    return { aestheticism, caving, approach };
1✔
48
  },
49

50
  /**
51
   * @param {integer} entranceId - id of the entrance for which time infos are needed
52
   *
53
   * @returns {Promise} which resolves to the succesfully getTimeInfos
54
   */
55
  getTimeInfos: async (entranceId) => {
56
    // query to get time infos average
NEW
57
    const TIME_INFO_QUERY = `
×
58
    SELECT avg(e_t_trail) AS avg_t_trail, avg(e_t_underground) AS avg_t_underground
59
    FROM t_comment WHERE id_entrance=$1`;
60

UNCOV
61
    const timeInfosQueryResult = await CommonService.query(TIME_INFO_QUERY, [
×
62
      entranceId,
63
    ]);
64
    const timeInfos = timeInfosQueryResult.rows[0];
×
65

66
    let avgTTrailFormatted = null;
×
67
    let avgTUndergroundFormatted = null;
×
68
    if (timeInfos.avg_t_trail !== null) {
×
69
      avgTTrailFormatted = module.exports.postgreIntervalObjectToDbString(
×
70
        timeInfos.avg_t_trail
71
      );
72
    }
73
    if (timeInfos.avg_t_underground !== null) {
×
74
      avgTUndergroundFormatted = module.exports.postgreIntervalObjectToDbString(
×
75
        timeInfos.avg_t_underground
76
      );
77
    }
78

79
    return {
×
80
      eTTrail: avgTTrailFormatted,
81
      eTUnderground: avgTUndergroundFormatted,
82
    };
83
  },
84

85
  /**
86
   *
87
   * @param pgInterval PostgresInterval Object {hours: ${number}, minutes: ${number}, seconds: ${number}}
88
   * @returns string with format hh:mm:ss
89
   */
90
  postgreIntervalObjectToDbString: (pgInterval) => {
91
    if (isNil(pgInterval)) return null;
17!
92
    const emptyDuration = {
17✔
93
      days: 0,
94
      hours: 0,
95
      minutes: 0,
96
      seconds: 0,
97
    };
98
    return moment
17✔
99
      .duration(Object.assign(emptyDuration, pgInterval))
100
      .format('hh:mm:ss', {
101
        trim: false,
102
      });
103
  },
104

105
  getEntranceComments: async (entranceId, where = {}) => {
×
106
    if (!entranceId) return [];
1!
107
    return TComment.find({ ...where, entrance: entranceId })
1✔
108
      .populate('author')
109
      .populate('reviewer');
110
  },
111

112
  getEntranceHComments: async (entranceId, where = {}) => {
×
NEW
113
    if (!entranceId) return [];
×
NEW
114
    const commentIds = await TComment.find({
×
115
      where: { ...where, entrance: entranceId },
116
      select: ['id'],
117
    });
NEW
118
    return module.exports.getHComments(commentIds.map((e) => e.id));
×
119
  },
120

121
  getComment: async (commentId) =>
122
    TComment.findOne({ id: commentId }).populate('author').populate('reviewer'),
3✔
123

124
  getHComments: async (commentId) =>
NEW
125
    HComment.find({ t_id: commentId }).populate('reviewer').populate('author'),
×
126
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc