I am trying to use a library from GitHub found here: https://github.com/cubing/jsss
the readMe has an example of how to use it:
// index.html
<script src="index.js" type="module" defer></script>
<select id="eventID">
<option value="333" selected>3x3x3</option>
<option value="444">4x4x4</option>
</select>
<button id="new-scramble">New scramble</button><br>
<div id="scramble-string"></div>
// index.js
import { randomScrambleStringForEvent } from "scrambles";
const eventSelect = document.querySelector("#eventID");
const scrambleStringElem = document.querySelector("#scramble-string");
async function newScramble() {
scrambleStringElem.textContent += " ⏳";
const scrambleString = await randomScrambleStringForEvent(eventSelect.value);
scrambleStringElem.textContent = scrambleString;
}
document.querySelector("#eventID").addEventListener("change", newScramble);
document.querySelector("#new-scramble").addEventListener("click", newScramble);
newScramble(); // Initial scramble
The repo is full of so many folders I am not sure which ones I need. I used the src to and put this in a folder called libs with but I have no idea if this is right. I tried using the whole repo and it still didn't work. Whenever I try following the "full example" that they have I get an error. As someone who has never done this before:
Where do I put the index.js file
what files do I need to copy to my project to make this work
Putting index.html and index.js in the root directory I get the error
'Uncaught TypeError: Failed to resolve module specifier "scrambles". Relative references must start with either "/", "./", or "../".'
When adding the correct directory to scrambles, I get the error
'Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.'
In short I have no idea what I am doing and no idea how to use this in my project, please help...
Related
I'm working on a react.js website where I'm supposed to call a javascript function in index.html. I'm experiencing some difficulties in calling the function.
This is what I'm doing in index.html
<head>
<script>
const getVar = getVarFromJs()
</script>
</head>
but whenever I do this, I get an error saying getVarFromJs is not defined. I also tried importing the function then I get an error saying "cannot use statement outside a module".
This is my js file:
let var = {};
export function getVarFromJs()
{return var;}
When I change the script type to module in index.html, I get this error:
Failed to load module script: Expected a Javascript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
I am just getting started with TypeScript (and front end development in general) coming from a c# background so sorry if this is a really basic question, but I can't figure out where I'm going wrong...
What I'm trying to do for now is create a really basic program to retrieve some sample data from a url in JSON format, parse to TS classes, and display it on the page.
In order to get the json response I found this answer that recommends using a node package. I got it installed and it seems to be ok (at least TS doesn't give me any errors).
I also figured out that I need to compile (not sure if that's the right term?) with Browserify to make it browser compatible since it's using a node module. I did that but now when I try to run in a browser it's telling me my method is not defined.
export class Keynote {
KeyValue: string;
Description: string;
Parent: string;
}
Retrieval class is:
import {Keynote} from "./Keynote";
import * as request from "request-promise-native";
function GetKeynotes(): Array<Keynote> {
const baseUrl = 'https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteProvider.php';
var options = {uri: baseUrl};
const result = JSON.parse(request.get(options));
return result;
}
and html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Keynotes Testing</title>
<script src="bundle.js"></script>
<script>
function Retrieve() {
var notes = GetKeynotes();
document.getElementById('container').innerText = JSON.stringify(notes);
}
</script>
</head>
<body>
<div>
<button content="Get some notes" onclick="Retrieve()">Get some notes</button>
</div>
<div id="container">
</div>
</body>
</html>
Browserify is really long so I didn't want to copy here but you can see it at https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteDisplay.html in the source if you want.
When I click the button I get this error in the browser:
KeynoteDisplay.html:9 Uncaught ReferenceError: GetKeynotes is not defined
at Retrieve (KeynoteDisplay.html:9)
at HTMLButtonElement.onclick (KeynoteDisplay.html:16)
Retrieve # KeynoteDisplay.html:9
onclick # KeynoteDisplay.html:16
GetKeynotes is defined in my typescript, and on the 5th line of bundle.js I see a function with that name... Why is it undefined?
UPDATE
Ok I have played with jspm and SystemJs but I still don't have something right. I referenced the module with jspm and did a bundle to build.js and uploaded the whole thing just to make sure everything is there. Here are the tags in my html for scripts:
<script src="../../jspm_packages/system.js"></script>
<script src="../../config.js"></script>
<script src="build.js"></script>
<script>
System.import("Sandbox/TypeScript/build.js")
function Retrieve() {
System.import("Sandbox/TypeScript/build.js")
var notes = GetKeynotes();
document.getElementById('container').innerText = JSON.stringify(notes);
}
</script>
When I press the button I can debug in my function, but it still gives the error, 'GetKeynotes is not defined' just like before... Again I can see a function with that name in the build.js file so I don't understand why it's not finding it.
I also tried System.import("Sandbox/TypeScript/KeynoteRetrieval.js") but it gives the error:
Uncaught (in promise) Error: (SystemJS) Node tls module not supported in browsers.
Error loading https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteRetrieval.js
My app works fine when i deploy it and run it in a browser
I can successfully reach all my controllers/services. and they were linked together via submodules.
I used submodules to organize the states/routes better for ui-router. (Previously we had ALL of our states in the app dot js file. There were like 50. Now they're organized out into smaller modules).
app.js [Module file]
var phpApp = angular.module("phpApp",
[
"ui-router"
"phpApp.components" , ...
]).config(...).run(...);
components.js [Module file, contains states/routes]
var ComponentModule = angular.module("phpApp.components",
[
"ui-router"
"phpApp.components.user" ,
"phpApp.components.client"
...
]).config(...).run(...);
user.js [Module file, contains states/routes]
var UserModule = angular.module("phpApp.components.user",
[
"ui-router"
]).config(...).run(...);
user-controller.js // LOADS fine; is a controller.
angular.module('phpApp.components').controller('UserController', ....);
client-controller.js // does NOT load! Cannot find 'phpApp.components' module...
angular.module('phpApp.components').controller('ClientController', ...);
My index.html file loads the scripts in this order:
<script src="app.js"></script>
<script src="components/components-module.js"></script>
<script src="components/user/user-module.js"></script>
<script src="components/client/client-module.js"></script>
...
<script src="components/user/user-controller.js"></script>
<script src="components/client/**client-controller.js**"></script>
I dont get it. My client-controller loads AFTER my user-controller... yet it is not able to locate the proper module?
I get the error:
Uncaught Error: [$injector:nomod] Module 'phpApp.components'
is not available! You either misspelled the module name or
forgot to load it.
I am very confused and frustrated at this point. I am not sure where I am going wrong.
The answer lies in the karma config file (karma.conf.js by default)
The answer, as expected, was a simple one.
I had a rule to include all JavaScript files:
"app/app.js",
"app/components/**/*.js",
You will need to make sure you rewrite your load rules to load all module JS files first:
"app/app.js",
"app/components/**/*-module.js", <-- modules must load first
"app/components/**/*.js",
To help expound, i have my project set up where:
1) controllers are in their respective xxx-controller.js files,
2) ervices are in xxx-service.js files and
3) modules are in xxx-module.js files
I'm trying to add unit testing for JavaScript into my web site. I use VS2013 and my project is an ASP.NET web site.
Based on recommendations (http://www.rhyous.com/2013/02/20/creating-a-qunit-test-project-in-visual-studio-2010/) I've done so far:
Created new ASP.NET app
Imported QUnit (using NuGet)
Into "Scripts" added links to js-file in my original web site (files PlayerSkill.js - containts PlayerSkill class and trainings.js - contains Trainer and some other classes)
Created new folder "TestScripts"
Added TrainingTests.js file
Wrote simple test:
test( "Trainer should have non-empty group", function () {
var group = "group";
var trainer = new Trainer(123, "Name123", group, 123);
EQUAL(trainer.getTrainerGroup(), group);
});
Notice: my trainings.js file among others contains
function Trainer(id, name, group, level) {
...
var _group = group;
this.getTrainerGroup = function () { return _group ; }
};
When I execute my test I see error: Trainer is not defined.
It looks like reference to my class is not recognized. I feel like linking file is not enough, but what did I miss?
Please help add reference to the original file with class and run unit test.
Thank you.
P.S. Question 2: Can I add reference to 2 files (my unit test will require one more class which is in another file)? How?
You should add all the relevant logic of your application to your unit testing file so they all execute before you run your tests
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Test Results</title>
<link rel="stylesheet" href="/Content/qunit.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="/Scripts/qunit.js"></script>
<script src="/Scripts/PlayerSkill.js"></script>
<script src="/Scripts/trainings.js"></script>
<script src="/TestScripts/TrainingTests.js"></script>
</body>
</html>
You should not use linked files because they will not exist physically in the script folder.
If you really want to use them you should let the Visual Studio intellisense resolve the physical path of the file like this.
Type the script tag <script src=""></script>
Place the cursor inside the quotes in the src attribute and press CTRL + SPACE
Search your files and let the resolved path untouched
If your project location changes you must update the linked files and also the script references.
{Edit1}
Solution 2:
You could also use an MVC Controller and a Razor View to create your unit testing page and the linked files will work as expected with the only issue that you will have an extra controller in your project but this is not bad at all if for example you want to test the loading of content using ajax that is by default blocked by the browser if they are run from a local file.
Solution 3:
You can also setup a new MVC project just for your javascript unit testing just as you usually setup a new project for any server side code and this will help to prevent your testing to interfere with your production code
{Edit 2}
Solution 4:
As part of the javascript ecosystem you could use grunt or gulp to automate the copy of your scripts from anywhere to your project before running the tests. You could write a gulpfile.js like this
var sourcefiles = [/*you project file paths*/];
gulp.task('default', function () {
return gulp.src(sourcefiles).pipe(gulp.dest('Scripts'));
});
And then run it opening a console and running the command gulp or gulp default
Looks like trainings.js is not defined when calling TrainingTests.js . See this question for more details regarding why this happens! Once that is fixed it does work. And yes similar to trainings.js you can have any number of files in any folder as long as you reference them properly. I have created a sample fiddle accessible # http://plnkr.co/edit/PnqVebOzmPpGu7x2qWLs?p=preview
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="http://code.jquery.com/qunit/qunit-1.18.0.js"></script>
<script src="trainings.js"></script>
<script src="TrainingTests.js"></script>
</body>
In my case I wanted to run my tests from within my ASP.NET web application, and also on a CI server. In addition to the other information here I needed the following, otherwise I experienced the same error as the OP on my CI server:
Add one or more require() calls to test scripts.
Set the NODE_PATH environment variable to the root of my application.
Example of require()
Within my test scripts I include a requires block, the conditional allows me to use this script from a web browser without needing to adopt a third-party equivalent such as requirejs (which is convenient.)
if (typeof(require) !== 'undefined') {
require('lib/3rdparty/dist/3p.js');
require('js/my.js');
require('js/app.js');
}
Example of setting NODE_PATH
Below, 'wwwroot' is the path of where /lib/ and other application files are located. My test files are located within /tests/.
Using bash
#!/bin/bash
cd 'wwwroot'
export NODE_PATH=`pwd`
qunit tests
Using powershell
#!/usr/bin/pwsh
cd 'wwwroot'
$env:NODE_PATH=(pwd)
qunit tests
This allowed me to run tests both within my ASP.NET web application, and also from a CI server using a script.
HTH.
If you're wondering how to make your tests see your code when running from command line (not from browser!), here is a bit expanded version of Shaun Wilson's answer (which doesn't work out-of-the-box, but contains a good idea where to start)
Having following structure:
project
│ index.js <--- Your script with logic
└───test
tests.html <--- QUnit tests included in standard HTML page for "running" locally
tests.js <--- QUnit test code
And let's imagine that in your index.js you have following:
function doSomething(arg) {
// do smth
return arg;
}
And the test code in tests.js (not that it can be the whole content of the file - you don't need anything else to work):
QUnit.test( "test something", function( assert ) {
assert.ok(doSomething(true));
});
Running from command line
To make your code accessible from the tests you need to add two things to the scripts.
First is to explicitly "import" your script from tests. Since JS doesn't have sunch a functionality out-of-the box, we'll need to use require coming from NPM. And to keep our tests working from HTML (when you run it from browser, require is undefined) add simple check:
// Add this in the beginning of tests.js
// Use "require" only if run from command line
if (typeof(require) !== 'undefined') {
// It's important to define it with the very same name in order to have both browser and CLI runs working with the same test code
doSomething = require('../index.js').doSomething;
}
But if index.js does not expose anything, nothing will be accessible. So it's required to expose functions you want to test explicitly (read more about exports). Add this to index.js:
//This goes to the very bottom of index.js
if (typeof module !== 'undefined' && module.exports) {
exports.doSomething = doSomething;
}
When it's done, just type
qunit
And the output should be like
TAP version 13
ok 1 Testing index.js > returnTrue returns true
1..1
# pass 1
# skip 0
# todo 0
# fail 0
Well, due to help of two answers I did localize that problem indeed was in inability of VS to copy needed file into test project.
This can be probably resolved by multiple ways, I found one, idea copied from: http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
Solution is simple: add tag dynamically
In order to achieve this, I've added the following code into tag:
<script>
var fileref = document.createElement('script');
fileref.setAttribute("type", "text/javascript");
var path = 'path'; // here is an absolute address to JS-file on my web site
fileref.setAttribute("src", path);
document.getElementsByTagName("head")[0].appendChild(fileref);
loadjscssfile(, "js") //dynamically load and add this .js file
</script>
And moved my tests into (required also reference to jquery before)
$(document).ready(function () {
QUnit.test("Test #1 description", function () { ... });
});
Similar approach also works for pure test files.
I was following along to this post by Rebecca Murphey: http://blog.rebeccamurphey.com/scaffolding-a-buildable-dojo-application
I was substituting her file structure with my own.
Running the normal version of the scripts works fine, but the moment I compile them using the build tool, the script errors.
It's very likely a small problem with how the files are referenced via my Profile.js script but maybe someone here can help me get the settings correct before running the build tool so the compiled files will work as they should.
My file structure is as follows...
/www
/Assets
/Scripts
/Classes
build.sh
Init.js
Load.js
Profile.js
/Dojo
Dojo.js
/dojo-sdk
index.html
My index.html file has the following code...
<script>
var djConfig = {
modulePaths : {
'Integralist' : '../Classes'
}
};
</script>
<script src="Assets/Scripts/Dojo/Dojo.js"></script>
<script>
dojo.require('Integralist.Init');
</script>
...and the Init.js file has the following code...
dojo.provide('Integralist.Init');
dojo.require('Integralist.Load');
dojo.declare('MyApp', null, {
constructor: function(config) {
this.version = config.version || '1.0';
this.author = config.author || 'Unknown';
}
});
var myapp = new MyApp({
author: 'Mark McDonnell'
});
alert(myapp.author);
alert(myapp.version);
...lastly, the Load.js file has nothing in it but this...
dojo.provide('Integralist.Load');
alert('I\'m the Load.js file');
...and this all runs fine. When I load index.html I get 3 alert messages, brilliant.
The problem occurs when I try to run the build tool.
Via Mac OSX i locate the /Classes/ directory and run 'sh build.sh' and the build.sh file within the /Classes/ directory consists of the following code...
cd ../../../dojo-sdk/util/buildscripts
./build.sh profileFile=../../../Assets/Scripts/Classes/Profile.js releaseDir=../../../Assets/Scripts/Release
...now, after running the build tool I have a new /Release/ directory created within my /Scripts/ directory, this /Release/ directory consists of...
/www
/Assets
/Scripts
/Release
/Integralist
/Classes
Init.js
Init.js.uncompressed.js
/dojo
--loads of dojo related files--
...I then created a separate index file called index-release-version.html and changed the script code as suggested by the article, so it looks like this...
<script src="Assets/Scripts/Release/Integralist/dojo/dojo.js"></script>
<script>
dojo.require('Integralist.Init');
</script>
...from here I get the following error...
Failed to load resource: the server responded with a status of 404 (Not Found)
Uncaught Error: Could not load 'Integralist.Init'; last tried '../Integralist/Init.js'
...and just for reference my Profile.js file that is used by the build tool consists of the following (and it's here I think the problem may be)...
dependencies = {
stripConsole : 'all',
action : 'clean,release',
optimize : 'shrinksafe',
releaseName : 'Integralist',
localeList : 'en-gb',
layers: [
{
name: "../Classes/Init.js",
resourceName : "Integralist.Init",
dependencies: [
"Integralist.Init"
]
}
],
prefixes: [
[ "Integralist", "../Classes" ]
]
}
Any help really appreciated as I desperately want to get my head around how Dojo works :-)
Thanks!
M.
I'd suggest working from the repo I linked to from my blog post (http://github.com/rmurphey/dojo-scaffold) -- I double-checked that it's definitely working :) -- and make changes to it until your changes break something, rather than trying to create your own structure right off the bat.
At a glance, I'm not 100% clear why you've got a Dojo.js file inside your directory structure, (is this the base Dojo lib or something else?), but the rest of Dojo is located elsewhere. If you use the structure I proposed, you can safely remove the djConfig declaration when using the built files, but as Dan mentioned, you may need to keep it if you're using a different configuration.
Do you have that djConfig variable in your index-release-version.html? It looks like Dojo is trying to find init.js at ../Integralist/Init.js, but you somehow need to tell it to look in ../Classes/Init.js
This is what your modulePaths : {'Integralist' : '../Classes'} was doing in your Index.html