Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix findtrainingsby test #3209

Draft
wants to merge 3 commits into
base: credential-engine
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions backend/src/credentialengine/CredentialEngineUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,30 +91,37 @@ const fetchCertificateData = async (url: string): Promise<CTDLResource | null> =
"ceterms:ctid": ctid,
"search:recordPublishedBy": "ce-cc992a07-6e17-42e5-8ed1-5b016e743e9d",
};

const response = await credentialEngineAPI.getResults(query, 0, 10);

return response.data.data.length > 0 ? response.data.data[0] : null;

} catch (error) {
logError(`Error fetching data for CTID`, error as Error);
return null;
}
};


const fetchValidCEData = async (urls: string[]): Promise<CTDLResource[]> => {
try {
const processFn = async (url: string): Promise<CTDLResource | null> => {
// Validate CTID before processing
if (!(await validateCtId(url))) {
const ctid = await getCtidFromURL(url);
if (!(await validateCtId(ctid))) {
console.error(`Invalid CE ID: ${url}`);
return null;
}

// Fetch certificate data with retry and exponential backoff
return await retryWithBackoff(
const result = await retryWithBackoff(
() => fetchCertificateData(url),
3, // Max retries
1000, // Initial delay in ms
`fetchValidCEData for URL: ${url}`
);
console.log(result);
return result;
};

// Use processInBatches for concurrency and retries
Expand Down
39 changes: 27 additions & 12 deletions backend/src/domain/search/allTrainings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { allTrainings } from "./allTrainings";
import { AxiosResponse, InternalAxiosRequestConfig } from "axios";
import ceTestData from "../test-objects/ceTestData.json"
import expectedData from "../test-objects/allTrainingsTestData.json"
import {ContactPoint} from "../training/Training";

jest.mock("@sentry/node");
jest.mock("../../credentialengine/CredentialEngineAPI");
Expand All @@ -12,23 +13,37 @@ describe('allTrainings', () => {
const getAllTrainings = allTrainings()
const getResultsSpy = jest.spyOn(credentialEngineAPI, 'getResults');
const getAddressSpy = jest.spyOn(credentialEngineUtils, 'getAvailableAtAddresses')
const ceData: AxiosResponse = {
data: { data: ceTestData, extra: {TotalResults: 2} },
status: 200,
statusText: 'OK',
headers: {},
config: {} as InternalAxiosRequestConfig,
};

afterEach(() => {
jest.clearAllMocks()
});

it('should return all trainings', async () => {
it("should return all trainings", async () => {
const ceData: AxiosResponse = {
data: { data: ceTestData, extra: { TotalResults: ceTestData.length } },
status: 200,
statusText: "OK",
headers: {},
config: {} as InternalAxiosRequestConfig,
};

getResultsSpy.mockResolvedValue(ceData);
getAddressSpy.mockResolvedValue([{"@type": "ceterms:Place",city: 'Newark', county:'Middlesex'}])
getAddressSpy.mockImplementation(async (certificate) =>
Promise.resolve(
(certificate["ceterms:availableAt"] || []).flat().map(place => ({
"@type": "ceterms:Place",
street_address: place["ceterms:streetAddress"]?.["en-US"] || "",
city: place["ceterms:addressLocality"]?.["en-US"] || "",
state: place["ceterms:addressRegion"]?.["en-US"] || "",
zipCode: place["ceterms:postalCode"] || "",
county: "",
targetContactPoints: (place["ceterms:targetContactPoint"] || []) as ContactPoint[]
}))
)
);

const result = await getAllTrainings();
expect(result).toEqual(expectedData);
expect(getResultsSpy).toHaveBeenCalledTimes(2);
});
});
expect(getResultsSpy).toHaveBeenCalledTimes(1);
expect(getAddressSpy).toHaveBeenCalledTimes(ceTestData.length);
});});
29 changes: 16 additions & 13 deletions backend/src/domain/search/allTrainings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,39 +67,42 @@ function buildQuery() {

async function transformLearningOpportunityCTDLToTrainingResult(learningOpportunity: CTDLResource): Promise<AllTrainingsResult> {
try {
const training_id = learningOpportunity["ceterms:ctid"] || "";
const title = learningOpportunity["ceterms:name"]?.["en-US"] || "";
const address = await credentialEngineUtils.getAvailableAtAddresses(learningOpportunity);
const cipCode = await credentialEngineUtils.extractCipCode(learningOpportunity);
//const cipCode = await credentialEngineUtils.extractCipCode(learningOpportunity);
const socName = learningOpportunity["ceterms:occupationType"] && learningOpportunity["ceterms:occupationType"][0] && learningOpportunity["ceterms:occupationType"][0]["ceterms:targetNodeName"] && learningOpportunity["ceterms:occupationType"][0]["ceterms:targetNodeName"]["en-US"]
? learningOpportunity["ceterms:occupationType"][0]["ceterms:targetNodeName"]["en-US"] as string : 'Not Available';
const socCode = learningOpportunity["ceterms:occupationType"] ? learningOpportunity["ceterms:occupationType"][0]["ceterms:codedNotation"] as string : '999999';
const socCodeReplaced = socCode.replace(/-/g, '').replace(/\.00$/, '');
const duration = await credentialEngineUtils.getCalendarLengthId(learningOpportunity);

return {
training_id: learningOpportunity["ceterms:ctid"] || "",
title: learningOpportunity["ceterms:name"]?.["en-US"] || "",
training_id: training_id,
title: title,
area: address.length > 0 ? address[0].city as string : "",
link: `https://mycareer.nj.gov/training/${cipCode}`,
duration: 15.0, //TODO: replace with actual duration
link: `https://mycareer.nj.gov/training/${training_id}`,
duration: duration,
soc: socCodeReplaced,
roi: 0,
soc3:socCodeReplaced.substring(0, 3),
id: `training#${cipCode}`,
id: `training#${training_id}`,
method: `classroom`,
soc_name: socName,
location: address.length > 0 ? address[0].county as string : "",
title_en: learningOpportunity["ceterms:name"]?.["en-US"] || "",
title_en: title,
soc_name_en: socName,
title_es: learningOpportunity["ceterms:name"]?.["en-US"] || "",
title_es: title,
soc_name_es: socName,
title_tl: learningOpportunity["ceterms:name"]?.["en-US"] || "",
title_tl: title,
soc_name_tl: socName,
title_zh: learningOpportunity["ceterms:name"]?.["en-US"] || "",
title_zh: title,
soc_name_zh: socName,
title_ja: learningOpportunity["ceterms:name"]?.["en-US"] || "",
title_ja: title,
soc_name_ja: socName,
duration_units: `Weeks`,
duration_slider_val_min: `15.0`,
duration_slider_val_max: `15.0`,
duration_slider_val_min: duration.toString(),
duration_slider_val_max: duration.toString(),
duration_units_en: `Weeks`,
duration_units_es: `Semanas`,
duration_units_tl: `tuần`,
Expand Down
75 changes: 21 additions & 54 deletions backend/src/domain/test-objects/allTrainingsTestData.json
Original file line number Diff line number Diff line change
@@ -1,67 +1,34 @@
[
{
"area": "Newark",
"duration": 15,
"duration_slider_val_max": "15.0",
"duration_slider_val_min": "15.0",
"area": "Mays Landing",
"duration": 3,
"duration_slider_val_max": "3",
"duration_slider_val_min": "3",
"duration_units": "Weeks",
"duration_units_en": "Weeks",
"duration_units_es": "Semanas",
"duration_units_ja": "週間",
"duration_units_tl": "tuần",
"duration_units_zh": "周",
"id": "training#123456",
"link": "https://mycareer.nj.gov/training/123456",
"location": "Middlesex",
"id": "training#ce-73263b7f-07fd-4c4a-8caa-f31bab4b3de5",
"link": "https://mycareer.nj.gov/training/ce-73263b7f-07fd-4c4a-8caa-f31bab4b3de5",
"location": "Mays Landing",
"method": "classroom",
"roi": 0,
"soc": "151121",
"soc": "151212",
"soc3": "151",
"soc_name": "Software Engineer",
"soc_name_en": "Software Engineer",
"soc_name_es": "Software Engineer",
"soc_name_ja": "Software Engineer",
"soc_name_tl": "Software Engineer",
"soc_name_zh": "Software Engineer",
"title": "Example Training Program",
"title_en": "Example Training Program",
"title_es": "Example Training Program",
"title_ja": "Example Training Program",
"title_tl": "Example Training Program",
"title_zh": "Example Training Program",
"training_id": "ctid123"
},
{
"area": "Newark",
"duration": 15,
"duration_slider_val_max": "15.0",
"duration_slider_val_min": "15.0",
"duration_units": "Weeks",
"duration_units_en": "Weeks",
"duration_units_es": "Semanas",
"duration_units_ja": "週間",
"duration_units_tl": "tuần",
"duration_units_zh": "周",
"id": "training#110901",
"link": "https://mycareer.nj.gov/training/110901",
"location": "Middlesex",
"method": "classroom",
"roi": 0,
"soc": "113021",
"soc3": "113",
"soc_name": "Computer and Information Systems Managers",
"soc_name_en": "Computer and Information Systems Managers",
"soc_name_es": "Computer and Information Systems Managers",
"soc_name_ja": "Computer and Information Systems Managers",
"soc_name_tl": "Computer and Information Systems Managers",
"soc_name_zh": "Computer and Information Systems Managers",
"title": "",
"title_en": "",
"title_es": "",
"title_ja": "",
"title_tl": "",
"title_zh": "",
"training_id": ""
"soc_name": "Information Security Analysts",
"soc_name_en": "Information Security Analysts",
"soc_name_es": "Information Security Analysts",
"soc_name_ja": "Information Security Analysts",
"soc_name_tl": "Information Security Analysts",
"soc_name_zh": "Information Security Analysts",
"title": "Computer Security Specialist",
"title_en": "Computer Security Specialist",
"title_es": "Computer Security Specialist",
"title_ja": "Computer Security Specialist",
"title_tl": "Computer Security Specialist",
"title_zh": "Computer Security Specialist",
"training_id": "ce-73263b7f-07fd-4c4a-8caa-f31bab4b3de5"
}
]

Loading