Many classes have shortcut names used when creating (instantiating) a class with a
configuration object. The shortcut name is referred to as an alias
(or xtype
if the
class extends Ext.Component). The alias/xtype is listed next to the class name of
applicable classes for quick reference.
Framework classes or their members may be specified as private
or protected
. Else,
the class / member is public
. Public
, protected
, and private
are access
descriptors used to convey how and when the class or class member should be used.
Public classes and class members are available for use by any other class or application code and may be relied upon as a stable and persistent within major product versions. Public classes and members may safely be extended via a subclass.
Protected class members are stable public
members intended to be used by the
owning class or its subclasses. Protected members may safely be extended via a subclass.
Private classes and class members are used internally by the framework and are not intended to be used by application developers. Private classes and members may change or be omitted from the framework at any time without notice and should not be relied upon in application logic.
static
label next to the
method name. *See Static below.Below is an example class member that we can disect to show the syntax of a class member (the lookupComponent method as viewed from the Ext.button.Button class in this case).
Let's look at each part of the member row:
lookupComponent
in this example)( item )
in this example)Ext.Component
in this case). This may be omitted for methods that do not
return anything other than undefined
or may display as multiple possible values
separated by a forward slash /
signifying that what is returned may depend on the
results of the method call (i.e. a method may return a Component if a get method calls is
successful or false
if unsuccessful which would be displayed as
Ext.Component/Boolean
).PROTECTED
in
this example - see the Flags section below)Ext.container.Container
in this example). The source
class will be displayed as a blue link if the member originates from the current class
and gray if it is inherited from an ancestor or mixed-in class.view source
in the example)item : Object
in the example).undefined
a "Returns" section
will note the type of class or object returned and a description (Ext.Component
in the
example)Available since 3.4.0
- not pictured in
the example) just after the member descriptionDefaults to: false
)The API documentation uses a number of flags to further commnicate the class member's function and intent. The label may be represented by a text label, an abbreviation, or an icon.
classInstance.method1().method2().etc();
false
is returned from
an event handler- Indicates a framework class
- A singleton framework class. *See the singleton flag for more information
- A component-type framework class (any class within the Ext JS framework that extends Ext.Component)
- Indicates that the class, member, or guide is new in the currently viewed version
- Indicates a class member of type config
- Indicates a class member of type property
- Indicates a class member of type
method
- Indicates a class member of type event
- Indicates a class member of type
theme variable
- Indicates a class member of type
theme mixin
- Indicates that the class, member, or guide is new in the currently viewed version
Just below the class name on an API doc page is a row of buttons corresponding to the types of members owned by the current class. Each button shows a count of members by type (this count is updated as filters are applied). Clicking the button will navigate you to that member section. Hovering over the member-type button will reveal a popup menu of all members of that type for quick navigation.
Getting and setter methods that correlate to a class config option will show up in the methods section as well as in the configs section of both the API doc and the member-type menus just beneath the config they work with. The getter and setter method documentation will be found in the config row for easy reference.
Your page history is kept in localstorage and displayed (using the available real estate) just below the top title bar. By default, the only search results shown are the pages matching the product / version you're currently viewing. You can expand what is displayed by clicking on the button on the right-hand side of the history bar and choosing the "All" radio option. This will show all recent pages in the history bar for all products / versions.
Within the history config menu you will also see a listing of your recent page visits. The results are filtered by the "Current Product / Version" and "All" radio options. Clicking on the button will clear the history bar as well as the history kept in local storage.
If "All" is selected in the history config menu the checkbox option for "Show product details in the history bar" will be enabled. When checked, the product/version for each historic page will show alongside the page name in the history bar. Hovering the cursor over the page names in the history bar will also show the product/version as a tooltip.
Both API docs and guides can be searched for using the search field at the top of the page.
On API doc pages there is also a filter input field that filters the member rows
using the filter string. In addition to filtering by string you can filter the class
members by access level and inheritance. This is done using the checkboxes at the top of
the page. Note that filtering out private
members also filters the API class
navigation tree.
Clicking on an empty search field will show your last 10 searches for quick navigation.
Each API doc page (with the exception of Javascript primitives pages) has a menu view of metadata relating to that class. This metadata view will have one or more of the following:
Ext.button.Button
class has an alternate class name of Ext.Button
). Alternate class
names are commonly maintained for backward compatibility.Runnable examples (Fiddles) are expanded on a page by default. You can collapse and expand example code blocks individually using the arrow on the top-left of the code block. You can also toggle the collapse state of all examples using the toggle button on the top-right of the page. The toggle-all state will be remembered between page loads.
Class members are collapsed on a page by default. You can expand and collapse members using the arrow icon on the left of the member row or globally using the expand / collapse all toggle button top-right.
Viewing the docs on narrower screens or browsers will result in a view optimized for a smaller form factor. The primary differences between the desktop and "mobile" view are:
The class source can be viewed by clicking on the class name at the top of an API doc page. The source for class members can be viewed by clicking on the "view source" link on the right-hand side of the member row.
Sencha Studio 允许开发人员快速和自动测试一个应用程序或 web 页面的细微粒度方面。随着代码库的增长,单元 测试可以确保应用程序的所有部分按照你的预期运行。
本指南, 我们学习生成一个新的应用程序,并设置测试环境, 创建一个可测试的类, 并对它进行单元测试. 所有这些工作都可以在 Sencha Studio 中完成.
如果你有一个已存在的应用程序, 请看 测试已有应用程序.
本文假定你已经对 Jasmine 测试框架比较熟悉. 如果你不熟悉 Jasmine 或 测试的概念, 请查阅他们优秀的 文档,来获取更多关于编写 Jasmine 测试的信息. 本指南也使用了 Sencha Cmd 来生成 一个 Ext JS 应用程序,并假定你已经下载安装它了.
让我们开始吧!
先打开 Sencha Studio.
你可以在 Sencha Studio 工具栏上点击下面的菜单来生成你需要的 workspace:
Sencha Studio -> New -> Workspace...
选择合适的文件路径,然后点击 "OK". 你会发现新生成的 workspace 中有一个测试项目了.
接下来, 我们添加一个应用程序到这个新的 workspace 中.
简单起见, 我们生成一个 Classic 应用程序到我们的 workspace 中. 我们也可以用 Sencha Test 来生成应用程序!
点击下面的菜单即可:
Sencha Studio -> New -> Application...
接着, 输入应用程序名称, 选择 classic, 然后把 workspace 的位置作为保存论斤. 你的应用程序就会出现在 workspace 下面了.
这个简单的应用程序只有很少的功能, 所以我们来加点东西用于测试. 此处, 我们创建一个 WindowEditor 类,在 MyApp/app/view/main/WindowEditor.js
文件里,你可以使用任何 IDE 编写. 你可以使用下面这段代码:
Ext.define('MyApp.view.main.WindowEditor', {
extend: 'Ext.Window',
alias: 'widget.windoweditor',
width:400,
height:200,
padding:20,
autoShow: true,
title: 'Update Email',
items: [{
xtype: 'form',
items: [{
xtype: 'textfield',
allowBlank: false,
vtype: 'email'
},{
xtype: 'button',
text: 'Submit Change',
formBind: true
}]
}]
});
该类继承 window,里面有一个 form, form 里面包含一个文本框和一个按钮. 我们指明了文本框不允许为空而且必须输入一个邮箱地址.
此外, 我们还把按钮的 formBind
配置为了 true. 这表明,如果表单验证不通过,按钮则一直处于不可用状态. 一旦验证通过, 按钮就可以被点击了.
你还可以把 MyApp/app/view/main/MainController.js
的 onItemSelected
函数替换为下面的代码:
onItemSelected: function (sender, record) {
Ext.create('MyApp.view.main.WindowEditor');
}
这将为表格打开一个 email editor. 在 Sencha Studio 创建接下来的测试之前,最好不要修改控制器的代码. 也就是说,你会发现,你的应用程序的创建逻辑,和你接下来要写的测试 spec 是平行执行的.
我们最终会使用这个类来测试,当输入的文本满足我们的规定的时候,按钮是否能够成功启用/禁用。
注意: 这个 "editor" 此时其实还没啥功能, 不过已经满足我们测试的需要了.
我们选择 "Applications" 下的 "Tests" 节点,来设置测试项目. 再点击右手边明细页的 "Initialize Test Project". 点击之后, 你会看到一些项目设置. 此时我们还不需要变动它们. 不过, 如果你改了设置, 记得点击 "Save" 才能生效.
下面, 我们来添加一个应用程序场景(scenario).
一个测试项目必须要有 “场景”, 而后才能添加一套测试 specs.
场景 - 场景下包含了接下来要创建的测试套件.
要创建一个场景, 点击 Scenarios 标题下面的 "+ Add" 按钮. 然后你可以改变场景的名称和文件路径. 通常, 你会基于你将要测试的内容来命名. 此处, 我们取名 "WindowEditor". 添加完之后, 一定要点击 "Save". 现在我们可以添加一套测试 specs 到场景中了.
现在你可以看到 “WindowEditor” 是 "Tests" 的一个子节点. 点击它, 你会看到一个浏览器列表,还有一个带有 "无测试用例(No tests found)" 字样的面板. 我们来改变它!
我们来添加一个 Jasmine 测试套件.
套件 - 套件是一个文件,包含了一组 代表应用程序某些方面 的测试. 这些方面可以是一个类,一个组件,或者是一组方法. 具体地,还要取决于你是如何组织你的测试套件的.
"右击" “Window Editor” 节点,然后点击 "New->Jasmine Test Suite". 弹出了一个模态对话框,需要你输入套件名称. 我们取名叫 "WindowValidation" 吧.
添加好之后, 可以看到 "WindowEditor" 底下多了个 "WindowValidation.js" 文件. 点击这个文件,会看到一段默认代码,方便我们开始.
describe("my test suite", function() {
it("should pass", function() {
expect(1).toBe(1);
});
});
为了便于使用, "右击" WindowValidation.js
标签页,点击 "Move Right". 这个操作会将WindowEditor和你的 场景的测试运行器分隔开来. 这样,改动之后,可以很快地测试它们.
目前套件中的代码没什么用处, 我们来给它添加一个 spec.
Spec - 指的是一个单独的测试,用一个 JavaScript 函数的形式来解释你的程序应该完成什么. 我们应当用简单的语言来解释测试所期望的结果是什么. 然后提供 JavaScript 代码执行测试,以达到期望.
需要注意的是,对于创建类和获得对组件的引用来说,多次测试可能会并行应用程序代码的多个方面.
暂时我们先复制下面的代码到你的 WindowEditor.js
文件,然后点击 "Save":
describe("formBind true", function() {
it("should disable button if email is not valid", function(done) {
// Create and reference the WindowEditor and then
// get reference to the button and textfield
var win = Ext.create('MyApp.view.main.WindowEditor'),
button = win.down('button'),
field = win.down('textfield');
// Set the field's value to a valid email address
// in order to have the button fire an enable event
field.setValue('valid@email.com');
button.on('enable', function() {
// Set the field's value to an invalid email address (nothing)
// in order to have the button fire a disable event
field.setValue('');
button.on('disable', function() {
// Once the disable event has been called after setting a
// bad value, we can safely say that the button is properly
// hooked into the form's validity. Thusly, we can
// alert the spec to return by calling the done function.
done();
});
});
});
});
可以看到, 我们测试了表单是否验证通过会改变按钮的可用状态. 如果文本框的值有效, 表单验证通过, 按钮就可用. 相反的, 如果输入框值无效,表单验证不通过,按钮就不可用. 这种行为是由于按钮的 formBind
配置被设置为 true
.
我们可以用过监听按钮的 enable/disable 事件来测试这些条件是否达到. 如果按钮触发了 "enable", 我们就知道表单通过了验证. 如果按钮触发了 "disable" 事件, 那么表单就没有通过验证. 此时, 我们就认为测试成功,然后调用 Jasmine 的 done()
函数.
很多情况下, 你应该使用一个断言(expectation)来确保结果满足你的要求. 断言使用 expect 函数, 此函数接收一个值, 称作实际值. 然后通过一个接收期望值的 Matcher 函数将2者链接起来. 断言的结果是 true/false, 或者也称作 pass/fail.
也就是说, 这个例子中我们不需要使用断言. done()
函数会作为参数传递给 it()
方法. 当我们决定执行完毕时,我们可以简单调用 done()
函数. 在处理异步测试时,
done()
通常作为一个 "成功" 回调. 不过此处, 我们可以用 done()
,而不需要设置一个断言. 因为在最后的事件中, 我们知道测试已经满足了, 所以不需要断言. 如果最后的事件永远触发不了, done()
就不会被调用, 测试就会在5秒后超时, 表示测试失败了.
现在我们有了一个测试用例, 我们来执行它,以确保我们的应用程序编辑器正确实现了表单验证.
现在已经连接上了测试, 我们用本地浏览器(local browser)运行一下.
首先, 在 Workspace 导航视图上选择 "WindowEditor" 场景节点,以便显示场景的测试执行标签页. 然后, 在测试执行标签页左侧,根据你的需要选择浏览器. 此处, 我们选择 Chrome.
选择完成后, 你会发现你选择的浏览器正在打开你的应用程序.
注意: 如果 "sencha app watch" 正在初始化, 你会在应用程序节点右侧看到一个黄色的眼睛图标. 当图标变成黑色的时候,浏览器才会打开, 表示 "app watch" 初始化完成.
在 WindowEditor 的测试运行器中选择 "WindowValidation.js", 然后点击顶栏的 "Run Selection" . 如果一切正常, 你会得到一个绿色的勾,表示测试执行通过.
再来看看测试失败时发生什么, 我们来改一下测试用例的代码,强制使得测试执行失败.
我们把下面的代码:
// Set the field's value to a valid email address
// in order to have the button fire an enable event
field.setValue('valid@email.com');
改为:
field.setValue('');
可以想象, 这个改动会使得输入框值无效,按钮的 enable 事件永远不会触发,也就永远不会调用 done()
. 5 秒之后, 测试超时并执行失败.
保存 spec,然后重新执行一下. 你会看到一个红色的 "1". 表示一个 spec 失败了. 如果你展开 WindowValidation.js, 然后展开 formBind true
, 你会看到我们的 spec 后边跟着一个红色的 "x". 如果你点击红色的 "x", 你就可以在摘要面板上看到错误的摘要.
可以想象, 本指南只接触了通过 Sencha Studio 使用 Sencha Test 的表面. 希望本文为你提供了基础知识,来探索和发现 Sencha Studio 中更多功能强大的工具.
如果你有更多疑问, 或者 bug 报告, 请访问 Sencha Test 论坛.