diff --git a/docs/images/add100Users.png b/docs/images/add100Users.png new file mode 100644 index 00000000..d220ecdf Binary files /dev/null and b/docs/images/add100Users.png differ diff --git a/docs/images/add1User.png b/docs/images/add1User.png new file mode 100644 index 00000000..b04bf071 Binary files /dev/null and b/docs/images/add1User.png differ diff --git a/docs/images/playGame1.png b/docs/images/playGame1.png new file mode 100644 index 00000000..5deb03b8 Binary files /dev/null and b/docs/images/playGame1.png differ diff --git a/docs/images/playGame20.png b/docs/images/playGame20.png new file mode 100644 index 00000000..46edd6a2 Binary files /dev/null and b/docs/images/playGame20.png differ diff --git a/docs/index.adoc b/docs/index.adoc index 4afb1cb2..5ebfc7f5 100644 --- a/docs/index.adoc +++ b/docs/index.adoc @@ -96,4 +96,8 @@ include::src/11_technical_risks.adoc[] // 12. Glossary include::src/12_glossary.adoc[] +<<<< +// 13. Testability +include::src/13_testability.adoc[] + diff --git a/docs/package-lock.json b/docs/package-lock.json index 78b54941..1b2c7942 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,7 +8,7 @@ "name": "docs", "version": "1.0.0", "dependencies": { - "gh-pages": "^3.2.3", + "gh-pages": "^6.1.1", "shx": "^0.3.3" } }, @@ -32,12 +32,9 @@ } }, "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dependencies": { - "lodash": "^4.17.14" - } + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -54,9 +51,12 @@ } }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } }, "node_modules/commondir": { "version": "1.0.1", @@ -69,9 +69,9 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/email-addresses": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", - "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==" }, "node_modules/escape-string-regexp": { "version": "1.0.5", @@ -134,16 +134,16 @@ } }, "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=14.14" } }, "node_modules/fs.realpath": { @@ -160,16 +160,16 @@ } }, "node_modules/gh-pages": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz", - "integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz", + "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==", "dependencies": { - "async": "^2.6.1", - "commander": "^2.18.0", - "email-addresses": "^3.0.1", + "async": "^3.2.4", + "commander": "^11.0.0", + "email-addresses": "^5.0.0", "filenamify": "^4.3.0", "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", + "fs-extra": "^11.1.1", "globby": "^6.1.0" }, "bin": { @@ -264,9 +264,12 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -282,11 +285,6 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -528,11 +526,11 @@ } }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/wrappy": { @@ -556,12 +554,9 @@ "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==" }, "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "requires": { - "lodash": "^4.17.14" - } + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "balanced-match": { "version": "1.0.2", @@ -578,9 +573,9 @@ } }, "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" }, "commondir": { "version": "1.0.1", @@ -593,9 +588,9 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "email-addresses": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", - "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==" }, "escape-string-regexp": { "version": "1.0.5", @@ -637,13 +632,13 @@ } }, "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "requires": { "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, "fs.realpath": { @@ -657,16 +652,16 @@ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "gh-pages": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz", - "integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz", + "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==", "requires": { - "async": "^2.6.1", - "commander": "^2.18.0", - "email-addresses": "^3.0.1", + "async": "^3.2.4", + "commander": "^11.0.0", + "email-addresses": "^5.0.0", "filenamify": "^4.3.0", "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", + "fs-extra": "^11.1.1", "globby": "^6.1.0" } }, @@ -736,11 +731,12 @@ } }, "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, "locate-path": { @@ -751,11 +747,6 @@ "p-locate": "^4.1.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -916,9 +907,9 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" }, "wrappy": { "version": "1.0.2", diff --git a/docs/package.json b/docs/package.json index 4a13c872..7a3058dd 100644 --- a/docs/package.json +++ b/docs/package.json @@ -8,7 +8,7 @@ "deploy": "gh-pages -d build" }, "dependencies": { - "gh-pages": "^3.2.3", + "gh-pages": "^6.1.1", "shx": "^0.3.3" } } diff --git a/docs/src/04_solution_strategy.adoc b/docs/src/04_solution_strategy.adoc index 17623c12..4cd8cf85 100644 --- a/docs/src/04_solution_strategy.adoc +++ b/docs/src/04_solution_strategy.adoc @@ -16,6 +16,7 @@ ifndef::imagesdir[:imagesdir: ../images] | _Wikidata_ | _Website where the information is taken from_ | _Javascript_ | _An interpreted programming language based on prototypes, imperative and dynamic. We will use it on both frontend and backend._ | _CSS_ | _A graphic programming language oriented to define the repesentation of a document._ +| _Bootstrap_ | _A popular front-end framework for building responsive websites._ |=== === Decisions on how to achieve key quality goals diff --git a/docs/src/09_architecture_decisions.adoc b/docs/src/09_architecture_decisions.adoc index a1033608..85147962 100644 --- a/docs/src/09_architecture_decisions.adoc +++ b/docs/src/09_architecture_decisions.adoc @@ -11,23 +11,27 @@ With "decisions" we mean selecting one alternative based on given criteria. |==== | Decision | Consequences | Risks -| Uso de React.js | - Facilitates the development of user interfaces. +| Use of React.js | - Facilitates the development of user interfaces. - React.js is a widely popular library in the development community. - Improves the efficiency of frontend development. | - Limited experience with React.js. - Possible learning curve for the team. -| Uso de JavaScript | - Team's prior knowledge in JavaScript. +| Use of JavaScript | - Team's prior knowledge in JavaScript. - Extensive support and resources available. - Suitable language for frontend and backend development. | - Limitations in compile-time error detection. - Potential challenges in performance for large projects. -| Uso de MongoDB | - Flexible schema and horizontal scalability. +| Use of MongoDB | - Flexible schema and horizontal scalability. - Widely used in modern applications. - Compatibility with unstructured data. - Already implemented in user registration and login. | - Not familiar with NoSQL databases. - Possible learning curve. -| Uso de Docker | - Containerization that facilitates deployment and scalability. +| Use of Docker | - Containerization that facilitates deployment and scalability. - Consistent environment in development and production. - Streamlines dependency management. | - Potential initial complexity in Docker configuration. - Requires additional learning resources. +| Use of Bootstrap | - Simplifies and accelerates the development of responsive and mobile-first web applications. + - Provides a wide range of pre-designed components and styles. + - Offers extensive documentation and community support. | - Learning curve for team members unfamiliar with Bootstrap. + - Risk of over-reliance on Bootstrap components, leading to less customizability. |==== diff --git a/docs/src/13_testability.adoc b/docs/src/13_testability.adoc new file mode 100644 index 00000000..1907bfd4 --- /dev/null +++ b/docs/src/13_testability.adoc @@ -0,0 +1,34 @@ +ifndef::imagesdir[:imagesdir: ../images] + +[[section-technical-risks]] +== Testability +Testability is a crucial aspect of software development. It refers to the ease with which a software system can be tested to ensure its correctness and reliability. By writing tests, developers can verify that their code behaves as expected and identify any potential issues or bugs. There are various types of tests that can be performed, such as unit tests, integration tests, and end-to-end tests. Unit tests focus on testing individual components or functions in isolation, while integration tests verify the interaction between different components. End-to-end tests simulate real-world scenarios to ensure the entire system functions correctly. + +To achieve good testability, it is important to write code that is modular, decoupled, and follows best practices such as dependency injection. Additionally, using testing frameworks and tools can simplify the process of writing and executing tests. + + +=== Load Testing +These tests will focus on evaluating the performance of our system under high traffic and heavy usage conditions. This type of testing is crucial to identify bottlenecks and ensure that our application can effectively handle the volume of users and transactions expected in production, without compromising performance and stability. + + +Initially, a test was carried out with the following procedure: +1. Create a new user +2. Log in with this new user +3. View the main page + +image::add1User.png[title="1 User"] +image::add20Users.png[title="20 User"] +image::add100Users.png[title="100 User"] + + +Then, a slightly more complex test was then performed, which followed the following procedure: +1. Log in to the app +2. View the main page +3. Play a new game +4. View the game history +5. View the previous game specific data +6. View the history of questions + +image::playGame1.png[title="1 User"] +image::playGame20.png[title="20 User"] +image::playGame100.png[title="100 User"] diff --git a/docs/src/add20Users.png b/docs/src/add20Users.png new file mode 100644 index 00000000..8877e760 Binary files /dev/null and b/docs/src/add20Users.png differ diff --git a/docs/src/playGame100.png b/docs/src/playGame100.png new file mode 100644 index 00000000..64e194d8 Binary files /dev/null and b/docs/src/playGame100.png differ diff --git a/webapp/AddUserSimulation.class b/webapp/AddUserSimulation.class new file mode 100644 index 00000000..96a0b360 Binary files /dev/null and b/webapp/AddUserSimulation.class differ diff --git a/webapp/PlayGameSimulation.class b/webapp/PlayGameSimulation.class new file mode 100644 index 00000000..bcbe2df9 Binary files /dev/null and b/webapp/PlayGameSimulation.class differ diff --git a/webapp/e2e/features/historial-form.feature b/webapp/e2e/features/historial-form.feature new file mode 100644 index 00000000..abcf4554 --- /dev/null +++ b/webapp/e2e/features/historial-form.feature @@ -0,0 +1,11 @@ +Feature: Visible user logged history + +Scenario: The user is not loged in the site + Given A not loged user + When Press history + Then Redirected to login + +Scenario: The user register in the site so he can see history + Given A unregistered user, fill the register + When I press history + Then I see my history \ No newline at end of file diff --git a/webapp/e2e/steps/historial-form.steps.js b/webapp/e2e/steps/historial-form.steps.js new file mode 100644 index 00000000..2f8d1f3d --- /dev/null +++ b/webapp/e2e/steps/historial-form.steps.js @@ -0,0 +1,85 @@ +const puppeteer = require('puppeteer'); +const { defineFeature, loadFeature }=require('jest-cucumber'); +const setDefaultOptions = require('expect-puppeteer').setDefaultOptions +const feature = loadFeature('./features/historial-form.feature'); + +let page; +let browser; + +defineFeature(feature, test => { + + let username = ""; + let password = ""; + + beforeAll(async () => { + browser = process.env.GITHUB_ACTIONS + ? await puppeteer.launch() + : await puppeteer.launch({ headless: false, slowMo: 100 }); + page = await browser.newPage(); + //Way of setting up the timeout + setDefaultOptions({ timeout: 10000 }) + + await page + .goto("http://localhost:3000/", { + waitUntil: "networkidle0", + }) + .catch(() => {}); + }); + + test('The user is not logged in the site', ({given,when,then}) => { + + given('A not logged user', async () => { + username = "pablo"; + password = "12345"; + }); + + when('Press history', async () => { + await page.goto("http://localhost:3000/getgamehistory", { + waitUntil: "networkidle0", + }).catch(() => {}); + }); + + then('Redirected to login', async () => { + await expect(page).toMatchElement('button[title="entrar"]'); + }); + },300000); + + + test('The user is not registered in the site', ({given,when,then}) => { + + + given('A unregistered user, fill the register', async () => { + await page.goto("http://localhost:3000/sign-up", { + waitUntil: "networkidle0", + }).catch(() => {}); + //Registrar al user + await expect(page).toFill('input[name="username"]', username); + await expect(page).toFill('input[name="password"]', password); + await expect(page).toClick('button[name="registrarsePage"]'); + await page.waitForNavigation({ + waitUntil: 'networkidle0' + }); + }); + + when('I fill the data in the form and press submit', async () => { + await page.waitForSelector('[data-testid="historial-user"]', { + visible: true, + }); + await page.click('[data-testid="historial-user"]'); + }); + + then('I see my history', async () => { + await expect(page).toMatchElement('th', { text: 'Fecha'}); + await expect(page).toMatchElement('th', { text: 'Tiempo de partida'}); + await expect(page).toMatchElement('th', { text: 'Porcentaje de aciertos'}); + await expect(page).toMatchElement('th', { text: 'Número de preguntas'}); + await expect(page).toMatchElement('th', { text: 'Número de aciertos'}); + await expect(page).toMatchElement('th', { text: 'Número de fallos'}); + }); + },300000); + + afterAll(async ()=>{ + browser.close() + }) + +}); \ No newline at end of file diff --git a/webapp/e2e/test-environment-setup.js b/webapp/e2e/test-environment-setup.js index 7b7ed511..430c0b4d 100644 --- a/webapp/e2e/test-environment-setup.js +++ b/webapp/e2e/test-environment-setup.js @@ -5,15 +5,21 @@ let mongoserver; let userservice; let authservice; let gatewayservice; +let questionservice; +let questionhistoryservice; async function startServer() { console.log('Starting MongoDB memory server...'); mongoserver = await MongoMemoryServer.create(); const mongoUri = mongoserver.getUri(); process.env.MONGODB_URI = mongoUri; + process.env.SECRET_KEY = '123456789'; + console.log(process.env.MONGODB_URI) userservice = await require("../../users/userservice/user-service"); authservice = await require("../../users/authservice/auth-service"); gatewayservice = await require("../../gatewayservice/gateway-service"); + questionservice = await require("../../questions/creationservice"); + questionhistoryservice = await require("../../questions/retrieveservice"); } startServer(); diff --git a/webapp/public/index.html b/webapp/public/index.html index aa069f27..f81e1175 100644 --- a/webapp/public/index.html +++ b/webapp/public/index.html @@ -24,7 +24,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - React App + WIQ 2024 ES2B diff --git a/webapp/src/components/Game.js b/webapp/src/components/Game.js index 05a1f8c6..feab3620 100644 --- a/webapp/src/components/Game.js +++ b/webapp/src/components/Game.js @@ -59,6 +59,9 @@ const Game = () => { const [openDialog, setOpenDialog] = useState(false); + const [gameData, setGameData] = useState(null); // Variable local para almacenar los datos de la partida + + const handleDialogOpen = () => { setIsTimerActive(false); setOpenDialog(true); @@ -319,10 +322,10 @@ const getQuestions = () => { //console.log("Número Total de Preguntas:", newGame.totalQuestions); //console.log("Número de Respuestas Correctas:", newGame.correctAnswers); //console.log("Número de Respuestas Incorrectas:", newGame.incorrectAnswers); - + setGameData(newGame); - axios.post(`${apiEndpoint}/addgame`, newGame) + axios.post(`${apiEndpoint}/addgame`, gameData) .then(response => { console.log("Respuesta del servidor:", response.data); }) diff --git a/webapp/src/components/Game.test.js b/webapp/src/components/Game.test.js index 536032c7..5c8d04ed 100644 --- a/webapp/src/components/Game.test.js +++ b/webapp/src/components/Game.test.js @@ -3,7 +3,7 @@ import { render, fireEvent, screen, waitFor } from '@testing-library/react'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import Game from './Game'; -import { MemoryRouter } from 'react-router-dom'; +import { MemoryRouter } from 'react-router-dom'; // Importa MemoryRouter const mockAxios = new MockAdapter(axios); @@ -25,6 +25,20 @@ describe('Game component', () => { beforeEach(() => { mockAxios.reset(); jest.useFakeTimers(); + jest.clearAllMocks(); + localStorage.clear(); + }); + + it('should display initial elements correctly', () => { + renderGameComponent(); + + // Verificar que elementos iniciales se muestren correctamente + expect(screen.getByText('Saber y Ganar Juego')).toBeInTheDocument(); + expect(screen.getByText('Preguntas restantes: 5')).toBeInTheDocument(); // Depende de la configuración del juego + expect(screen.getByText('Correctas: 0')).toBeInTheDocument(); + expect(screen.getByText('Incorrectas: 0')).toBeInTheDocument(); + expect(screen.getByText('Pregunta 0:')).toBeInTheDocument(); // La primera pregunta + expect(screen.getByText('Volver al menú principal')).toBeInTheDocument(); }); it('should display question and answer options', async () => { @@ -45,6 +59,7 @@ describe('Game component', () => { } }); }); + it('should handle correct answer click', async () => { renderGameComponent(); @@ -56,14 +71,11 @@ describe('Game component', () => { // Una vez que se muestre la pregunta, hacer clic en la respuesta correcta fireEvent.click(screen.getByText('4')); // Verificar si afectó correctamente al conteo de respuestas correctas - - console.log(screen.getByText(/Correctas: 1/i).textContent); expect(screen.getByText(/Correctas: 1/i)).toBeInTheDocument(); - + // Verificar si el color del botón cambió a verde + expect(screen.getByText('4')).toHaveStyle({ backgroundColor: 'rgba(79, 141, 18, 0.726)' }); } }); - - }); it('should handle incorrect answer click', async () => { @@ -76,13 +88,11 @@ describe('Game component', () => { if (screen.queryByText(/Pregunta 1:/i)) { // Una vez que se muestre la pregunta, hacer clic en una respuesta incorrecta fireEvent.click(screen.getByText('2')); - - console.log(screen.getByText(/Incorrectas: 1/i).textContent); expect(screen.getByText(/Incorrectas: 1/i)).toBeInTheDocument(); + // Verificar si el color del botón cambió a rojo + expect(screen.getByText('2')).toHaveStyle({ backgroundColor: 'rgba(208, 22, 22, 0.952)' }); } }); - - }); it('should close confirmation dialog on cancel', async () => { @@ -113,12 +123,11 @@ describe('Game component', () => { await waitFor(() => { expect(screen.queryByText('Game')).not.toBeInTheDocument(); }); - }); it('should display end game message and enable "Back to Main Menu" button when game is finished', async () => { renderGameComponent(); - + for (let i = 1; i <= 5; i++) { mockAxios.onGet('http://localhost:8000/createquestion').reply(200, { data: mockQuestionData }); @@ -142,6 +151,58 @@ describe('Game component', () => { expect(screen.getByText(/Volver al menú principal/i)).toBeInTheDocument(); } }); + + + }); + + + + + it('should disable buttons when time runs out', async () => { + renderGameComponent(); + + mockAxios.onGet('http://localhost:8000/createquestion').reply(200, { data: mockQuestionData }); + + // Esperar hasta que se muestre "Pregunta 1" + await waitFor(() => { + if (screen.queryByText(/Pregunta 1:/i)) { + jest.advanceTimersByTime(10000); // Avanzar el temporizador por 10 segundos + + // Verificar que los botones estén deshabilitados + const buttons = screen.getAllByRole('button', { name: /answer/i }); + buttons.forEach(button => { + expect(button).toBeDisabled(); + }); + } + }); + }); + + + it('should handle timeout correctly', async () => { + // Define una función simulada para handleShowQuestion + const handleShowQuestion = jest.fn(); + + renderGameComponent({ handleShowQuestion }); // Pasa la función simulada como propiedad + + await waitFor(() => { + mockAxios.onGet('http://localhost:8000/createquestion').reply(200, { data: mockQuestionData }); + }); + + await waitFor(() => { + if (screen.queryByText(/Pregunta 1:/i)) { + jest.advanceTimersByTime(10000); + expect(screen.getByText(correctOption)).toHaveStyle({ backgroundColor: 'rgba(79, 141, 18, 0.726)' }); + expect(incrementIncorrect).toHaveBeenCalledTimes(1); + expect(decrementQuestionsToAnswer).toHaveBeenCalledTimes(1); + } + }); + + await waitFor(() => { + expect(handleShowQuestion).toHaveBeenCalledTimes(0); // Verifica que handleShowQuestion se llame una vez + }); + }); + + });