9.1 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
587d824a367417b2b2512c43 | 個人図書館 | 4 | 301571 | personal-library |
--description--
https://personal-library.freecodecamp.rocks/ と同様の機能を持つフルスタック JavaScript アプリを構築してください。 プロジェクトに取り組むにあたり、以下の方法のうち 1 つを用いてコードを記述します。
- GitHub レポジトリをクローンし、ローカル環境でチャレンジを完了させる。
- Replit 始動プロジェクトを使用して、プロジェクトを完了させる。
- 使い慣れたサイトビルダーを使用してプロジェクトを完了させる。 必ず GitHub リポジトリのすべてのファイルを取り込む。
完了したら、プロジェクトの動作デモをどこか公開の場にホストしてください。 そして、Solution Link
フィールドでデモへの URL を送信してください。 必要に応じて、GitHub Link
フィールドでプロジェクトのソースコードへのリンクを送信してください。
--instructions--
.env
に、MongoDB 接続文字列をDB
として引用符を使用せずに追加してください。例:DB=mongodb://admin:pass@1234.mlab.com:1234/fccpersonallib
.env
ファイルで、引用符を使用せずにNODE_ENV
にtest
を設定してください。routes/api.js
内に、すべてのルートを作成する必要があります。tests/2_functional-tests.js
に、すべての機能テストを作成します。
--hints--
サンプルの URL ではなく、自分で作成したプロジェクトを提供することができます。
(getUserInput) => {
assert(
!/.*\/personal-library\.freecodecamp\.rocks/.test(getUserInput('url'))
);
};
フォームデータの一部として title
を指定して、/api/books
へ POST リクエストを送信し、ブックを追加することができます。 返されるレスポンスは、title
と一意の _id
をキーとして持つオブジェクトになります。 title
がリクエストに含まれていない場合、返されるレスポンスは文字列 missing required field title
である必要があります。
async (getUserInput) => {
try {
let data1 = await $.post(getUserInput('url') + '/api/books', {
title: 'Faux Book 1'
});
assert.isObject(data1);
assert.property(data1, 'title');
assert.equal(data1.title, 'Faux Book 1');
assert.property(data1, '_id');
let data2 = await $.post(getUserInput('url') + '/api/books');
assert.isString(data2);
assert.equal(data2, 'missing required field title');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
GET リクエストを /api/books
へ送信し、すべてのブックを表す JSON レスポンスを受け取ることができます。 JSON レスポンスはオブジェクトの配列であり、それぞれのオブジェクト (ブック) に title
、_id
および commentcount
プロパティが含まれます。
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let a = $.post(url, { title: 'Faux Book A' });
let b = $.post(url, { title: 'Faux Book B' });
let c = $.post(url, { title: 'Faux Book C' });
await Promise.all([a, b, c]).then(async () => {
let data = await $.get(url);
assert.isArray(data);
assert.isAtLeast(data.length, 3);
data.forEach((book) => {
assert.isObject(book);
assert.property(book, 'title');
assert.isString(book.title);
assert.property(book, '_id');
assert.property(book, 'commentcount');
assert.isNumber(book.commentcount);
});
});
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
GET リクエストを /api/books/{_id}
へ送信して、プロパティ title
、_id
および comments
配列 (コメントがない場合は、空の配列) を含むブックの単一のオブジェクトを取得できます。 ブックが見つからない場合は、文字列 no book exists
を返してください。
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let noBook = await $.get(url + '/5f665eb46e296f6b9b6a504d');
assert.isString(noBook);
assert.equal(noBook, 'no book exists');
let sampleBook = await $.post(url, { title: 'Faux Book Alpha' });
assert.isObject(sampleBook);
let bookId = sampleBook._id;
let bookQuery = await $.get(url + '/' + bookId);
assert.isObject(bookQuery);
assert.property(bookQuery, 'title');
assert.equal(bookQuery.title, 'Faux Book Alpha');
assert.property(bookQuery, 'comments');
assert.isArray(bookQuery.comments);
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
comment
を含む フォームボディデータとして指定して、POST リクエストを /api/books/{_id}
へ送信し、ブックにコメントを追加することができます。 返されるレスポンスは、前述のテストの GET /api/books/{_id}
リクエストと同様のブックオブジェクトになります。 comment
がリクエストに含まれていない場合は、文字列 missing required field comment
を返してください。 ブックが見つからない場合は、文字列 no book exists
を返してください。
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let commentTarget = await $.post(url, { title: 'Notable Book' });
assert.isObject(commentTarget);
let bookId = commentTarget._id;
let bookCom1 = await $.post(url + '/' + bookId, {
comment: 'This book is fab!'
});
let bookCom2 = await $.post(url + '/' + bookId, {
comment: 'I did not care for it'
});
assert.isObject(bookCom2);
assert.property(bookCom2, '_id');
assert.property(bookCom2, 'title');
assert.property(bookCom2, 'comments');
assert.lengthOf(bookCom2.comments, 2);
bookCom2.comments.forEach((comment) => {
assert.isString(comment);
assert.oneOf(comment, ['This book is fab!', 'I did not care for it']);
});
let commentErr = await $.post(url + '/' + bookId);
assert.isString(commentErr);
assert.equal(commentErr, 'missing required field comment');
let failingComment = await $.post(url + '/5f665eb46e296f6b9b6a504d', {
comment: 'Never Seen Comment'
});
assert.isString(failingComment);
assert.equal(failingComment, 'no book exists');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
DELETE リクエストを /api/books/{_id}
へ送信して、コレクションからブックを削除できます。 成功した場合、文字列 delete successful
のレスポンスを返します。 ブックが見つからない場合、文字列 no book exists
を返してください。
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let deleteTarget = await $.post(url, { title: 'Deletable Book' });
assert.isObject(deleteTarget);
let bookId = deleteTarget._id;
let doDelete = await $.ajax({ url: url + '/' + bookId, type: 'DELETE' });
assert.isString(doDelete);
assert.equal(doDelete, 'delete successful');
let failingDelete = await $.ajax({
url: url + '/5f665eb46e296f6b9b6a504d',
type: 'DELETE'
});
assert.isString(failingDelete);
assert.equal(failingDelete, 'no book exists');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
DELETE リクエストを /api/books
へ送信して、データベース内のすべてのブックを削除することができます。 成功した場合、文字列 'complete delete successful
のレスポンスを返します。
async (getUserInput) => {
try {
const deleteAll = await $.ajax({
url: getUserInput('url') + '/api/books',
type: 'DELETE'
});
assert.isString(deleteAll);
assert.equal(deleteAll, 'complete delete successful');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
10 種類の必須の機能テストがすべて完了し、合格しています。
async (getUserInput) => {
try {
const getTests = await $.get(getUserInput('url') + '/_api/get-tests');
assert.isArray(getTests);
assert.isAtLeast(getTests.length, 10, 'At least 10 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.
*/