はじめに
LIFF InspectorとLIFF Mockをリリースされたとのことで。ローカルでのテストが楽になりそうなLIFF Mockを早速使ってみることにします。
やってみる
サンプルコードとしてこちらも最近リリースされたcreate-liff-appを使います。まずはプロジェクトの作成。設定は好みで。
npx @line/create-liff-app
Need to install the following packages:
@line/create-liff-app
Ok to proceed? (y) y
Welcome to the Create LIFF App
? Enter your project name: (my-app) my-app
? Which template do you want to use? react
? JavaScript or TypeScript? TypeScript
? Please enter your LIFF ID: xxxxxx
? Do you want to install it now with package manager? (Y/n) Yes
? Which package manager do you want to use? yarn
あとでMock化するのでLIFF IDは適当にxxxxxx
としておきました
@line/liff-mock
を追加します
cd my-app
yarn add @line/liff-mock
開発環境を起動します
yarn dev
http://localhost:3000/にアクセスするとサンプルアプリが表示されます。存在しないLIFF IDを設定したためliff.ini()
が失敗しています
src/App.tsx
を以下のように更新してLIFF Mock pluginを追加します
import { useEffect, useState } from "react";
import liff from "@line/liff";
import "./App.css";
import { LiffMockPlugin } from '@line/liff-mock';
liff.use(new LiffMockPlugin());
function App() {
const [message, setMessage] = useState("");
const [error, setError] = useState("");
useEffect(() => {
liff
.init({
liffId: import.meta.env.VITE_LIFF_ID,
mock: true, // enable mock mode
})
.then(() => {
setMessage("LIFF init succeeded.");
})
.catch((e: Error) => {
setMessage("LIFF init failed.");
setError(`${e}`);
});
});
return (
<div className="App">
<h1>create-liff-app</h1>
{message && <p>{message}</p>}
{error && (
<p>
<code>{error}</code>
</p>
)}
<a
href="https://developers.line.biz/ja/docs/liff/"
target="_blank"
rel="noreferrer"
>
LIFF Documentation
</a>
</div>
);
}
export default App;
npm-typescript-exampleを参考にtypes/liff.d.ts
を追加します。TypeScriptの場合この型定義がないと型エラーが発生します
import { ExtendedInit, LiffMockApi } from '@line/liff-mock';
declare module '@line/liff' {
interface Liff {
init: ExtendedInit;
$mock: LiffMockApi;
}
}
LIFF Mockを追加するとliff.init()
が成功するようになりました。うまくMock化できたようです。
Mock化されたliff.getProifle()
を呼んでみます。取得したプロファイルはsetMessage()
を拝借して表示してみます
import { useEffect, useState } from "react";
import liff from "@line/liff";
import "./App.css";
import { LiffMockPlugin } from '@line/liff-mock';
liff.use(new LiffMockPlugin());
function App() {
const [message, setMessage] = useState<string>("");
const [error, setError] = useState("");
useEffect(() => {
const f = async () => {
const options = {
liffId: import.meta.env.VITE_LIFF_ID,
mock: true, // enable mock mode
};
try {
await liff.init(options);
if (!liff.isLoggedIn()) {
liff.login();
const profile = await liff.getProfile();
setMessage(JSON.stringify(profile));
}
} catch (e) {
setMessage("LIFF init failed.");
setError(`${e}`);
}
};
f();
});
return (
<div className="App">
<h1>create-liff-app</h1>
{message && <p>{message}</p>}
{error && (
<p>
<code>{error}</code>
</p>
)}
<a
href="https://developers.line.biz/ja/docs/liff/"
target="_blank"
rel="noreferrer"
>
LIFF Documentation
</a>
</div>
);
}
export default App;
実行するとダミーのプロファイルが取得できました
おもしろいので他のメソッドもモック化されているのか試してみました。scanCodeV2()
を呼んでみます
try {
await liff.init(options);
if (!liff.isLoggedIn()) {
liff.login();
const scaned = await liff.scanCodeV2();
setMessage(JSON.stringify(scaned));
}
} catch (e) {
setMessage("LIFF init failed.");
setError(`${e}`);
}
QRコードのスキャン結果としてhttps://line.me
が返ってきました
liff.sendMessages()
もエラーなく正常に実行されました
try {
await liff.init(options);
if (!liff.isLoggedIn()) {
liff.login();
await liff.sendMessages([ { type: "text", text: "Hello, World!", } ]);
setMessage('Message sent');
}
} catch (e) {
setMessage("LIFF init failed.");
setError(`${e}`);
}
liff.$mock.set()
を利用してMock APIが返すデータを設定することができます
import { useEffect, useState } from "react";
import liff from "@line/liff";
import "./App.css";
import { LiffMockPlugin } from '@line/liff-mock';
liff.use(new LiffMockPlugin());
liff.$mock.set((p) => ({
...p,
getProfile: { displayName: 'bathtimefish', userId: '123456789' },
}));
function App() {
const [message, setMessage] = useState<string>("");
const [error, setError] = useState("");
useEffect(() => {
const f = async () => {
const options = {
liffId: import.meta.env.VITE_LIFF_ID,
mock: true, // enable mock mode
};
try {
await liff.init(options);
if (!liff.isLoggedIn()) {
liff.login();
const profile = await liff.getProfile();
setMessage(JSON.stringify(profile));
}
} catch (e) {
setMessage("LIFF init failed.");
setError(`${e}`);
}
};
f();
});
return (
<div className="App">
<h1>create-liff-app</h1>
{message && <p>{message}</p>}
{error && (
<p>
<code>{error}</code>
</p>
)}
<a
href="https://developers.line.biz/ja/docs/liff/"
target="_blank"
rel="noreferrer"
>
LIFF Documentation
</a>
</div>
);
}
export default App;
liff.$mock.clear()
はliff.$mock.set()
で設定したデータをデフォルト値に戻します
liff.$mock.set((p) => ({
...p,
getProfile: { displayName: 'bathtimefish', userId: '123456789' },
}));
....
await liff.init(options);
if (!liff.isLoggedIn()) {
liff.login();
liff.$mock.clear();
const profile = await liff.getProfile();
// {"displayName":"Brown","userId":"123456789","statusMessage":"hello"}
setMessage(JSON.stringify(profile));
}
現時点でLIFF MockのAPIは以上です
おわりに
ローカルでLIFFアプリを開発する場合は一部のAPIがローカルで正常に動作しないのを回避するために工夫する必要がありました。LIFF Mockプラグインを使うことでその苦労がなくなります。個人的にはプロトタイピングする前にチャンネルを作ったりLIFF IDやLIFF URLを生成したりする手間がなくLIFF APIを試せるのが気持ちよくなったところです。
これからLIFFアプリを開発しようとする方はcreate-liff-appとLIFF Mockを利用してカジュアルにLIFF APIを試してみるところからはじめるといいんじゃないでしょうか。