Tell us what’s happening:
My problem is that the 7th test doesn’t pass. I made sure that NODE_ENV=test is on, and I tested my code and also checked other peoples’ codes on my local host setup(I’m not sure if they work on gitpod or not), although all the functional tests(that I created) pass on mocha. I checked every other solution on the forum(except for really old ones) and didn’t find the answer to my problem. This is what fcc console says: “actual: false
-
expected: true
-
message: “expected false to be true”
-
operator: “strictEqual”
-
showDiff: true
-
stack: “AssertionError: expected false to be true\n at eval (eval at #a (https://www.freecodecamp.org/js/test-runner/5.4.1/dom-test-evaluator.js:2:255051), :5:10)\n at async #a (https://www.freecodecamp.org/js/test-runner/5.4.1/dom-test-evaluator.js:2:255391)\n at async DOMTestEvaluator.handleMessage (https://www.freecodecamp.org/js/test-runner/5.4.1/dom-test-evaluator.js:2:256100)”
-
[[Prototype]]: Error”.
My server.js code:
'use strict';
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const helmet = require('helmet');
const apiRoutes = require('./routes/api.js');
const fccTestingRoutes = require('./routes/fcctesting.js');
const runner = require('./test-runner');
const app = express();
app.use(helmet());
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'"],
imgSrc: ["'self'"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
upgradeInsecureRequests: true
}
}));
app.use(express.json());
app.use('/public', express.static(process.cwd() + '/public'));
app.use(cors({origin: '*'})); //For FCC testing purposes only
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//Index page (static HTML)
app.route('/')
.get(function (req, res) {
res.sendFile(process.cwd() + '/views/index.html');
});
//For FCC testing purposes
fccTestingRoutes(app);
//Routing for API
apiRoutes(app);
//404 Not Found Middleware
app.use(function(req, res, next) {
res.status(404)
.type('text')
.send('Not Found');
});
//Start our server and tests!
const listener = app.listen(process.env.PORT || 3000, function () {
console.log('Your app is listening on port ' + listener.address().port);
if(process.env.NODE_ENV==='test') {
console.log('Running Tests...');
setTimeout(function () {
try {
runner.run();
} catch(e) {
console.log('Tests are not valid:');
console.error(e);
}
}, 3500);
}
});
module.exports = app; //for testing
My sample.env code:
PORT=3000
NODE_ENV=test
My api.js code:
'use strict';
const fetch = require('node-fetch');
const express = require('express');
const crypto = require('crypto');
const likesDB = {};
function anonymizeIP(ip) {
if (!ip) return 'unknown';
return crypto.createHash('sha256').update(ip).digest('hex');
}
async function getRealPrice(symbol) {
const url = `https://stock-price-checker-proxy.freecodecamp.rocks/v1/stock/${symbol}/quote`;
const response = await fetch(url);
const data = await response.json();
return parseFloat(data.latestPrice);
}
module.exports = function (app) {
app.route('/api/stock-prices')
.get(async function (req, res){
const ip = req.ip || req.headers['x-forwarded-for'];
const anonymizedIP = anonymizeIP(ip);
const stock = req.query.stock;
const like = req.query.like === 'true';
if (!stock) {
return res.status(400).json({ error: 'Missing stock parameter' });
}
const stocks = Array.isArray(stock) ? stock.map(s => s.toUpperCase()) : [stock.toUpperCase()];
try {
const stockData = await Promise.all(stocks.map(async (symbol) => {
const price = await getRealPrice(symbol);
if (!likesDB[symbol]) {
likesDB[symbol] = new Set();
}
if (like && !likesDB[symbol].has(anonymizedIP)) {
likesDB[symbol].add(anonymizedIP);
}
return {
stock: symbol,
price,
likes: likesDB[symbol].size
}
}));
if (stockData.length === 2) {
return res.json({
stockData: stocks.map(symbol => {
const current = stockData.find(s => s.stock === symbol);
const other = stockData.find(s => s.stock !== symbol);
return {
stock: current.stock,
price: current.price,
rel_likes: current.likes - other.likes
}
})
});
}
res.json({ stockData: stockData[0] });
} catch (e) {
console.error('Error fetching stock data:', e.message);
res.status(500).json({ error: 'Failed to fetch stock price' });
}
});
};
My functional tests’ code:
const chaiHttp = require('chai-http');
const chai = require('chai');
const assert = chai.assert;
const server = require('../server');
chai.use(chaiHttp);
describe('Functional Tests', function() {
this.timeout(5000);
it('Viewing one stock: GET request to /api/stock-prices/', function(done) {
chai.request(server).keepOpen().get('/api/stock-prices').query({ stock: 'GOOG' })
.end(function(err, res) {
assert.equal(res.status, 200);
assert.property(res.body, 'stockData');
assert.isObject(res.body.stockData);
assert.equal(res.body.stockData.stock, 'GOOG');
assert.isNumber(res.body.stockData.price);
assert.isNumber(res.body.stockData.likes);
done();
});
})
it('Viewing one stock and liking it: GET request to /api/stock-prices/', function(done) {
chai.request(server).keepOpen().get('/api/stock-prices').query({ stock: 'GOOG',
like: true
})
.end(function(err, res) {
assert.equal(res.status, 200);
assert.property(res.body, 'stockData');
assert.equal(res.body.stockData.stock, 'GOOG');
assert.isNumber(res.body.stockData.likes);
done();
});
})
it('Viewing the same stock and liking it again: GET request to /api/stock-prices/', function(done) {
chai.request(server).keepOpen().get('/api/stock-prices').query({ stock: 'GOOG',
like: true
})
.end(function(err, res) {
assert.equal(res.status, 200);
assert.property(res.body, 'stockData');
assert.equal(res.body.stockData.stock, 'GOOG');
done();
});
})
it('Viewing two stocks: GET request to /api/stock-prices/', function(done) {
chai.request(server).keepOpen().get('/api/stock-prices').query({ stock: ['GOOG', 'MSFT'] })
.end(function(err, res) {
assert.equal(res.status, 200);
assert.property(res.body, 'stockData');
assert.isArray(res.body.stockData);
assert.lengthOf(res.body.stockData, 2);
res.body.stockData.forEach(stock => {
assert.isString(stock.stock);
assert.isNumber(stock.price);
assert.isNumber(stock.rel_likes);
})
done();
});
})
it('Viewing two stocks and liking them: GET request to /api/stock-prices/', function(done) {
chai.request(server).keepOpen().get('/api/stock-prices').query({ stock: ['GOOG', 'MSFT'],
like: true
})
.end(function(err, res) {
assert.equal(res.status, 200);
assert.property(res.body, 'stockData');
assert.isArray(res.body.stockData);
assert.lengthOf(res.body.stockData, 2);
res.body.stockData.forEach(stock => {
assert.isString(stock.stock);
assert.isNumber(stock.price);
assert.isNumber(stock.rel_likes);
})
done();
});
})
});
Is there an issue with my code? Should I restructure or remake something in it? Is it an issue with the fcc?
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Challenge Information:
Information Security Projects - Stock Price Checker