This is a draft, the content is not complete and of poor quality!
book nodejs npm
web development with node and express
× myThoughts: Run npm install in the root folder of the project or lesson folder where package-lock.json is located
As of version of 5 of npm, an additional file, package-lock.json, will be created. Whereas package.json can be “loose” in its specification of dependency versions (with the ^ and ~ version modifiers), package-lock.json records the exact versions that were installed, which can be helpful if you need to re-create the exact dependency versions in your project. I recommend you check this file into source control and don’t modify it by hand. See the package-lock.json documentation for more information.
Beaware Node modules (also called CJS) use a different syntax than ECMAScript modules(ESM), and you may have to switch between the two syntaxes when you go between frontend and backend code. It’s a good idea to be familiar with both.
goodPoint! Whenever you have a dependency, you have something that needs to be mocked(simulated) for effective testing. For example, our primary dependency is Express, which is already thoroughly tested, so we don’t need or want to test Express itself, just how we use it. The only way we can determine if we’re using Express correctly is tosimulate Express itself.
Important:
constfortune=require('./fortune')exports.home=(req,res)=>res.render('home')exports.about=(req,res)=>res.render('about',{fortune:fortune.getFortune()})exports.notFound=(req,res)=>res.render('404')// Express recognizes the error handler by way of its four// argumetns, so we have to disable ESLint's no-unused-vars rule/* eslint-disable no-unused-vars */exports.serverError=(err,req,res,next)=>res.render('500')
Note:
> how to write a test script using Jest
consthandlers=require('../handlers')test('home page renders',()=>{constreq={}constres={render:jest.fn()}handlers.home(req,res)expect(res.render.mock.calls.length).toBe(1)expect(res.render.mock.calls[0][0]).toBe('home')})// the first array index specifies which invocation, and the second one specifies which argumenttest('about page renders with fortune',()=>{constreq={}constres={render:jest.fn()}handlers.about(req,res)expect(res.render.mock.calls.length).toBe(1)expect(res.render.mock.calls[0][0]).toBe('about')expect(res.render.mock.calls[0][1]).toEqual(expect.objectContaining({fortune:expect.stringMatching(/\W/),}))})test('404 handler renders',()=>{constreq={}constres={render:jest.fn()}handlers.notFound(req,res)expect(res.render.mock.calls.length).toBe(1)expect(res.render.mock.calls[0][0]).toBe('404')})test('500 handler renders',()=>{consterr=newError('some error')constreq={}constres={render:jest.fn()}constnext=jest.fn()handlers.serverError(err,req,res,next)expect(res.render.mock.calls.length).toBe(1)expect(res.render.mock.calls[0][0]).toBe('500')})
To invoke our render, we need request and response objects. We’d be writing code all week if we wanted to simulate the whole request and response objects, but fortunately we don’t actually need much from them. We know that we don’t need anything at all from the request object in this case (so we just use an empty object), and the only thing we need from the response object is a render method. Note how we construct the render function: we just call a Jest method called jest.fn(). This creates a generic mock function that keeps track of how it’s called.
1. Starts our application server on an unoccupied port
2. Launches a headless Chrome browser and opens a page
3. Navigates to our application’s home page
4. Finds a link with data-test-id="about" to click it
5. Waits for the navigation to happen
6. Verifies that we are on the /about page
constportfinder=require('portfinder')constpuppeteer=require('puppeteer')constapp=require('../meadowlark.js')letserver=nullletport=nullbeforeEach(async()=>{port=awaitportfinder.getPortPromise()server=app.listen(port)})afterEach(()=>{server.close()})test('home page links to about page',async()=>{constbrowser=awaitpuppeteer.launch()constpage=awaitbrowser.newPage()awaitpage.goto(`http://localhost:${port}`)awaitPromise.all([page.waitForNavigation(),page.click('[data-test-id="about"]'),])expect(page.url()).toBe(`http://localhost:${port}/about`)awaitbrowser.close()})
Eslint
Broadly speaking, a linting error has one of three causes:
• It’s a legitimate problem, and you should fix it. It may not always be obvious, in which case you may need to refer to the ESLint documentation for the particular error.
• It’s a rule you don’t agree with, and you can simply disable it. Many of the rules in ESLint are a matter of opinion. I’ll demonstrate disabling a rule in a moment.
• You agree with the rule, but there’s an instance where it’s infeasible or costly to fix in some specific circumstance. For those situations, you can disable rules for only specific lines in a file, which we’ll also see an example of.
Thi
Install NodeJS & NPM
Install multiple versions
First, need to install nvm. Run the line of curl and then run/add-to-zsh the line of export.
::: warning
Below commands are mostly for Linux/MacOS users.
:::
::: col-2-equal
# FIRST INSTALL: the most recent lts release
nvm install--lts
# install a specific version
nvm install 12.13.0
# install latest version
nvm install node
# list all installed versions
nvm ls
# set default version of node
nvm alias default 12.13.0
# full list of available versions# be careful, it's too long!!!
nvm ls-remote
# switch between versions
nvm use 12.13.0
# or (more quickly)
nvm use v15
npm install package_name # if it's in package.json, the indicated version will be installed# otherwise, the newsest version will be installed
npm install--global package_name # global package
# install all package in package.json
npm install
# install + save to package.json
npm install--save package_name # save to package.json
npm install--save-dev package_name # save to package.json, in devDependencies
npm install--no-save package_name # don't save
# install with version
npm install express@4.16.1
# install a local package
npm install /path/to/package
# from github repository
npm i git+https://github.com/abc/xyz.git # https# or
npm i git+ssh://git@github.com/abc/xyz.git # ssh
# list all installed packages (current project only)ls node_modules
# list all local (installed) packages
npm list # -g for globel # or use "ls"
npm list --depth=0 # without dependencies# Check the current version of a (installed) package
npm list package_name # with "-g" for global# Check the latest (not current) version of a package
npm view package_name version
# Set python2 by default when installing npm packages
npm config set python python2
Update package
::: col-2-equal
# which global packages need to be updated?
npm outdated -g--depth=0
# update all global packages
npm update -g
# update a package
npm update package_name # -g for global
이제 이 함수의 결과를 확인하는 테스트 코드를 작성해보겠습니다.
함수의 결과 값을 result라 하고, 기대 값을 expected라고 하겠습니다.
varresult=sum(1,2);varexpected=5;if(result!==expected){thrownewError(result+' is not equal to '+expected);}
두 개의 합을 더한 결과(result)는 3이고 기대 값(expected)는 5이기 때문에 아래와 같은 오류가 발생합니다.
간단한 테스트 함수 만들어보기
앞의 코드를 API 형태로 사용할 수 있게 함수로 변환해보겠습니다. 아래의 API 형태는 일반적인 테스트 라이브러리에서 흔하게 찾아볼 수 있습니다.
expect(result).toBe(expected)
위와 같은 API를 사용하기 위해 앞에서 살펴본 테스트 코드를 expect()라는 함수에 포함합니다.
테스트 함수의 코드는 다음과 같습니다.
functionsum(a,b){returna+b;}functionexpect(result){return{toBe:function(expected){if(result!==expected){thrownewError(result+' is not equal to '+expected);}}}}
위의 함수를 아래와 같이 실행하면 아까와 같이 동일한 에러가 발생합니다.
expect(sum(1,2)).toBe(5);
그럴싸한 테스트 함수 만들어보기
앞에서 작성한 테스트 함수는 몇 번째 줄에서 오류가 났는지 추적하기가 어렵다는 단점이 있습니다.
또한, 각 테스트 함수의 역할이 구분되지 않죠. 이번엔 좀 더 의미 있는 테스트 함수를 작성해보겠습니다.
functiontest(title,testCode){try{testCode();}catch(error){console.error(error);}}functionexpect(result){return{toBe:function(expected){if(result!==expected){thrownewError(result+' is not equal to '+expected);}}}}
위 코드의 모양은 전형적인 테스트 라이브러리의 API 형태와 비슷합니다.
위 함수를 이용하면 다음과 같이 테스트를 할 수 있습니다.
test('sum(1, 2) is not equal 5',function(){expect(sum(1,2)).toBe(5);});
앞의 예제와 마찬가지로 동일한 오류를 발생시키지만 이번엔 좀 더 추적하기가 쉽습니다.
The following wiki, pages and posts are tagged with