建設予定地

当面はやったことの備忘録

【解決】画像ファイルの読み込みでシンタックスエラーが発生する

画像ファイルをインポートする必要のあるVueコンポーネントをjestでテストした際に発生したエラーでしたが、大分長いこと格闘して、ようやく解決したのでまとめておきます。

症状

Vue.jsのテストコードを書いていて、以下のようなシンタックスエラーに遭遇した

/home/user/hogehoge/src/assets/image.png:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){�PNG
                                                                                         

SyntaxError: Invalid or unexpected token
テストツール

Vue test Utils, Jest

テスト対象のコンポーネント
// sampleComponent.vue
<template>
    ...
</teplate>
<script>
  name: 'sampleComponent',
  mixins: [sampleMixin],

  data() {
    return {
      hogehoge: require('@/assets/piyopiyo.png'),
    }
  },
  methods: {
    move() {
      ...
    },
  },
}
</script>
<style></style>

原因と対処法

data()メソッドの返り値を画像ファイルとした場合のみに発生するエラーで、つまるところ

画像ファイルをインポートすると、Jestは画像のバイナリコードを.jsとして解釈しようとするため、エラーが発生します。
reactjs - 画像をインポートするとjestテストが壊れます - ITツールウェブ

ということらしい。インポート時画像ファイルを正しく解釈できるようにする必要があります。

なのd、package.jsonのtransformとmoduleNameMapperに以下のような設定を追加してあげましょう。
jestjs.io

// package.json
    "transform": {
      ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest",
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
+      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js" 
    },
    "moduleNameMapper": {
+      "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js", 
+      "^@/(.*)$": "<rootDir>/src/$1" 
    }

transformでは画像ファイルの拡張子がインポートされたときにroot直下にあるfileTransformer.jsをインポートするように指示しています。
同様に、moduleNameMapperでは、css、scssがインポートされたときにrootディレクトリからmocks/styleMock.jsを参照するように指示しています。
なので、package.jsonの追加記述と対応させてrootディレクトリ(基本的にはpackage.jsonと同階層です)*1にfileTransformer.js、mocksディレクトリを作成し、mocksディレクトリにはstyleMock.jsを作成します。
そのうえで、これらには以下のように記述します。

// fileTransformer.js
const path = require('path')

module.exports = {
  process(src, filename, config, options) {
    return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';'
  },
}
// styleMock.js
module.exports = {}

以上の設定のもと、テスト対象のコンポーネントをmount/shallowMountして検証することにより、問題なくテストが通りました。

参考
【Jest】画像ファイルやCSSのインポートに失敗する場合の対処法 - Qiita
reactjs — JestとReactおよびCSSファイルのインポートを伴うSyntaxError

明けたけど、2020年を振り返る

あけましておめでとうございます!
あけましたが、せっかくなのでざっくりと2020年を振り返っていきたいと思います

終わってみるとあっという間でしたねー。
対面コミュニケーションでの制約があった分、オンラインを通じてたくさんの出会いがあり、多方面で色々な方にお世話になりました。
アウトプットを意識するようになったのも大きな変化で、学びの多い一年でした。

1月

Local学生部に加入して最初の総大会に参加。
第11回 LOCAL学生部総大会 開催レポート

前年に参加したMH4YがWordPress脆弱性を題材としていたため、Webをやりたい!という気持ちがありました。

2月

ドットインストールとProgateとpaizaを右往左往してやっていた記憶。
gitで初コミットしたり、glideでアプリを作ったり、PHP本を一冊やる。


4月

CSSの勉強をちゃんとする(決意をする)。

cistLTに参加したのもこのころでした。
cist-lt-group.web.app

5月

この辺りからUnityの勉強をちゃんと始める(Udemyの講座を買う)
Javaの勉強をはじめる

6月、7月

2回目のOSC(オンライン)に参加する。
キャリアセレクトさんのDjango勉強会に参加したり、
技育祭に参加したり。
talent.supporterz.jp


ポチる。

8月

ひっそりはてブ開設

SC4Yに参加する
hackteck.hatenablog.com

大学のプロジェクトの成果物としてGAS×Glideのアプリをつくる。

Unityの3D系チュートリアルやったり

Unity1Weekに参加し、初めて自作ゲームを公開する。
unityroom.com

最初のポートフォリオを作る。(コンテンツはほぼなし)

9月

初LT
cist-lt.connpass.com
cistLTのポートフォリオハッカソン2個目のポートフォリオを作る。
Firebaseに足を向けて寝られなくなる。


Laravelとかやってた(フレームワークに初めて触れた)。

10月

プロメン成果物のアプリをWeb版で公開。
chitose-fts.web.app
フロントエンドに強くなりたいという気持ちになる。


11月

セキュリティミニキャンプに初参戦。


WSL2でGUIを使ってみたり
GASでユーザー登録フォームを作った
Reactの素振りをしたり


ポートフォリオ(3個目)を作った

12月

momijiLTで初めてチーム開発を経験。
unityroom.com

久しぶりに触れたUnityが楽しすぎて、ここにきてUnity熱が再熱。

小学生向けプログラミング教室に参加したり、
Springbootの勉強をしたり、大学の課題でLineBotを作ったり。

12月からは長期インターンに参加させていただけることになり、Vue.jsのテストを書いたりしています。

抱負とか

今年はゲーム作りやCTFやハッカソンなど、去年やり残したことをやっていきたいですねー。
f:id:denham:20210101013547p:plain
もっと草を生やし隊。

Open Hack頑張る!

Vuetifyでちょっとリッチな画面を作る

こんにちは!この記事はLOCAL学生部アドベントカレンダー22日目への寄稿です。

adventar.org

今回はVuetifyのUIコンポーネントはいいですね、というお話です。
vuetifyjs.com

Vue.js+Vuetifyの素振りとして自作のポートフォリオを作り直してみたのですが、ほぼCSSなしでいい感じにレイアウトを組めてとても良いですね。
実装されているコンポーネントの種類が豊富さが凄い。カレンダーやグリッドデザイン、カルーセルからタイムライン表示までetc.

基本的にはメインのコンポーネントに固有コンテンツを記述し、メニューバーはv-navigation-drawer, ヘッダーはv-app-bar,フッターはv-footerといったようにパーツ単位でUIコンポーネントを選択してレイアウトを組むことになりますが、プラモデルを組んでいる感覚に近いです。

ワイヤーフレームの例を見ていると、Discordのクローンなんかも作れそうですね。

余談ですがUIについて
mkan-0141.hatenablog.com このようなエントリーを見かけて、次はFlutterを使って何か作ってみようかなぁと考えています。

ちとせオンラインワークショップに参加した話

こんにちは。この記事はcistLTサークルアドベントカレンダー18日目への寄稿です!
adventar.org

技術系とは少し毛色が異なりますが、今回は11/28(土)に行われた、ちとせ創業支援オンラインセミナーのWSに参加した話をしたいと思います。

f:id:denham:20201211211853p:plain

本来は2部構成のWSのようですが、初回のほうは都合上参加できず、2回目となる28日に参加させていただいていました。

講師はPLAYWORKS代表のタキザワケイタさん。

プログラム前半で3分アイデアソンを行い、後半ではチーム分けを行い、ビジネスモデルキャンバスとストーリーボートの作成を通じて発想した事業を具体化する、という構成でした。

イデア発想法

「アイデアとは、既存の要素の新しい組合せ以外の何物でもない」
『アイデアのつくり方』J.ヤング(1988)

ヤング先生いわく、アイデアは既存のアイデアのかけあわせから生まれる。ということで、アイデアソンのテーマはかけあわせです。

f:id:denham:20201211220416p:plain

かけあわせとは?
お題となるテーマ×テーマから遠いモノをかけあわせ、強制発想(リフレーミングし、新しい価値を見つけ出すという考え方

イデアソンとは?
イデア×ラソンを意味する造語で、特定テーマについて短時間に集中してアイデアを出し合うイベント

今回のアイデアソンでは、3分間隔で新しい掛け合わせテーマが提示されるので、それら2つのテーマにまつわる要素をかけあわせた事業アイデアを出し続ける、ということを行いました。

たとえば
f:id:denham:20201211213337p:plain こちらは「和食」から連想される要素をかきだしてみて、プリンとの掛け合わせを考える、という例ですね。

f:id:denham:20201211214518p:plain
こちらはバスプリン。語感がよいです

出題テーマは千歳市×あつ森、Uber Eats、ペヤング、グランピングetc。

3分アイデアソン、実際やってみると想像以上にしんどいです笑
チームの皆さんの発想力豊かさに唸らされっぱなしでした。
柔軟な発想力ほしいです。頭の体操大事。

後半はチームに分かれて、アイデアソンであがった一つのテーマについてのブラッシュアップを行いました。

こうしたアイデア出し→具体化の手法は、起業にかかわらず、個人開発など色々な場面で活かしていけるなぁと思いました。

Vue.jsでユニットテストを書くために

この記事はLOCAL学生部アドベントカレンダー2020 15日目への寄稿です!
adventar.org

12日目はaruneko99さん。

今回は既存のVue-cliプロジェクトにJestでのテスト環境を構築したこと、その際にはまったところをかき起こしておきたいと思います。

Vue.jsでテストがしたい

Vue.jsでは単体テストの効率化のためにVue Test Utilsを提供しており、こちらはJestやMochaのようなテストランナーと組み合わせて使うのが一般的のようです。
ということで、*Jest+vue-test-utilsを導入してテストを試してみます。

環境
node v14.15.1 yarn 1.22.5 vue 2.6.12
@vue/test-utils 1.1.1

Jest+vue-test-utilsをyarn(npm)でインストール

yarn add -D @vue/test-utils babel-jest jest vue-jest

公式ドキュメント
Jest を使用した単一ファイルコンポーネントのテスト | Vue Test Utils にしたがって環境設定を行います。

package.jsonを編集

// package.json
{
  "scripts": {
    "test": "jest"
  },
    "jest": {
      "moduleFileExtensions": [
        "js",
        "json",
        "vue" // *.vue ファイルを処理するように Jest に指示する
      ],
      "transform": {
        ".*\\.(vue)$": "vue-jest", // vue-jest で *.vue ファイルを処理する
        "^.+\\.js$": "<rootDir>/node_modules/babel-jest" // babel-jest で js を処理する
        },
        "moduleNameMapper": { // ソースコードにある @ を src へと割当てる
          "^@/(.*)$": "<rootDir>/src/$1"
        }
   }
}

次にBabelの設定ファイルを編集します。Jestを使うときはbabel.config.jsまたは.babelrcの2通りの記法があるようですが、今回はすでに用意されていたbabel.config.jsのほうを編集します。

{
  "presets": [["env", { "modules": false }]],
  "env": {
    "test": {
      "presets": [["env", { "targets": { "node": "current" } }]]
    }
  }
}

ここまでの実行結果をみてみる

yarn testで実行します。

FAIL  src/models/order-item.test.js
Test suite failed to run

Cannot find module 'babel-preset-env' from '/home/denham/workspace'
- Did you mean "@babel/env"?

(中略)
Test Suites: 2 failed, 2 total
Tests:       0 total
Snapshots:   0 total
Time:        2.546 s

怒られた...

babel-preset-envが存在しないよといわれているので探します。
babel7における変更点で多くのパッケージがscoped packagesとして提供されるようになり、モジュール名にbabel- がついていたパッケージは@babel/にリネームされているようです。
ということで、babel.config.jsenv@babel/preset-envに書き換えてみます。

テストはファイル名.test.jsとすると自動検知してくれます。

Vue.jsは学習し始めて間もないですが、既存のソースコードのロジック、DOMの状態チェックなど考えなければならないことが多く、想像以上に検証コードを書くハードルは高そうです。

いれて便利なVSCodeExtention

vscode-jest
f:id:denham:20201215184339p:plain テストコード上でDebugが実行できたり、テスト結果をインライン表示してくれて便利。
この恩恵を被れるくらいにテストコードを書けるようになりたい(来年の抱負)

榊さんのアドカレ、勉強になります。

GASでユーザー登録フォームを作った

cistLTサークルのアドベントカレンダー4日目への寄稿です。

adventar.org

目的

友人と共同で制作し、10月のサークル合同LTで発表したWebサイト(未完成)chitose-fts.web.appにお気に入り機能追加したい。

合同LTcist-lt.connpass.comで使用したスライドについてはこちら

経緯

友人とGASを使って共同でまたやろうか、という運びになり

  • スプレッドシートでデータベースっぽいこともっとしたい
  • ユーザー登録ページ作ってお気に入り機能とか実装したいね
  • ページ遷移どうする? -> GASプロジェクトは基本1プロジェクト1htmlしか呼び出せない*1のでページ遷移大変そう...

などなどありました。

結果

わりとなんとかなりました。

実際に作成したページ
script.google.com スプレッドシート
docs.google.com

以下でソースコードと軽い解説を。

<!DOCTYPE html>
<html>

<head>
<base target=”_top”>
</head>

<body>
<h1>ユーザー登録フォーム</h1>

<form action="https://script.google.com/macros/s/AKfycbwLU-A0l5788vTO0sAXT1nL5VYWLNZqCt5hfy8vH8EFO_1rSvY/exec" method="post">
<p>
ユーザー名:<input type="text" name="namae">
</p>
<p>
性別:<br />
<input type="radio" name="gender" value="男性">男性<br />
<input type="radio" name="gender" value="女性">女性
</p>
<p>
<input type="submit" value="送信する">
<input type="reset" value="入力内容をリセットする">
</p>

</form>

</body>

</html>

<input>タグのname属性で付与した名前をスプレッドシートに書き込む際に受け渡します
<form>タグのaction属性でWEBアプリケーションとして公開したページのURLを指定しpostしています

<!DOCTYPE html>
<html>
<head>
<base target=”_top”>
</head>
<body>
送信が完了しました。<br><br>
<!-- ページ内遷移ここから -->
<?var url = getScriptUrl();?>
<input type="button" value="もう一度回答する" onclick="window.top.location.href = '<?!=url?>?page=kakunin';"/>
<!-- ここまで -->
</body>
</html>

ここの<input>タグでページを切り替えるためのボタンを作成しています。
onclicでwindow.top.location.href(現在のページの場所を指します)に<?!=url?>?page=kakunin';"/>を渡してあげることで
kakunin.htmlに遷移させてあげることができます。

function doGet(e) {
    Logger.log( Utilities.jsonStringify(e) );
    if (!e.parameter.page) {
        return HtmlService.createTemplateFromFile('index').evaluate();
    }  
  return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate(); /* page=kakuninのpage,この配列に"kakunin"のようなページ名が追加されていく */
}

function doPost(postdata){

var sh=SpreadsheetApp.openById('1juOUKCyip7z0EBwVFSLriP30whTEBvB_lYJV12ZtEuw');
var time=new Date();

var namae=postdata.parameters.namae.toString();
var gender=postdata.parameters.gender.toString();

sh.appendRow([time,namae,gender]);

  return HtmlService.createTemplateFromFile("result").evaluate();
}

function getScriptUrl() {
    var url = ScriptApp.getService().getUrl();
    return url;
}

doGet()では
function doGet(e)
で、e.parameterの中にURLのパラメーターが配列として格納され、
return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate()
で、URLのpage="kakunin"のパラメーターの値を取得し、変数pageに格納したものを戻り値として返しています

<input type=”submit”>でdoPost関数を呼び出した際の処理をみてみます。
今回のGASはスタンドアロンスクリプトで作成しているので
SpreadsheetApp.openById(“”)
とします。
(
部分に入るシートIDはスプレッドシートのURLのd/と/editの間
https://docs.google.com/spreadsheets/d/**********/edit#gid=597941997 で確認できます)

スクリプトと紐付いていないスプレッドシートを指定して取得しています。
引数で受け取ったオブジェクト型のpostdataをtoString()メソッドで文字列型に変換し、appendRowメソッドでスプレッドシートの最終行にtime,name,genderを追加しています。

感想

ネックだったページ遷移の問題は解決できたので、残る課題はログインページとお気に入り機能の実装ですね。
ゆくゆく着手していきたい。

またサークルのLTなどで何度かプレゼンしているのですが、GASのよいところは

①無料(お財布にやさしい)
②サーバーレスであること
スプレッドシートをデータベースとして代用できること
であると思います

制約のないレンサバはお金かかるし、データベースは学習コストが重いので、小規模でWeb開発したいとか、とりえあずデータベースつかってみたい
って人にもGASおすすめできると思うなぁという記事でした。

余談
f:id:denham:20201204181140p:plain
ページ上部のバナー、英文になってちょっと主張がおちついた感じ

*1:GASのHtmlServiceで提供されるHTMLはホスティングページではないため、Webアプリ公開時に作成されるURLが唯一のURLとなる

PostgreSQL導入備忘録(peer認証エラー)

環境

・Ubuntu18.04(WSL2)
・postgres (PostgreSQL) 11.2

問題

$ psql -U postgres -d postgres コマンドでpsqlにログインできず、 psql: error: FATAL: Peer authentication failed for user "postgres" なるエラーが表示される

原因

・peer認証が有効になっている

peer認証とは、ローカルからのアクセス時にpostgres(OS側)のユーザー名がpostgres(データベース側)のものと一致している場合のみ接続を許可する認証方法で、ここが不一致のために怒られているらしい

解決策

・postgres(OS側)のパスワードを設定
・postgres(データベース側)のパスワードを設定
・クライアント認証設定ファイルのgpg_hba.confを書き換える

$ sudo passwd postgres


$ su - postgres  
$ psql  
psql (11.2)  
Type "help" for help.  
  
postgres=#  

以下のSQL文を実行してパスワードを設定
ALTER USER postgres with encrypted password 'パスワード';

次にfindコマンドでpg_hba.confを探します
$ sudo find / -name pg_hba.conf

自分の環境では
/etc/postgresql/13/main下にありました

# Database administrative login by Unix domain socket  
local   all             postgres                                peer  

の行をみてみる
postgresユーザーからの接続がデフォルトではpeerとなっているので、ここを
peer→md5
と変更

$ /etc/init.d/postgresql restartpsqlを再起動

補足

公式ドキュメント
に従ってインストール後、psqlコマンドを実行すると

error: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

というエラー文が表示される

$ pg_lsclusterspsqlのstatusを確認→サーバーがダウンしている模様

10  main    5432 down   postgres  /var/lib/postgresql/13/main /var/log/postgresql/postgresql-13-main.log

$ /etc/init.d/postgresql startで起動
statusがonline postgresになっていればOK

参考 ryotatake.hatenablog.com www.utsushiiro.jp