Why should we not just replace beforeAll(function(){ let foo = 'test' }) with let foo = 'test' ? What's the purpose of beforeAll if the second way is fine?
Here's the official definition by the way: The beforeAll function executes once and only once for the describe block containing it, before any of the beforeEach functions or any of the specs.
There are some substantial differences between beforeAll block and plain code in the scope of describe function.
beforeAll setup is supposed to be coupled with afterAll teardown.
Errors in before* blocks are not critical and won't prevent the list of specs from being populated and specs from being run. An error in describe block will result in empty list of specs.
before* and it blocks have this as the context of current spec which can be used as recommended way to share data between blocks. It is generally more preferable than plain variables from parent scope because there's no risk to cross-contaminate tests this way. describe function doesn't have this context. However, this approach isn't compatible with ES6 arrow functions.
There may be Jasmine helpers that are supposed to be work in conjunction with before* and it blocks, e.g. in Angular testing:
beforeAll(fakeAsync(() => {
asyncInitializationThatDoesntNeedDoneCallback();
}));
If it is a constant that should be defined for the entire block, then it can surely be defined without beforeAll:
describe('...', () => {
const foo = 'test'; // not let
...
});
Related
In the following React-Application, I am using a JS-Feature to declare a function within a function and call it on a certain event:
export default function App() {
OnClick = (input) => { //Why is no var/let needed
//do something...
}
return (<button onClick={this.OnClick}/>); //and it is called like this
}
My resulting questions are:
How is the "feature"/"notation" called? - it seems weird not to use var/let/const
In which ES-Version was it introduced?
Does it only work with Lambda-Functions?
How is the "feature" called? - it seems weard not to use var/let/const
I call it The Horror of Implciit Globals. OnClick gets created as a global variable, not a local one. I don't think it has an official name. A less opinionated one might be "implicit global variable creation." :-)
In wich ES-Version was it introduced?
Before ECMAScript version 1. I think it was in the very first version of JavaScript ever in 1995.
Does it only work with Lambda-Functions?
No, you can do this with any value. OnClick = 42 would also "work."
But don't. Again, it creates a global, not a local. Instead, declare your variables.
Use const for your example (or let if you prefer). I also recommend using JavaScript modules ("ESM" or "ECMAScript" modules), because code in modules is in strict mode and assigning to an undeclared identifier is the error it always should have been in strict mode. If you don't want to use JavaScript modules, add "use strict"; to the top of your files to put them in strict mode.
Here's a demonstration of the fact it creates a global:
function example(value) {
OnClick = () => {
console.log(value);
};
}
example(42);
OnClick(); // Logs 42
console.log(typeof window.OnClick); // "function"
My code is like below...
describe('The Home Page',() =>{
before(()=>{
cy.fixture('WorkHours').then(function(data){
this.xxx = data
cy.log(this.xxx.weekDate+'..One')
})
})
it( 'checkNavis',() =>{
cy.log(this.xxx.weekDate+'..two')
cy.visit('/')
Gets an error ....[Cypress Log]
why dose it not referring to global variable?
could not be synchronization problem since waiting for promises??
since xxx is a declared global, shouldn't be scope??
this is related but doesn't give me a clue to identify problem...
Cypress - Typescript - How can i make my fixture variables global?
In your tests or hooks you cannot access aliases using this.* using arrow functions.
This is most likely because when this is used in an arrow functions it will have the same value as the context in which the arrow function was created (ie. undefined). The classic function () has its own this which is has global access.
Another example of this behaviour is in mocha. It has a restriction on the use of arrow functions.
Instead try:
describe('The Home Page',() =>{
before(function() {
cy.fixture('WorkHours').then(function(data){
this.xxx = data
cy.log(this.xxx.weekDate+'..One')
})
})
it('checkNavis', function() {
cy.log(this.xxx.weekDate + '..two')
cy.visit('/')
I'm using Meteor and am writing unit tests for a Collection. I've got Helper methods for the collection in addition to just regular JS functions.
I.e.
Collection.helpers({
helperFn: function () {
return 'foo';
}
});
//And in the same file
function bar() {
return "bar";
}
Then in my tests file I have something like
import { Collection } from '../collections'
//Use Factory or Stub to create test Document
//This then works just fine and I can assert, etc..
testDoc.helperFn
My question is with wanting to test just the regular 'bar' JS function. This isn't a big deal using ES6 classes because then I can just export the whole class and call any function with an instance of it. But with Meteor I'm finding the only way I can access the function is by using the 'export' keyword.
So in my Collection file
export function bar ({ return bar; });
And now in my test file I'd do something like
import { bar } from '../collection'
I'd rather not add an export statement for every time I test a new function. Is there any way around this or is it not a big deal?
I do think that the export/import is the way to go, but to answer the first part of your question: yes, you can fall back to the original scoping of meteor and put these functions in the global scope of meteor as follows:
do not put your files in the imports/ folder, but into another folder in your project, e.g., server/.
defined the functions as:
bar = function() { /* function body */ }
These variables are interpreted by meteor as being global to the project, and hence do not need to be imported before use.
That said, there was a reason meteor introduced the imports/ folder and corresponding export/import paradigm in version 1.3. It avoids polluting the global scope and makes it much easier to see where things are defined.
In each spec I have beforeEach and afterEach statements. Is it possible to add it somehow globally to avoid code duplication between specs ?
Purpose of beforeEach() and afterEach() functions are to add a block of repetitive code that you would need to execute every time you start or complete executing each spec(it). There are other ways to add generalised code to avoid code repetition, here are few -
If you have a piece of code that you would require to run only once before starting a test suite(describe), then you can use beforeAll() and afterAll() functions that jasmine provides.
If you want to run a piece of code that you want to run only once when the execution starts before starting all the test scripts, then add it in your onPrepare() and onComplete() function.
If you want to add a piece of code that should run even before protractor has started instantiating itself or after it has shut itself down, then use beforeLaunch and afterLaunch.
So it all depends on the scenario that you want to use them in. Hope it helps.
My team has the same desire, to run bits of boilerplate code at the start of every test file. From the discussion here, it doesn't sound like there are hooks to globally add to the beforeEach(), afterEach(), etc.
However, we do use the onPrepare() function to abbreviate the amount of before/after boilerplate code that gets repeated in each spec file. Below is a beforeAll() example, but the pattern could be used for beforeEach()/afterEach(). In this case, we're setting up test users in the database with a DataSeeder class, which we do in the outer-most describe() block in every spec file. (I'm also leaving in my catchProtractorErrorInLocation pattern, because it's super useful for us.)
In protractor.conf.ts add boilerplate code to browser.params object.
onPrepare: function () {
...
const browser = require('protractor').browser;
// Define the ConsoleHelper & DataSeeder instances, which will be used by all tests.
const DataSeeder = require('./e2e/support/data-seeder.js');
browser.params.dataSeeder = new DataSeeder();
browser.catchProtractorErrorInLocation = (error, location) => {
throw new Error(`Error in ${location}\n ${error}`);
};
browser.catchProtractorErrorInBeforeAll = (error) => browser.catchProtractorErrorInLocation(error, 'beforeAll()');
// Return a promise that resolves when DataSeeder is connected to service and ready to go
return browser.params.dataSeeder.waitForConnect();
},
With that in place, we can easily do beforeAll() setup code in an abbreviated set of lines.
beforeAll(() => {
return browser.params.dataSeeder.createTestUsers()
.catch(browser.catchProtractorErrorInBeforeAll);
});
You obviously need to do different things in your setup, but you can see how the pattern can apply.
I have been writing modules in nodejs as following :
module.exports = function (logger, db, external,constants) {
return {
//something
}
}
Recently someone in my team suggested that whole script should be wrapped in a function to avoid global confusion of variables i.e. like this :
(function () {
'use strict';
module.exports = function (logger, db, external,constants) {
return {
//something
}
}
}());
I understand that this practice is generally used at client side code. But during server side in nodejs is this required? I think that in nodejs there is really no global scope and only module.exports is the one which is accessible really irrespective of whatever we write in script file (ofcourse don't go wild over here).
No, IIFEs aren't required with Node.js.
They can be useful for any scripts that may be used in multiple environments (UMD).
But, each module/file executed by Node.js is given a "module scope," similar to the scope an IIFE provides, as described under "Globals":
In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a global variable. In Node this is different. The top-level scope is not the global scope; var something inside a Node module will be local to that module.
Though, there is still a global scope with Node.js. When a module creates a global, it will be accessible in other modules used by the same process.
foo = 'bar'; // lack of `var` defines a global
console.log(global.foo); // 'bar'
You're actually already doing this.
What he's suggesting is to wrap the entire script in a function like this:
function () {
}
That's all. Nothing special. Of course, in regular javascript a function definition just defines a function and the code inside the function doesn't run. So to automatically run the function you wrap it in an expression context and invoke it:
(function () {
})()
However, in node.js you don't need to do this. Instead you can simply call the function when you require the module. So in node.js, this does the exact same thing in terms of creating a private scope:
module.exports = function () {
}
So tell your friend you're already wrapping the entire script in a function.
This is perhaps the first case that I see the harm in naming things and design patterns. In this case your friend is thinking IIFE. But IIFE is nothing special. IIFE doesn't create a private scope. It's functions that create scope. IIFE is just a means for the function to call itself. Which is why I prefer calling it self-calling-function to avoid giving it a sense of magic which may cause some people to perceive it as something special.