いろいろエラー吐きまくりでゲロゲロだったけど、なんとか形になったので記録を残す。
ーローカル環境ー
macOS Big Sur 11.4
Docker version 20.10.5
docker-compose version 1.28.5
まずは作業ディレクトリ(任意の名前)を作成後、Dockerfileを作成。
$ mkdir vue-docker $ cd vue-docker $ touch Dockerfile
中身をテキストエディタ等で以下のように記述。
FROM node:14-slim # appは任意の名前でOK。後のdocker-compose.ymlのvolumesと合わせること。 WORKDIR /app # Puppeteerの起動に必要なChromeと関連パッケージ等のインストール。 # 公式参照(https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-in-docker) # 上に加えて、Vueのイントールでエラーが出るためlibxtst6を、Puppeteerの実行でエラーが出るためprocpsを追加している。 RUN apt-get update \ && apt-get install -y wget gnupg vim procps \ && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ && apt-get update \ && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 libxtst6 \ --no-install-recommends \ && rm -rf /var/lib/apt/lists/* RUN npm install -g @vue/cli
Nodeイメージの2021年5月時点最新の16では、Vueのインストールが上手くいかなかったので、node:14-slimを指定。
一つ目のRUNでは、Puppetter公式のトラブルシューティングの記述に加え、パッケージのインストールにprocpsを、chrome関連パッケージとしてlibxtst6を追加している。理由はコメントに書いているとおり。
また、Docker内でファイル編集する機会もあるかと予想したのでvimも追加した(試行錯誤しているときに無くて困った)。
ここではDocker内でChromeを起動するためにいろいろインストールしている(
Running Puppeteer in Docker の翻訳とメモ - ベーコンになります。を参照
)わけだが、先の記事に書いているユーザー権限まわりは省略した。そのかわり--no-sandbox等の必要な設定は後で書く。
次に同ディレクトリにdocker-compose.ymlを作成。
$ touch docker-compose.yml
開いて中身を記述。.ymlファイルはインデントや文字間の空白数が厳密なので、気をつけて書こう。
version: "3" # web のところは任意の名前でOK services: web: build: . ports: - 8080:8080 volumes: - .:/app init: true tty: true stdin_open: true command: npm run serve
buildやvolumesに出てくる . はカレントディレクトリの意味。volumesは . とdockerコンテナ内の/appディレクトリをマウントしている。
これで準備ができた。次はコンテナに入ってvueをインストールする。(ここから以下すべてコンテナ内で作業(# でコマンドライン表記))
$ docker-compose run web bash # vue create .
インストール時の設定は以下。自分の好みややりたいことに合わせて設定を。テストランナーはJestを使うので始めから入れておく。
? Your connection to the default yarn registry seems to be slow. Use https://registry.npm.taobao.org for faster installation? (Y/n) > n ? Generate project in current directory? (Y/n) > y ? Please pick a preset: Default ([Vue 2] babel, eslint) Default (Vue 3) ([Vue 3] babel, eslint) ❯ Manually select features ? Check the features needed for your project: ◉ Choose Vue version ◉ Babel ◯ TypeScript ◯ Progressive Web App (PWA) Support ◉ Router ◯ Vuex ◉ CSS Pre-processors ◉ Linter / Formatter ❯◉ Unit Testing ◯ E2E Testing ? Choose a version of Vue.js that you want to start the project with (Use arrow keys) ❯ 2.x 3.x ? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) > y ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys) ❯ Sass/SCSS (with dart-sass) Sass/SCSS (with node-sass) Less Stylus ? Pick a linter / formatter config: ESLint with error prevention only ESLint + Airbnb config ESLint + Standard config ❯ ESLint + Prettier ? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection) ❯◉ Lint on save ◯ Lint and fix on commit (requires Git) ? Pick a unit testing solution: Mocha + Chai ❯ Jest ? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys) ❯ In dedicated config files In package.json ? Save this as a preset for future projects? (y/N) > n ? Pick the package manager to use when installing dependencies: Use Yarn ❯ Use NPM
Vueの開発環境ができた。
ここでDockerfileに以下を追記しておく(npm install -g @vue/cliより前の部分)。
(省略) COPY package.json . RUN npm install \ && npm install -g @vue/cli
次はテスト環境を構築する。 ここからインストールするものが多くなる。
まずはJestのunitテスト環境を整えよう。これはVue公式が参考になる。
Jest を使用した単一ファイルコンポーネントのテスト | Vue Test Utils
公式のとおりやればOK…とはいかなかったので、少し記述を変えたり追加したものがある。
最初のJestとtest-utilsはインストール済みなので省略。
次のpackage.jsonの記述は以下のようにした。"test"の名前はコマンドになるので、好みで変えてOK。
{ (省略), "scripts": { (省略)", "test:unit": "jest", (省略) }, (省略) }
次のvue-jestのインストール〜設定までは公式のとおりやろう。
その次のbabel-jestインストール→package.jsonに記述追加後、.babelrcを設定とあるが、この環境では.babel.config.jsが替わりにあるので、こちらを設定する。jsファイルなので書き方が若干異なる。
module.exports = { presets: ["@vue/cli-plugin-babel/preset", ["env", { modules: false }]], env: { test: { presets: [["env", { targets: { node: "current" } }]], }, }, };
これで設定完了。テストを走らせてみよう(デフォルトで/src/tests/unit/example.spec.jsがあるはず)。
# npm run test:unit
あれ?エラーが。
Error: Cannot find module 'babel-preset-env' とある。のでbabel-preset-envをインストール。
# npm install babel-preset-env
.babel.config.jsの"env" → "@babel/preset-env"に変更(2箇所とも)。
module.exports = { presets: [ "@vue/cli-plugin-babel/preset", ["@babel/preset-env", { modules: false }], ], env: { test: { presets: [["@babel/preset-env", { targets: { node: "current" } }]], }, }, };
これで先ほどのテストコマンドを走らせると...…通った!これでunitテストの設定は完了。
次はE2Eテスト環境に取り掛かる。
まずはPuppeteerと、それをJest上で扱いやすくjest-puppeteerをインストールする。
# npm install puppeteer jest-puppeteer
次に、必須ではないと思うが、お手軽に設定を追加してくれるvue-cli-plugin-jest-puppeteerを入れる。
# vue add jest-puppeteer
これで/test/e2eディレクトリが作成されるが、testsとtestの2つあるのは鬱陶しいので、1つ(tests)に統一する。
# mv ./test/e2e ./tests/. # rmdir test
ディレクトリの変更をjest.e2e.config.jsに反映する。下記のようにtestMatch: の/test/ を/tests/に変更。
module.exports = { preset: "jest-puppeteer", moduleFileExtensions: ["js"], testMatch: ["**/tests/e2e/**/*.spec.(js|ts)"], watchPlugins: [], };
package.jsonに以下が自動で追加されている。コマンドは好みで変更してもOK。
{ (省略), "scripts": { (省略), "test:e2e": "jest --config=jest.e2e.config.js --runInBand", (省略), }, (省略) }
この状態でテストを走らせると、
# npm run test:e2e
Error: Failed to launch the browser process!
Running as root without --no-sandbox is not supported.
となるので、jest-puppeteer.config.jsに設定を追加する。
module.exports = { launch: { headless: true, args: ["--no-sandbox", "--disable-setuid-sandbox"], }, (省略), };
デフォルトで用意されているtests/e2e/basic.spe.jsを走らせてみたいが、そのままでは内容がVueの初期画面と合致しないのでちょっと修正(HelloWorld → Welcome to Your Vue.js App)。
describe("your Vue app", () => { beforeAll(async () => { await page.goto("http://localhost:8080"); }); it("can be tested with jest and puppeteer", async () => { await expect(page).toMatchElement("h1", "Welcome to Your Vue.js App"); }); });
あとは/src/views/Home.vueと/src/components/HelloWorld.vueの要らない記述(name: ~の行)を削除(TypeErrorになるので)。
これでテストコマンドを走らせれば、
# npm run test:e2e
PASS!!
お疲れ様でした。