ロコガイド テックブログ

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの技術部ブログです。主にトクバイ・ロコナビのサービス開発について発信しています。

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの技術部ブログです。
主にトクバイ・ロコナビのサービス開発について発信しています。

ゼロから始めるFigma Plugin③ 〜ユニットテスト編〜

eyecatch

こんにちはこんにちは!ロコガイドでバックエンド・Webフロントエンドを担当している @ar_tama です。
最近ハマっているものは、限りなくりんごジュースに近いサイダー、JK'S Farmhouse Ciders! お酒好きも苦手な人もきっと気に入るはず🥳

さて今回は、5月に id:rei-suzuki から紹介のあったFigma Plugin「Shinadashi」に導入したテストの仕組みとその周辺についての知見をお伝えします。

Figma Pluginにテストは必要か

みなさんはFigma Pluginの開発時にテストを書いていますか?
先人のプロジェクトたちを眺めてみても、(たとえ機構が複雑なものであっても) 意外なほどテストが書かれていない ように見受けられます。

個人的には「小規模な開発には不要だが、中〜大規模な開発には必要」と感じています。
今のところ両者の線引きは code.tsに全て押し込めるにはちょっとつらい規模になってきた 程度と置いており、これはちょうどBoilerplateの導入を検討するラインとも重なります。

さて、なぜテストの書かれたプラグインが少ないのか、いくつか仮説を立ててみました。

  1. TypeScriptで最低限の品質は担保できているから
  2. Run Pluginしたら動作をチェックできるから
  3. Figma Objectのスタブが難しいから
  4. そもそもテストを書く文化がないから

4の信憑性はさておいて、初めのうちは1の恩恵・2の動作チェックにより動作を担保できたとしても、分岐が増えてきたタイミングで早晩頭打ちになるでしょう。
OSSとして公開するのであればなおさら、コントリビューターが全ての動作を手動でテストするには限界があります。

と、そこで立ちはだかるのが3の壁。API経由で操作をするFigma世界のオブジェクト(便宜上Figma Objectと呼びます)は付け焼き刃のスタブが通用しにくい作りになっています。
基本的に複数のMixinの集合で型が定義されており、スタブするには全てのケースをカバーする必要があるためです。
Figma Objectの操作に関わらないところだけテストする(それで品質が担保できるように設計する)という手もありますが、そうもいかないケースのほうが多いでしょう。*1
同じように困っている人、絶対にいるはず!と思い必死で調べたら、ありました。

Figma API Stub

https://github.com/react-figma/figma-api-stub

React Figmaというプロジェクトの中で副産物として生まれたスタブ実装とのこと。
以下は、Jest上でこのFigma API Stubを用いた場合のサンプルコードです。

import { createFigma } from 'figma-api-stub'

// セットアップ
beforeEach(async () => {
  // @ts-ignore
  global.figma = createFigma({
      simulateErrors: true
  })
  await figma.loadFontAsync({ family: "Roboto", style: "Regular" })
})

describe('replacer', () => {
  it('replaces characters', async () => {
    // TextNodeを作成
    const node = figma.createText()
    node.name = '#Name'
    node.characters = ''

    // GroupNodeの作成もできる
    const group = figma.group([node], figma.currentPage)
    group.name = '#Component'

    // Figma Objectへの操作を実行
    await new Replacer(group).replace()

    // テスト
    expect(node.characters).toEqual(expectedName)
  })
)

すごく自然に書けますね!ありがたい〜

しかし、

⚠️ Warning! It's not official implementation and it hasn't purpose to fully reproduce Figma behavior and API.

とあるように、この実装では最低限のインターフェイスのみがサポートされていることに注意する必要があります。
ぱっと見た限りでは、(Rectangle)NodeのfillsやPaint、その他こまごまとしたAPIは実装がないようですね。
せっかくOSSとして公開されているので、折を見て試しに拡充のPRを出してみようかなと考えています*2

まとめ

Shinadashiは短期間で仕様と実装と夢がどんどん膨らみ、メンテナンスや動作チェックが難しくなってしまっていたのですが*3
Boilerplateとテストの導入により安心してリファクタを進めることができ、コードのダイエットにも無事成功しました。
Figma Plugin部は当座の目標を完遂してしばしの休部を迎えようとしていますが、一緒に開発をしてくれる仲間はいつでも募集中です(もちろんプラグイン以外も!)。
気になった方はTwitterやWantedlyなんかでいつでもお気軽にご連絡ください😉

*1:プラグインを作る動機の大半が入力に応じてFigma Objectを操作する(もしくはその逆)でしょうし

*2:もしかしたら、このスタブが彼らの必要以上に育つことは意図に反するのかもしれませんが…

*3:現場でもよく見るやつ〜