Files
freeCodeCamp/curriculum/challenges/espanol/06-quality-assurance/quality-assurance-projects/personal-library.md
2022-02-20 07:36:06 -08:00

8.3 KiB

id, title, challengeType, forumTopicId, dashedName
id title challengeType forumTopicId dashedName
587d824a367417b2b2512c43 Biblioteca personal 4 301571 personal-library

--description--

Construye una aplicación full stack de JavaScript que sea funcionalmente similar a esta: https://personal-library.freecodecamp.rocks/. Trabajar en este proyecto implicará escribir tu código utilizando uno de los siguientes métodos:

Cuando hayas terminado, asegúrate de que una demostración funcional de tu proyecto esté alojado en algún lugar público. Luego, envía la URL en el campo Solution Link. Opcionalmente, también envía un enlace al código fuente de tu proyecto en el campo GitHub Link.

--instructions--

  1. Agrega tu cadena de conexión MongoDB a tu .env sin comillas como DB Ejemplo: DB=mongodb://admin:pass@1234.mlab.com:1234/fccpersonallib
  2. En tu archivo .env establece NODE_ENV a test, sin comillas
  3. Es necesario crear todas la rutas dentro de routes/api.js
  4. Escribe las siguientes pruebas en tests/2_functional-tests.js

--hints--

Debes proporcionar tu propio proyecto, no la URL de ejemplo.

(getUserInput) => {
  assert(
    !/.*\/personal-library\.freecodecamp\.rocks/.test(getUserInput('url'))
  );
};

Puedes enviar una petición POST a /api/books con title como parte de los datos del formulario para agregar un libro. La respuesta devuelta será un objeto con las propiedades title y un _id único como claves. Si title no está incluido en la petición, la respuesta devuelta será una cadena con 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);
  }
};

Puedes enviar una petición GET a /api/books y recibir una respuesta JSON que representa todos los libros. La respuesta JSON será un arreglo de objetos, cada objeto (libro) contienen las propiedades de title, _id, y 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);
  }
};

Puedes enviar una petición GET a /api/books/{_id} para recuperar un solo objeto de un libro que contiene las propiedades title, _id, y un arreglo comments (arreglo vacío si no hay comentarios). Si no se encuentra ningún libro, devuelve la cadena 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);
  }
};

Puedes enviar una petición de POST que contenga un comment como los datos del cuerpo del formulario a /api/books/{_id} para agregar un comentario a un libro. La respuesta devuelta será el objeto de libros similar a la petición GET /api/books/{_id} en una prueba anterior. Si comment no está incluido en la petición, la respuesta devuelta será una cadena con missing required field comment. Si no se encuentra ningún libro, devuelve la cadena 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);
  }
};

Puedes enviar una petición de DELETE a /api/books/{_id} para eliminar un libro de la colección. La respuesta devuelta será la cadena delete successful si tiene éxito. Si no se encuentra ningún libro, devuelve la cadena 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);
  }
};

Puedes enviar una petición de DELETE a /api/books para eliminar todos los libros de la base de datos. La respuesta devuelta será la cadena 'complete delete successful si tiene éxito.

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);
  }
};

Las 10 pruebas funcionales requeridas están completas y aprobadas.

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.
*/