This one works fine when promise is resolved. but if the promise is rejected, the test will wait for a maximum of 5 seconds timeout, and then fail. while others will fail immediately.
Posted onEdited onInjest Symbols count in article: 576Reading time ≈2 mins.
In this post, I will show you how to set up a Jest project from scratch. We won’t use any front-end frameworks like React, Angular, or Vue, just a simple vanilla JavaScript project.
CommonJs
Step 1: Create a new project
Run the following command to init a new project directory, it will simply create a package.json file in the current directory.
1
npm init -y # with -y, you don't need to answer the questions
Step 2: Install Jest
Run the following command to install Jest as a dev dependency.
1
npm install --save-dev jest
Step 3: Create a javascript file
We’ll first focus on CommonJs, create a new file named sum.js in the root directory of your project, and add the following code:
1 2 3 4
functionsum(a, b) { return a + b; } module.exports = sum;
Step 4: Create a test file
Create a new file named sum.test.js in the root directory of your project, and add the following code:
Jest encountered an unexpected token SyntaxError: Cannot use import statement outside a module
This is because you are trying to use ESModule syntax in a CommonJs environment, to fix this, you can update your file name to sum.test.mjs or you need to add the following line to the package.json file:
describe('local storage should work', () => { it('should set and get item', () => { const item = { name: 'John Doe', age: 30 }; saveItem(item); const storedItem = getItem('item'); expect(storedItem).toEqual(item); }); });
When you run this test with Jest
1 2
# first, navigate to the directory where the test file is located. jest storage-utils.spec.ts
Everything works fine, but localStorage is only available in browser environment, and you didn’t mock it, why?
This is because Jest now use jsdom as the default environment, and jsdom has implemented localStorage and sessionStorage APIs, so you don’t need to mock them anymore.
To test this, you can find the jest.config.js file in the root directory of your project, and add the following line to the testEnvironment property:
1 2 3 4 5
module.exports = { preset: 'jest-preset-angular', setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'], testEnvironment: 'node', // <-- change this to 'node' };
Then run the test again, you will see the test failed because localStorage is not available in the node environment, and you will get the following error:
1 2
localStorage is not defined ReferenceError: localStorage is not defined
Use jsdom by in test file
Suppose you global jest config is node(in file jest.config.js under project root), but you want to use jsdom in some test cases, you can use the following code in the test file, add @jest-environment jsdom at the top of the file.(Don’t use // comment, it will not work)
Posted onEdited onInhtml Symbols count in article: 209Reading time ≈1 mins.
Introduction
noscript is used in following senarios:
When the browser does not support JavaScript.
When the browser has disabled JavaScript.
How to disable JavaScript in Chrome
Open your page with Chrome.
Press F12 to open the developer tools.
Click on the three dots on the top right corner.(Or press Ctrl + Shift + P)
Type disable JavaScript in the search bar.
Click on the Disable JavaScript option.
When JavaScript was disabled, there will be a warning sign on Source tab. mouse hove on that warning sign, it will show the message JavaScript is disabled.
Example
The following code will print Hello, world! in the console if JavaScript is enabled. If JavaScript is disabled, the message This page requires JavaScript. will be displayed.
As I know, currently, React framework will generate a noscript tag in the body tag when you create your project with create-react-app.
But Angular does not have a noscript tag in the body tag. there is no browser does not support JavaScript or disable JavaScript, so it is not necessary to add a noscript tag in the body tag.
You can import the default export of a module using the following syntax:
1 2 3 4
// math.mjs exportdefaultfunctionadd(a, b) { return a + b; }
You can use any name here, not limited to add. But you can only have one default export per module.
1 2
// main.mjs import add from'./math.mjs';
Namespace imports
You can also import all exports from a module using the following syntax:
1 2 3 4 5 6 7 8
// math.mjs exportfunctionadd(a, b) { return a + b; }
exportfunctionsubtract(a, b) { return a - b; }
1 2
// main.mjs import * as math from'./math.mjs';
Side effects imports
You can also import a module for its side effects only, without importing any bindings. This is useful when you just want to run the code in the module, but don’t need to import any of its bindings.
1
import'./math.mjs';
This is very common in Angular code, especially with Module Federation, where you import a module for its side effects only.
main.ts use side effect import here which will run all global code in bootstrap.ts but not import any bindings. (Note, the following code is dynamic import, not static import)
When you run main.mjs, you will see only one random number printed in the console, which means the math module is only executed once.
1 2 3
0.2534933886729216 3 1
Dynamic import
Introduction
import() is dynamic import, it returns a promise. The import() syntax, commonly called dynamic import, is a function-like expression that allows loading an ECMAScript module asynchronously and dynamically into a potentially non-module environment.
import() can be used in non-module environment, such as in a .js file or script tag without type="module".
1 2 3 4
// test.js, you don't need test.mjs here. import("chat-box").then(module => { module.load(); });
1 2 3 4 5 6
<!-- You don't need type="module" in script tag--> <script> import("chat-box").then(module => { module.load(); }); </script>
But static import can’t be used in non-module environment, you will got Error: SyntaxError: Cannot use import statement outside a module, to make static import work, you must use file end with .mjs or add type="module" in script tag.
1 2
import {load} from"./chat-box.mjs"; load();
1 2 3 4 5
<!-- You need type="module" in script tag--> <scripttype="module"> import {load} from"./chat-box.mjs"; load(); </script>
pass by reference
There is no real pass by reference in JavaScript like in C/C++ language, but you can use import to achieve similar effect.
First, create a module module.mjs, in this file, we export an object person.
Create another module module1.mjs, in this file, we import person from module.mjs and change the age to 40.
1 2 3
// module1.mjs import { person } from'./module.mjs'; person.age = 40;
Finally, import module1.mjs and module.mjs in main.mjs, and print the person object, you will found the age is 40 now.
1 2 3 4 5
// main.mjs import'./module1.mjs'; // This will execute the code in module1.mjs import { person } from'./module.mjs';
console.log(person);
输出如下:
1
{ name: 'zdd', age: 40 }
import.meta.url
import.meta.url The full URL to the module, includes query parameters and/or hash (following the ? or #). In browsers, this is either the URL from which the script was obtained (for external scripts), or the URL of the containing document (for inline scripts). In Node.js, this is the file path (including the file:// protocol).
In Node.js, import.meta.url is the file path of the current module. It is similar to __filename in CommonJS modules.
This is server.ts file generated by angular SSR, you can see import.meta.url is used to get the current file path.
// The Express app is exported so that it can be used by serverless Functions. exportfunctionapp(): express.Express { const server = express(); const serverDistFolder = dirname(fileURLToPath(import.meta.url)); const browserDistFolder = resolve(serverDistFolder, '../browser'); const indexHtml = join(serverDistFolder, 'index.server.html'); }
1. 使用 ng-container 来包裹多个元素,而不需要额外的 div 或者 span 等元素。
1 2 3 4 5
<!-- This way will generate an extra div element --> <div *ngIf="true"> <div>Content 1</div> <div>Content 2</div> </div>
1 2 3 4 5
<!-- This way will not generate any extra div element --> <ng-container *ngIf="true"> <div>Content 1</div> <div>Content 2</div> </ng-container>
2. 使用 ng-container来分隔多个结构化指令。
在Angular中,一个元素只能有一个结构性指令,比如 *ngIf, *ngFor 等等。如果需要在一个元素上使用多个结构性指令,可以使用 ng-container 来分隔。 比如下面的代码我们在li元素上同时使用了ngFor和ngIf,这会导致编译错误:Only one structural directive can be applied