15 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
587d8249367417b2b2512c42 | 課題トラッカー | 4 | 301569 | issue-tracker |
--description--
https://issue-tracker.freecodecamp.rocks/ と同様の機能を持つフルスタック JavaScript アプリを構築してください。 プロジェクトに取り組むにあたり、以下の方法のうち 1 つを用いてコードを記述します。
- GitHub リポジトリをクローンし、ローカル環境でプロジェクトを完了させる。
- Replit 始動プロジェクトを使用して、プロジェクトを完了させる。
- 使い慣れたサイトビルダーを使用してプロジェクトを完了させる。 必ず GitHub リポジトリのすべてのファイルを取り込む。
完了したら、プロジェクトの動作デモをどこか公開の場にホストしてください。 そして、Solution Link
フィールドでデモへの URL を送信してください。 必要に応じて、GitHub Link
フィールドでプロジェクトのソースコードへのリンクを送信してください。
--instructions--
/routes/api.js
で、必要なルートを完成させてください。tests/2_functional-tests.js
にすべての機能テストを作成してください。sample.env
ファイルを.env
にコピーし、変数を適切に設定してください。- テストを実行するには、
.env
ファイルのNODE_ENV=test
をコメント解除してください。 - コンソールでテストを実行するには、コマンド
npm run test
を使用してください。 Replit コンソールを開くには、Ctrl+Shift+P (Macの場合はCmd) を押して「open shell」と入力してください。
tests/2_functional-tests.js
に以下のテストを記述してください。
- すべてのフィールドについて課題を作成してください:
/api/issues/{project}
への POST リクエスト - 必須フィールドのみについて課題を作成してください:
/api/issues/{project}
への POST リクエスト - 不足している必須フィールドについて課題を作成してください:
/api/issues/{project}
への POST リクエスト - プロジェクトの課題を表示してください:
/api/issues/{project}
への GET リクエスト - 1 つのフィルターでプロジェクトの課題を表示してください:
/api/issues/{project}
への GET リクエスト - 複数のフィルターでプロジェクトの課題を表示してください:
/api/issues/{project}
への GET リクエスト - 課題の 1 つのフィールドを更新してください:
/api/issues/{project}
への PUT リクエスト - 課題の複数フィールドを更新してください:
/api/issues/{project}
への PUT リクエスト _id
が不足している課題を更新してください:/api/issues/{project}
への PUT リクエスト- 更新すべきフィールドがない課題を更新してください:
/api/issues/{project}
への PUT リクエスト - 無効な
_id
の課題を更新してください:/api/issues/{project}
への PUT リクエスト - 課題を削除してください:
/api/issues/{project}
への DELETE リクエスト - 無効な
_id
の課題を削除してください:/api/issues/{project}
への DELETE リクエスト _id
が不足している課題を削除してください:/api/issues/{project}
への DELETE リクエスト
--hints--
サンプルの URL ではなく、自分で作成したプロジェクトを提供することができます。
(getUserInput) => {
assert(!/.*\/issue-tracker\.freecodecamp\.rocks/.test(getUserInput('url')));
};
必須フィールド issue_title
、issue_text
、created_by
、およびオプションフィールド assigned_to
および status_text
を含むフォームデータを使用して、/api/issues/{projectname}
へ POST
リクエストを送信することができます。
async (getUserInput) => {
try {
let test_data = {
issue_title: 'Faux Issue Title',
issue_text: 'Functional Test - Required Fields Only',
created_by: 'fCC'
};
const data = await $.post(
getUserInput('url') + '/api/issues/fcc-project',
test_data
);
assert.isObject(data);
assert.nestedInclude(data, test_data);
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
/api/issues/{projectname}
への POST
リクエストは、作成されたオブジェクトを返します。また、送信したすべてのフィールドが含まれている必要があります。 除外されたオプションフィールドは空の文字列として返します。 さらに、created_on
(日付/時間)、updated_on
(日付/時間)、open
(ブール値、open の場合はデフォルト値の true
、closed の場合は false
) および _id
を含めてください。
async (getUserInput) => {
try {
let test_data = {
issue_title: 'Faux Issue Title 2',
issue_text: 'Functional Test - Every field filled in',
created_by: 'fCC',
assigned_to: 'Chai and Mocha'
};
const data = await $.post(
getUserInput('url') + '/api/issues/fcc-project',
test_data
);
assert.isObject(data);
assert.nestedInclude(data, test_data);
assert.property(data, 'created_on');
assert.isNumber(Date.parse(data.created_on));
assert.property(data, 'updated_on');
assert.isNumber(Date.parse(data.updated_on));
assert.property(data, 'open');
assert.isBoolean(data.open);
assert.isTrue(data.open);
assert.property(data, '_id');
assert.isNotEmpty(data._id);
assert.property(data, 'status_text');
assert.isEmpty(data.status_text);
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
/api/issues/{projectname}
への POST
リクエストを必須フィールドなしで送信した場合は、エラー { error: 'required field(s) missing' }
を返します。
async (getUserInput) => {
try {
let test_data = { created_by: 'fCC' };
const data = await $.post(getUserInput('url') + '/api/issues/fcc-project', {
created_by: 'fCC'
});
assert.isObject(data);
assert.property(data, 'error');
assert.equal(data.error, 'required field(s) missing');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
特定の projectname
に対するすべての課題の配列 (課題ごとにすべてのフィールドが存在します) に対して、/api/issues/{projectname}
へ GET
リクエストを送信できます。
async (getUserInput) => {
try {
let test_data = { issue_text: 'Get Issues Test', created_by: 'fCC' };
const url =
getUserInput('url') +
'/api/issues/get_issues_test_' +
Date.now().toString().substring(7);
const data1 = await $.post(
url,
Object.assign(test_data, { issue_title: 'Faux Issue 1' })
);
assert.isObject(data1);
const data2 = await $.post(
url,
Object.assign(test_data, { issue_title: 'Faux Issue 2' })
);
assert.isObject(data2);
const data3 = await $.post(
url,
Object.assign(test_data, { issue_title: 'Faux Issue 3' })
);
assert.isObject(data3);
const getIssues = await $.get(url);
assert.isArray(getIssues);
assert.lengthOf(getIssues, 3);
let re = new RegExp('Faux Issue \\d');
getIssues.forEach((issue) => {
assert.property(issue, 'issue_title');
assert.match(issue.issue_title, re);
assert.property(issue, 'issue_text');
assert.property(issue, 'created_by');
assert.property(issue, 'assigned_to');
assert.property(issue, 'status_text');
assert.property(issue, 'open');
assert.property(issue, 'created_on');
assert.property(issue, 'updated_on');
assert.property(issue, '_id');
});
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
/api/issues/{projectname}
へ GET
リクエストを送信し、任意のフィールドと値を URL クエリとして渡すことにより、リクエストをフィルターで絞り込むことができます (例: /api/issues/{project}?open=false
)。 1 つ以上のフィールド/値のペアを一度に渡すことができます。
async (getUserInput) => {
try {
let test_data = {
issue_title: 'To be Filtered',
issue_text: 'Filter Issues Test'
};
const url =
getUserInput('url') +
'/api/issues/get_issues_test_' +
Date.now().toString().substring(7);
const data1 = await $.post(
url,
Object.assign(test_data, { created_by: 'Alice', assigned_to: 'Bob' })
);
const data2 = await $.post(
url,
Object.assign(test_data, { created_by: 'Alice', assigned_to: 'Bob' })
);
const data3 = await $.post(
url,
Object.assign(test_data, { created_by: 'Alice', assigned_to: 'Eric' })
);
const data4 = await $.post(
url,
Object.assign(test_data, { created_by: 'Carol', assigned_to: 'Eric' })
);
const getSingle = await $.get(url + '?created_by=Alice');
assert.isArray(getSingle);
assert.lengthOf(getSingle, 3);
const getMultiple = await $.get(url + '?created_by=Alice&assigned_to=Bob');
assert.isArray(getMultiple);
assert.lengthOf(getMultiple, 2);
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
_id
と 1 つ 以上の更新すべきフィールドを指定して、/api/issues/{projectname}
へ PUT
リクエストを送信することができます。 成功した場合は、updated_on
フィールドを更新し、 { result: 'successfully updated', '_id': _id }
を返す必要があります。
async (getUserInput) => {
try {
let initialData = {
issue_title: 'Issue to be Updated',
issue_text: 'Functional Test - Put target',
created_by: 'fCC'
};
const url = getUserInput('url') + '/api/issues/fcc-project';
const itemToUpdate = await $.post(url, initialData);
const updateSucccess = await $.ajax({
url: url,
type: 'PUT',
data: { _id: itemToUpdate._id, issue_text: 'New Issue Text' }
});
assert.isObject(updateSucccess);
assert.deepEqual(updateSucccess, {
result: 'successfully updated',
_id: itemToUpdate._id
});
const getUpdatedId = await $.get(url + '?_id=' + itemToUpdate._id);
assert.isArray(getUpdatedId);
assert.isObject(getUpdatedId[0]);
assert.isAbove(
Date.parse(getUpdatedId[0].updated_on),
Date.parse(getUpdatedId[0].created_on)
);
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
/api/issues/{projectname}
へ送信した PUT
リクエストに _id
が含まれていない場合、戻り値は { error: 'missing _id' }
です。
async (getUserInput) => {
try {
const url = getUserInput('url') + '/api/issues/fcc-project';
const badUpdate = await $.ajax({ url: url, type: 'PUT' });
assert.isObject(badUpdate);
assert.property(badUpdate, 'error');
assert.equal(badUpdate.error, 'missing _id');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
/api/issues/{projectname}
へ送信した PUT
リクエストに更新フィールドが含まれていない 場合、戻り値は { error: 'no update field(s) sent', '_id': _id }
です。 それ以外のエラーでは、戻り値は { error: 'could not update', '_id': _id }
です。
async (getUserInput) => {
try {
const url = getUserInput('url') + '/api/issues/fcc-project';
const badUpdate = await $.ajax({
url: url,
type: 'PUT',
data: { _id: '5f665eb46e296f6b9b6a504d' }
});
assert.deepEqual(badUpdate, {
error: 'no update field(s) sent',
_id: '5f665eb46e296f6b9b6a504d'
});
const badIdUpdate = await $.ajax({
url: url,
type: 'PUT',
data: { _id: '5f665eb46e296f6b9b6a504d', issue_text: 'New Issue Text' }
});
assert.deepEqual(badIdUpdate, {
error: 'could not update',
_id: '5f665eb46e296f6b9b6a504d'
});
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
_id
を指定して /api/issues/{projectname}
へ DELETE
リクエストを送信して、課題を削除することができます。 _id
が送信されていない場合、戻り値は { error: 'missing _id' }
です。 成功した場合、戻り値は { result: 'successfully deleted', '_id': _id }
です。 失敗した場合、戻り値は { error: 'could not delete', '_id': _id }
です。
async (getUserInput) => {
try {
let initialData = {
issue_title: 'Issue to be Deleted',
issue_text: 'Functional Test - Delete target',
created_by: 'fCC'
};
const url = getUserInput('url') + '/api/issues/fcc-project';
const itemToDelete = await $.post(url, initialData);
assert.isObject(itemToDelete);
const deleteSuccess = await $.ajax({
url: url,
type: 'DELETE',
data: { _id: itemToDelete._id }
});
assert.isObject(deleteSuccess);
assert.deepEqual(deleteSuccess, {
result: 'successfully deleted',
_id: itemToDelete._id
});
const noId = await $.ajax({ url: url, type: 'DELETE' });
assert.isObject(noId);
assert.deepEqual(noId, { error: 'missing _id' });
const badIdDelete = await $.ajax({
url: url,
type: 'DELETE',
data: { _id: '5f665eb46e296f6b9b6a504d', issue_text: 'New Issue Text' }
});
assert.isObject(badIdDelete);
assert.deepEqual(badIdDelete, {
error: 'could not delete',
_id: '5f665eb46e296f6b9b6a504d'
});
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
14 種類の機能テストがすべて完了し、合格しています。
async (getUserInput) => {
try {
const getTests = await $.get(getUserInput('url') + '/_api/get-tests');
assert.isArray(getTests);
assert.isAtLeast(getTests.length, 14, 'At least 14 tests passed');
getTests.forEach((test) => {
assert.equal(test.state, 'passed', 'Test in Passed State');
assert.isAtLeast(
test.assertions.length,
1,
'At least one assertion per test'
);
});
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
--solutions--
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/