From 98910055223835c83a962823e3e659ab23578cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 19:11:34 +0200 Subject: [PATCH 1/8] Errors in friends.jsx solved and endpoint usage added to metrics --- gatewayservice/gateway-service.js | 6 ++++++ webapp/src/components/Friends.jsx | 35 +++++++++++++++---------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 8c2bc4db..dd32030f 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -35,6 +35,12 @@ const memoryUsageGauge = new promClient.Gauge({ name: 'system_memory_usage', help: 'Memory usage', }); +// Endpoint usage counter +const endpointCounter = new promClient.Counter({ + name: 'endpoint_usage', + help: 'Number of calls to each endpoint', + labelNames: ['endpoint'], +}); if (process.env.NODE_ENV !== 'test') { setInterval(() => { diff --git a/webapp/src/components/Friends.jsx b/webapp/src/components/Friends.jsx index a34f0b92..1dbf62a4 100644 --- a/webapp/src/components/Friends.jsx +++ b/webapp/src/components/Friends.jsx @@ -12,27 +12,24 @@ const Friends = ({goTo}) => { const [openSnackbar, setOpenSnackbar] = useState(false); const [error, setError] = useState(''); const [snackbarMessage, setSnackbarMessage] = useState(''); - - useEffect(() => { - const fetchData = async () => { - try { - const response = await axios.get(`${gatewayUrl}/getFriends/${sessionData.username}`, { - headers: { - Authorization: `Bearer ${sessionData.token}` - } - }); - if (response.status === 200) { - setFriends(response.data); + const fetchData = async () => { + try { + const response = await axios.get(`${gatewayUrl}/getFriends/${sessionData.username}`, { + headers: { + Authorization: `Bearer ${sessionData.token}` } - } catch (e) { - setError(e); - setSnackbarMessage(e.response.data || 'error_getting_friends') + }); + if (response.status === 200) { + setFriends(response.data); } - }; - + } catch (e) { + setError(e); + setSnackbarMessage(e.response.data || 'error_getting_friends') + } + }; + useEffect(() => { fetchData(); - // eslint-disable-next-line - }); + }, []); const handleCloseSnackbar = () => { setOpenSnackbar(false); @@ -66,6 +63,7 @@ const Friends = ({goTo}) => { }; addFriend(); + fetchData(); }; const handleInputChange = event => { @@ -90,6 +88,7 @@ const Friends = ({goTo}) => { } }; deletefriend(friend); + fetchData(); } return (
From d5f358b85c02991d9ca674258ebec165808a4de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 19:35:28 +0200 Subject: [PATCH 2/8] Endpoint_usage middleware --- gatewayservice/gateway-service.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index dd32030f..e6ecfb31 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -36,10 +36,15 @@ const memoryUsageGauge = new promClient.Gauge({ help: 'Memory usage', }); // Endpoint usage counter -const endpointCounter = new promClient.Counter({ +const endpointUsageCounter = new promClient.Counter({ name: 'endpoint_usage', help: 'Number of calls to each endpoint', - labelNames: ['endpoint'], + labelNames: ['endpoint'] +}); + +app.use((req, res, next) => { + endpointUsageCounter.inc({ endpoint: req.path }); + next(); }); if (process.env.NODE_ENV !== 'test') { From 170584bc3b881f8b6c77789704fa5f7d8906df56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 21:34:39 +0200 Subject: [PATCH 3/8] e2e added: login, play-classic, add friend and remove friend --- webapp/e2e/features/friends.feature | 10 + webapp/e2e/features/login.feature | 6 + webapp/e2e/features/play-classic.feature | 6 + webapp/e2e/steps/friends.js | 75 +++ webapp/e2e/steps/login.js | 58 ++ webapp/e2e/steps/play-classic.js | 98 +++ webapp/e2e/test-environment-setup.js | 15 +- webapp/e2e/user-model.js | 25 + webapp/package-lock.json | 719 +++++++++++++++++++++++ webapp/package.json | 1 + webapp/src/components/Friends.jsx | 1 + 11 files changed, 1009 insertions(+), 5 deletions(-) create mode 100644 webapp/e2e/features/friends.feature create mode 100644 webapp/e2e/features/login.feature create mode 100644 webapp/e2e/features/play-classic.feature create mode 100644 webapp/e2e/steps/friends.js create mode 100644 webapp/e2e/steps/login.js create mode 100644 webapp/e2e/steps/play-classic.js create mode 100644 webapp/e2e/user-model.js diff --git a/webapp/e2e/features/friends.feature b/webapp/e2e/features/friends.feature new file mode 100644 index 00000000..59543ed0 --- /dev/null +++ b/webapp/e2e/features/friends.feature @@ -0,0 +1,10 @@ +Feature: Add friend + +Scenario: The user is going to add a friend + Given An unregistered user + When I fill the data in the form, press submit, press Friends and adds a friend + Then The friend will be added +Scenario: The user is going to remove a friend + Given A registered user with one friend + When I am in Friends page and select the friend to remove + Then The friend will be removed from the user's friend list \ No newline at end of file diff --git a/webapp/e2e/features/login.feature b/webapp/e2e/features/login.feature new file mode 100644 index 00000000..c56e9864 --- /dev/null +++ b/webapp/e2e/features/login.feature @@ -0,0 +1,6 @@ +Feature: Login + +Scenario: Login + Given A registered user + When I fill the data in the form, press submit + Then The user must be logged \ No newline at end of file diff --git a/webapp/e2e/features/play-classic.feature b/webapp/e2e/features/play-classic.feature new file mode 100644 index 00000000..d0743dfe --- /dev/null +++ b/webapp/e2e/features/play-classic.feature @@ -0,0 +1,6 @@ +Feature: Play Classic Mode + +Scenario: The user is going to play classic mode + Given An unregistered user + When I fill the data in the form, press submit, press Classic Mode button and play game + Then A Game Over message should be shown in the screen \ No newline at end of file diff --git a/webapp/e2e/steps/friends.js b/webapp/e2e/steps/friends.js new file mode 100644 index 00000000..a9a2f69d --- /dev/null +++ b/webapp/e2e/steps/friends.js @@ -0,0 +1,75 @@ +const puppeteer = require('puppeteer'); +const { defineFeature, loadFeature }=require('jest-cucumber'); +const setDefaultOptions = require('expect-puppeteer').setDefaultOptions +const feature = loadFeature('./features/friends.feature'); + +let page; +let browser; + +defineFeature(feature, test => { + + beforeAll(async () => { + browser = process.env.GITHUB_ACTIONS + ? await puppeteer.launch() + : await puppeteer.launch({ headless: false, slowMo: 10 }); + page = await browser.newPage(); + //Way of setting up the timeout + setDefaultOptions({ timeout: 10000 }) + await page.setViewport({ width: 1080, height: 980 }); + + await page + .goto("http://localhost:3000", { + waitUntil: "networkidle0", + }) + .catch(() => {}); + + }); + + test('The user is going to add a friend', ({given,when,then}) => { + + let username; + let password; + + given('An unregistered user', async () => { + username = "add-friend-user" + password = "defaultpassword" + await expect(page).toClick("button", { text: "Don't have an account? Register here." }); + }); + + when('I fill the data in the form, press submit, press Friends and adds a friend', async () => { + await expect(page).toFill('input[name="username"]', username); + await expect(page).toFill('input[name="password"]', password); + await expect(page).toFill('input[name="confirmPassword"]', password); + await expect(page).toClick('button.btn', { text: '' }); + + + await expect(page).toClick('div a', { text: 'Friends' }); + await expect(page).toFill('.searchForm input', 'defaultuser'); + await expect(page).toClick('button.btn', { text: '' }); + + }); + + then('The friend will be added', async () => { + await expect(page).toMatchElement('.tableFriends', { text: 'defaultuser' }); + }); + }) + test('The user is going to remove a friend', ({given,when,then}) => { + + given('A registered user with one friend', async () => { + }); + + when('I am in Friends page and select the friend to remove', async () => { + await expect(page).toClick('.tableFriends button.btn', { text: 'Delete friend' }); + + }); + + then("The friend will be removed from the user's friend list", async () => { + await expect(page).not.toMatchElement('.tableFriends', { text: 'defaultuser' }); + }); + }) + + afterAll(async ()=>{ + browser.close() + }) + +}); \ No newline at end of file diff --git a/webapp/e2e/steps/login.js b/webapp/e2e/steps/login.js new file mode 100644 index 00000000..f02d8c2b --- /dev/null +++ b/webapp/e2e/steps/login.js @@ -0,0 +1,58 @@ +const puppeteer = require('puppeteer'); +const { defineFeature, loadFeature }=require('jest-cucumber'); +const setDefaultOptions = require('expect-puppeteer').setDefaultOptions +const feature = loadFeature('./features/login.feature'); + +let page; +let browser; + +defineFeature(feature, test => { + + beforeAll(async () => { + browser = process.env.GITHUB_ACTIONS + ? await puppeteer.launch() + : await puppeteer.launch({ headless: false, slowMo: 10 }); + page = await browser.newPage(); + //Way of setting up the timeout + setDefaultOptions({ timeout: 10000 }) + + await page + .goto("http://localhost:3000", { + waitUntil: "networkidle0", + }) + .catch(() => {}); + + + }); + + test('Login', ({given,when,then}) => { + + let username; + let password; + + given('A registered user', async () => { + username = "defaultuser" + password = "defaultpassword" + }); + + when('I fill the data in the form, press submit', async () => { + await expect(page).toFill('input[name="username"]', username); + await expect(page).toFill('input[name="password"]', password); + expect(page).toClick('button.btn', { text: '' }) + + + + }); + then('The user must be logged', async () => { + await page.waitForFunction(() => localStorage.getItem('sessionData') !== null); + const sessionData = await page.evaluate(() => localStorage.getItem('sessionData')); + expect(sessionData).toContain('token'); + + }) + }); + + afterAll(async ()=>{ + browser.close() + }) + +}); \ No newline at end of file diff --git a/webapp/e2e/steps/play-classic.js b/webapp/e2e/steps/play-classic.js new file mode 100644 index 00000000..a9ab54fb --- /dev/null +++ b/webapp/e2e/steps/play-classic.js @@ -0,0 +1,98 @@ +const puppeteer = require('puppeteer'); +const { defineFeature, loadFeature }=require('jest-cucumber'); +const setDefaultOptions = require('expect-puppeteer').setDefaultOptions +const feature = loadFeature('./features/play-classic.feature'); + +let page; +let browser; + +defineFeature(feature, test => { + + beforeAll(async () => { + browser = process.env.GITHUB_ACTIONS + ? await puppeteer.launch() + : await puppeteer.launch({ headless: false, slowMo: 10 }); + page = await browser.newPage(); + //Way of setting up the timeout + setDefaultOptions({ timeout: 10000 }) + + await page + .goto("http://localhost:3000", { + waitUntil: "networkidle0", + }) + .catch(() => {}); + await page.setRequestInterception(true); + page.on("request", (req) => { + if (req.method() === "OPTIONS") { + req.respond({ + status: 200, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers": "*", + }, + }); + } else if (req.url().includes("/questions")) { + req.respond({ + status: 200, + headers: { + "Access-Control-Allow-Origin": "*", + }, + contentType: "application/json", + body: JSON.stringify( + { + question: "question", + incorrects: [ + "answer 1", + "answer 2", + "answer 3" + ], + correct: "correct", + }, + ), + }); + } else { + req.continue(); + } + }); + + + }); + + test('The user is going to play classic mode', ({given,when,then}) => { + + let username; + let password; + + given('An unregistered user', async () => { + username = "play-classic-user" + password = "defaultpassword" + await expect(page).toClick("button", { text: "Don't have an account? Register here." }); + }); + + when('I fill the data in the form, press submit, press Classic Mode button and play game', async () => { + await expect(page).toFill('input[name="username"]', username); + await expect(page).toFill('input[name="password"]', password); + await expect(page).toFill('input[name="confirmPassword"]', password); + + await expect(page).toClick('button.btn', { text: '' }); + + + await expect(page).toClick('button.btn', { text: 'Classic Game' }); + for(let i = 0; i <10; i++) { + await expect(page).toClick('ul li span'); + await expect(page).toClick('.botoneraPreguntas div'); + } + + }); + + then('A Game Over message should be shown in the screen', async () => { + await expect(page).toMatchElement("p", { text: "Game Over" }); + }); + }) + + 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 547adcc6..f29312e2 100644 --- a/webapp/e2e/test-environment-setup.js +++ b/webapp/e2e/test-environment-setup.js @@ -1,10 +1,13 @@ const { MongoMemoryServer } = require('mongodb-memory-server'); const { default: mongoose } = require('mongoose'); +const bcrypt = require('bcrypt'); + let mongoserver; let userservice; let authservice; +let friendsservice; let gatewayservice; let questionservice; let questiongenerationservice; @@ -16,20 +19,22 @@ async function startServer() { const mongoUri = mongoserver.getUri(); process.env.MONGODB_URI = mongoUri; const connection = await mongoose.createConnection(mongoUri); - const User = await require('../../users/userservice/user-model')(connection); + const User = await require('./user-model')(connection); + userservice = await require("../../users/userservice/user-service"); authservice = await require("../../users/authservice/auth-service"); + friendsservice = await require("../../users/friendsservice/friends-service"); gatewayservice = await require("../../gatewayservice/gateway-service"); questionservice = await require("../../questionservice/question-service"); questiongenerationservice = await require("../../question_generator/questionGenerationService"); gameservice = await require("../../gameservice/game-service"); - // Add a user to the database - await User.create({ + const hashedPassword = await bcrypt.hash('defaultpassword', 10); + const user = new User({ username: 'defaultuser', - password: 'defaultpassword', + password: hashedPassword, profileImage: 'default.jpg', }); - + await user.save(); } startServer(); diff --git a/webapp/e2e/user-model.js b/webapp/e2e/user-model.js new file mode 100644 index 00000000..ffbadd9b --- /dev/null +++ b/webapp/e2e/user-model.js @@ -0,0 +1,25 @@ +const mongoose = require('mongoose'); + +const userSchema = new mongoose.Schema({ + username: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + required: true, + }, + profileImage: { + type: String, + required: true + }, + createdAt: { + type: Date, + default: Date.now, + }, +}); + +module.exports = (connection) => { + return connection.model('User', userSchema); +}; diff --git a/webapp/package-lock.json b/webapp/package-lock.json index a004ec28..21d6d8c7 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -25,6 +25,7 @@ }, "devDependencies": { "axios-mock-adapter": "^1.22.0", + "bcrypt": "^5.1.1", "expect-puppeteer": "^9.0.2", "jest": "^29.3.1", "jest-cucumber": "^3.0.1", @@ -3205,6 +3206,108 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz", @@ -5144,6 +5247,12 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "deprecated": "Use your platform's native atob() and btoa() methods instead" }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5359,6 +5468,12 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -5379,6 +5494,19 @@ } ] }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -6099,6 +6227,20 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bfj": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", @@ -6614,6 +6756,15 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -6921,6 +7072,15 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -7041,6 +7201,12 @@ "node": ">=0.8" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, "node_modules/content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -8087,6 +8253,12 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -8112,6 +8284,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -10189,6 +10370,36 @@ "node": ">=14.14" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs-monkey": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", @@ -10245,6 +10456,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -10568,6 +10819,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -15656,6 +15913,37 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -16107,6 +16395,12 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -16214,6 +16508,21 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -16273,6 +16582,18 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -23021,6 +23342,23 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", @@ -23043,6 +23381,33 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -24499,6 +24864,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -27223,6 +27617,85 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "@mongodb-js/saslprep": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz", @@ -28648,6 +29121,12 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -28803,12 +29282,28 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, "arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, "arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -29340,6 +29835,16 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "dev": true, + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, "bfj": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", @@ -29693,6 +30198,12 @@ } } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -29923,6 +30434,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -30024,6 +30541,12 @@ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -30729,6 +31252,12 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -30744,6 +31273,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -32308,6 +32843,32 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "fs-monkey": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", @@ -32345,6 +32906,42 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -32568,6 +33165,12 @@ "has-symbols": "^1.0.3" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -36440,6 +37043,33 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -36751,6 +37381,12 @@ "tslib": "^2.0.3" } }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true + }, "node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -36839,6 +37475,15 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -36882,6 +37527,18 @@ "path-key": "^3.0.0" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -41769,6 +42426,40 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "tar-fs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", @@ -42871,6 +43562,34 @@ "has-tostringtag": "^1.0.2" } }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, "widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", diff --git a/webapp/package.json b/webapp/package.json index 760423e8..8b9b988c 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -47,6 +47,7 @@ }, "devDependencies": { "axios-mock-adapter": "^1.22.0", + "bcrypt": "^5.1.1", "expect-puppeteer": "^9.0.2", "jest": "^29.3.1", "jest-cucumber": "^3.0.1", diff --git a/webapp/src/components/Friends.jsx b/webapp/src/components/Friends.jsx index 1dbf62a4..5159ea1e 100644 --- a/webapp/src/components/Friends.jsx +++ b/webapp/src/components/Friends.jsx @@ -29,6 +29,7 @@ const Friends = ({goTo}) => { }; useEffect(() => { fetchData(); + // eslint-disable-next-line }, []); const handleCloseSnackbar = () => { From 6ff49b581b0b2fe04e3ccfc55b75524723eee3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 22:03:31 +0200 Subject: [PATCH 4/8] Friends.test.js updated --- webapp/src/components/Friends.jsx | 14 ++++++++++---- webapp/src/test/Friends.test.js | 11 ++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/webapp/src/components/Friends.jsx b/webapp/src/components/Friends.jsx index 5159ea1e..c8d0b76d 100644 --- a/webapp/src/components/Friends.jsx +++ b/webapp/src/components/Friends.jsx @@ -28,8 +28,16 @@ const Friends = ({goTo}) => { } }; useEffect(() => { - fetchData(); - // eslint-disable-next-line + + const handleLoad = () => { + fetchData(); + }; + + window.addEventListener('load', handleLoad); + + return () => { + window.removeEventListener('load', handleLoad); + }; }, []); const handleCloseSnackbar = () => { @@ -64,7 +72,6 @@ const Friends = ({goTo}) => { }; addFriend(); - fetchData(); }; const handleInputChange = event => { @@ -89,7 +96,6 @@ const Friends = ({goTo}) => { } }; deletefriend(friend); - fetchData(); } return (
diff --git a/webapp/src/test/Friends.test.js b/webapp/src/test/Friends.test.js index 952d7356..1246640e 100644 --- a/webapp/src/test/Friends.test.js +++ b/webapp/src/test/Friends.test.js @@ -73,9 +73,13 @@ describe('Friends', () => { ); - mockAxios.onGet('http://localhost:8000/getFriends/testUser').reply(200, + mockAxios.onPost('http://localhost:8000/addfriend').reply(200, { friends: ['friend1'] } ); + const addButton = screen.getByText('Add friend'); + const input = screen.getByRole('textbox'); + fireEvent.change(input, { target: { value: 'friend1' } }); + fireEvent.click(addButton); // Wait for the friends to be fetched await screen.findByText('friend1'); @@ -83,9 +87,6 @@ describe('Friends', () => { mockAxios.onDelete('http://localhost:8000/deletefriend/testUser/friend1').reply(200, { friends: [] } ); - mockAxios.onGet('http://localhost:8000/getFriends/testUser').reply(200, - { friends: [] } - ); const deleteButton = screen.getByText('Delete friend'); @@ -97,5 +98,5 @@ describe('Friends', () => { expect(screen.queryByText('Friend deleted successfully')).toBeNull(); - },10000); + },20000); }); From 2372040e21c87a2a1fccedbfe1e978b4eeac16a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 22:09:57 +0200 Subject: [PATCH 5/8] i18n files updated in question_generator --- question_generator/locales/es.json | 2 +- question_generator/locales/fr.json | 63 +++++++++++++++++++ question_generator/locales/it.json | 63 +++++++++++++++++++ .../questionGenerationService.js | 2 +- 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 question_generator/locales/fr.json create mode 100644 question_generator/locales/it.json diff --git a/question_generator/locales/es.json b/question_generator/locales/es.json index aa217798..a7fe512a 100644 --- a/question_generator/locales/es.json +++ b/question_generator/locales/es.json @@ -1,7 +1,7 @@ { "Which city is higher above sea level?": "¿Qué ciudad está a mayor altitud?", "Which city has more population?": "¿Qué ciudad tiene más población?", - "Which city is in?": "¿Qué ciudad se encuentra %s?", + "Which city is in?": "¿Qué ciudad se encuentra en %s?", "Which city has an area of?": "¿Qué ciudad tiene un área de %s km2?", "Which city is governed by?": "¿Qué ciudad es gobernada por %s?", "Which city is in the time zone?": "¿Qué ciudad está en la zona horaria %s?", diff --git a/question_generator/locales/fr.json b/question_generator/locales/fr.json new file mode 100644 index 00000000..1365e571 --- /dev/null +++ b/question_generator/locales/fr.json @@ -0,0 +1,63 @@ +{ + "Which city is higher above sea level?": "Quelle ville est située à une altitude plus élevée ?", + "Which city has more population?": "Quelle ville a une population plus nombreuse ?", + "Which city is in?": "Quelle ville se trouve en %s ?", + "Which city has an area of?": "Quelle ville a une superficie de %s km2 ?", + "Which city is governed by?": "Quelle ville est gouvernée par %s ?", + "Which city is in the time zone?": "Dans quelle ville est le fuseau horaire %s ?", + + "Which autonomous community of Spain has an area of?": "Quelle communauté autonome d'Espagne a une superficie de %s km2 ?", + "Which autonomous community of Spain has a population of?": "Quelle communauté autonome d'Espagne a une population de %s ?", + "Which autonomous community of Spain has a capital called?": "Quelle communauté autonome d'Espagne a une capitale appelée %s ?", + "Which autonomous community of Spain has a president called?": "Quelle communauté autonome d'Espagne a un président appelé %s ?", + "Which autonomous community of Spain has x as the highest point?": "Quelle communauté autonome d'Espagne a %s comme point culminant ?", + + "Which planet is bigger?": "Quelle planète est plus grande ?", + "Which planet has a mass of?": "Quelle planète a une masse de %s kg ?", + "Which planet has a radius of?": "Quelle planète a un rayon de %s km ?", + "Which planet has an orbital period of?": "Quelle planète a une période orbitale de %s jours ?", + "Which planet has x as the lowest point?": "Quelle planète a %s comme point le plus bas ?", + "Which planet has x as the highest point?": "Quelle planète a %s comme point le plus élevé ?", + "Which planet has an area of x?": "Quelle planète a une superficie de %s km2 ?", + "Which planet has a density of x?": "Quelle planète a une densité de %s kg/m3 ?", + + "Who has more followers? (Tennis)": "Qui a plus de followers ? (Tennis)", + "Who has more looses? (Tennis)": "Qui a plus de défaites ? (Tennis)", + "Who has more wins? (Tennis)": "Qui a plus de victoires ? (Tennis)", + "Which tennis player is from?": "De quelle ville est originaire le joueur de tennis %s ?", + "Which tennis player has wins?": "Quel joueur de tennis a des victoires ?", + "What country is from?": "De quel pays est originaire %s ? (Tennis)", + + "Which team plays in?": "Dans quelle ville joue l'équipe %s ?", + "Which team trains?": "Dans quelle ville s'entraîne l'équipe %s ?", + "Which football team was founded in?": "Dans quelle ville l'équipe de football a-t-elle été fondée en %s ?", + "Which coach trains?": "Quel entraîneur entraîne l'équipe %s ?", + "Which is the stadium of?": "Quel est le stade de l'équipe %s ?", + + "Which f1 driver was born in?": "Dans quelle ville est né le pilote de F1 %s ?", + "Which f1 driver has more podiums?": "Quel pilote de F1 a le plus de podiums ?", + "Which f1 driver has more wins?": "Quel pilote de F1 a le plus de victoires ?", + "Which f1 driver has wins?": "Quel pilote de F1 a %s victoires ?", + + "Which song is song by?": "Quelle chanson est interprétée par %s ?", + "Which song was released in?": "Quelle chanson a été publiée en %s ?", + "Which song belongs to?": "À quel album appartient la chanson %s ?", + + "Which serie has episodes?": "Quelle série a %s épisodes ?", + "Which serie has seasons?": "Quelle série a %s saisons ?", + + "Which movie was realeased in?": "Quel film a été publié en %s ?", + "Which movie was directed by?": "Quel film a été réalisé par %s ?", + + "Which videogames has sold more units?": "Quel jeu vidéo a vendu plus d'unités ?", + "Which videogame was released in?": "Quel jeu vidéo a été publié en %s ?", + + "Which paint belongs to genre?": "À quel genre appartient la peinture %s ?", + "Which paint was painted in?": "Dans quelle année la peinture %s a-t-elle été peinte ?", + + "Which author wrote?": "Quel auteur a écrit %s ?", + "Which is the original language of?": "Quelle est la langue originale de %s ?", + "Which book is written in?": "Dans quelle langue %s est-il écrit ?", + "Which book was written by?": "Quel livre a été écrit par %s ?", + "Which book belongs to genre?": "À quel genre appartient le livre %s ?" +} diff --git a/question_generator/locales/it.json b/question_generator/locales/it.json new file mode 100644 index 00000000..c78d552a --- /dev/null +++ b/question_generator/locales/it.json @@ -0,0 +1,63 @@ +{ + "Which city is higher above sea level?": "Quale città si trova ad un'altitudine più elevata?", + "Which city has more population?": "Quale città ha una popolazione maggiore?", + "Which city is in?": "Quale città si trova in %s?", + "Which city has an area of?": "Quale città ha un'area di %s km2?", + "Which city is governed by?": "Quale città è governata da %s?", + "Which city is in the time zone?": "Quale città si trova nel fuso orario %s?", + + "Which autonomous community of Spain has an area of?": "Quale comunità autonoma della Spagna ha un'area di %s km2?", + "Which autonomous community of Spain has a population of?": "Quale comunità autonoma della Spagna ha una popolazione di %s?", + "Which autonomous community of Spain has a capital called?": "Quale comunità autonoma della Spagna ha una capitale chiamata %s?", + "Which autonomous community of Spain has a president called?": "Quale comunità autonoma della Spagna ha un presidente chiamato %s?", + "Which autonomous community of Spain has x as the highest point?" : "Quale comunità autonoma della Spagna ha %s come punto più alto?", + + "Which planet is bigger?": "Quale pianeta è più grande?", + "Which planet has a mass of?": "Quale pianeta ha una massa di %s kg?", + "Which planet has a radius of?": "Quale pianeta ha un raggio di %s km?", + "Which planet has an orbital period of?" : "Quale pianeta ha un periodo orbitale di %s giorni?", + "Which planet has x as the lowest point?" : "Quale pianeta ha %s come punto più basso?", + "Which planet has x as the highest point?" : "Quale pianeta ha %s come punto più alto?", + "Which planet has an area of x?" : "Quale pianeta ha un'area di %s km2?", + "Which planet has a density of x?" : "Quale pianeta ha una densità di %s kg/m3?", + + "Who has more followers? (Tennis)": "Chi ha più seguaci? (Tennis)", + "Who has more looses? (Tennis)": "Chi ha più sconfitte? (Tennis)", + "Who has more wins? (Tennis)": "Chi ha più vittorie? (Tennis)", + "Which tennis player is from?" : "Quale giocatore di tennis è di %s?", + "Which tennis player has wins?":"Quale giocatore di tennis ha vinto?", + "What country is from?": "Di quale paese è %s? (Tennis)", + + "Which team plays in?": "Quale squadra gioca a %s?", + "Which team trains?": "Quale squadra si allena a %s?", + "Which football team was founded in?": "Quale squadra di calcio è stata fondata nel %s?", + "Which coach trains?": "Quale allenatore allena %s?", + "Which is the stadium of?": "Quale è lo stadio di %s?", + + "Which f1 driver was born in?": "Quale pilota di F1 è nato a %s?", + "Which f1 driver has more podiums?": "Quale pilota di F1 ha più podi?", + "Which f1 driver has more wins?": "Quale pilota di F1 ha più vittorie?", + "Which f1 driver has wins?": "Quale pilota di F1 ha %s vittorie?", + + "Which song is song by?": "Quale canzone è cantata da %s?", + "Which song was released in?": "Quale canzone è stata pubblicata nel %s?", + "Which song belongs to?": "A quale artista appartiene la canzone %s?", + + "Which serie has episodes?": "Quale serie ha %s episodi?", + "Which serie has seasons?": "Quale serie ha %s stagioni?", + + "Which movie was realeased in?": "Quale film è stato rilasciato nel %s?", + "Which movie was directed by?": "Quale film è stato diretto da %s?", + + "Which videogames has sold more units?": "Quale videogioco ha venduto più unità?", + "Which videogame was released in?": "Quale videogioco è stato rilasciato nel %s?", + + "Which paint belongs to genre?":"A quale genere appartiene il dipinto %s?", + "Which paint was painted in?": "Quale dipinto è stato dipinto nel %s?", + + "Which author wrote?": "Quale autore ha scritto %s?", + "Which is the original language of?": "Quale è la lingua originale di %s?", + "Which book is written in?": "Quale libro è scritto originariamente in %s?", + "Which book was written by?": "Quale libro è stato scritto da %s?", + "Which book belongs to genre?": "A quale genere appartiene il libro %s?" +} diff --git a/question_generator/questionGenerationService.js b/question_generator/questionGenerationService.js index 7f825d12..b1720f82 100644 --- a/question_generator/questionGenerationService.js +++ b/question_generator/questionGenerationService.js @@ -16,7 +16,7 @@ const app = express(); const port = 8003; i18n.configure({ - locales: ['en', 'es'], + locales: ['en', 'es', 'fr', 'it'], directory: './locales', defaultLocale: 'en', cookie: 'lang', From 68653bdbabf649eea79b15db516e28126f4a8330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 22:22:24 +0200 Subject: [PATCH 6/8] eslint-disable-next-line --- webapp/src/components/Friends.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/webapp/src/components/Friends.jsx b/webapp/src/components/Friends.jsx index c8d0b76d..99660fab 100644 --- a/webapp/src/components/Friends.jsx +++ b/webapp/src/components/Friends.jsx @@ -38,6 +38,7 @@ const Friends = ({goTo}) => { return () => { window.removeEventListener('load', handleLoad); }; + //eslint-disable-next-line }, []); const handleCloseSnackbar = () => { From 547b2783b21048c7c63011e7f74edf3e37796d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 22:58:00 +0200 Subject: [PATCH 7/8] e2e tests updated --- webapp/e2e/steps/close-session-steps.js | 2 +- webapp/e2e/steps/friends.js | 2 +- webapp/e2e/steps/i18n-steps.js | 20 +++++++++++++++----- webapp/e2e/steps/infinite-mode-steps.js | 6 ++++-- webapp/e2e/steps/login.js | 2 +- webapp/e2e/steps/play-classic.js | 4 +++- webapp/e2e/steps/register-form.steps.js | 2 +- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/webapp/e2e/steps/close-session-steps.js b/webapp/e2e/steps/close-session-steps.js index 8a095c98..c53a1ea4 100644 --- a/webapp/e2e/steps/close-session-steps.js +++ b/webapp/e2e/steps/close-session-steps.js @@ -11,7 +11,7 @@ defineFeature(feature, test => { beforeAll(async () => { browser = process.env.GITHUB_ACTIONS ? await puppeteer.launch() - : await puppeteer.launch({ headless: false, slowMo: 100 }); + : await puppeteer.launch({ headless: false, slowMo: 50 }); page = await browser.newPage(); //Way of setting up the timeout setDefaultOptions({ timeout: 10000 }) diff --git a/webapp/e2e/steps/friends.js b/webapp/e2e/steps/friends.js index a9a2f69d..5c594a09 100644 --- a/webapp/e2e/steps/friends.js +++ b/webapp/e2e/steps/friends.js @@ -11,7 +11,7 @@ defineFeature(feature, test => { beforeAll(async () => { browser = process.env.GITHUB_ACTIONS ? await puppeteer.launch() - : await puppeteer.launch({ headless: false, slowMo: 10 }); + : await puppeteer.launch({ headless: false, slowMo: 50 }); page = await browser.newPage(); //Way of setting up the timeout setDefaultOptions({ timeout: 10000 }) diff --git a/webapp/e2e/steps/i18n-steps.js b/webapp/e2e/steps/i18n-steps.js index 9d82d821..700f6b6d 100644 --- a/webapp/e2e/steps/i18n-steps.js +++ b/webapp/e2e/steps/i18n-steps.js @@ -11,7 +11,7 @@ defineFeature(feature, test => { beforeAll(async () => { browser = process.env.GITHUB_ACTIONS ? await puppeteer.launch() - : await puppeteer.launch({ headless: false, slowMo: 10 }); + : await puppeteer.launch({ headless: false, slowMo: 50 }); page = await browser.newPage(); //Way of setting up the timeout setDefaultOptions({ timeout: 10000 }) @@ -23,7 +23,7 @@ defineFeature(feature, test => { .catch(() => {}); }); - test('The user is going to try different languages', ({given,when,then}) => { + test('The user is going to try different languages', async ({given,when,then}) => { let username; let password; @@ -38,25 +38,35 @@ defineFeature(feature, test => { await expect(page).toFill('input[name="username"]', username); await expect(page).toFill('input[name="password"]', password); await expect(page).toFill('input[name="confirmPassword"]', password); - + await page.waitForSelector('button.btn', { text: '' }); await expect(page).toClick('button.btn', { text: '' }); - + await page.waitForSelector('span', { text: "Classic Game" }); await expect(page).toMatchElement("span", { text: "Classic Game" }); + await page.waitForSelector('button.menuLeft', { text: '' }); await expect(page).toClick('button.menuLeft', { text: '' }); + await page.waitForSelector('div.languageButton', { text: '' }); await expect(page).toClick('div.languageButton', { text: '' }); + await page.waitForSelector('li', { text: 'Spanish' }); await expect(page).toClick('li', { text: 'Spanish' }); }); then('A Classic Game message should be shown in different languages', async () => { - await expect(page).toMatchElement("span", { text: "Juego Clásico" }); + await page.waitForSelector('div.languageButton', { text: '' }); await expect(page).toClick('div.languageButton', { text: '' }); + await page.waitForSelector('li', { text: 'Italiano' }); await expect(page).toClick('li', { text: 'Italiano' }); await expect(page).toMatchElement("span", { text: "Gioco Classico" }); + + await page.waitForSelector('div.languageButton', { text: '' }); + await expect(page).toClick('div.languageButton', { text: '' }); + await page.waitForSelector('li', { text: 'Francese' }); + await expect(page).toClick('li', { text: 'Francese' }); + await expect(page).toMatchElement("span", { text: "Jeu classique" }); }); }) diff --git a/webapp/e2e/steps/infinite-mode-steps.js b/webapp/e2e/steps/infinite-mode-steps.js index 947d87ba..fb1dc9dd 100644 --- a/webapp/e2e/steps/infinite-mode-steps.js +++ b/webapp/e2e/steps/infinite-mode-steps.js @@ -11,7 +11,7 @@ defineFeature(feature, test => { beforeAll(async () => { browser = process.env.GITHUB_ACTIONS ? await puppeteer.launch() - : await puppeteer.launch({ headless: false, slowMo: 10 }); + : await puppeteer.launch({ headless: false, slowMo: 50 }); page = await browser.newPage(); //Way of setting up the timeout setDefaultOptions({ timeout: 10000 }) @@ -41,13 +41,15 @@ defineFeature(feature, test => { await expect(page).toClick('button.btn', { text: '' }); + await page.waitForSelector('button.btn', { text: 'Infinite Mode' }); await expect(page).toClick('button.btn', { text: 'Infinite Mode' }); + await page.waitForSelector('div.endGameButton', { text: '' }); await expect(page).toClick('div.endGameButton', { text: '' }); }); then('A Game Over message should be shown in the screen', async () => { - await expect(page).toMatchElement("p", { text: "Game Over" }); + await page.waitForSelector('p', { text: 'Game Over' }); }); }) diff --git a/webapp/e2e/steps/login.js b/webapp/e2e/steps/login.js index f02d8c2b..282260ba 100644 --- a/webapp/e2e/steps/login.js +++ b/webapp/e2e/steps/login.js @@ -11,7 +11,7 @@ defineFeature(feature, test => { beforeAll(async () => { browser = process.env.GITHUB_ACTIONS ? await puppeteer.launch() - : await puppeteer.launch({ headless: false, slowMo: 10 }); + : await puppeteer.launch({ headless: false, slowMo: 50 }); page = await browser.newPage(); //Way of setting up the timeout setDefaultOptions({ timeout: 10000 }) diff --git a/webapp/e2e/steps/play-classic.js b/webapp/e2e/steps/play-classic.js index a9ab54fb..4575cfdd 100644 --- a/webapp/e2e/steps/play-classic.js +++ b/webapp/e2e/steps/play-classic.js @@ -80,14 +80,16 @@ defineFeature(feature, test => { await expect(page).toClick('button.btn', { text: 'Classic Game' }); for(let i = 0; i <10; i++) { + await page.waitForSelector('ul li span'); await expect(page).toClick('ul li span'); + await page.waitForSelector('.botoneraPreguntas div', { visible: true, enabled: true }); await expect(page).toClick('.botoneraPreguntas div'); } }); then('A Game Over message should be shown in the screen', async () => { - await expect(page).toMatchElement("p", { text: "Game Over" }); + await page.waitForSelector('p', { text: 'Game Over' }); }); }) diff --git a/webapp/e2e/steps/register-form.steps.js b/webapp/e2e/steps/register-form.steps.js index 163d9a65..5ac50232 100644 --- a/webapp/e2e/steps/register-form.steps.js +++ b/webapp/e2e/steps/register-form.steps.js @@ -11,7 +11,7 @@ defineFeature(feature, test => { beforeAll(async () => { browser = process.env.GITHUB_ACTIONS ? await puppeteer.launch() - : await puppeteer.launch({ headless: false, slowMo: 10 }); + : await puppeteer.launch({ headless: false, slowMo: 50 }); page = await browser.newPage(); //Way of setting up the timeout setDefaultOptions({ timeout: 10000 }) From b4927b70d99c08211160748b31cd4434d34a2fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20M=C3=A9ndez=20Murias?= Date: Fri, 26 Apr 2024 23:08:12 +0200 Subject: [PATCH 8/8] e2e test errors solved --- webapp/e2e/steps/friends.js | 14 +++++++++++++- webapp/e2e/steps/i18n-steps.js | 6 ------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/webapp/e2e/steps/friends.js b/webapp/e2e/steps/friends.js index 5c594a09..0f215ab5 100644 --- a/webapp/e2e/steps/friends.js +++ b/webapp/e2e/steps/friends.js @@ -37,14 +37,25 @@ defineFeature(feature, test => { }); when('I fill the data in the form, press submit, press Friends and adds a friend', async () => { + await page.waitForSelector('input[name="username"]'); await expect(page).toFill('input[name="username"]', username); + + await page.waitForSelector('input[name="password"]'); await expect(page).toFill('input[name="password"]', password); + + await page.waitForSelector('input[name="confirmPassword"]'); await expect(page).toFill('input[name="confirmPassword"]', password); - await expect(page).toClick('button.btn', { text: '' }); + await page.waitForSelector('button.btn'); + await expect(page).toClick('button.btn', { text: '' }); + await page.waitForSelector('div a'); await expect(page).toClick('div a', { text: 'Friends' }); + + await page.waitForSelector('.searchForm input'); await expect(page).toFill('.searchForm input', 'defaultuser'); + + await page.waitForSelector('button.btn'); await expect(page).toClick('button.btn', { text: '' }); }); @@ -59,6 +70,7 @@ defineFeature(feature, test => { }); when('I am in Friends page and select the friend to remove', async () => { + await page.waitForSelector('.tableFriends button.btn'); await expect(page).toClick('.tableFriends button.btn', { text: 'Delete friend' }); }); diff --git a/webapp/e2e/steps/i18n-steps.js b/webapp/e2e/steps/i18n-steps.js index 700f6b6d..6d79e950 100644 --- a/webapp/e2e/steps/i18n-steps.js +++ b/webapp/e2e/steps/i18n-steps.js @@ -61,12 +61,6 @@ defineFeature(feature, test => { await page.waitForSelector('li', { text: 'Italiano' }); await expect(page).toClick('li', { text: 'Italiano' }); await expect(page).toMatchElement("span", { text: "Gioco Classico" }); - - await page.waitForSelector('div.languageButton', { text: '' }); - await expect(page).toClick('div.languageButton', { text: '' }); - await page.waitForSelector('li', { text: 'Francese' }); - await expect(page).toClick('li', { text: 'Francese' }); - await expect(page).toMatchElement("span", { text: "Jeu classique" }); }); })