Sencha Architect と Sencha Test の開発環境に REST API モックサーバーを追加する手順をメモっとく。
この記事では、Ext.ux.ajax.SimManager
と Ext.ux.ajax.Simlet
を用いて REST API のモックサーバーを Sencha Architect と Sencha Test の開発環境に追加する。そうすることでコンポーネントごとにサーバーとの通信が発生するテストを書けるようにしている。
Sencha Architect と Sencha Test で開発環境を構築するの続き。
前提条件
この記事では下記バージョンの Sencha ツール群を使用している。
Tool | Version |
---|---|
Sencha Architect | 4.2.7 |
Sencha Ext JS | 7.1.0.48 |
Sencha Cmd | 7.1.0.16 |
Sencha Test | 2.3.0.328 |
REST API モックサーバーを追加する
app.json にある依存パッケージの設定に "ux"
を追加する。Ext.ux.ajax.SimManager
と Ext.ux.ajax.Simlet
を使用するために必要な設定になる。
$ sed -i "" 's|"font-awesome"$|"font-awesome", "ux"|' test/app.json
RestSimlet.js と Server.js を app ディレクトリに追加する。
Ext.define('RestSimlet', {
extend: 'Ext.ux.ajax.JsonSimlet',
alias: 'simlet.rest',
doGet: function (ctx) {
ctx.matches = this.getMatches(ctx);
return this.callParent(arguments);
},
doPut: function (ctx) {
return this.doGet(ctx);
},
doDelete: function (ctx) {
return this.doGet(ctx);
},
privates: {
getMatches: function (ctx) {
var url = ctx.url.split(/\?|#/)[0],
pattern = ctx.xhr.simlet.url;
return url.match(pattern);
}
}
});
Ext.define('Server', {
requires: [
'RestSimlet'
],
singleton: true,
start: resources => {
Ext.ux.ajax.SimManager.init({
defaultType: 'rest',
delay: 0
}).register([{
url: RegExp('^/(\\w+)(/(\\d+))?$'),
data: ctx => {
var method = ctx.method.toUpperCase(),
resource = ctx.matches[1],
id = Number(ctx.matches[3]);
resources = resources || {};
resources[resource] = resources[resource] || [];
var records = resources[resource];
switch (method) {
case 'GET':
if (id) {
var index = records.findIndex(record => record.id === id);
if (index < 0) {
this.status = 404;
this.statusText = 'Not Found';
return;
} else {
this.status = 200;
this.statusText = 'OK';
return records[index];
}
} else {
this.status = 200;
this.statusText = 'OK';
return records;
}
case 'POST':
if (id) {
this.status = 405;
this.statusText = 'Method Not Allowed';
return;
} else {
var record = Ext.decode(ctx.xhr.body);
if (record) {
record.id = records.reduce((maximum, record) => Math.max(maximum, record.id), 0) + 1;
records.push(record);
this.status = 201;
this.statusText = 'Created';
return record;
} else {
this.status = 400;
this.statusText = 'Bad Request';
return;
}
}
case 'PUT':
if (id) {
var record = Ext.decode(ctx.xhr.body);
if (record) {
record.id = id;
var index = records.findIndex(record => record.id === id);
if (index < 0) {
records.push(record);
this.status = 201;
this.statusText = 'Created';
return record;
} else {
records[index] = record;
this.status = 200;
this.statusText = 'OK';
return record;
}
} else {
this.status = 400;
this.statusText = 'Bad Request';
return;
}
} else {
this.status = 405;
this.statusText = 'Method Not Allowed';
return;
}
case 'DELETE':
if (id) {
var index = records.findIndex(record => record.id === id);
if (index < 0) {
this.status = 404;
this.statusText = 'Not Found';
return;
} else {
records.splice(index, 1);
this.status = 204;
this.statusText = 'No Content';
return;
}
} else {
this.status = 405;
this.statusText = 'Method Not Allowed';
return;
}
}
}
}]);
},
stop: () => Ext.ux.ajax.SimManager.simlets = []
});
app.js に依存クラスとして Server
を追加する。
/*
* This call registers your application to be launched when the browser is ready.
*/
Ext.application({
requires: [
'Ext.Panel',
'Server'
],
name: 'ExampleTest',
launch: () => {
var config = { floated: true, right: 0, bottom: 0 };
if (Ext.isChrome) Ext.merge(config, { iconCls: 'x-fab fa-chrome', title: 'Chrome' });
if (Ext.isEdge ) Ext.merge(config, { iconCls: 'x-fab fa-edge', title: 'Edge' });
if (Ext.isGecko ) Ext.merge(config, { iconCls: 'x-fab fa-firefox', title: 'Firefox' });
if (Ext.isOpera ) Ext.merge(config, { iconCls: 'x-fab fa-opera', title: 'Opera' });
if (Ext.isSafari) Ext.merge(config, { iconCls: 'x-fab fa-safari', title: 'Safari' });
Ext.create('Ext.Panel', config).show();
}
});
$ git add .
$ git commit -m "Add REST API mock server"
REST API モックサーバーの動作を確認する
Sencha Architect を開く。
User モデルを作成する。
- userClassName: User
- fields:
- id
- name
- proxy:
- type: rest
- url: /users
Users ストアを作成する。
- userClassName: Users
- storeId: Users
- autoLoad: true
- model: Example.model.User
- data:
[
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
{ id: 4, name: "Dave" }
]
Users グリッドを作成する。デザインビューにレコードが表示されていれば動作している。
- userClassName: Books
- store: Users
- columns:
- Column
- xtype: gridcolumn
- flex: auto
- width: (none)
- dataIndex: id
- text: id
- Column
- xtype: gridcolumn
- flex: 1
- width: (none)
- dataIndex: name
- text: name
- Column
Sencha Architect のプロジェクトを保存する。そして、プレビューをクリックし、下記のように表示されていれば実装がきちんとできている。
Sencha Studio で Jasmine テストスイートを UsersTest という名前で作成する。
Users
グリッドに自動ロードで5件のユーザーが読み込まれることを確認するテストを記述する。
ここで beforeEach
メソッドで、REST API モックサーバーを開始させ、テスト対象の Users
ストアと Users
コンポーネントを生成し、テストアプリケーションのビューポートにコンポーネントを追加している。テストではそのグリッドを取得し、グリッドが参照するストアのレコード数が5であることを検証している。afterEach メソッドでテストのために生成したストアとコンポーネントを破棄し、REST API モックサーバーを停止させ、ひとつのテストケースが完了する。
describe("UsersTest", function () {
let store;
let component;
beforeEach(function () {
Server.start({
users: [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
{ id: 4, name: "Dave" },
{ id: 5, name: "Eve" }
]
});
store = Ext.create("Example.store.Users");
component = Ext.create("Example.view.Users");
Ext.getApplication().viewport.add(component);
});
afterEach(function () {
component.destroy();
store.destroy();
Server.stop();
});
it("loads 5 records", function () {
ST.grid("users")
.and(grid => {
var users = grid.getStore();
expect(users.count()).toBe(5);
});
});
});
このテストが無事に完了すれば開発環境に REST API モックサーバーを追加できたことになる。
この記事では Sencha Architect と Sencha Test の開発環境に REST API モックサーバーを追加する方法について説明した。SPA のコンポーネントテストも高速に実現できる環境なので、興味のある人はトライアル版で試してみてほしい。