chore(i8n,learn): processed translations
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
15047f2d90
commit
e5c44a3ae5
@@ -1,63 +1,361 @@
|
||||
---
|
||||
id: 587d8249367417b2b2512c42
|
||||
title: 问题跟踪器
|
||||
title: Issue Tracker
|
||||
challengeType: 4
|
||||
videoUrl: ''
|
||||
forumTopicId: 301569
|
||||
dashedName: issue-tracker
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
构建一个功能类似于此的完整堆栈JavaScript应用程序: [https](https://protective-garage.glitch.me/) : [//protective-garage.glitch.me/](https://protective-garage.glitch.me/) 。在这个项目上工作将涉及您在我们的入门项目上在Glitch上编写代码。完成此项目后,您可以将公共故障网址(到应用程序的主页)复制到此屏幕进行测试!您可以选择在另一个平台上编写项目,但必须公开显示我们的测试。使用[此链接](https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-project-issuetracker/)在Glitch上启动此项目或在GitHub上克隆[此存储库](https://github.com/freeCodeCamp/boilerplate-project-issuetracker/) !如果您使用Glitch,请记住将项目链接保存到安全的地方!
|
||||
Build a full stack JavaScript app that is functionally similar to this: <https://issue-tracker.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
|
||||
|
||||
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-issuetracker/) and complete your project locally.
|
||||
- Use [this repl.it starter project](https://repl.it/github/freeCodeCamp/boilerplate-project-issuetracker) to complete your project.
|
||||
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
|
||||
|
||||
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
|
||||
|
||||
# --instructions--
|
||||
|
||||
- Complete the necessary routes in `/routes/api.js`
|
||||
- Create all of the functional tests in `tests/2_functional-tests.js`
|
||||
- Copy the `sample.env` file to `.env` and set the variables appropriately
|
||||
- To run the tests uncomment `NODE_ENV=test` in your `.env` file
|
||||
- To run the tests in the console, use the command `npm run test`. To open the Repl.it console, press Ctrl+Shift+P (Cmd if on a Mac) and type "open shell"
|
||||
|
||||
Write the following tests in `tests/2_functional-tests.js`:
|
||||
|
||||
- Create an issue with every field: POST request to `/api/issues/{project}`
|
||||
- Create an issue with only required fields: POST request to `/api/issues/{project}`
|
||||
- Create an issue with missing required fields: POST request to `/api/issues/{project}`
|
||||
- View issues on a project: GET request to `/api/issues/{project}`
|
||||
- View issues on a project with one filter: GET request to `/api/issues/{project}`
|
||||
- View issues on a project with multiple filters: GET request to `/api/issues/{project}`
|
||||
- Update one field on an issue: PUT request to `/api/issues/{project}`
|
||||
- Update multiple fields on an issue: PUT request to `/api/issues/{project}`
|
||||
- Update an issue with missing `_id`: PUT request to `/api/issues/{project}`
|
||||
- Update an issue with no fields to update: PUT request to `/api/issues/{project}`
|
||||
- Update an issue with an invalid `_id`: PUT request to `/api/issues/{project}`
|
||||
- Delete an issue: DELETE request to `/api/issues/{project}`
|
||||
- Delete an issue with an invalid `_id`: DELETE request to `/api/issues/{project}`
|
||||
- Delete an issue with missing `_id`: DELETE request to `/api/issues/{project}`
|
||||
|
||||
# --hints--
|
||||
|
||||
防止跨站点脚本(XSS)攻击。
|
||||
You can provide your own project, not the example URL.
|
||||
|
||||
```js
|
||||
|
||||
(getUserInput) => {
|
||||
assert(!/.*\/issue-tracker\.freecodecamp\.rocks/.test(getUserInput('url')));
|
||||
};
|
||||
```
|
||||
|
||||
我可以使用包含所需issue_title,issue_text,created_by和可选的assigned_to和status_text的表单数据POST / api / issues / {projectname}。
|
||||
You can send a `POST` request to `/api/issues/{projectname}` with form data containing the required fields `issue_title`, `issue_text`, `created_by`, and optionally `assigned_to` and `status_text`.
|
||||
|
||||
```js
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
保存(和返回)的对象将包括所有这些字段(空白表示可选无输入),还包括created_on(日期/时间),updated_on(日期/时间),打开(布尔值,true表示打开,false表示关闭),和\_id。
|
||||
The `POST` request to `/api/issues/{projectname}` will return the created object, and must include all of the submitted fields. Excluded optional fields will be returned as empty strings. Additionally, include `created_on` (date/time), `updated_on` (date/time), `open` (boolean, `true` for open - default value, `false` for closed), and `_id`.
|
||||
|
||||
```js
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
我可以使用id和对象中的任何字段PUT / api / issues / {projectname},并使用值来对象表示对象。返回将“成功更新”或“无法更新”+ id。这应该始终更新updated_on。如果没有发送字段,则返回“未发送更新字段”。
|
||||
If you send a `POST` request to `/api/issues/{projectname}` without the required fields, returned will be the error `{ error: 'required field(s) missing' }`
|
||||
|
||||
```js
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
我可以使用id DELETE / api / issues / {projectname}来完全删除问题。如果没有发送\_id,则返回“id error”,成功:“删除”+ id,失败:“无法删除”+ id。
|
||||
You can send a `GET` request to `/api/issues/{projectname}` for an array of all issues for that specific `projectname`, with all the fields present for each issue.
|
||||
|
||||
```js
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
我可以GET / api / issues / {projectname}获取该特定项目中所有问题的数组,其中包含发布时返回的每个问题的所有信息。
|
||||
You can send a `GET` request to `/api/issues/{projectname}` and filter the request by also passing along any field and value as a URL query (ie. `/api/issues/{project}?open=false`). You can pass one or more field/value pairs at once.
|
||||
|
||||
```js
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
我可以通过传递查询中的任何字段和值来过滤我的获取请求(即。/ api / issues / {project}?open = false)。我可以传递尽可能多的字段/值。
|
||||
You can send a `PUT` request to `/api/issues/{projectname}` with an `_id` and one or more fields to update. On success, the `updated_on` field should be updated, and returned should be `{ result: 'successfully updated', '_id': _id }`.
|
||||
|
||||
```js
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
所有11项功能测试都已完成并通过。
|
||||
When the `PUT` request sent to `/api/issues/{projectname}` does not include an `_id`, the return value is `{ error: 'missing _id' }`.
|
||||
|
||||
```js
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
When the `PUT` request sent to `/api/issues/{projectname}` does not include update fields, the return value is `{ error: 'no update field(s) sent', '_id': _id }`. On any other error, the return value is `{ error: 'could not update', '_id': _id }`.
|
||||
|
||||
```js
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
You can send a `DELETE` request to `/api/issues/{projectname}` with an `_id` to delete an issue. If no `_id` is sent, the return value is `{ error: 'missing _id' }`. On success, the return value is `{ result: 'successfully deleted', '_id': _id }`. On failure, the return value is `{ error: 'could not delete', '_id': _id }`.
|
||||
|
||||
```js
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
All 14 functional tests are complete and passing.
|
||||
|
||||
```js
|
||||
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--
|
||||
|
Reference in New Issue
Block a user