Making grunt-mocha works with requirejs - requirejs

Running the following Mocha tests in a browser works, but when I use grunt mocha in the command line, I get Warning: PhantomJS timed out. I have turned the gruntfile mocha.options.run to false, because, if true, the requirejs do not have the time to run.
Sadly, I cannot find any complete sample on the matter.
the gruntfile contains:
mocha: {
test: {
src: ['tests/index.html']
},
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Mocha Test</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" type="text/css" charset="utf-8" />
</head>
<body>
<div id="mocha"></div>
<script src="../node_modules/mocha/mocha.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
mocha.setup('bdd');
</script>
<script src="../node_modules/chai/chai.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var expect = chai.expect;
</script>
<script data-main="requireRunner.js" src="../vendor/require-2.1.9.js"></script>
</body>
</html>
requireRunner:
require.config({
baseUrl: '/',
paths: {
'jquery' : '../vendor/jquery-2.0.3',
'underscore' : '../vendor/underscore-1.5.2',
'backbone' : '../vendor/backbone-1.1.0'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
}
},
urlArgs: 'bust=' + (new Date()).getTime()
});
require([
'tests/models/todoTest'
], mocha.run
);
todoTest
define(['js/models/todo'], function(Todo) {
describe('Todo', function(){
var todo;
before(function() {
todo = new Todo();
})
it('defaults are ok', function(){
expect(todo.get('title')).to.equal('');
expect(todo.get('completed')).to.be.false;
})
})
})
todo
/*global define*/
define([
'underscore',
'backbone'
], function (_, Backbone) {
'use strict';
var TodoModel = Backbone.Model.extend({
// Default attributes for the todo
// and ensure that each todo created has `title` and `completed` keys.
defaults: {
title: '',
completed: false
}
});
return TodoModel;
});

Multiple little things to make it work properly:
paths seem to be more tolerant on the browser, path problem can occur only on grunt-mocha (this is not a problem, just a reminder)
running grunt mocha is not enough, grunt server mocha is the way, a server has to be up
using options:{log: true} combined with requirejs debugging traces in the index.html is good help

Your post has helped me to set up my grunt-mocha task ! Thx
I had de turn false the mocha.options.run, otherwise grunt-mocha handled no tests (guess requirejs had not time to load as you said)
however I did not have to set up any server to make it works.
Running grunt mocha is plenty enough !
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FdP - Tests</title>
<link rel="stylesheet" href="../app/vendor/mocha/mocha.css"/>
</head>
<body>
<div id="mocha"></div>
<script src="../app/vendor/mocha/mocha.js"></script>
<script src="../app/vendor/chai/chai.js"></script>
<script>
mocha.setup('bdd');
chai.should();
</script>
<script data-main="specRunner.js" src="../app/vendor/requirejs/require.js"></script>
</body>
</html>
my mocha task
mocha: {
test: {
src: ['test/index.html']
}
}
specRunner.js
...
function (testSuite) {
'use strict';
require(testSuite.specs, function () {
mocha.run();
});
...
Grunt-mocha version : 0.4.7

I think may be there is some files include error in you test html file. you can go to folder of your html file, double click the file, if test case can run normally in browser, then grunt-mocha can run it too. So, maybe the problem is something like require.js not found.

Related

How setup react-helmet with Server Side Rendering?

I've been trying to setup react-helmet with server-side-rendering. I followed the docs and some blog posts on how to setup react-helmet with SSR, but have been unable to produce the desired results. Here's a code snippet of how I'm rendering the App:
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './src/App';
const express = require('express');
const app = express();
app.get('*', (req, res) => {
const app = renderToString(<App />);
const helmet = Helmet.renderStatic();
res.send(formatHTML(app, helmet));
})
function formatHTML(appStr, helmet) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
</head>
<body>
<div id="root">
${ appStr }
</div>
<script src="./bundle.js"></script>
</body>
</html>
`
}
When I run the above code, I get an error saying 'cannot use import statement outside a module'. Is it possible to use both es5 and es6 syntax at the same time? Or is there is better way to setup React-helmet?
This is my babel configuration file
{
"presets": [
[
"#babel/preset-env",
{
"modules": false
}
],
"#babel/preset-react",
"#babel/preset-flow"
],
"env": {
"development": {
"only": [
"app",
"internals/scripts"
],
"plugins": [
"#babel/plugin-transform-react-jsx-source"
]
},
"production": {
"only": [
"app"
],
"plugins": [
"transform-react-remove-prop-types",
"#babel/plugin-transform-react-constant-elements",
"#babel/plugin-transform-react-inline-elements"
]
},
"test": {
"plugins": [
"#babel/plugin-transform-modules-commonjs",
"dynamic-import-node"
]
}
},
"compact": true,
"plugins": [
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-syntax-import-meta",
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-json-strings",
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"#babel/plugin-proposal-function-sent",
"#babel/plugin-proposal-export-namespace-from",
"#babel/plugin-proposal-numeric-separator",
"#babel/plugin-proposal-throw-expressions",
"#babel/plugin-proposal-export-default-from",
"#babel/plugin-proposal-logical-assignment-operators",
"#babel/plugin-proposal-optional-chaining",
[
"#babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/plugin-proposal-do-expressions",
"#babel/plugin-proposal-function-bind",
"lodash"
]
}
You need to wrap your server using #babel/register.
This is how I handle that for my TypeScript CRA projects without ejecting.
NOTICE: I use this method to inject metadata into index.html vs render the whole app (some components I use don’t play well with SSR).
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js
"use strict"
require("ignore-styles")
require("#babel/register")({
ignore: [/(node_modules)/],
presets: [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-typescript",
],
extensions: [".tsx"],
cache: false,
})
require("./server")
server.js (excerpt)
const indexPath = path.join(__dirname, "build/index.html")
const middleware = async (req, res, next) => {
let context = {}
let html = renderToString(
React.createElement(StaticRouter, {
location: req.url,
context: context,
})
)
const helmet = Helmet.renderStatic()
if (context.url) {
res.redirect(context.url)
} else if (!fs.existsSync(indexPath)) {
next("Site is updating... please reload page in a few minutes.")
} else {
let index = fs.readFileSync(indexPath, "utf8")
let status = 200
if (typeof context.status === "number") {
status = context.status
}
return res.status(status).send(
index
.replace('<div id="root"></div>', `<div id="root">${html}</div>`)
.replace("</head>", `${helmet.meta.toString()}</head>`)
.replace("</head>", `${helmet.title.toString()}</head>`)
.replace("</head>", `${helmet.script.toString()}</head>`)
)
}
}
server.get("/", middleware)
server.use(express.static(path.join(__dirname, "build")))
server.get("*", middleware)

Is there a way to parcel a nodejs app which uses express and ejs?

I am trying to parcel my nodejs app which uses epxress and ejs but I am getting a parcel error during the process
My app already runs as expected if I use the standard way:
node app.js
However, when I try to run it with parcel I am getting an error.
my package.json (showing only relevant parts):
"scripts": {
"start": "parcel views/index.ejs",
"build": "parcel build --public-url . views/index.ejs"
},
"dependencies": {
"parcel-plugin-ejs": "^0.2.0",
"parcel-plugin-ejs-template": "^0.1.1",
},
"devDependencies": {
"parcel-bundler": "^1.12.3"
}
this is how I am rendering the page:
router.get("/" , function(req, res) {
(async () => {
const client = await pool.connect()
try {
const result = await client.query('select id, name from mytable')
res.render("index", {
items: result.rows
})
} finally {
client.release()
}
})().catch(e => console.error(e.stack))
});
and my index.ejs file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My website</title>
</head>
<body>
<div class="menu">
<% items.forEach(function(row){ %>
<div class="item" data-value="<%= row.id %>"> <%= row.name %></div>
<% }) %>
</div>
.
.
.
.
</body>
</html>
I would expect my app to be be parceled successfully and to be able to access it through the url provided.
However, I am getting this error:
$ npm run start
> my_project#1.0.0 start /home/user/my_project
> parcel views/index.ejs
Server running at http://localhost:1234
🚨 /home/user/my_project/views/index.ejs: items is not defined
at eval (eval at compile (/home/user/my_project/node_modules/ejs/lib/ejs.js:618:12), <anonymous>:5:8)
at returnedFn (/home/user/my_project/node_modules/ejs/lib/ejs.js:653:17)
at EjsAsset.generate (/home/user/my_project/node_modules/parcel-plugin-ejs-template/EjsAsset.js:30:12)
at <anonymous>
Where items is just a list of products that I am sending from back-end with res.render() in order to create a drop-down.
Any help would be appreciated.
maybe if you change the parts of the start and build scripts where you have views/index.ejs for index.ejs

"Target container is not a DOM element." When Running Webpack server

I have recently switched from using 'npm start' script that comes with create-react-app to Weback's 'npm run build' and then running the server. After slowly getting all the dependencies working I got my bundle to complete building. However, when I use 'npm start' the server starts and nothing shows up on my website.
I tried inputting <div id="root"> into my .html file in my "public" directory, but it didn't work. I then found out Webpack created a second for me? Either way placing a <div> or even a <script> in either one doesn't work.
I have updated all of my dependencies for react so that the ReactDOM could render peacefully. my React code worked perfectly before I switched to webpack so I'm sure it's not a problem with my index.js and whatever it imports.
I'm convinced it's a problem in webpack, but I've tried plenty of different presets in webpack.config.js and can't seem to find any that works (I have forgotten the ones I've tried so I will take any suggestions).
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: './main.js',
path: path.resolve(__dirname, '/dist')
},
plugins: [new webpack.ProgressPlugin(), new HtmlWebpackPlugin(), new webpack.IgnorePlugin(/^pg-native$/)],
module: {
rules: [
{
test: /.(js|jsx)$/,
include: [path.resolve(__dirname, 'src')],
loader: 'babel-loader',
options: {
plugins: [
'syntax-dynamic-import'
],
presets: [
'#babel/preset-env',
'#babel/preset-react',
{
'plugins': ['#babel/plugin-proposal-class-properties']
}
]
}
},
{
test:/\.(s*)css$/,
use:['style-loader','css-loader', 'sass-loader']
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
loader: 'url-loader?limit=100000'
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},
chunks: 'async',
minChunks: 1,
minSize: 30000,
name: true
}
},
node: {
fs: 'empty'
}
,
devServer: {
open: true
}
};
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import App from './App.js';
import * as serviceWorker from './serviceWorker';
let state = {};
window.setState = (changes) => {
state = Object.assign({}, state, changes);
ReactDOM.render(
<App {...state}/>,
document.getElementById('root')
);
}
/* eslint no-restricted-globals: 0*/
let initialState = {
name: 'Name Test',
location: location.pathname.replace(/^\/?|\/$/g, "")
};
window.setState(initialState);
serviceWorker.unregister();
<!-- .HTML created by Webpack -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
<!-- .HTML created by create-react-app (before webpack)-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Skedge</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
when I go into the web console this shows up as an error -
Uncaught Invariant Violation: Target container is not a DOM element.
at invariant (webpack:///./node_modules/react-dom/cjs/reactdom.development.js?:55:15)
at Object.render (webpack:///./node_modules/react-dom/cjs/reactdom.development.js?:21151:36)
at eval (webpack:///./src/index.js?:35:50)
at Module../src/index.js (http://localhost:8080/main.js:3970:1)
at webpack_require (http://localhost:8080/main.js:20:30)
at eval (webpack:///multi_(webpack)-dev-server/client?:2:18)
at Object.0 (http://localhost:8080/main.js:4015:1)
at webpack_require (http://localhost:8080/main.js:20:30)
at http://localhost:8080/main.js:84:18
at http://localhost:8080/main.js:87:10
It says it doesn't understand the ReactDOM.render() function.
I even threw in a <h1>Test</h1> to see if it was my code but it still bugged out, so I'm sure it's something in my webpack.config.js that isn't right but I just can't figure out what.
Edit
I gave up on using webpack, I undid my npm eject and went back to just using npm start.

formvalidation v1.3.0 not working with requirejs

I have the following code that is currently WORKING code
Form:
<form id="demoForm" method="POST">
// bootstrap form...
</form>
on page Script:
<script src="~/scripts/Framework/jquery-3.3.1.min.js"></script>
<script src="~/scripts/Framework/bootstrap-4/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.3/es6-shim.min.js"></script>
<script src="~/scripts/Plugins/formvalidation-1.3.0/js/FormValidation.full.min.js"></script>
<script src="~/script/Plugins/formvalidation-1.3.0/js/plugins/Bootstrap.min.js"></script>
<script src="~/script/Plugins/formvalidation-1.3.0/js/plugins/J.min.js"></script>
<script>
$(function(){
$('#demoFrom').formValidation({
plugins: {
declarative: new FormValidation.plugins.Declarative({ html5Input: true }),
trigger: new FormValidation.plugins.Trigger(),
bootstrap: new FormValidation.plugins.Bootstrap(),
submitButton: new FormValidation.plugins.SubmitButton(),
icon: new FormValidation.plugins.Icon({
valid: 'fa fa-check',
invalid: 'fa fa-times',
validating: 'fa fa-refresh'
})
}
});
});
</script>
But when I try with requirejs its not. The NOT WORKING code below:
<script src="~/scripts/Framework/require.js" data-main="~/scripts/app.js">
App.js:
require.config({
baseUrl: '/Scripts/',
paths: {
jquery: 'Framework/jquery-3.3.1.min',
bootstrap:'Framework/bootstrap-4/js/bootstrap.bundle.min',
es6Shim: 'Framework/es6-shim.min',
fvMain: 'Plugins/formvalidation-1.3.0/js/FormValidation.full.min',
fvBootstrap: 'Plugins/formvalidation-1.3.0/js/plugins/Bootstrap.min',
fvJQuery: 'Plugins/formvalidation-1.3.0/js/plugins/J.min'
},
shim: {
jquery: {
exports: '$'
},
bootstrap: {
deps:['jquery']
},
fvBootstrap: {
deps: ['es6Shim', 'fvMain','fvJQuery']
}
}
});
require(['jquery', 'bootstrap'],
function ($) {
//... some other tasks
require[('fvBootstrap'), function(){
$('#demoFrom').formValidation({
plugins: {
declarative: new FormValidation.plugins.Declarative({ html5Input: true }),
trigger: new FormValidation.plugins.Trigger(),
bootstrap: new FormValidation.plugins.Bootstrap(),
submitButton: new FormValidation.plugins.SubmitButton(),
icon: new FormValidation.plugins.Icon({
valid: 'fa fa-check',
invalid: 'fa fa-times',
validating: 'fa fa-refresh'
})
}
});
});
});
in the requirejs code I am getting the error "FormValidation is not defined"
I have tried to contact the developer with this issue without any luck. Can anyone help me on this, please?
Check your imports again, i guess you are including this library but actually you don't have it in your directory.
check this import
<script src="~/scripts/Plugins/formvalidation-1.3.0/js/FormValidation.full.min.js"></script>

Angular2 XHR error(404 Not Found) while loading main.js

I use gulp to watch typescript files and I store translated .js files in public/js. Whenever I start my project, angular2 doesn't work, because of this error:
Cannot get main.js
Here is the Error that I'm getting.
system.config.js
(function (global) {
System.config({
paths: {
'npm:': 'node_modules/'
},
map: {
app: 'public/js',
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
packages: {
app: {
main: './main',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
index.ejs
(I'm using express and all files below are loaded correctly).
<head>
<title>Chat room</title>
<link rel="stylesheet" href="/css/index.css">
<script src="/systemjslib/system.src.js"></script>
<script src="/systemjsconf"></script>
<script src="/shimlib/shim.min.js"></script>
<script src="/zonelib/zone.js"></script>
<script src="/rxjslib/Reflect.js"></script>
</head>
<body>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
<my-app>Loading AppComponent content here ...</my-app>
</body>
main.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var platform_browser_dynamic_1 = require("#angular/platform-browser-dynamic");
var app_module_1 = require("./app.module");
platform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule);
Project files structure
I would really appreciate some help. Thanks in advance. If I missed out some files that are important, let me know I will edit this post, I really need this fixed.

Resources