feat: Add tests for challenge>buildUserUpdate

This commit is contained in:
Bouncey
2019-02-23 21:43:51 +00:00
committed by mrugesh mohapatra
parent 75190d3a43
commit 953e1b2e11
3 changed files with 227 additions and 42 deletions

View File

@ -74,10 +74,14 @@ const jsProjects = [
'aa2e6f85cab2ab736c9a9b24' 'aa2e6f85cab2ab736c9a9b24'
]; ];
function buildUserUpdate(user, challengeId, _completedChallenge, timezone) { export function buildUserUpdate(
user,
challengeId,
_completedChallenge,
timezone
) {
const { files } = _completedChallenge; const { files } = _completedChallenge;
let completedChallenge = {}; let completedChallenge = {};
if (jsProjects.includes(challengeId)) { if (jsProjects.includes(challengeId)) {
completedChallenge = { completedChallenge = {
..._completedChallenge, ..._completedChallenge,

View File

@ -1,9 +1,10 @@
/* global describe xdescribe it expect */ /* global describe xdescribe it expect */
import { isEqual } from 'lodash'; import { isEqual, first, find } from 'lodash';
import sinon from 'sinon'; import sinon from 'sinon';
import { mockReq, mockRes } from 'sinon-express-mock'; import { mockReq, mockRes } from 'sinon-express-mock';
import { import {
buildUserUpdate,
buildChallengeUrl, buildChallengeUrl,
createChallengeUrlResolver, createChallengeUrlResolver,
createRedirectToCurrentChallenge, createRedirectToCurrentChallenge,
@ -11,48 +12,144 @@ import {
isValidChallengeCompletion isValidChallengeCompletion
} from '../boot/challenge'; } from '../boot/challenge';
const firstChallengeUrl = '/learn/the/first/challenge'; import {
const requestedChallengeUrl = '/learn/my/actual/challenge'; firstChallengeUrl,
const mockChallenge = { requestedChallengeUrl,
id: '123abc', mockChallenge,
block: 'actual', mockFirstChallenge,
superBlock: 'my', mockUser,
dashedName: 'challenge' mockApp,
}; mockGetFirstChallenge,
const mockFirstChallenge = { firstChallengeQuery,
id: '456def', mockCompletedChallenge,
block: 'first', mockCompletedChallenges
superBlock: 'the', } from './fixtures';
dashedName: 'challenge'
};
const mockUser = {
username: 'camperbot',
currentChallengeId: '123abc'
};
const mockApp = {
models: {
Challenge: {
find() {
return firstChallengeUrl;
},
findById(id, cb) {
return id === mockChallenge.id
? cb(null, mockChallenge)
: cb(new Error('challenge not found'));
}
}
}
};
const mockGetFirstChallenge = () => firstChallengeUrl;
const firstChallengeQuery = {
// first challenge of the first block of the first superBlock
where: { challengeOrder: 0, superOrder: 1, order: 0 }
};
describe('boot/challenge', () => { describe('boot/challenge', () => {
xdescribe('backendChallengeCompleted'); xdescribe('backendChallengeCompleted');
xdescribe('buildUserUpdate'); describe('buildUserUpdate', () => {
it('returns an Object with a nested "completedChallenges" property', () => {
const result = buildUserUpdate(
mockUser,
'123abc',
mockCompletedChallenge,
'UTC'
);
expect(result).toHaveProperty('updateData.$set.completedChallenges');
});
it('preserves file contents if the completed challenge is a JS Project', () => {
const jsChallengeId = 'aa2e6f85cab2ab736c9a9b24';
const completedChallenge = {
...mockCompletedChallenge,
completedDate: Date.now(),
id: jsChallengeId
};
const result = buildUserUpdate(
mockUser,
jsChallengeId,
completedChallenge,
'UTC'
);
const firstCompletedChallenge = first(
result.updateData.$set.completedChallenges
);
expect(firstCompletedChallenge).toEqual(completedChallenge);
});
it('preserves the original completed date of a challenge', () => {
const completedChallengeId = 'aaa48de84e1ecc7c742e1124';
const completedChallenge = {
...mockCompletedChallenge,
completedDate: Date.now(),
id: completedChallengeId
};
const originalCompletion = find(
mockCompletedChallenges,
x => x.id === completedChallengeId
).completedDate;
const result = buildUserUpdate(
mockUser,
completedChallengeId,
completedChallenge,
'UTC'
);
const firstCompletedChallenge = first(
result.updateData.$set.completedChallenges
);
expect(firstCompletedChallenge.completedDate).toEqual(originalCompletion);
});
it('does not attempt to update progressTimestamps for a previously completed challenge', () => {
const completedChallengeId = 'aaa48de84e1ecc7c742e1124';
const completedChallenge = {
...mockCompletedChallenge,
completedDate: Date.now(),
id: completedChallengeId
};
const { updateData } = buildUserUpdate(
mockUser,
completedChallengeId,
completedChallenge,
'UTC'
);
const hasProgressTimestamps =
'$push' in updateData && 'progressTimestamps' in updateData.$push;
expect(hasProgressTimestamps).toBe(false);
});
it('provides a progressTimestamps update for new challenge completion', () => {
expect.assertions(2);
const { updateData } = buildUserUpdate(
mockUser,
'123abc',
mockCompletedChallenge,
'UTC'
);
expect(updateData).toHaveProperty('$push');
expect(updateData.$push).toHaveProperty('progressTimestamps');
});
it('removes repeat completions from the completedChallenges array', () => {
const completedChallengeId = 'aaa48de84e1ecc7c742e1124';
const completedChallenge = {
...mockCompletedChallenge,
completedDate: Date.now(),
id: completedChallengeId
};
const {
updateData: {
$set: { completedChallenges }
}
} = buildUserUpdate(
mockUser,
completedChallengeId,
completedChallenge,
'UTC'
);
expect(completedChallenges.length).toEqual(
mockCompletedChallenges.length
);
});
it('adds newly completed challenges to the completedChallenges array', () => {
const {
updateData: {
$set: { completedChallenges }
}
} = buildUserUpdate(mockUser, '123abc', mockCompletedChallenge, 'UTC');
expect(completedChallenges.length).toEqual(
mockCompletedChallenges.length + 1
);
});
});
describe('buildChallengeUrl', () => { describe('buildChallengeUrl', () => {
it('resolves the correct Url for the provided challenge', () => { it('resolves the correct Url for the provided challenge', () => {
@ -122,6 +219,7 @@ describe('boot/challenge', () => {
expect(result).toEqual(firstChallengeUrl); expect(result).toEqual(firstChallengeUrl);
}); });
it('returns the learn base if no challenges found', async () => { it('returns the learn base if no challenges found', async () => {
const result = await getFirstChallenge(createMockChallengeModel(false)); const result = await getFirstChallenge(createMockChallengeModel(false));
@ -212,7 +310,7 @@ describe('boot/challenge', () => {
}); });
}); });
xdescribe('modernChallengeCompleted', () => {}); xdescribe('modernChallengeCompleted');
xdescribe('projectCompleted'); xdescribe('projectCompleted');

View File

@ -0,0 +1,83 @@
export const firstChallengeUrl = '/learn/the/first/challenge';
export const requestedChallengeUrl = '/learn/my/actual/challenge';
export const mockChallenge = {
id: '123abc',
block: 'actual',
superBlock: 'my',
dashedName: 'challenge'
};
export const mockFirstChallenge = {
id: '456def',
block: 'first',
superBlock: 'the',
dashedName: 'challenge'
};
export const mockCompletedChallenge = {
id: '890xyz',
challengeType: 0,
files: [
{
contents: 'file contents',
key: 'indexfile',
name: 'index',
path: 'index.file',
ext: 'file'
}
],
completedDate: Date.now()
};
export const mockCompletedChallenges = [
{
id: 'bd7123c8c441eddfaeb5bdef',
completedDate: 1538052380328.0
},
{
id: '587d7dbd367417b2b2512bb4',
completedDate: 1547472893032.0,
files: []
},
{
id: 'aaa48de84e1ecc7c742e1124',
completedDate: 1541678430790.0,
files: [
{
contents:
"function palindrome(str) {\n const clean = str.replace(/[\\W_]/g, '').toLowerCase()\n const revStr = clean.split('').reverse().join('');\n return clean === revStr;\n}\n\n\n\npalindrome(\"eye\");\n",
ext: 'js',
path: 'index.js',
name: 'index',
key: 'indexjs'
}
]
},
{
id: '5a24c314108439a4d4036164',
completedDate: 1543845124143.0,
files: []
}
];
export const mockUser = {
username: 'camperbot',
currentChallengeId: '123abc',
timezone: 'UTC',
completedChallenges: mockCompletedChallenges
};
export const mockApp = {
models: {
Challenge: {
find() {
return firstChallengeUrl;
},
findById(id, cb) {
return id === mockChallenge.id
? cb(null, mockChallenge)
: cb(new Error('challenge not found'));
}
}
}
};
export const mockGetFirstChallenge = () => firstChallengeUrl;
export const firstChallengeQuery = {
// first challenge of the first block of the first superBlock
where: { challengeOrder: 0, superOrder: 1, order: 0 }
};