- 投稿日:2020-07-21T23:23:59+09:00
[Node.js] 一時的ファイル(temp file)を使ってFirebase Storageへファイルをアップロードする
環境・バージョン
- node version v14.4.0
- "firebase-admin": "^8.7.0"
- "tmp": "^0.2.1"
実装
Firebase Admin SDKの初期化
firebase-admin.jsvar admin = require('firebase-admin') // Retrieve environment variables const ServiceAccountFilePath = process.env.FIREBASE_SERVICEACCOUNT_FILEPATH const StorageURL = process.env.FIREBASE_STORAGE_URL // xxxxx.appspot.com const serviceAccount = require(ServiceAccountFilePath) admin.initializeApp({ credential: admin.credential.cert(serviceAccount), storageBucket: StorageURL, }) module.exports = admintemp fileを使ってアップロード
Firebase Storageに対してファイルをアップロードするために、GCP Node.jsライブラリのBucket.uploadメソッドを利用しました。
一時的ファイル作成と削除にはtmpというサードパッケージを利用しました。
firebase-storage.jsconst fs = require('fs') const tmp = require('tmp') const admin = require('./firebase-admin') // 上記の初期化コードをインポート const requestToStorageService = (cloudFilePath, fileContent) => { var promise tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback) { if (err) throw err try { const bucket = admin.storage().bucket() fs.writeFile(path, JSON.stringify(fileContent), err => { // 一時ファイルに書き込み if (err) throw err }) promise = bucket.upload(path, { // ファイルをFirebase Storageへアップロード destination: cloudFilePath, metadata: { contentType: 'application/json' }, }) } finally { cleanupCallback() // ファイル削除 } }) return promise }
tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback)
によって一時的ファイルのパス(path
)とファイルディスクリプタ(fd
)が渡されます。そのファイルに書き込みし、Firebase Storageへアップロードします。
また、
bucket.upload
はPromiseを返します。
- 投稿日:2020-07-21T21:30:49+09:00
簡単レシート印刷 receiptline の API を調べてみた
日本発のオープンソース receiptline でレシート印刷に少しずつトライしています。
何と超速でマクドナルドのレシートを再現している方を発見!びっくりこ!落札したレシートプリンターは無事届きました。
しかしまだ準備ができていないので、前回利用した開発ツールを引き続き使います。
今回は receiptline の API です。開発ツールは何をしている?
開発ツールの左側の編集エリアに文字を入力すると、右側のレシート用紙にプレビューが表示されます。
Web ブラウザーのデベロッパーツールを使って、開発ツールの内部を解析してみました。入力データ
ReceiptLine^^領収書| 2019/07/20 01:23| #NGC17TH| 缶ビール | ¥211~ シュークリーム | ¥129*出力データ
見やすいように整形して、
を 
に置換しておきました。<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="576px" height="168px" viewBox="0 0 576 168" preserveAspectRatio="xMinYMin meet" version="1.1"> <defs> <filter id="receiptlineinvert" x="0" y="0" width="100%" height="100%"> <feFlood flood-color="#000"></feFlood> <feComposite in="SourceGraphic" operator="xor"></feComposite> </filter> </defs> <g font-family="'MS Gothic', 'San Francisco', 'Osaka-Mono', 'Courier New', 'Courier', monospace" fill="#000" font-size="24" dominant-baseline="text-after-edge"> <g transform="translate(0,48)"> <text transform="scale(1,2)" x="504,528,552">領収書</text> </g> <g transform="translate(0,72)"> <text x="384,396,408,420,432,444,456,468,480,492,504,516,528,540,552,564">2019/07/20 01:23</text> </g> <g transform="translate(0,96)"> <text x="480,492,504,516,528,540,552,564">#NGC17TH</text> </g> <g transform="translate(0,120)"> <text x="0"> </text> </g> <g transform="translate(0,144)"> <text x="0,24,48,72">缶ビール</text> <text x="516,528,540,552,564">¥211 </text> </g> <g transform="translate(0,168)"> <text x="0,24,48,72,96,120,144">シュークリーム</text> <text x="516,528,540,552,564">¥129*</text> </g> </g> </svg>ソースコード
開発ツールの内部で、入力データを出力データに変換しているはずです。
ソースコードを解読して、該当部分を探し出しました。designer/script/receiptline-designer.jsconst printer = { cpl: Number(cpl.textContent), encoding: /^ja/.test(window.navigator.language) ? 'cp932' : 'cp437' }; const svg = receiptline.transform(edit.value, printer);ありました。transform メソッドです。
引数は、編集エリアの文字列と、オプション (レシート用紙の桁数、日本語 or 英語)。
戻り値は SVG の文字列です。これを DOM に変換して表示しています。アプリ開発では、このメソッドに渡す文字列の組み立て処理がメインになりますね。
サンプルプログラム
receiptline パッケージには、コピーして使えるサンプルプログラムが添付されています。
・・・はじめからこちらをチェックすべきでしたね。Web ブラウザー用
example/js/ja.html// for SVG output const printer = { // cpl: characters per line (required) cpl: 48, // font: Japanese, encoding: utf-8 (required) encoding: 'cp932', // upsideDown: ignored (optional) upsideDown: false, // gamma: ignored (optional) gamma: 1.0, // command: SVG (optional) command: 'svg' }; const svg = receiptline.transform(reader.result, printer);テキストファイルを読み込んで、変換して、表示しています。
中身は開発ツールのソースコードとほとんど一緒です。Node.js 用
example/nodejs/start.jssock.on('connect', () => { const command = receiptline.transform(text, printer); sock.write(command, /^<svg/.test(command) ? 'utf8' : 'binary'); });テキストデータを HTTP で受信して、変換して、仮想プリンターへ送信しています。
開発ツールを起動する designer.js のソースコードと全く同じでした。変換 API を使ったプログラミングは後日トライすることにします。
次回は仮想プリンターを試してみようと思います。
- 投稿日:2020-07-21T19:03:04+09:00
ESLint 7.5.0
前 v7.4.0 | 次 (2020-08-01 JST)
ESLint v7.5.0 has been released: https://t.co/YOq2XU6htO
— ESLint (@geteslint) July 18, 2020ESLint
7.5.0
がリリースされました。小さな機能追加とバグ修正が含まれています。質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。
? 日本語 Issue 管理リポジトリ
? 日本語サポート チャット (招待リンク)
? 本家リポジトリ
? 本家サポート チャット (招待リンク)
[PR] ESLint は開発リソースを確保するための寄付を募っています。
応援してくださると嬉しいです。
✨ 本体への機能追加
Optional Chaining 構文をサポートしました
? #13416
Optional Chaining 構文をサポートしました。新しい構文を利用するには、
parserOptions.ecmaVersion
を2020
に設定する必要があります。.eslintrc.json (例){ "parserOptions": { "ecmaVersion": 2020 } }id-blacklist ルールが非推奨になりました
? #13465
前回のリリースで id-blacklist ルールは id-denylist に名称変更され、既存の id-blacklist は id-denylist の別名になりました。
しかし、同じルールが複数の名称で存在するのは関連ツールにとって不便だったため、id-blacklist は非推奨としてマークされることになりました。今後は id-denylist をご利用ください。
? 新しいルール
特になし
? オプションが追加されたルール
sort-imports
allowSeparatedGroups
? #13455
他の文、または空行やコメントによって分離された
import
文について、それぞれ別個に並び順を矯正するためのオプションが追加されました。例/*eslint sort-imports: [error, { allowSeparatedGroups: true }]*/ //✔ GOOD import b from 'b.js'; import c from 'c.js'; // 空行やコメント行などで分離されているので、`import a` は `import b` より下にあっても良い import a from 'a.js'; //✘ BAD import b2 from 'b.js'; import c2 from 'c.js'; import a2 from 'a.js'; // 空行やコメント行などで分離されていないので、`import a2` は `import b2` より上にないとダメ
- 投稿日:2020-07-21T17:57:58+09:00
error TS1192: Module '"fs"' has no default export.
モジュール '"fs"' に既定エクスポートがありません
error TS1192: Module '"fs"' has no default export.のようなエラーが出た時の対処法メモ
はじめに
これはnode.jsのデフォルトモジュールの
fs
が原因で起こるエラーでは有りません。
TypeScriptの仕様によるものです。
tsconfig.jsonのオプションでこのエラーを解決する方法があります。結論
tsconfig.json
に"allowSyntheticDefaultImports": true
を追記する{ "compilerOptions": { "allowSyntheticDefaultImports": true } }または
// error TS1192: Module '"fs"' has no default export. import fs from 'fs' // no error import * as fs from 'fs'解説(tsconfigのオプション追加は省略)
TypeScriptでES6のデフォルト構文を使うとエラーでコンパイルエラーが起きます。
そういう時は下記の様な構文で指定ファイルの全てをインポートしてあげましょう。
import * as fs from 'fs'エラーが出ないもの
また、下記の様に個別に
export
されたものをimportする場合はエラーが出ません。// hogeModuleファイル export const hoge = () => {}import { hoge } from 'hogeModule'上記と同様に
export default
が指定されているものもエラーになりません。// hogeModule export default class hoge {}import hoge from 'hogeModule'記事のもと
https://github.com/microsoft/TypeScript/issues/3337
https://qiita.com/bouzuya/items/edf5274241b50f32c621
https://qiita.com/alfas/items/539ade65926deb530e0e
- 投稿日:2020-07-21T15:40:08+09:00
nodebrew使ってColorfulbox(レンタルサーバー)にNode.jsをインストールする
参考記事
https://qiita.com/yni17196791/items/f49b3e2f683cd06b3120やってみる
$ wget git.io/nodebrew $ perl nodebrew setup $ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc $ source ~/.bashrc確認
$ nodebrew -v $ nodebrew install-binary stable $ nodebrew ls $ nodebrew use v8.7.0$ node -v
- 投稿日:2020-07-21T12:02:26+09:00
VSCodeのRemote-ContainerでReact(Node.js+TypeScript)環境をサクッと構築する。
環境構築はDockerで作りたい。
Dockerに慣れてくると何でもDockerを使いたくなりませか?
僕はそんな人間の一人で、パソコンを買い換えてDockerを本格的に使い始めてから、手元の環境が汚れるのが嫌で環境構築は全てDockerを使っています。潔癖症かな?今回は、VSCodeでDockerを使い倒すための神拡張機能のRemote-Containersを使って、JavaScriptのライブラリのReactの開発環境を作っていきます。
事前に準備が必要なもの
- Docker
- VSCode
Remote-Containersを使って環境を作る
事前にDockerがインストールされているものとします。
拡張機能のDockerとRemote-Containers をインストールします。
適当なフォルダを開いて、コマンドパレットから
Remote-Containers:Add Development Containers Configuration Files
を選択。
インストールしたい環境のサンプルが表示されるので、Show All Definitionsを選択し、
最新版であるNode.js 14 & TypeScriptを選択。
そうすると.devcontainerフォルダが生成され、中にはMS社が用意してくれた指定した環境のDockerFileと追加設定を行うdevcontainer.jsonが保存されています。
Reactを利用するにはコマンドラインツールのcreate-react-appを使うのがラクチンなので、これをnpmでインストールする設定をDockerFileに追記しておきます。
また、コンテナ側の3000番ポートを使用することになるので、devcontinaer.jsonファイルにフォワードポートの設定を追記します。
最後にこれらのファイルを元にDockerイメージとコンテナを生成します。拡張機能からRemote-Containers:Rebuild and Reopen in Container 実行。
(または右下に出てるであろうポップアップをクリック)
画面が一度閉じ、再び開いたあと少し待つと、VScodeの左下がコンテナの中に入っていることを示す状態に変わっていると思います。
これでReactの環境は完成です。簡単!
実際に動かしてみる
create-react-appを実際に使って、サンプルアプリを動かしてみます。
ターミナルを開いて、
# npx create-react-app test
を実行。必要なライブラリ一式がダウンロードされていきます。
Happy hacking!の文字が出たら完了です。
testディレクトリが作成されており、中にはReactを動かすためのテンプレート になるファイルが生成されています。
こいつを動かしてみます。
# cd/test //カレントディレクトリを移動 # npm start //アプリを起動アプリを起動したらlocalhost:3000にアクセス。下記のような画面が表示されていたら成功です!
コンテナから抜けるには、VSCodeの画面を閉じるだけでコンテナOKです。
再びコンテナに入るには、VSCodeのDockerのオプションからお目当てのコンテナを右クリックして、Startをクリック。
そうするとコンテナが立ち上がるので、もう一度右クリックしてAttach Visual Studio Codeをクリックして完了です。
それでは、良いDocker & Reactライフを!
- 投稿日:2020-07-21T10:22:31+09:00
CodeceptJS (+ Puppeteer) を触ってみた
きっかけ
今までSelenium WebDriverでE2Eテストを書いてきました。
が、開発チームから「もっと楽に書こうよ」という話が出て調べてみたところ、CodeceptJSが良さそうなので触ってみた話。
CodeceptJS + WebDriverも出来るようですが、Puppeteerの方が手軽で実行速度も速いようなのでPuppeteerを選択。
ただクロスブラウザやBrowserStackでテストをしたいので将来的にはWebDriverに移行予定。けど今じゃない。CodeceptJSの何が良かったのか
- テストコードが自然言語っぽく書けて誰でも読みやすい
- 要素指定が簡単で分かりやすい(良い意味で雑に書ける)
- プラグインが充実してる
- WebDriverとかPuppeteerとか複数のヘルパーに対応してる
インストール + 初期設定
$ npm init -y $ npm install codeceptjs puppeteer --save-dev $ npx codeceptjs init # ここから対話形式 ? Where are your tests located? (./*_test.js) # 指定のファイル名を自動でテストファイルと認識してくれる ? What helpers do you want to use? (Use arrow keys) # Puppeteerを選択 WebDriver ❯ Puppeteer TestCafe Protractor Nightmare Appium Playwright ? Where should logs, screenshots, and reports to be stored? (./output) # スクリーンショット等の出力先 ? Do you want localization for tests? (See https://codecept.io/translation/) (Use arrow keys) # 日本語を選択 pl-PL zh-CN zh-TW ❯ ja-JP de-DE English (no localization) pt-BR (Move up and down to reveal more choices) ? [Puppeteer] Base url of site to be tested (http://localhost) # ドメイン以降が同じ構成で、ドメインでテスト環境や本番環境を分けている場合はBase URLを指定すると便利 ? [Puppeteer] Show browser window (Y/n) # テスト時にブラウザを表示するかどうか ? [Puppeteer] Browser viewport size (1200x900) # ブラウザサイズ一旦ここで初期設定は終了です。初期設定が終わると必要なファイルやフォルダが作成されます。
npx codeceptjs init
がうまく行かない場合があるようなので、その場合は代わりにnode node_modules/.bin/codeceptjs
を実行します。
作成されたファイルの中のcodecept.conf.js
に上記で設定した内容が書かれています。もちろん後からも内容変更可能です。
続いてテストケースファイルの作成が対話形式で行われます。Almost ready... Next step: Creating a new test... ---------------------- ? Feature which is being tested (ex: account, login, etc) # テストケースファイル毎に付けられる名前 ? Filename of a test (『上で付けたFeature名』_test.js) # ファイル名なお、この対話形式のテストケースファイル作成は、初期設定後に以下のコマンドでも呼び出せます。
$ npx codeceptjs gt
以下が作成されたテストケースファイルの中身です。
(ここではFeatureをQiita Test
とし、ファイル名をQiita_Test_test.js
としています)Feature('Qiita Test'); // ? Feature which is being tested で指定した名前 Scenario('test something', (I) => { });作成されたファイル・フォルダは以下になります。
. ├── codecept.conf.js ├── jsconfig.json ├── node_modules ├── output ├── package-lock.json ├── package.json ├── Qiita_Test_test.js ├── steps.d.ts └── steps_file.js
テストケースの書き方
最初にも上げましたが、CodeceptJSは自然言語っぽく書くので、テスト内容が分かりやすいです。
また要素指定もボタン名とかを書くと、いい感じに要素特定してくれて素敵です。具体的にはこんな感じになります。Feature('Qiita Test'); Scenario('test something', (I) => { I.amOnPage('https://qiita.com/'); // 指定URLにアクセスして I.seeInTitle('Qiita'); // ページタイトルが「Qiita」になっていることを確認して I.see('How developers code is here.'); // 画面上に「How developers code is here.」と表示されていることを確認して I.click('マイルストーン'); // 「マイルストーン」と書かれているところをクリックして I.wait(1); // 1秒待って I.seeCurrentUrlEquals('https://qiita.com/milestones'); // URLが期待値通りか確認して I.saveScreenshot('Qiita01.png', true); // スクリーンショットを撮る(撮ったファイルはoutputフォルダの中に入る) });詳しくはTesting with Puppeteer | CodeceptJSを参照してみてください。
テスト実施
テスト実施方法は複数あります。
まずは基本パターンです。
最初の初期設定? Where are your tests located? (./*_test.js)
で設定したファイル形式のファイルをすべて実行します。$ npx codeceptjs run #### 以下結果 #### CodeceptJS v2.6.6 Using test root "xxxxxxxxxxxxxxxx" Qiita Test -- ✔ test something in 6668ms OK | 1 passed // 9s指定のファイルのみ実施したい場合はファイル名を指定します。
$ npx codeceptjs run [ファイル名]上記のやり方だとテスト成功した場合、詳しい結果が分かりません。
なので詳しく知りたい場合は以下の3つの方法で実施します。
--steps
をつけるとテストケースっぽく出力されます。$ npx codeceptjs run --steps #### 以下結果 #### CodeceptJS v2.6.6 Using test root "xxxxxxxxxxxxxxxx" Qiita Test -- test something 私は ページを移動する "https://qiita.com/" 私は タイトルに文字が含まれるか確認する "Qiita" 私は テキストがあるか確認する "How developers code is here." 私は クリックする "マイルストーン" 私は 待つ 1 私は U r lが等しいか確認する "https://qiita.com/milestones" 私は スクリーンショットを保存する "Qiita01.png", true ✔ OK in 7568ms OK | 1 passed // 11sもっと詳しく実施。
$ npx codeceptjs run --debugさらに詳しく実施。
$ npx codeceptjs run --verbose詳しい使い方はReporters | CodeceptJSを参照してみてください。
レポート
プラグインを導入するとかっこいいレポートを出力できます。
インストール
$ npm install -g allure-commandline --save-dev
codecept.conf.js
のplugins
にallureを追加します。// 編集前 plugins: { retryFailedStep: { enabled: true }, screenshotOnFail: { enabled: true } }// 編集後 plugins: { retryFailedStep: { enabled: true }, screenshotOnFail: { enabled: true }, allure: { enabled: true } }起動
レポート出力するには以下のようにallureを有効にしてテストを実施します。
$ npx codeceptjs run --plugins allure
output
フォルダがある場所(=codecept.conf.js
がある場所)で以下のコマンドを実行してレポートサーバを立ち上げます。$ allure serve output
するとブラウザが自動で立ち上がり、レポートが表示されます。
レポートサーバーはCtrl+c
で終了です。(macの場合)まとめ
Puppeteerはどの文字が2つ続くのか毎回分からなくなる
We're hiring!
AIチャットボットを開発しています。
ご興味ある方は Wantedlyページ からお気軽にご連絡ください!参考
Testing with Puppeteer | CodeceptJS
Reporters | CodeceptJS
Plugins | CodeceptJS
E2Eテストの面倒くさいことはCodeceptJSにお願いしよう - Qiita
E2EテストでWEBサイトをチェック(CodeceptJS × Puppeteer) | HAFILOG