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

wger-project / react / 19083732741

04 Nov 2025 09:45PM UTC coverage: 75.147% (-0.04%) from 75.183%
19083732741

Pull #1143

github

web-flow
Merge db926fe91 into 094955eb9
Pull Request #1143: Fix #1127: Move exercise search to new endpoint

1737 of 2616 branches covered (66.4%)

Branch coverage included in aggregate %.

16 of 28 new or added lines in 5 files covered. (57.14%)

2 existing lines in 2 files now uncovered.

5535 of 7061 relevant lines covered (78.39%)

28.2 hits per line

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

50.94
/src/services/exerciseTranslation.ts
1
import axios from 'axios';
94✔
2
import { Exercise, ExerciseAdapter } from "components/Exercises/models/exercise";
94✔
3
import { Translation, TranslationAdapter } from "components/Exercises/models/translation";
94✔
4
import { ENGLISH_LANGUAGE_CODE, LANGUAGE_SHORT_ENGLISH } from "utils/consts";
94✔
5
import { makeHeader, makeUrl } from "utils/url";
94✔
6
import { ResponseType } from "./responseType";
7

8
export const EXERCISE_PATH = 'exercise';
94✔
9
export const EXERCISE_TRANSLATION_PATH = 'exercise-translation';
94✔
10

11

12
/*
13
 * Fetch all exercise translations for a given exercise base
14
 */
15
export const getExerciseTranslations = async (id: number): Promise<Translation[]> => {
94✔
16
    const url = makeUrl(EXERCISE_PATH, { query: { exercise: id } });
×
17
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
NEW
18
    const { data } = await axios.get<ResponseType<Translation>>(url, {
×
19
        headers: makeHeader(),
20
    });
21
    const adapter = new TranslationAdapter();
×
22
    return data.results.map(e => adapter.fromJson(e));
×
23
};
24

25

26
/*
27
 * Search for exercises by name using the exerciseinfo endpoint
28
 */
29
export const searchExerciseTranslations = async (name: string,languageCode: string = ENGLISH_LANGUAGE_CODE,searchEnglish: boolean = true): Promise<Exercise[]> => {
94!
30
    const languages = [languageCode];
×
31
    if (languageCode !== LANGUAGE_SHORT_ENGLISH && searchEnglish) {
×
32
        languages.push(LANGUAGE_SHORT_ENGLISH);
×
33
    }
34

NEW
35
    const url = makeUrl('exerciseinfo', {
×
36
        query: {
37
            name__search: name,
38
            language__code: languages.join(','),
39
            limit: 50,
40
        }
41
    });
42

NEW
43
    try {
×
NEW
44
        const { data } = await axios.get<ResponseType<Exercise>>(url);
×
45
        
NEW
46
        if (!data || !data.results || !Array.isArray(data.results)) {
×
NEW
47
            return [];
×
48
        }
49
        
NEW
50
        const adapter = new ExerciseAdapter();
×
NEW
51
        return data.results.map((item: unknown) => adapter.fromJson(item));
×
52
    } catch {
NEW
53
        return [];
×
54
    }
55
};
56

57

58
/*
59
 * Create a new exercise translation
60
 */
61
export interface AddTranslationParams {
62
    exerciseId: number;
63
    languageId: number;
64
    name: string;
65
    description: string;
66
    author: string;
67
}
68

69
export const addTranslation = async (params: AddTranslationParams): Promise<Translation> => {
94✔
70
    const { exerciseId, languageId, name, description, author } = params;
1✔
71

72
    const url = makeUrl(EXERCISE_TRANSLATION_PATH);
1✔
73
    const baseData = {
1✔
74
        exercise: exerciseId,
75
        language: languageId,
76
        name: name,
77
        description: description,
78
        // eslint-disable-next-line camelcase
79
        license_author: author
80
    };
81
    const response = await axios.post(url, baseData, {
1✔
82
        headers: makeHeader(),
83
    });
84

85
    const adapter = new TranslationAdapter();
1✔
86
    return adapter.fromJson(response.data);
1✔
87
};
88

89
/*
90
 * Edit an existing exercise translation
91
 */
92
export interface EditTranslationParams extends AddTranslationParams {
93
    id: number;
94
}
95

96
export const editTranslation = async (data: EditTranslationParams): Promise<Translation> => {
94✔
97
    const { id, exerciseId, languageId, name, description } = data;
1✔
98

99
    const url = makeUrl(EXERCISE_TRANSLATION_PATH, { id: id });
1✔
100
    const baseData = {
1✔
101
        exercise: exerciseId,
102
        language: languageId,
103
        name: name,
104
        description: description,
105
    };
106
    const response = await axios.patch(
1✔
107
        url,
108
        baseData,
109
        { headers: makeHeader() }
110
    );
111

112
    const adapter = new TranslationAdapter();
1✔
113
    return adapter.fromJson(response.data);
1✔
114
};
115

116
/*
117
 * Delete an existing exercise translation
118
 */
119
export const deleteExerciseTranslation = async (id: number): Promise<number> => {
94✔
120
    const url = makeUrl(EXERCISE_TRANSLATION_PATH, { id: id });
1✔
121
    const response = await axios.delete(
1✔
122
        url,
123
        { headers: makeHeader() }
124
    );
125

126
    return response.status;
1✔
127
};
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