lesson-3_ダウンロード機能を実装しよう
🛸 IPFS へファイルをアップロードする
次のステップは、Webアプリケーションへの商品の追加です。
商品データをサーバーやクラウドストレージに保存しておくこともできますが、今回はIPFSを利用します。
IPFSはInterPlanetary File Systemの略で、データを分散的に保存してくれる分散型ストレージです。
IPFSに保存されたデータは一定期間内にアクセスがないと消えてしまう可能性があるので、ユーザーは定期的にストレージにアクセス(ピン)する必要があります(今回のチュートリアルでは実施しません)。
※IPFSの詳細については ここ を参照してみてください。
今回はIPFS pinning serviceのPinataを利用します。
それでは、Pinataを利用してIPFSに画像をアップロードしてください。
※アップロードするためにはPinataにログイン後、ページ右上の+ Add Files
-> File
と進みます。
続いて、アップロードした画像の「Content Identifier(CID)」の欄に記載されたIDハッシュをコピーしておきましょう。
CIDはIPFS上でコンテンツにアクセスするためのアドレスで、以 下のようなリンクを作成してアクセスすることができます。
https://cloudflare-ipfs.com/ipfs/あなたの画像ファイルのCID
🎈 IPFS からファイルをダウンロードする
hooks
フォルダ内にIPFSゲートウェイのURLにハッシュとファイル名を追加するuseIPFS.js
ファイルがあります。
これは、フロントエンド側でIPFSからのダウンロードの動作を担うものです。
useIPFS()
を使うため、components
フォルダの中にIpfsDownload.js
ファイルを作成し、useIPFS()
を呼び出すコンポーネントを作成していきます。
// IpfsDownload.js
import useIPFS from "../hooks/useIPFS";
const IPFSDownload = ({ hash, filename }) => {
const file = useIPFS(hash, filename);
return (
<div>
{file ? (
<div className="download-component">
<a className="download-button" href={file} download={filename}>
Download
</a>
</div>
) : (
<p>Downloading file...</p>
)}
</div>
);
};
export default IPFSDownload;
ダウンロードリンクを描画するだけのシンプルなコンポーネントです。
では、テストスクリプトを実行して模擬的に動作確認をしてみましょう。
簡単にテストの内容を説明します。__tests__/IpfsDownload.test.js
では、コンポーネントに仮の値を渡して期待する結果がDownloadリンクに設定されているかをテストしています。
最初に、テストで使用する仮の値を設定します。
// __tests__/IpfsDownload.test.js
/** 準備 */
/** IPFSDownloadコンポーネントに渡す引数と、useIPFSフックの戻り値を定義します */
const mockHash = "hash";
const mockFilename = "filename";
const mockFile = `https://gateway.ipfscdn.io/ipfs/${mockHash}?filename=${mockFilename}`;
useIPFS.mockReturnValue(mockFile);
モック(Mock)という言葉は、実際のものや状況を「模倣」するものを指します。
テストにおいては、実際のオブジェクトや関数の代わりに使用される模擬的なオブ ジェクトや関数を指します。上記のテストスクリプトでは、コンポーネントに渡す引数・useIPFSフックをモックしています。これにより、テスト対象のコードとそれ以外の部分(コンポーネントの外から渡されるデータや外部モジュールなど)を分離し、テスト対象のコードのみを独立してテストできるようになります。
次に、対象コンポーネントのレンダリングを行います。ここで、先ほど定義した値を渡しています。
// __tests__/IpfsDownload.test.js
/** 実行 */
render(<IPFSDownload hash={mockHash} filename={mockFilename} />);
最後に、テスト対象のコンポーネントが期待する結果を返しているかをテストします。
// __tests__/IpfsDownload.test.js
/** 確認 */
const linkElement = screen.getByRole("link", {
name: /Download/i,
});
/** useIPFSフ ックが呼び出され、ダウンロードリンクが適切に設定されていることを確認します */
expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute("href", mockFile);
expect(linkElement).toHaveAttribute("download", mockFilename);
screen.getByRole()
は、指定されたrole
属性を持つ要素を返します。今回テスト対象のコンポーネントでは、下記の要素が該当します。
<a className="download-button" href={file} download={filename}>
Download
</a>
それではテストスクリプトを実行してみましょう。package.json
ファイルのjestコマンドを更新してIPFSDownloadコンポーネントのテストのみ実行されるようにします。
// package.json
"scripts": {
// 下記に更新
"test": "jest IpfsDownload.test.js"
}
jestコマンドを更新したら、ターミナルでyarn test
を実行してみましょう。
yarn test
テストがパスしたら、IPFSDownloadコンポーネントの実装は完了です。