Skip to content

Commit 0fc066b

Browse files
sonar fixes
1 parent 84c04a6 commit 0fc066b

4 files changed

Lines changed: 101 additions & 40 deletions

File tree

src/update_db.py

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,82 @@ def _fetch_all_endpoints(request_dict: dict, limit: int, test_mode: bool, test_l
200200
return full_dict
201201

202202

203+
def _build_related_entry(value: dict, fields: list) -> dict:
204+
"""
205+
Build a new entry dict from value containing only the specified fields.
206+
207+
Parameters
208+
----------
209+
value : dict
210+
The source item dictionary.
211+
fields : list
212+
The list of field names to include.
213+
214+
Returns
215+
-------
216+
dict
217+
A dictionary containing only the requested fields present in value.
218+
"""
219+
return {field: value[field] for field in fields if field in value}
220+
221+
222+
def _append_item_to_endpoint(full_dict: dict, endpoint: str, item_type: str, value: dict, fields: list) -> None:
223+
"""
224+
Append a single related item into all matching destination entries in the endpoint.
225+
226+
Parameters
227+
----------
228+
full_dict : dict
229+
The combined data dictionary (mutated in-place).
230+
endpoint : str
231+
The destination endpoint name.
232+
item_type : str
233+
The type key under which to append the entry.
234+
value : dict
235+
The source item containing a list of destination IDs under the endpoint key.
236+
fields : list
237+
Fields to copy from value into the new entry.
238+
"""
239+
append_to = value.get(endpoint)
240+
if not append_to:
241+
return
242+
243+
new_entry = _build_related_entry(value=value, fields=fields)
244+
245+
for item_id_dest in append_to:
246+
if item_id_dest not in full_dict[endpoint]:
247+
continue
248+
if item_type not in full_dict[endpoint][item_id_dest]:
249+
full_dict[endpoint][item_id_dest][item_type] = []
250+
full_dict[endpoint][item_id_dest][item_type].append(new_entry)
251+
252+
253+
def _append_item_type(full_dict: dict, endpoint: str, item_type: str, fields: list) -> None:
254+
"""
255+
Append all items of a given type into the appropriate endpoint entries.
256+
257+
Parameters
258+
----------
259+
full_dict : dict
260+
The combined data dictionary (mutated in-place).
261+
endpoint : str
262+
The destination endpoint name.
263+
item_type : str
264+
The source item type to iterate over.
265+
fields : list
266+
Fields to include in each appended entry.
267+
"""
268+
print(f'adding {item_type} to {endpoint}')
269+
for value in full_dict[item_type].values():
270+
_append_item_to_endpoint(
271+
full_dict=full_dict,
272+
endpoint=endpoint,
273+
item_type=item_type,
274+
value=value,
275+
fields=fields,
276+
)
277+
278+
203279
def _append_related_items(full_dict: dict, request_dict: dict) -> None:
204280
"""
205281
Append related items (e.g. characters to games, games to platforms) into full_dict in-place.
@@ -212,32 +288,17 @@ def _append_related_items(full_dict: dict, request_dict: dict) -> None:
212288
Endpoint configuration containing 'append' sub-dicts.
213289
"""
214290
for endpoint, endpoint_dict in request_dict.items():
215-
try:
216-
append_dict = endpoint_dict['append']
217-
except KeyError:
291+
append_dict = endpoint_dict.get('append')
292+
if not append_dict:
218293
continue
219294

220295
for item_type, item_type_dict in append_dict.items():
221-
print(f'adding {item_type} to {endpoint}')
222-
for item_id_src, value in full_dict[item_type].items():
223-
try:
224-
append_to = value[endpoint]
225-
except KeyError:
226-
continue
227-
228-
for item_id_dest in append_to:
229-
if item_id_dest not in full_dict[endpoint]:
230-
continue
231-
232-
if item_type not in full_dict[endpoint][item_id_dest]:
233-
full_dict[endpoint][item_id_dest][item_type] = []
234-
235-
new_entry = {}
236-
for field in item_type_dict['fields']:
237-
if field in value:
238-
new_entry[field] = value[field]
239-
240-
full_dict[endpoint][item_id_dest][item_type].append(new_entry)
296+
_append_item_type(
297+
full_dict=full_dict,
298+
endpoint=endpoint,
299+
item_type=item_type,
300+
fields=item_type_dict['fields'],
301+
)
241302

242303

243304
def _add_platform_game_counts(full_dict: dict) -> None:

tests/game_detail.test.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ describe('game_detail.js', () => {
478478
});
479479
const bigImgs = document.getElementById('header-big-imgs');
480480
expect(bigImgs.dataset.numImg).toBe('2');
481-
expect(bigImgs.getAttribute('data-img-src-1')).toContain('art1');
481+
expect(bigImgs.dataset.imgSrc1).toContain('art1');
482482
});
483483

484484
test('hides page heading when no artworks and heading exists', () => {
@@ -489,7 +489,7 @@ describe('game_detail.js', () => {
489489

490490
test('does nothing when no artworks and no .page-heading in DOM', () => {
491491
const pageHeading = document.querySelector('.page-heading');
492-
pageHeading.parentNode.removeChild(pageHeading);
492+
pageHeading.remove();
493493
// Should not throw and should not affect any element
494494
expect(() => setupGameBanner({})).not.toThrow();
495495
});
@@ -506,7 +506,7 @@ describe('game_detail.js', () => {
506506
test('does not throw when artworks present but no intro-header.big-img', () => {
507507
// Remove intro-header from DOM entirely
508508
const introHeader = document.querySelector('.intro-header');
509-
introHeader.parentNode.removeChild(introHeader);
509+
introHeader.remove();
510510
expect(() => setupGameBanner({
511511
artworks: [{ url: '//images.igdb.com/t_thumb/art.jpg' }],
512512
})).not.toThrow();
@@ -515,7 +515,7 @@ describe('game_detail.js', () => {
515515
test('skips pageHeading visibility when pageHeading absent (no .page-heading)', () => {
516516
// Remove page-heading from DOM
517517
const pageHeading = document.querySelector('.page-heading');
518-
pageHeading.parentNode.removeChild(pageHeading);
518+
pageHeading.remove();
519519
document.querySelector('.intro-header').classList.add('big-img');
520520
expect(() => setupGameBanner({
521521
artworks: [{ url: '//images.igdb.com/t_thumb/art.jpg' }],
@@ -535,7 +535,7 @@ describe('game_detail.js', () => {
535535
test('does not throw when artworks present but no .page-heading anywhere', () => {
536536
// Remove header.header-section entirely
537537
const header = document.querySelector('header.header-section');
538-
header.parentNode.removeChild(header);
538+
header.remove();
539539
expect(() => setupGameBanner({ artworks: [{ url: '//img.igdb.com/t.jpg' }] })).not.toThrow();
540540
});
541541
});
@@ -549,10 +549,10 @@ describe('game_detail.js', () => {
549549
test('sets initial image and cycles when multiple artworks', () => {
550550
const bigImgs = document.getElementById('header-big-imgs');
551551
bigImgs.dataset.numImg = '2';
552-
bigImgs.setAttribute('data-img-src-1', 'https://example.com/art1.jpg');
553-
bigImgs.setAttribute('data-img-src-2', 'https://example.com/art2.jpg');
554-
bigImgs.setAttribute('data-img-desc-1', 'null');
555-
bigImgs.setAttribute('data-img-desc-2', 'Artwork 2');
552+
bigImgs.dataset.imgSrc1 = 'https://example.com/art1.jpg';
553+
bigImgs.dataset.imgSrc2 = 'https://example.com/art2.jpg';
554+
bigImgs.dataset.imgDesc1 = 'null';
555+
bigImgs.dataset.imgDesc2 = 'Artwork 2';
556556

557557
const introHeader = document.querySelector('.intro-header');
558558
introHeader.classList.add('big-img');
@@ -574,16 +574,16 @@ describe('game_detail.js', () => {
574574
test('returns early when no intro-header.big-img found', () => {
575575
const bigImgs = document.getElementById('header-big-imgs');
576576
bigImgs.dataset.numImg = '1';
577-
bigImgs.setAttribute('data-img-src-1', 'https://example.com/art.jpg');
577+
bigImgs.dataset.imgSrc1 = 'https://example.com/art.jpg';
578578
// intro-header does NOT have big-img class — should return early
579579
expect(() => initGameBanner()).not.toThrow();
580580
});
581581

582582
test('sets background image without crashing when no .img-desc inside intro-header', () => {
583583
const bigImgs = document.getElementById('header-big-imgs');
584584
bigImgs.dataset.numImg = '1';
585-
bigImgs.setAttribute('data-img-src-1', 'https://example.com/art.jpg');
586-
bigImgs.setAttribute('data-img-desc-1', 'Some description');
585+
bigImgs.dataset.imgSrc1 = 'https://example.com/art.jpg';
586+
bigImgs.dataset.imgDesc1 = 'Some description';
587587
const introHeader = document.querySelector('.intro-header');
588588
introHeader.classList.add('big-img');
589589
// Do NOT add .img-desc — covers the if(imgDesc) false branch
@@ -633,7 +633,7 @@ describe('game_detail.js', () => {
633633
test('renders game without header h1 (pageHeaderH1 is null)', () => {
634634
// Remove .page-heading h1 from DOM
635635
const h1 = document.querySelector('header.header-section .page-heading h1');
636-
if (h1) h1.parentNode.removeChild(h1);
636+
if (h1) h1.remove();
637637
expect(() => renderGame({ name: 'No Header Game' })).not.toThrow();
638638
expect(document.getElementById('game-name').textContent).toBe('No Header Game');
639639
});

tests/item_loader.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ globalThis.$ = function() {
2828
};
2929
globalThis.$.ajaxSetup = () => {};
3030
globalThis.$.ajax = function(opts) {
31-
if (opts && opts.success) {
31+
if (opts?.success) {
3232
// Return mock data appropriate to the URL
33-
if (opts.url && opts.url.includes('cross-reference')) {
33+
if (opts?.url?.includes('cross-reference')) {
3434
opts.success({});
35-
} else if (opts.url && opts.url.includes('all.json')) {
35+
} else if (opts?.url?.includes('all.json')) {
3636
opts.success({
3737
'1': {
3838
id: 1, name: 'PC', url: 'https://igdb.com', summary: 'Personal computer.',

tests/platform_detail.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ describe('platform_detail.js', () => {
138138

139139
describe('renderPlatformMetadata', () => {
140140
test('renders game count (plural)', () => {
141-
renderPlatformMetadata({ games: Array(42).fill({}) });
141+
renderPlatformMetadata({ games: new Array(42).fill({}) });
142142
expect(document.getElementById('platform-meta').textContent).toContain('42 games');
143143
});
144144

0 commit comments

Comments
 (0)