node.js ～ npm ～ vue.CLI 導入～ Jest 導入迄

## Vue.CLI でサンプルプロジェクトを作って、サンプルコンポーネントいじって、Jestでテストコード実行までやってみようと思い立ちました。

先ずは、node.js 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/bda675ef-da78-e2e9-332d-f2c5cad4c5e9.png)

かなり古めが入っていたのでバージョンアップ

ダウンロード https://nodejs.org/en
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/03adf228-65ed-e900-b868-3955aaf3c520.png)

インストーラー
```
node-v20.12.1-x64.msi
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/d644638a-d279-b4a6-e231-6c088be9c766.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/aaeda26e-e72a-5305-28b6-bbd5a5388fef.png)

```
C:\nodej>node -v
v20.12.1
```
### nodej のサンプル web server を立ち上げてみる。
```
>node
>.help
>.edtiror
```

```nodej:hello-world.js
const http = require('node:http');

const hostname = '127.0.0.1';
const port = 3001;

const myServer = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World oooooooooo!\n');
});

myServer.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
```

### Ctrl + D する


```
  _eventsCount: 3,
  _maxListeners: undefined,
  _connections: 0,
  _handle: null,
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  _listeningId: 1,
  allowHalfOpen: true,
  pauseOnConnect: false,
  noDelay: true,
  keepAlive: false,
  keepAliveInitialDelay: 0,
  highWaterMark: 16384,
  httpAllowHalfOpen: false,
  timeout: 0,
  maxHeadersCount: null,
  maxRequestsPerSocket: 0,
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(shapeMode)]: false,
  [Symbol(kCapture)]: false,
  [Symbol(async_id_symbol)]: -1,
  [Symbol(kUniqueHeaders)]: null
}
> Server running at http://127.0.0.1:3001/
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/7a0fd5f1-79ed-53a4-6144-9530ad4b613a.png)


次に、雛形プロジェクトツール Vue CLI を入れる。
```
npm install -g @vue/cli
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/877e570d-6f49-b50d-8c80-75fe9b7e92e5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/4b39093b-0580-0de4-a891-c4358f51fdba.png)

### プロジェクトを生成

```
vue create mycli
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/6eaf0ffb-3b9d-e0bf-7177-44c6af02e62e.png)

([Vue 2] babel, eslint ) 選択
```
・・・・・
📄  Generating README.md...

🎉  Successfully created project mycli.
👉  Get started with the following commands:

 $ cd mycli
 $ npm run serve
 ```

### 生成プログラムを適度に修正してみる。

C:\nodej\mycli\src\main.js 
./App.vue のimport別名をAppMyに変更
```Js:main.js
import Vue from 'vue'
import AppMy from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(AppMy),
}).$mount('#app')
```

C:\nodej\mycli\src\App.vue
 ・コンポーネントの名称を HelloWorldTomo に変更
・コンポーネント props プロパティ名称を msgTomo: String  に変更

```Vue:App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorldTomo msgTomo="Welcome to Your Vue.js App ooooooooooooooooooo"/>
  </div>
</template>

<script>
import HelloWorldTomo from './components/MyHelloWorldCompo.vue'

export default {
  name: 'App',
  components: {
    HelloWorldTomo
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

```

C:\nodej\mycli\src\components\MyHelloWorldCompo.vue
・components\MyHelloWorldCompo.vue に変更
・コンポーネント props プロパティ名称を msgTomo: String に変更
```vue:MyHelloWorldCompo.vue
<template>
  <div class="hello">
    <h1>{{ msgTomo }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msgTomo: String
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
```

### Compiles and hot-reloads for development
```
mycli> run serve
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/d9aafc3a-d597-5a8d-c717-f4e6c33dcede.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/0dfd4415-fb66-e641-a2b5-90efadfc8f74.png)


### Jest と vue-test-utils をインストール (JUnitみたいなツール)

```
vue add unit-jest
```

C:\nodej\mycli>vue add unit-jest
 WARN  There are uncommitted changes in the current repository, it's recommended to commit or stash them first.
? Still proceed? Yes

📦  Installing @vue/cli-plugin-unit-jest...


added 416 packages in 2m

135 packages are looking for funding
  run `npm fund` for details
✔  Successfully installed plugin: @vue/cli-plugin-unit-jest


🚀  Invoking generator for @vue/cli-plugin-unit-jest...
📦  Installing additional dependencies...


added 6 packages in 15s

135 packages are looking for funding
  run `npm fund` for details
⚓  Running completion hooks...

✔  Successfully invoked generator for plugin: @vue/cli-plugin-unit-jest


以下、間違い。やると変になる。
``` 
> npm install --save-dev jest @vue/test-utils
> npm install jest --save
> npm install ts-jest @types/jest --save
```


以下、自動生成ソース
C:\nodej\mycli\tests\unit
example.spec.js
```
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})
```

適度に編集したソースに合わせて、テストコード編集する

```
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/MyHelloWorldCompo.vue'

describe('HelloWorldTEST.vue', () => {
  it('renders props.msg when passed.....', () => {
    const msgTomo = 'new message meeee'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msgTomo }
    })
    expect(wrapper.text()).toMatch(msgTomo)
  })
})
```

package.json
```
{
  "name": "mycli",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "lint": "vue-cli-service lint"
  },
・・・・・
・・・・・
```

### テスト実施

```
> npm run test:unit
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610057/44c31b9c-77a7-92a2-4734-271b6af89114.png)