Running a js file with node is giving me an "HTMLDivElement" is not defined. Do i need to import it, or is that specific to browsers outside of Node? - node.js

I was trying to run some tests, but needed test data, so i created a generation file which created dummy html. When I attempt to run it though, it gives me a Reference Error: HTMLDivElement is not defined.
Is there something I need to import such that Node knows what HTMLDivElement is? I am not rendering anything, but just want correct data to pipe into follow on code.
I run my file through TSC, and then run it through node.
Sample Code:
const main = () => {
let root = new HTMLDivElement();
}
main();
Edit:
I was trying to just bypass it with: let root = document.createElement("div"); but node does not understand what document is, so I cant seem to get that running either as a fallback.

Indeed, Node.js doesn't come with a DOM implementation. If you want to run tests that use the DOM, you'll need to either load a Node.js-compatible DOM implementation such as jsdom, or if that doesn't meet your requirements, switch to a browser-based testing environment such as Selenium.

Related

Does organizing code in multiple modules that require the same package decrease performance in Node.js?

I'm working with Node.js and Puppeteer, I'm using Puppeteer to scrape multiple websites. I'm thinking of organizing the code by separating each site implementation to its own file. So I will have like example.com.js example2.com.js etc
each of this will will require the same module(puppeteer/jsdom) and will export an object that contains variables and functions. This way, I can import all of these modules in the index.js file.
I've read about Nodejs caching modules and that this way of organizing of code is standard, however, in my case, if say I have 100 different website that I want to scrape, so I will have 100 module that will require (puppeteer/jsdom) in each one of them, so if Nodejs is caching the modules, I'm still using 100 different variables to store the modules.
const puppeteer = require('puppeteer');
So I'll have this line of code in 100 files, even if Nodejs is caching Puppeteer module, I'm still creating 100 puppeteer variable where I could have created just one if I wrote all code in a single file.
Am I missing something here ?
From the official document here
Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.
You're correct about "Nodejs is caching Puppeteer module", but "I'm still creating 100 puppeteer variable" isn't true. So, I would say, don't worry :), you can continue to organize your code in multiple files.
For example, if this is your setup:
// a.js
const puppeteer = require('puppeteer');
// b.js
const puppeteer = require('puppeteer');
// c.js
const a = require('./a.js');
const b = require('./b.js');
The following will happen;
File a.js is required
The module puppeteer is being parsed and referenced by the variable puppeteer inside the file.
File b.js is required
Also creates a reference to puppeteer, but the module has already been parsed and executed, so it is 'cached'
Doing this won't cause a performance issue, regarding the import of the same module multiple times.
Regarding your statement
I'm still creating 100 puppeteer variable
As mentioned above, you're only creating references, the contents won't be deeply cloned.

Retrieve file contents during Gatsby build

I need to pull in the contents of a program source file for display in a page generated by Gatsby. I've got everything wired up to the point where I should be able to call
// my-fancy-template.tsx
import { readFileSync } from "fs";
// ...
const fileContents = readFileSync("./my/relative/file/path.cs");
However, on running either gatsby develop or gatsby build, I'm getting the following error
This dependency was not found:
⠀
* fs in ./src/templates/my-fancy-template.tsx
⠀
To install it, you can run: npm install --save fs
However, all the documentation would suggest that this module is native to Node unless it is being run on the browser. I'm not overly familiar with Node yet, but given that gatsby build also fails (this command does not even start a local server), I'd be a little surprised if this was the problem.
I even tried this from a new test site (gatsby new test) to the same effect.
I found this in the sidebar and gave that a shot, but it appears it just declared that fs was available; it didn't actually provide fs.
It then struck me that while Gatsby creates the pages at build-time, it may not render those pages until they're needed. This may be a faulty assessment, but it ultimately led to the solution I needed:
You'll need to add the file contents to a field on File (assuming you're using gatsby-source-filesystem) during exports.onCreateNode in gatsby-node.js. You can do this via the usual means:
if (node.internal.type === `File`) {
fs.readFile(node.absolutePath, undefined, (_err, buf) => {
createNodeField({ node, name: `contents`, value: buf.toString()});
});
}
You can then access this field in your query inside my-fancy-template.tsx:
{
allFile {
nodes {
fields { content }
}
}
}
From there, you're free to use fields.content inside each element of allFile.nodes. (This of course also applies to file query methods.)
Naturally, I'd be ecstatic if someone has a more elegant solution :-)

How to use `index.js` in a Node.js when creating an Express service?

Hi I am structuring my Node.js project based on this, like so:
Root
product name
index.js: (contains requires for the product and the main export)
productName.js: contains application logic
test
test1.js
test2.js
...
Now I have two questions
What should logically go in index.js? At the moment I have this (would this be a good way to do things and what else might I include in index.js?):
// index.js
var myServer = require('./myServer.js'); // "product name" = "myServer"
module.exports = {
run: myServer.listen
}
Does it matter what I call the object key in module.exports (currently "run")? Why does the server always run when I execute index.js with $ node index.js how does it automatically know to run myServer.listen?
P.S.: I am aware of web structure auto-generation tools, I just wish to understand the logical reason for this suggested structure (the idea of not having any logic in index.js)
As you mentioned this is a Express service, if it is only handling backend of some application or more specifically this is only backend application, I would suggest you change name of your index.js to server.js(Thus explicitly stating that it'll process all service requests).
But if not then even index.js is fine.
Now for
1
What you've put is absolutely fine, apart from this you could require all modules, routes(or controllers whatever you name them) in a way that it serves as entry point to your application. Try not to put any logic in here.
2
Actually the server runs because it executes the script in the file called index.js, the script says myServer.listen, now if you had written console.log("Hello World") and used $ node index.js it would've printed Hello World instead.
Node just expects and executes script that is there in index.js, in your case it is to start the server.
About the logic that why not put anything else in index.js, for me the reasoning I consider good enough is it provides abstraction as it is the entry point I don't want index.js to worry about things like what to do with this data and all. I believe it should provide a base to setup server. Thus following single responsibility to some extent. Also I won't have to touch it ever in projects lifetime unless some major change occurs e.g. I decide to shift from express to something else.
EDIT
Why have a key called run
You seem to have answered it yourself(in comments), you are giving or more proper description would be you're attaching an object to module.exports as it is a object similar to JSON it was supposed to have a key(which could be anything not necessarily run it could've been hii). Now if you don't want to pass a key and export only one thing that is server.listen then you could write same as module.exports = myServer.listen; instead of
module.exports = {
hii: myServer.listen
}
Note that you could export more modules using the way you did. For more details about module.exports refer this or better google about it as this link might expire anytime and does not seem an ideal thing to put on SO.

webdriver-sync running asynchronously?

I'm trying to create selenium tests that run each step synchronously, without using .then(), or async/await. The reason for this is that I want to create a set of functions that allow pretty much anyone on our test team, almost regardless of tech skills to write easy to read automated tests. It looks to me like webdriver-sync should give me exactly what I want. However, the following dummy code is producing problems:
var wd = require('webdriver-sync');
var By = wd.By;
var Chromedriver = wd.Chromedriver;
var driver = new Chromedriver;
driver.get('https://my.test.url');
var myButton = driver.findElement(By.cssSelector('[id*=CLICK_ME]'));
myButton.click();
It tries to run - browser is launched, and page starts to load... but the steps are not executed synchronously - it goes on and tries to find and click "myButton" before the page has finished loading, throwing a "no such element" error... which to me kinda defeats the point of webdriver-sync?! Can someone tell me where I am going wrong?
FWIW, I have webdriver-sync 1.0.0, node v7.10.0, java 1.8.0_74, all running on CentOS 7.
Thanks in advance!
You need to put double-quotes around "CLICK_ME" as it's a string value.
Generally, though, it's a good idea to Wait for specific elements because dynamic pages are often "ready" before all their elements have been created.

Using Lucid outside of AdonisJS controller

I'm building a project with AdonisJS, and I want to build it as a modular, two-part application: The AdonisJS server runs a control panel, and a custom script outside that server runs an IRC bot. I've been trying to load Lucid into the second script so that I can interface with my database, but it only ever returns an empty object, {}. Some things to note:
I've made sure my database is populated.
I've tested code in my controllers that works and fetches results as expected.
The secondary script boots up all the same parts of Adonis as server.js, sans the actual HTTP server.
I have tried attaching this script to an HTTP server but it made no difference.
I have also tried creating raw QueryBuilder objects with the same results.
Here's the least amount of code I can put together as an example:
#!/usr/bin/node
'use strict'
const fs = require('fs')
const bootstrap = require('./bootstrap/bot')
bootstrap(() =>
{
const AppConfig = use('AppConfig')
const Settings = use('App/Model/Settings')
const get_settings = function * () {
yield Settings.all()
}
console.log(get_settings())
})
console.log() prints {}, even though the same code called within a controller prints all entries from the settings table. bootstrap/bot.js is almost an exact replica of bootstrap/http.js. The only difference is that it doesn't start an HTTP server.
I've scoured the source code looking for things that might happen between starting the server and running controller code to see if there's something critical I'm missing, but I'm lost.
Does anyone know how I can use my Lucid models outside the confines of AdonisJS controllers?
It's because your function is a generator and you can only call a generator with the yield keyword.
So your console.log() should looks like console.log(yield get_settings()).
You may use the package co to create the root generator function.
bootstrap(co(function * () {
// ...
}))

Resources