Skip to content

Instantly share code, notes, and snippets.

@danilaplee
Created August 22, 2023 11:21
Show Gist options
  • Save danilaplee/2a67f80d25683e892fd4dda8508c74c5 to your computer and use it in GitHub Desktop.
Save danilaplee/2a67f80d25683e892fd4dda8508c74c5 to your computer and use it in GitHub Desktop.
/*
Feature: Data Source Join and Mapping
Scenario: Joining and mapping data from third-party API and local DB query in execute()
GIVEN two different data sources, one from a third-party API (call3partyAPI) and one from a local DB query (dbQuery)
AND the call3partyAPI() returns static "curriculum" data
AND the dbQuery() returns user learning progress data from our DB
WHEN the execute() function is called
THEN it should return an array of [{lessonName, readableStatus}]
AND the readableStatus for each lesson is defined as follows:
1: pending
2: submitted
3: passed
4: failed
definition of response:
[
{
userId: number
userName: string
lessons: {
lessonName: string
readableStatus: string
curriculumId: number
lessonId: number
}[]
}
]
*/
const StatusMap = {
1: "pending",
2: "submitted",
3: "passed",
4: "failed"
}
async function call3partyAPI() { //not enought data cases for unit testing
return {
status: 200, // could be 400 or 500 sometimes
data: [ // data property may or may not exist
{
curriculum: {
id: 1,
title: 'Technology and Sustainability',
lessons: [
{
id: 28,
name: 'Multiple Choice',
},
{
id: 76,
name: 'True or False Questions',
},
]
}
},
{
curriculum: {
id: 2,
title: 'Technology and Sustainability',
lessons: [
{
id: 120,
name: 'Chaos',
},
{
id: 160,
name: 'Order',
},
]
}
},
]
};
};
// Assume only one user will ever get returned
async function dbQuery() { //not enought data cases for unit testing
return [
{
user: { id: 1, name: 'Tom' },
progress: {
lessons: [
{
lesson_id: 28,
status: 2,
},
{
lesson_id: 76,
status: 1
}
]
},
},
{
user: { id: 2, name: 'Dan' },
progress: {
lessons: [
{
lesson_id: 76,
status: 1
},
{
lesson_id: 120,
status: 1
}
]
}
}
]
}
async function execute() {
const [client_response, students] = await Promise.all([call3partyAPI(), dbQuery()])
const curriculums = client_response.data
const curriculumIds = []
const curriculumsMap = curriculums.reduce((a, curriculum)=>{
const curriculumId = curriculum.curriculum.id;
curriculumIds.push(curriculumId)
const lessons = curriculum.curriculum.lessons
a[curriculumId] = {
lessons:lessons.reduce((aggr, lesson)=>{
aggr[lesson.id] = lesson.name
return aggr
}, {}),
set: new Set(lessons.map(lesson=>lesson.id))
}
return a
}, {})
// console.info("curriculumsMap", curriculumsMap)
const Response = [];
if (client_response) {
students.map(student => {
const studentResult = {
userId: student.user.id,
userName: student.user.name,
lessons: []
}
const studentLessonIds = []
const studentLessonMap = student.progress.lessons.reduce((a,i)=>{
studentLessonIds.push(i.lesson_id)
a[i.lesson_id] = i.status
return a
}, {})
// console.info("studentLessonMap", studentLessonMap)
curriculumIds.map((curriculumId) => {
const intersection = studentLessonIds.filter((x) => curriculumsMap[parseInt(curriculumId)].set.has(x));
// console.info("intersection", intersection, studentLessonIds, curriculumIds)
intersection.map(lessonId => {
studentResult.lessons.push({
lessonName: curriculumsMap[curriculumId].lessons[lessonId],
readableStatus: StatusMap[studentLessonMap[lessonId]],
curriculumId,
lessonId
});
})
})
Response.push(studentResult)
})
}
return Response;
}
execute().then((res) => console.log(JSON.stringify(res, 0, 2)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment