Commit 44149c53 authored by techird's avatar techird

remove spec

parent d2eb6994
{
"undef" : true,
"unused" : false,
"strict" : false,
"curly" : false,
"newcap" : true,
"trailing" : true,
"white": false,
"quotmark": false,
"predef" : [
"require",
"console",
"kity",
"KityMinder",
"KM",
"Minder",
"MinderNode",
"MinderEvent",
"Command",
"KITYMINDER_CONFIG",
"Utils",
"utils",
"describe",
"it",
"beforeEach",
"expect"
]
}
\ No newline at end of file
## 文件操作
- [ ] 创建新文件
- [ ] 操作:文件菜单点击新建
- [ ] 反馈:编辑区域剩一个跟节点,并且镜头会居中到根节点
- [ ] 反馈:草稿箱保存了上一个文件的内容
- [ ] 导入本地文件
- [ ] 操作:文件菜单点击导入
- [ ] 导入 .txt 格式
- [ ] 导入 .km 格式
- [ ] 导入 .xmind 格式
- [ ] 导入 .mm 格式
- [ ] 导入 .mmap 格式
- [ ] 操作:把文件拖放到编辑区域(格式同上述格式)
- [ ] 反馈:正确导入能显示文件正确的内容
- [ ] 节点树不缺不多
- [ ] 优先级和进度正确显示
- [ ] 超链接正确显示
- [ ] 反馈:错误的文件向用户提示文件损坏
- [ ] 草稿箱
- [ ] 加载完毕后加载上次打开的脑图
- [ ] 能打开草稿箱内容
- [ ] 草稿箱菜单的删除和清除功能正常
- [ ] 网盘文件
- [ ] 登录后,文件菜单上列出最近编辑的网盘脑图文件
- [ ] 点击脑图上的文件在编辑区加载其内容
- [ ] 格式支持同上
- [ ] 点击文件菜单的「保存到网盘」,文件保存到了个人的百度网盘上
- [ ] 文件保存
- [ ] 刚从网盘打开的文件,其状态是 「已保存」
- [ ] 新创建的文件、打开的文件发生了编辑,其状态是 「未保存」
- [ ] 「未保存」的文件在文件标题处会有一个 `*`
- [ ] 「未保存」的文件按 `Ctrl + S` 或点击「保存」菜单后,文件会保存到网盘上,状态变为「已保存」
- [ ] 如果当前文件「未保存」,草稿箱会记录其「未保存」的状态
- [ ] 可以创建新或打开其它文件,重新打开「未保存」的文件其状态依然是「未保存」,内容是上次编辑的内容
- [ ] 从网盘打开文件时,如果草稿箱的版本「未保存」,会打开草稿箱的版本。
- [ ] 如果再重新打开一次,会询问用户是否忽略未保存的版本,强制打开网盘的版本
- [ ] 文件分享
- [ ] 点击「分享」按钮,会生成一个分享链接
- [ ] 分享浮层中其它社交分享的信息正确
- [ ] 打开分享链接,会打开分享的脑图内容
## 工具箱
- [ ] 「工具箱」按钮点击切换工具箱的显示状态
## 节点操作
对于所有节点操作,都需要先有选中的节点,才能进行操作。
- [ ] 插入子节点
- [ ] 操作:按 Tab 插入
- [ ] 操作:右键菜单插入
- [ ] 操作:工具栏下拉菜单插入
- [ ] 反馈:选中节点产生了一个新的子节点,并且新节点文本被选中,进入编辑状态,同时布局会调整
- [ ] 插入兄弟节点
- [ ] 操作:按 Enter 插入
- [ ] 操作:右键菜单插入
- [ ] 操作:工具栏下拉菜单插入
- [ ] 反馈:选中节点产生了一个新的兄弟节点,并且新节点文本被选中,进入编辑状态,同时布局会调整
- [ ] 编辑节点
- [ ] 操作:按 F2 编辑
- [ ] 操作:右键菜单编辑
- [ ] 操作:工具栏下拉菜单编辑
- [ ] 反馈:节点进入编辑状态,文字全选
- [ ] 删除节点
- [ ] 操作:按 Del 删除
- [ ] 操作:右键菜单删除
- [ ] 操作:工具栏下拉菜单删除
- [ ] 反馈:节点被删除,同时布局会调整
- [ ] 展开/收起节点
- [ ] 点击非叶子节点上的 `-`,节点被收起
- [ ] 点击非叶子节点上的 `+`,节点被展开,展开后子树的展开收起状态跟收起前一致
- [ ] 点击工具栏上的「收起节点」按钮
- [ ] 如果选中了节点,会收起选中的节点
- [ ] 如果没有选中节点,会把所有节点收起至一级节点
- [ ] 点击工具栏上的「展开节点」按钮
- [ ] 如果选中了节点,会展开选中节点以及
- [ ] 节点拖动
- [ ] 节点不在编辑状态的时候可以随意拖动位置
- [ ] 节点拖动到同级节点的附近可以触发排序点,松开会将拖动的节点排序到指定的位置
- [ ] 节点拖动到非子树上的节点可以触发移动提示,松开会让拖动的节点变成目标节点的子节点
- [ ] 节点排序
- [ ] 可以用上述拖放的形式排序
- [ ] 可以使用 `Alt + Up``Alt + Down` 分别向上、向下调整顺序
- [ ] 节点复制、剪切、粘贴
- [ ] 使用 `Ctrl + C` 复制节点树到剪贴板
- [ ] 使用 `Ctrl + X` 剪切节点数到剪贴板
- [ ] 使用 `Ctrl + V` 粘贴节点树到目标节点
## 风格和模板设置
- [ ] 设置结构
- [ ] 使用「模板」下拉菜单可以切换脑图的布局形式
- [ ] 皮肤设置
- [ ] 使用「皮肤」下来菜单可以切换
- [ ] 老版本的文件打开
- [ ] 默认布局的使用「思维导图」的模板,使用「脑图经典」的皮肤
- [ ] 向下布局的使用「组织结构图」的模板,使用「温柔寒光」的皮肤
## 样式设置
- [ ] 工具栏上的「字体」、「字号」、「加粗」、「斜体」、「字体颜色」能正确设置
## 节点附件
- [ ] 使用工具栏或上下文菜单插入、移除超链接
- [ ] 超链接格式必须正确(只能是 HTTP 资源)
- [ ] 使用工具栏或上下文菜单插入、移除图片
- [ ] 图片资源必须存在
- [ ] 使用工具栏或上下文菜单设置优先级和进度
- [ ] 使用工具栏或上下文菜单设置资源
- [ ] 资源对话框会显示脑图上使用到的所有资源
- [ ] 可以对选中节点添加资源或勾选、取消资源
## 视野操作
- [ ] 可以使用工具栏上的「小手」按钮触发拖动模式,拖动模式可以随意拖动编辑区域
- [ ] 可以直接拖动根节点
- [ ] 可以使用触摸板双指拖动视野(Mac Chrome)
- [ ] 双击空白区域定位根节点到
- [ ] 可以使用工具栏上的「缩放组件」进行视野的缩放
//beforeEach( function () {
// // customMatcher 例子
// this.addMatchers( {
// //用的时候这么用:
// //expect('***').customMatchers(true);
// //expect('***').not.customMatchers(true);
//// customMatchers: function ( expected ) {
//// return expected === true;
//// },
//
// } );
//} );
This diff is collapsed.
/**
* Created by dongyancen on 14-3-26.
*/
var fs = require('fs');
var browsers = ['Chrome', 'Firefox', 'PhantomJS', 'IE'];
var result_forBrowser = {};
var jsonFileBasePath = './spec/coverage/json_files/';
var jsonFiles = fs.readdirSync(jsonFileBasePath);
var finalJsonFile = 'defaultFileName';
var curPath = '/spec';
var resultPath = 'spec/coverage';
//找出所有的json文件
for (var i = 0; i < jsonFiles.length; i++) {
// json文件名必须是有8位的日期和6位的时间戳如:-20140326_161249
if (!isJsonFiles(jsonFiles[i])) {
jsonFiles.splice(i, 1);
i--;
}
}
//没有找到合适的文件
if(jsonFiles.length==0)return;
//先排序 按时间从小到大 及从旧到新
jsonFiles.sort(function (f1, f2) {
var t1 = getFileTime(f1);//形如['-20140326_161249','20140326','161249']
var t2 = getFileTime(f2);
var dateDiff = parseInt(t1[1]) - parseInt(t2[1]);
if (dateDiff != 0)return dateDiff;
else return parseInt(t1[2]) - parseInt(t2[2]);
});
//以时间命名新的文件
finalJsonFile = getFileTime(jsonFiles[jsonFiles.length-1])[0].substring(1);
//如:20140326_161249
//取最新的
// 按浏览器类型分类 result_forBrowser属性形如:{'Crome':'filename1','Firefox':'filename2'}
for (i = 0; i < jsonFiles.length; i++) {
for (var j = 0; j < browsers.length; j++) {
if (eval('/' + browsers[j] + '/.test("' + jsonFiles[i] + '");')) {
eval('result_forBrowser.' + browsers[j] + '="' + jsonFiles[i] + '";');
}
}
}
//以上得到所有要合计的json文件
//读取,合计数字,需要合计的属性: 's' 'b' 'f' 'l'
//修正路径
var jsonToWrite = null;
for (var a in result_forBrowser) {
var r = fs.readFileSync(jsonFileBasePath + result_forBrowser[a]);
if (!jsonToWrite) {
jsonToWrite = JSON.parse(r);
continue;
} else {
jsonToWrite = mergeResult(jsonToWrite, JSON.parse(r));
}
}
//写文件
fs.writeFileSync(jsonFileBasePath+finalJsonFile+'.json',JSON.stringify(jsonToWrite));
function isJsonFiles(fileName) {
var e = fileName.substring(fileName.lastIndexOf(".") + 1);
// json文件名必须是有8位的日期和6位的时间戳如:-20140326_161249
//否则无法判断文件生成时间,也就无法合并同一次运行产生的结果
return e == 'json' && getFileTime(fileName);
}
function getFileTime(fileName) {
// json文件名必须是有8位的日期和6位的时间戳如:-20140326_161249
return fileName.match(/-(\d{8})_(\d{6})/);
}
function mergeResult(allR, addR) {
var resultR = {};
for (var allRKey in allR) {
if (addR[allRKey]) {
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 's', 1);
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 'f', 1);
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 'l', 1);
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 'b', 2);
}
//修正路径
resultR[fixPath(allRKey)] = allR[allRKey]
}
return resultR;
}
//type = 1 合并 s f l ,如:{"1":1,"2":1,"3":1}
//type = 2 合并 b ,如:{"1":[0,0],"2":[0,0]}
function mergeDetail(allEle, addEle, attrName, type) {
if (allEle[attrName] && addEle[attrName]) {
if (type == 1) {
for (var k in allEle[attrName]) {
//todo 现在没有考虑两个文件中同一项覆盖率的统计行数不一致的问题
if ( parseInt(allEle[attrName][k])==0 && parseInt(addEle[attrName][k]) ==1) {
allEle[attrName][k] = 1;
}
}
}
else if (type == 2) {
for (var k in allEle[attrName]) {
//todo 现在没有考虑两个文件中同一项覆盖率的统计行数不一致的问题
if (addEle[attrName][k]) {
if (parseInt(allEle[attrName][k][0])==0 &&parseInt(addEle[attrName][k][0])==1 ) {
allEle[attrName][k][0] = 1;
}
if (parseInt(allEle[attrName][k][1])==0 &&parseInt(addEle[attrName][k][1])==1 ) {
allEle[attrName][k][1] = 1;
}
}
}
}
}
return allEle;
}
//修正路径
function fixPath(oldPath){
//例如把 "D:/workspace/ufinder/_src/core/finder.js" 修正为
// spec/coverage/_src/core/finder.js 注意这里一定要用相对路径(相对于_spec/coverage)
var s = __dirname.replace(/\\/g,'/');
if(s.lastIndexOf(curPath)){
s = s.substring(0,s.lastIndexOf(curPath) );
}
oldPath = oldPath.replace(s,resultPath);
return oldPath;
}
console.log(finalJsonFile);
\ No newline at end of file
setlocal EnableDelayedExpansion
del /q /s .\spec\coverage\json_files\*.json
rd /s /q .\coverage
for /f %%j in ('karma start ./spec/karma.conf.js') do set karmaRe=%%j
for /f %%i in ('node ./spec/_mergeCoverageForIstanbul.js') do set re=%%i
istanbul report html spec/coverage/json_files/%re%.json
\ No newline at end of file
describe("command", function () {
//初始化kityminder
var kityMinderDiv = document.createElement("div");
kityMinderDiv.id = "kityminder";
kityMinderDiv.style.height = "500px";
kityMinderDiv.style.position = "relative";
var obj;
var km;
beforeEach(function(){
document.body.appendChild(kityMinderDiv);
km = KM.getMinder('kityminder', window.KITYMINDER_CONFIG);
obj = document.getElementById('kityminder');
});
afterEach(function(){
// obj = null;
// document.body.removeChild(kityMinderDiv);
});
//kityminder初始化end
it('',function(){
console.log(km);
obj = document.getElementById('kityminder');
console.log(obj);
})
});
\ No newline at end of file
describe("minder.command", function () {
//初始化kityminder
var kityMinderDiv = document.createElement("div");
kityMinderDiv.id = "kityminder";
kityMinderDiv.style.height = "500px";
kityMinderDiv.style.position = "relative";
var obj;
var km;
beforeEach(function(){
document.body.appendChild(kityMinderDiv);
km = KM.getMinder('kityminder', window.KITYMINDER_CONFIG);
obj = document.getElementById('kityminder');
});
afterEach(function(){
// obj = null;
// document.body.removeChild(kityMinderDiv);
});
//kityminder初始化end
it('',function(){
})
});
\ No newline at end of file
describe("node", function () {
//初始化kityminder
var kityMinderDiv = document.createElement("div");
kityMinderDiv.id = "kityminder";
kityMinderDiv.style.height = "500px";
kityMinderDiv.style.position = "relative";
var obj;
var km;
beforeEach(function(){
document.body.appendChild(kityMinderDiv);
km = KM.getMinder('kityminder', window.KITYMINDER_CONFIG);
obj = document.getElementById('kityminder');
});
afterEach(function(){
// obj = null;
// document.body.removeChild(kityMinderDiv);
});
//kityminder初始化end
var root = new KM.MinderNode('root');
var first = new KM.MinderNode('first');
first.appendChild(new KM.MinderNode('first.first'));
first.setData({
'layout':{
x:1,
y:1
}
})
var second = new KM.MinderNode('second');
second.appendChild(new KM.MinderNode('second.first'));
root.appendChild(first);
root.appendChild(second);
describe('clone',function(){
var _tmp = root.clone();
it('克隆的root有2级孩子',function(){
expect(_tmp.getFirstChild()).not.toBeNull();
expect(_tmp.getFirstChild().getFirstChild()).not.toBeNull();
expect(_tmp.getFirstChild().getData('text')).toBe('first');
expect(_tmp.getFirstChild().getFirstChild().getData('text')).toBe('first.first');
});
it('检测属性的深度复制',function(){
first.getData('layout').x = 2;
expect(_tmp.getFirstChild().getData('layout').x).toBe(1);
})
});
describe('contains',function(){
it('root contain first',function(){
expect(root.contains(first)).toBeTruthy();
});
it('root contain first.first',function(){
expect(root.contains(first.getFirstChild())).toBeTruthy();
});
it('first not contain second',function(){
expect(root.contains(first.getFirstChild())).toBeTruthy();
});
it('first contain first',function(){
expect(first.contains(first)).toBeTruthy();
});
});
describe('getCommonAncestor',function(){
it('first second commonAncestor is root',function(){
expect(first.getCommonAncestor(second)).toBe(root);
});
it('root first.first commonAncestor is root',function(){
expect(first.getFirstChild().getCommonAncestor(root)).toBe(root);
});
it('second.first first.first commonAncestor is root',function(){
var a = first.getFirstChild(),b=second.getFirstChild();
expect(a.getCommonAncestor(b)).toBe(root);
});
});
describe('setData',function(){
it('name and value both exist',function(){
root.setData('test',1);
expect(root.getData('test')).toBe(1);
});
it('name only exist clear property',function(){
root.setData('test');
expect(root.getData('test')).toBeUndefined();
});
it('name is object',function(){
root.setData({
'test':1
});
expect(root.getData('test')).toBe(1);
});
it('name and value both empty',function(){
root.setData('test',1);
root.setData('test1',2);
root.setData();
expect(root.getData('test')).toBeUndefined();
expect(root.getData('test1')).toBeUndefined();
});
it('layout:{x:1,y:1}',function(){
root.setData({
'layout':{
x:1,
y:1
}
});
expect(root.getData('layout').x).toBe(1);
});
});
});
\ No newline at end of file
describe("utils", function () {
//初始化kityminder
var kityMinderDiv = document.createElement("div");
kityMinderDiv.id = "kityminder";
kityMinderDiv.style.height = "500px";
kityMinderDiv.style.position = "relative";
var obj;
var km;
beforeEach(function(){
document.body.appendChild(kityMinderDiv);
km = KM.getMinder('kityminder', window.KITYMINDER_CONFIG);
obj = document.getElementById('kityminder');
});
afterEach(function(){
// obj = null;
// document.body.removeChild(kityMinderDiv);
});
//kityminder初始化end
describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
// console.log(km);
console.log(document.getElementById('kityminder'));
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});
describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});
describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});
describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});
describe('compareObject',function(){
var obj1 = {
'test':[1,2],
'test1':1
};
var obj2 = utils.clonePlainObject(obj1);
it('相等',function(){
expect(utils.compareObject(obj1,obj2)).toBeTruthy();
});
it('长度不同',function(){
obj2.test2 = '1';
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
it('数组中的数据不同',function(){
obj1.test[2] = {};
expect(utils.compareObject(obj1,obj2)).toBeFalsy();
})
});
});
\ No newline at end of file
karmaɵĽjsonʽ
\ No newline at end of file
/**
* Created by dongyancen on 13-12-27.
*/
///import core/kityminder;
///import core/utils;
///import core/command;
///import core/node;
///import core/module;
///import core/event;
///import core/minder;
///import core/minder.data.compatibility;
///import core/minder.data;
///import core/minder.event;
///import core/minder.module;
///import core/minder.command;
///import core/minder.node;
///import core/minder.select;
///import core/keymap;
///import core/minder.lang;
///import core/minder.defaultoptions;
///import core/minder.preference;
///import core/browser;
///import core/layout;
///import core/connect;
///import core/render;
///import core/theme;
///import core/template;
///import layout/default;
///import layout/default.connect;
///import layout/bottom;
///import layout/filetree;
///import theme/default;
///import theme/snow;
///import theme/fresh;
///import template/structure;
///import module/node;
///import module/text;
///import module/expand;
///import module/outline;
///import module/geometry;
///import module/history;
///import module/progress;
///import module/priority;
///import module/image;
///import module/resource;
///import module/view;
///import module/dragtree;
///import module/keyboard;
///import module/select;
///import module/history;
///import module/editor;
///import module/editor.keyboard;
///import module/editor.range;
///import module/editor.receiver;
///import module/editor.selection;
///import module/basestyle;
///import module/font;
///import module/zoom;
///import module/hyperlink;
///import module/arrange;
///import module/paste;
///import module/style;
///import protocal/xmind;
///import protocal/freemind;
///import protocal/mindmanager;
///import protocal/plain;
///import protocal/json;
///import protocal/png;
///import protocal/svg;
///import ui/ui;
///import ui/eve;
///import ui/fuix;
///import ui/fiox;
///import ui/doc;
///import ui/widget/commandbutton;
///import ui/widget/commandbuttonset;
///import ui/widget/commandinputmenu;
///import ui/widget/friendlytimespan;
///import ui/widget/locallist;
///import ui/widget/netdiskfinder;
///import ui/widget/menutab;
///import ui/menu/menu;
///import ui/menu/header;
///import ui/menu/default;
///import ui/menu/new/new;
///import ui/menu/open/open;
///import ui/menu/open/recent;
///import ui/menu/open/netdisk;
///import ui/menu/open/local;
///import ui/menu/open/draft;
///import ui/menu/save/save;
///import ui/menu/save/netdisk;
///import ui/menu/save/download;
///import ui/menu/share/share;
///import ui/topbar/history;
///import ui/topbar/user;
///import ui/topbar/search;
///import ui/topbar/title;
///import ui/ribbon/tabs;
///import ui/ribbon/idea/insert;
///import ui/ribbon/idea/arrange;
///import ui/ribbon/idea/operation;
///import ui/ribbon/idea/attachment;
///import ui/ribbon/idea/link;
///import ui/ribbon/idea/image;
///import ui/ribbon/idea/priority;
///import ui/ribbon/idea/progress;
///import ui/ribbon/idea/resource;
///import ui/ribbon/appearence/template;
///import ui/ribbon/appearence/theme;
///import ui/ribbon/appearence/layout;
///import ui/ribbon/appearence/style;
///import ui/ribbon/appearence/font;
///import ui/ribbon/appearence/color;
///import ui/ribbon/view/level;
<?php
/**
* Created by PhpStorm.
* User: dongyancen
* Date: 14-1-15
* Time: 下午6:50
*/
Header('Location:../spec/tools/list.php');
?>
\ No newline at end of file
// Karma configuration
// Generated on Wed Oct 09 2013 19:20:49 GMT+0800 (中国标准时间)
//karma-coverage@0.1.4
module.exports = function(config) {
var base_path = '../';
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// frameworks to use
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
base_path+'spec/tools/js/UserAction.js'
,base_path+'spec/SpecHelper.js'
,base_path+'lib/jquery-2.1.0.min.js'
,base_path+'lib/ZeroClipboard.min.js'
,base_path+'spec/tools/js/ZeroClipboard.js'
,base_path+'kity/dist/kity.js'
,base_path+'src/core/kityminder.js'
,base_path+'src/core/utils.js'
,base_path+'src/core/command.js'
,base_path+'src/core/node.js'
,base_path+'src/core/module.js'
,base_path+'src/core/event.js'
,base_path+'src/core/minder.js'
,base_path+'src/core/minder.data.compatibility.js'
,base_path+'src/core/minder.data.js'
,base_path+'src/core/minder.event.js'
,base_path+'src/core/minder.module.js'
,base_path+'src/core/minder.command.js'
,base_path+'src/core/minder.node.js'
,base_path+'src/core/minder.select.js'
,base_path+'src/core/keymap.js'
,base_path+'src/core/minder.lang.js'
,base_path+'src/core/minder.defaultoptions.js'
,base_path+'src/core/minder.preference.js'
,base_path+'src/core/browser.js'
,base_path+'src/core/layout.js'
,base_path+'src/core/connect.js'
,base_path+'src/core/render.js'
,base_path+'src/core/theme.js'
,base_path+'src/core/template.js'
,base_path+'src/layout/default.js'
,base_path+'src/layout/default.connect.js'
,base_path+'src/layout/bottom.js'
,base_path+'src/layout/filetree.js'
,base_path+'src/theme/default.js'
,base_path+'src/theme/snow.js'
,base_path+'src/theme/fresh.js'
,base_path+'src/template/structure.js'
,base_path+'src/module/node.js'
,base_path+'src/module/text.js'
,base_path+'src/module/expand.js'
,base_path+'src/module/outline.js'
,base_path+'src/module/geometry.js'
,base_path+'src/module/history.js'
,base_path+'src/module/progress.js'
,base_path+'src/module/priority.js'
,base_path+'src/module/image.js'
,base_path+'src/module/resource.js'
,base_path+'src/module/view.js'
,base_path+'src/module/dragtree.js'
,base_path+'src/module/dropfile.js'
,base_path+'src/module/keyboard.js'
,base_path+'src/module/select.js'
,base_path+'src/module/history.js'
,base_path+'src/module/editor.js'
,base_path+'src/module/editor.range.js'
,base_path+'src/module/editor.receiver.js'
,base_path+'src/module/editor.selection.js'
,base_path+'src/module/basestyle.js'
,base_path+'src/module/font.js'
,base_path+'src/module/zoom.js'
,base_path+'src/module/hyperlink.js'
,base_path+'src/module/arrange.js'
,base_path+'src/module/paste.js'
,base_path+'src/ui/jquery-ui-1.10.4.custom.min.js'
,base_path+'src/ui/widget.js'
,base_path+'src/ui/button.js'
,base_path+'src/ui/toolbar.js'
,base_path+'src/ui/menu.js'
,base_path+'src/ui/dropmenu.js'
,base_path+'src/ui/splitbutton.js'
,base_path+'src/ui/colorsplitbutton.js'
,base_path+'src/ui/popup.js'
,base_path+'src/ui/scale.js'
,base_path+'src/ui/colorpicker.js'
,base_path+'src/ui/combobox.js'
,base_path+'src/ui/buttoncombobox.js'
,base_path+'src/ui/modal.js'
,base_path+'src/ui/tooltip.js'
,base_path+'src/ui/tab.js'
,base_path+'src/ui/separator.js'
,base_path+'src/ui/scale.js'
,base_path+'src/adapter/utils.js'
,base_path+'src/adapter/adapter.js'
,base_path+'src/adapter/button.js'
,base_path+'src/adapter/combobox.js'
,base_path+'src/adapter/color.js'
,base_path+'src/adapter/saveto.js'
,base_path+'src/adapter/tooltips.js'
,base_path+'src/adapter/face.js'
,base_path+'src/adapter/node.js'
,base_path+'src/adapter/contextmenu.js'
,base_path+'src/adapter/dialog.js'
,base_path+'src/adapter/hyperlink.js'
,base_path+'src/adapter/image.js'
,base_path+'src/adapter/zoom.js'
,base_path+'src/protocal/xmind.js'
,base_path+'src/protocal/freemind.js'
,base_path+'src/protocal/mindmanager.js'
,base_path+'src/protocal/plain.js'
,base_path+'src/protocal/json.js'
,base_path+'src/protocal/png.js'
,base_path+'src/protocal/svg.js'
,base_path+'kityminder.config.js'
,base_path+'lang/zh-cn/zh-cn.js'
,base_path+'lib/zip.js'
,base_path+'spec/tools/js/inflate.js'
,base_path+'lib/jquery.xml2json.js'
,base_path+'lib/baidu-frontia-js-full-1.0.0.js'
// ,base_path+'social/draftmanager.js'
// ,base_path+'social/social.js'
,base_path+'social/social.css'
,base_path+'themes/default/css/import.css'
,base_path+'spec/core/*.js'
,base_path+'spec/module/*.js'
,base_path+'spec/protocal/*.js'
],
// list of files to exclude
exclude: [
'karma.conf.js'
],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
// reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['Firefox','Chrome'],//,'Chrome'
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true,
//coverage
reporters: ['progress', 'coverage','junit'],
preprocessors: {
'../src/core/*.js': ['coverage'],
'../src/adapter/*.js': ['coverage'],
'../src/module/*.js': ['coverage'],
'../src/protocal/*.js': ['coverage'],
'../src/ui/*.js': ['coverage'],
'../src/layout/*.js': ['coverage'],
'../src/template/*.js': ['coverage'],
'../src/theme/*.js': ['coverage']
}
,
coverageReporter: {
type: 'text',
dir: './coverage/json_files/'
}
,
junitReporter: {
outputFile: './test-results.xml'
}
});
};
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-12-10
* Time: 下午7:24
* To change this template use File | Settings | File Templates.
/**
* Created by dongyancen on 14-3-26.
*/
var fs = require('fs');
var browsers = ['Chrome', 'Firefox', 'PhantomJS', 'IE'];
var result_forBrowser = {};
var jsonFileBasePath = './coverage/json_files/';
var jsonFiles = fs.readdirSync(jsonFileBasePath);
var finalJsonFile = 'defaultFileName';
var curPath = '/spec';
var resultPath = '.';
//找出所有的json文件
for (var i = 0; i < jsonFiles.length; i++) {
// json文件名必须是有8位的日期和6位的时间戳如:-20140326_161249
if (!isJsonFiles(jsonFiles[i])) {
jsonFiles.splice(i, 1);
i--;
}
}
//没有找到合适的文件
if(jsonFiles.length==0)return;
//先排序 按时间从小到大 及从旧到新
jsonFiles.sort(function (f1, f2) {
var t1 = getFileTime(f1);//形如['-20140326_161249','20140326','161249']
var t2 = getFileTime(f2);
var dateDiff = parseInt(t1[1]) - parseInt(t2[1]);
if (dateDiff != 0)return dateDiff;
else return parseInt(t1[2]) - parseInt(t2[2]);
});
//以时间命名新的文件
finalJsonFile = getFileTime(jsonFiles[jsonFiles.length-1])[0].substring(1);
//如:20140326_161249
//取最新的
// 按浏览器类型分类 result_forBrowser属性形如:{'Crome':'filename1','Firefox':'filename2'}
for (i = 0; i < jsonFiles.length; i++) {
for (var j = 0; j < browsers.length; j++) {
if (eval('/' + browsers[j] + '/.test("' + jsonFiles[i] + '");')) {
eval('result_forBrowser.' + browsers[j] + '="' + jsonFiles[i] + '";');
}
}
}
//以上得到所有要合计的json文件
//读取,合计数字,需要合计的属性: 's' 'b' 'f' 'l'
//修正路径
var jsonToWrite = null;
for (var a in result_forBrowser) {
var r = fs.readFileSync(jsonFileBasePath + result_forBrowser[a]);
if (!jsonToWrite) {
jsonToWrite = JSON.parse(r);
continue;
} else {
jsonToWrite = mergeResult(jsonToWrite, JSON.parse(r));
}
}
//写文件
fs.writeFileSync(jsonFileBasePath+finalJsonFile+'.json',JSON.stringify(jsonToWrite));
function isJsonFiles(fileName) {
var e = fileName.substring(fileName.lastIndexOf(".") + 1);
// json文件名必须是有8位的日期和6位的时间戳如:-20140326_161249
//否则无法判断文件生成时间,也就无法合并同一次运行产生的结果
return e == 'json' && getFileTime(fileName);
}
function getFileTime(fileName) {
// json文件名必须是有8位的日期和6位的时间戳如:-20140326_161249
return fileName.match(/-(\d{8})_(\d{6})/);
}
function mergeResult(allR, addR) {
var resultR = {};
for (var allRKey in allR) {
if (addR[allRKey]) {
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 's', 1);
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 'f', 1);
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 'l', 1);
allR[allRKey] = mergeDetail(allR[allRKey], addR[allRKey], 'b', 2);
}
//修正路径
resultR[fixPath(allRKey)] = allR[allRKey]
}
return resultR;
}
//type = 1 合并 s f l ,如:{"1":1,"2":1,"3":1}
//type = 2 合并 b ,如:{"1":[0,0],"2":[0,0]}
function mergeDetail(allEle, addEle, attrName, type) {
if (allEle[attrName] && addEle[attrName]) {
if (type == 1) {
for (var k in allEle[attrName]) {
//todo 现在没有考虑两个文件中同一项覆盖率的统计行数不一致的问题
if ( parseInt(allEle[attrName][k])==0 && parseInt(addEle[attrName][k]) ==1) {
allEle[attrName][k] = 1;
}
}
}
else if (type == 2) {
for (var k in allEle[attrName]) {
//todo 现在没有考虑两个文件中同一项覆盖率的统计行数不一致的问题
if (addEle[attrName][k]) {
if (parseInt(allEle[attrName][k][0])==0 &&parseInt(addEle[attrName][k][0])==1 ) {
allEle[attrName][k][0] = 1;
}
if (parseInt(allEle[attrName][k][1])==0 &&parseInt(addEle[attrName][k][1])==1 ) {
allEle[attrName][k][1] = 1;
}
}
}
}
}
return allEle;
}
//修正路径
function fixPath(oldPath){
//例如把 "D:/workspace/ufinder/_src/core/finder.js" 修正为
// ./_src/core/finder.js 注意这里一定要用相对路径(相对于_spec/coverage)
var s = __dirname.replace(/\\/g,'/');
if(s.lastIndexOf(curPath)){
s = s.substring(0,s.lastIndexOf(curPath) );
}
oldPath = oldPath.replace(s,resultPath);
return oldPath;
}
console.log(finalJsonFile);
\ No newline at end of file
/**
* Created by dongyancen on 13-12-30.
*/
describe("connect", function () {
it("KityMinder 已定义", function () {
expect(KityMinder).toBeDefined();
});
});
describe("editor.range", function () {
var _div = document.createElement('div');
_div.setAttribute('contenteditable', true);
var range = new KM.Minder.Range(_div);
describe("getStartOffset",function(){
_div.innerHTML = 'xxx<br\/><br\/>xxx<br\/>';
it("选区在容器上", function () {
range.startContainer = _div;
range.startOffset = 2;
expect(range.getStartOffset()).toBe(4);
});
it("选区在文本节点上", function () {
range.startContainer = _div.childNodes[3];
range.startOffset = 2;
expect(range.getStartOffset()).toBe(7);
});
});
describe("setStartOffset",function(){
_div.innerHTML = 'sdfsdfsdfsdf<br><br>sdf3<br>23232<br>';
it("选区在容器上", function () {
range.container = _div;
debugger
range.setStartOffset(26);
expect(range.startContainer).toBe(_div);
});
// it("选区在文本节点上", function () {
//
// range.startContainer = _div.childNodes[3];
// range.startOffset = 2;
// expect(range.getStartOffset()).toBe(7);
// });
})
});
describe("editor.receiver", function () {
debugger
var _div = window.document.createElement('div');
_div.id ="testDiv";
var km = KM.getMinder('testDiv');
var sel = new KM.Minder.Selection();
var range = new KM.Minder.Range();
var receiver = new KM.Minder.Receiver(this,sel,range);
describe("getStartOffset",function(){
//
// _div.innerHTML = 'xxx<br\/><br\/>xxx<br\/>';
// it("选区在容器上", function () {
//
// range.startContainer = _div;
// range.startOffset = 2;
// expect(range.getStartOffset()).toBe(4);
// });
// it("选区在文本节点上", function () {
//
// range.startContainer = _div.childNodes[3];
// range.startOffset = 2;
// expect(range.getStartOffset()).toBe(7);
// });
})
});
describe("protocal/plain", function () {
var json, local, protocal;
beforeEach(function () {
protocal = KM.findProtocal('plain');
});
it('协议存在', function () {
expect(protocal).toBeDefined();
});
it('正确 encode', function () {
json = {
data: {
text: 'root',
anyway: 'omg'
},
children: [{
data: {
text: 'l1c1'
}
}, {
data: {
text: 'l1c2'
},
children: [{
data: {
text: 'l2c1'
}
}, {
data: {
text: 'l2c2'
}
}]
}, {
data: {
text: 'l1c3'
}
}]
};
local = protocal.encode(json);
expect(local).toBe(
'root\n' +
'\tl1c1\n' +
'\tl1c2\n' +
'\t\tl2c1\n' +
'\t\tl2c2\n' +
'\tl1c3\n'
);
});
});
\ No newline at end of file
setlocal EnableDelayedExpansion
del /q /s .\coverage\json_files\*.json
for /f %%j in ('karma start ./karma.conf.js') do set karmaRe=%%j
for /f %%i in ('node ./mergeCoverageForIstanbul.js') do set re=%%i
istanbul report html coverage/json_files/%re%.json
@echo off
setlocal EnableDelayedExpansion
del /q /s .\coverage\json_files\*.*
karma start ./karma.conf.js
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-10
* Time: 上午1:20
* To change this template use File | Settings | File Templates.
*/
require_once 'config.php';
class Kiss
{
public $projroot ;
public $name;
public $srcPath;
public $testPath;
public $empty = false;
public $case_id;
function __construct( $name = '' )
{
$this->projroot = Config::$projroot;
$this->srcPath = Config::$projroot.Config::$src_PATH;
$this->testPath = Config::$projroot.Config::$test_PATH;
$this->name = $name;
$this->case_id = 'id_case_' . join( '_' , explode( '.' , $name ) );
}
public function print_js( $cov)
{
if($cov){
$basePath = '../../spec/coverage';
}
else{
$basePath = '../../src';
}
// print "<script src='../../dist/dev.php'></script>";
print "<script type='text/javascript' src='./js/UserAction.js' ></script>\n";
/* load case and case dependents*/
$ps = explode( '/' , $this->name );
/*load helper*/
foreach(Config::$helperFiles as $f){
if ( file_exists( $this->testPath . $f ) ) {
print '<script type="text/javascript" src="' . $this->testPath . $f . '"></script>' . "\n";
}
}
//先引用kity
print "<script src='../../lib/jquery-2.1.0.min.js'></script>\n";
print "<script src='../../lib/jquery.xml2json.js' charset='utf-8'></script>\n";
print "<script src='../../lib/jquery.transit.min.js' charset='utf-8'></script>\n";
print "<script src='../../lib/jquery.blob.js' charset='utf-8'></script>\n";
print "<script src='../../lib/zip.js' charset='utf-8'></script>\n";
print "<script src='../../lib/promise-1.0.0.js' charset='utf-8'></script>\n";
print "<script src='../../lib/ZeroClipboard.min.js' charset='utf-8'></script>\n";
print "<script src='../../lib/fui/dev-lib/jhtmls.min.js' charset='utf-8'></script>\n";
print "<script src='../../lib/fui/dist/fui.all.js' charset='utf-8'></script>\n";
print "<script src='../../lib/fio/src/fio.js' charset='utf-8'></script>\n";
print "<script src='../../lib/fio/provider/netdisk/oauth.js' charset='utf-8'></script>\n";
print "<script src='../../lib/fio/provider/netdisk/netdisk.js' charset='utf-8'></script>\n";
print "<script src='../../lib/kity/dist/kity.js' charset='utf-8'></script>\n";
//分成两部分:一部分默认加载(可配置),一部分针对文件加载(例如在文件头部有注释标注依赖文件,根据依赖文件动态加载)
// core里面的文件全部加载,module加载用例对应的src文件,最后加载与用例同名的原文件
$importurl = "{$this->testPath}tools/import.php?f=$this->name";
if ( $cov ) $importurl .= '^&cov=true';
print "<script type='text/javascript' src='".$importurl."' ></script>\n";
print "<script src='../../kityminder.config.js' charset='utf-8'></script>\n";
print "<script src='../../lang/zh-cn/zh-cn.js' charset='utf-8'></script>\n";
print "<script type='text/javascript'>zip.inflateJSPath = '../../lib/inflate.js';</script>\n";
print "<script type='text/javascript'>window._bd_share_config={'common':{'bdSnsKey':{},'bdMini':'2','bdMiniList':[],'bdPic':'','bdStyle':'1','bdSize':'32'},'share':{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>\n";
// print "<script>zip.inflateJSPath = '../../lib/inflate.js';</script>\n";
// print "<script src='../../lib/baidu-frontia-js-full-1.0.0.js' charset='utf-8'></script>\n";
// print "<script src='../../social/draftmanager.js' charset='utf-8'></script>\n";
// print "<script src='../../social/social.js' charset='utf-8'></script>\n";
//引用测试文件
print '<script type="text/javascript" src="' .$this->testPath.$this->name. '.js"></script>' . "\n";
print "<link href='../../ui/theme/default/css/default.all.css' rel='stylesheet'>\n";
// print "<link href='../../themes/default/css/import.css' type='text/css' rel='stylesheet' />\n";
print "<link href='../../favicon.ico' type='image/x-icon' rel='shortcut icon'>\n";
print "<link href='../../favicon.ico' type='image/x-icon' rel='apple-touch-icon-precomposed'>\n";
}
public function match( $matcher )
{
if ( $matcher == '*' )
return true;
$len = strlen( $matcher );
/**
* 处理多选分支,有一个成功则成功,filter后面参数使用|切割
* @var unknown_type
*/
$ms = explode( ',' , $matcher );
if ( sizeof( $ms ) > 1 ) {
foreach ( $ms as $matcher1 ) {
if ( $this->match( $matcher1 ) )
return true;
}
return false;
}
/**
* 处理反向选择分支
*/
if ( substr( $matcher , 0 , 1 ) == '!' ) {
$m = substr( $matcher , 1 );
if ( substr( $this->name , 0 , strlen( $m ) ) == $m )
return false;
return true;
}
if ( $len > strlen( $this->name ) ) {
return false;
}
return substr( $this->name , 0 , $len ) == $matcher;
}
public static function listcase( $matcher = "*" ,$cov)
{
require_once 'fileHelper.php';
/*get files both in src path and test path*/
$caselist = getSameFile(Config::$projroot.Config::$src_PATH , Config::$projroot.Config::$test_PATH , '' );
sort($caselist,SORT_STRING);
foreach ( $caselist as $caseitem ) {
/*remove '.js' */
$name = substr( $caseitem , 0 , -3 );
$c = new Kiss( $name );
if ( $c->empty )
continue;
if ( $c->match( $matcher ) ) {
$newName = explode( '\\.' , $name );
$newName = $newName[ count( $newName ) - 1 ];
if($cov){
$covMsg = "&cov=true";
}else{
$covMsg="";
}
print( "<a href=\"run.php?case=$name".$covMsg."\" id=\"$c->case_id\" target=\"_blank\" title=\"$name\" onclick=\"run('$name');return false;\">". $newName . "</a>" );
}
}
}
public static function listSrcOnly( $print = true )
{
$srcpath = Config::$projroot.Config::$src_PATH;
$testpath = Config::$projroot.Config::$test_PATH;
require_once 'fileHelper.php';
$caselist = getSameFile( $srcpath , $testpath , '' );
$srclist = getSrcOnlyFile( $srcpath , $testpath , '' );
$srcList = array();
foreach ( $srclist as $case ) {
if ( in_array( $case , $caselist ) )
continue;
$name = str_replace( '/' , '.' , substr( $case , 0 , -3 ) );
$tag = "<a title=\"$name\">" . ( strlen( $name ) > 20 ? substr( $name , 6 )
: $name ) . "</a>";
array_push( $srcList , $tag );
if ( $print )
echo $tag;
}
return $srcList;
}
}
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-10
* Time: 上午1:50
* To change this template use File | Settings | File Templates.
*/
class Config
{
public static $projroot = "../../";
//相对于projroot的路径
public static $src_PATH = "src/" ;
public static $test_PATH = "spec/";
public static $helperFiles = array( "SpecHelper.js" );
}
\ No newline at end of file
* {
margin: 0;
padding: 0;
}
html {
border: 0;
height: 100%;
}
body {
font: 12px/1.5 Lucida Grande, Helvetica, Arial, sans-serif;
background: #F3F1F1;
color: #41464D;
}
body,#container {
width: 100%;
height: 100%;
}
.clear { /* generic container (i.e. div) for floating buttons */
overflow: hidden;
width: 100%;
}
a {
text-decoration: none;
overflow: hidden;
}
#title {
top: 0;
left: 0;
width: 100%;
padding: 5px 0;
background: #aaa;
background: #41464D;
color: #F3F1F1;
height: 30px;
}
a:link,a:visited {
color: #528CE0;
}
a:hover,a:active {
color: #41464D !important;
cursor: pointer !important;
}
#title h1 {
height: 30px;
font: 25px/1.1 Arial, sans-serif;
font-weight: bolder;
float: left;
margin: 1px 0 2px 20px;
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.4);
}
h3 {
font-size: 14px;
padding: 3px 5px 1px;
}
.control {
background: #d5ded7;
width: 99%;
}
.testlist {
max-height: 200px;
overflow-y: scroll;
border-style: double;
}
.testlist a {
display: block;
width: 150px;
color: #657528;
background: #d5dea7;
border: 1px solid #c8dc7b;
margin: 5px 0 0 5px;
text-indent: 5px;
line-height: 24px;
font-size: 14px;
float: left;
}
a.button {
background: transparent url('bg_button_a.gif') no-repeat scroll top
right;
color: #444;
display: block;
float: left;
font: normal 12px arial, sans-serif;
height: 24px;
margin-right: 6px;
padding-right: 18px; /* sliding doors padding */
text-decoration: none;
}
a.button span {
background: transparent url('bg_button_span.gif') no-repeat;
display: block;
line-height: 14px;
padding: 5px 0 5px 18px;
}
a.button:active {
background-position: bottom right;
color: #000;
outline: none; /* hide dotted outline in Firefox */
}
a.button:active span {
background-position: bottom left;
padding: 6px 0 4px 18px; /* push text down 1px */
}
.testlist a:link {
}
.testlist a:visited {
}
.testlist a:hover {
background: #c8dc7b;
}
.testlist a.jsframe_jsspec {
background: #DDDDDD
}
.testlist a.running_case {
color: yellow;
}
.testlist a.fail_case {
color: red;
}
.testlist a.pass_case {
color: green;
}
.runningarea {
height: 100%;
}
.runningmaindiv {
height: 99%;
}
.runningframe {
height: 99.99%;
width: 99.99%;
}
.runningstatus {
clear: both;
height: 10%;
border: solid
}
.reportarea {
padding: 10px;
border: 10px blue;
max-height: 200px;
overflow-y: scroll;
}
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午5:31
* To change this template use File | Settings | File Templates.
*///获取两个目录下的相同路径的文件数
function getSameFile($src, $test, $path=''){
$result = array();
$as = listFile($src.$path);
$ts = listFile($test.$path);
$ds = array_intersect($as, $ts);
foreach($ds as $item){
$si = $src.$path.$item;
$ti = $test.$path.$item;
if(is_dir($si) && is_dir($ti)){
$result = array_merge($result, getSameFile($src, $test, $path.$item.'/'));
}else if(is_file($si) && is_file($ti)){
if(substr($si, -3) == '.js')
array_push($result, $path.$item);
}
}
return $result;
}
//获取只在src中存在的文件,防止遗漏用例
function getSrcOnlyFile($src, $test, $path=''){
$result = array();
$as = listFile($src.$path);
$ts = listFile($test.$path);
foreach($as as $item){
$si = $src.$path.$item;
$ti = $test.$path.$item;
if(is_dir($si) && is_dir($ti)){
$result = array_merge($result, getSrcOnlyFile($src, $test, $path.$item.'/'));
}else if(is_file($si) && !is_file($ti)){
if(substr($si, -3) == '.js')
array_push($result,$path.$item);
}
else{
// print("error : $si");
}
}
return $result;
}
function listFile($dir){
$as = array();
if($dh = opendir($dir)){
while(($file = readdir($dh))!==false){
if(substr(basename($file), 0, 1) == '.')
continue;
array_push($as, basename($file));
}
closedir($dh);
}
return $as;
}
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-12-10
* Time: 上午1:48
* To change this template use File | Settings | File Templates.
*/
header('Content-Type: text/javascript');
$import = 'import.js';
function custom_strEmpty($s){
$str = strlen(trim($s));
if(empty($str)){
return true;
}
return false;
}
function importSrc(){
require_once 'config.php';
global $import;
if(file_exists(Config::$projroot.Config::$test_PATH.$import)){
$cnt = file_get_contents(Config::$projroot.Config::$test_PATH.$import);
}
if($cnt == ''){
if(Config::$DEBUG)
print "fail read file : ".Config::$test_PATH.$import;
return '';
}
$is = array();
$flag_ownSrc = 1;
$caseName = $_GET[ 'f' ];
$this_src = Config::$projroot.Config::$src_PATH.$caseName.".js";
//正则匹配,提取所有(///import xxx;)中的xxx
preg_match_all('/\/\/\/import\s+([^;]+);?/ies', $cnt, $is, PREG_PATTERN_ORDER);
foreach($is[1] as $i) {
if(strcasecmp($i,$caseName)==0){
$flag_ownSrc = 0;
}
$path = $i . '.js';
$srcFile = Config::$projroot . Config::$src_PATH . $path;
if (file_exists($srcFile)) {
echo "document.write('<script charset=utf-8 src=\"$srcFile\"></script>');\n";
}
}
if(file_exists($this_src)){
$file=fopen($this_src,"r");
while(!feof($file))
{
$statment = fgets($file);
if(custom_strEmpty($statment)){
continue ;
}else if(preg_match('/\/\/\/import\s+([^;]+);?/ies', $statment,$r)){
echo "document.write('<script charset=utf-8 src=\"".Config::$projroot . Config::$src_PATH.$r[1].".js\"></script>');\n";
}else{
break;
}
}
fclose($file);
}
//加载与用例同名的原文件,并避免重复加载
if($flag_ownSrc){
echo "document.write('<script charset=utf-8 src=\"".$this_src."\"></script>');\n";
}
}
importSrc();
\ No newline at end of file
This diff is collapsed.
ZeroClipboard.setDefaults( { moviePath: '../../../lib/ZeroClipboard.swf' } );
\ No newline at end of file
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-17
* Time: 上午2:24
* To change this template use File | Settings | File Templates.
*/
/**
* rewrite jasmine function to support batchrun
*/
(function() {
if (!jasmine)
return;
var s = jasmine.Queue.prototype.start
// ,n = jasmine.Queue.prototype.next_
,f = jasmine.Runner.prototype.finishCallback;
function _f(self,args /* failures, total */) {
//todo 写到调用HtmlReporter后
/*another way to apply:
*
* var reporterView = self.env.reporter.subReporters_[0].getReporterView();
*totalSpecCount,completeSpecCount,failedCount,passedCount
*reporterView.views.specs[0].detail
* */
var totalSpecCount = 0,failedCount = 0,passedCount = 0;
var tmpSpec = null;
for(var i=0;i<self.suites_.length;i++){
for(var j=0;j<self.suites_[i].specs_.length;j++){
totalSpecCount++;
tmpSpec = self.suites_[i].specs_[j].results_.items_;
for(var k=0;k<tmpSpec.length;k++){
if(tmpSpec[k].passed_){
passedCount++;
}else{
failedCount++;
}
}
}
}
//display failed Suite
// $('li.fail ol').toggle();
if (parent && parent.brtest) {
parent.brtest.customTrigger('done', [ new Date().getTime(), {
failed : failedCount,
passed : passedCount,
detail : self.suites_,
total : totalSpecCount
//todo jscoverage
}, window._$jscoverage || null ]);
}
}
jasmine.Runner.prototype.finishCallback = function(){
f.apply(this, arguments);
_f(this,arguments);
};
jasmine.Queue.prototype.start =function(){
//todo
/* wait for import.php return */
// var h = setInterval(function() {
// if (window && window['baidu']) {
// clearInterval(h);
s.apply(this, arguments);
// }
// }, 20);
};
// function _n(self,args /* failures, total */) {
/* // do not delete the following lines:
// the last Queue in the file has done ,there is no more Suite or Queue
if(self.index == self.blocks.length || (this.abort && !this.ensured[self.index])){
}
*/
// }
// jasmine.Queue.prototype.next_ = function() {
// _n(this,arguments);
// n.apply(this, arguments);
// };
})();
\ No newline at end of file
/**
*
* Created by Ryan on 14-9-3.
*/
zip.inflateJSPath = '../../../lib/inflate.js';
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午6:52
* To change this template use File | Settings | File Templates.
*/
/**
* 为批量运行提供入口,参数携带batchrun=true
*/
function run(kiss,runnext) {
window.document.title = kiss;
var wb = window.brtest = window.brtest || {};
triggerEvent.call(wb);
wb.timeout = wb.timeout || 60000;
wb.breakOnError = /breakonerror=true/gi.test(location.search)
|| document.getElementById('id_control_breakonerror').checked;
wb.runnext = /batchrun=true/gi.test(location.search) || runnext
|| document.getElementById('id_control_runnext').checked;
wb.kiss = kiss;
var cid = 'id_case_' + kiss.split('.').join('_');
/* 只有参数有showsrconly的时候才显示div */
if (/showsrconly=true/gi.test(location.search)) {
var div = document.getElementById('id_showSrcOnly');
div.style.display = 'block';
}
/* id中由于嵌入用例名称,可能存在导致通过id直接$无法正确获取元素的情况 */
wb.kissnode = document.getElementById(cid);
wb.kisses = wb.kisses || {};
// 把没有用例的情况加入到报告中
if (!wb.kisslost) {
var as = document.getElementById('id_showSrcOnly').getElementsByTagName('a');
for (var i = 0; i < as.length; i++) {
wb.kisses[this.title] = '0;0;_;0;0';
}
wb.kisslost = true;
}
wb.kisscov = wb.kisscov || {};
var wbkiss = wb.kisses[wb.kiss] = wb.kisses[wb.kiss] || '';
/**
* 超时处理
*/
var toh = setTimeout(function () {
if (!window.brtest.breakOnError)
wb.customTrigger('done', [ new Date().getTime(), {
failed: 1,
passed: 1,
detail: null,
total: 0
}, frames[0].$_jscoverage, 'timeout' ]);
}, wb.timeout);
/**
* 为当前用例绑定一个一次性事件
*/
wb.customOne('done', function (time, result, covinfo) {
clearTimeout(toh);
var wb = window.brtest, errornum = result.failed, allnum = result.total;
wb.kissend = new Date().getTime();
//todo jscoverage
// if ( covinfo !== null )// 如果支持覆盖率
// {
// wb.kisscov[wb.kiss] = covinfo;
// }
removeClass(wb.kissnode, 'running_case');
wb.kisses[wb.kiss] = errornum + ';' + allnum + ';_;' + wb.kissstart + ';' + wb.kissend;
//todo log
// var args = kiss + ': 失败/所有:' + errornum + '/' + allnum + ',耗时:' + (wb.kissend - wb.kissstart);
// var html = upath + '../br/log.php?loginfo=' + args;
// html += '&detail='+result.detail;
// if ( errornum > 0 )
// html += '&fail=true';
if (errornum > 0) {
addClass(wb.kissnode, 'fail_case');
} else
addClass(wb.kissnode, 'pass_case');
if (wb.runnext && (!wb.breakOnError || parseInt(wb.kisses[wb.kiss].split(',')[0]) == 0)) {
var nextA = wb.kissnode.nextSibling;
if (nextA.tagName.toLowerCase() == 'a') {
if (wb.kisses[nextA.title] === undefined) {
run(nextA.title, wb.runnext);
}
// html += "&next=" + nextA.title;
} else {
//
// /* ending 提交数据到后台 */
// html += '&next=@_@end';
wb.kisses['config'] = location.search.substring(1);
var url = 'report.php';
//todo jscoverage
// covcalc();
// /**
// * 启动时间,结束时间,校验点失败数,校验点总数
// */
$.ajax({
url: url,
type: 'post',
data: wb.kisses,
success: function (msg) {
/* 展示报告区 */
// $('#id_reportarea').show().html(msg);
},
error: function (xhr, msg) {
alert('fail' + msg);
}
});
}
}
//todo log
// te.log( html );
});
/**
* 初始化执行区并通过嵌入iframe启动用例执行
*/
var url = 'run.php?case=' + kiss + '&time=' + new Date().getTime() + "&"
+ location.search.substring(1);
var fdiv = 'id_div_frame_' + kiss.split('.').join('_');
var fid = 'id_frame_' + kiss.split('.').join('_');
addClass(wb.kissnode, 'running_case');
/* 隐藏报告区 */
// $( 'div#id_reportarea' ).empty().hide();
/* 展示执行区 */
var runningarea = document.getElementById('id_runningarea');
empty(runningarea).style.display = 'block';
var iframe = document.createElement('iframe');
iframe.id = fid;
iframe.src = url;
iframe.style.minHeight="1500px";
addClass(iframe, "runningframe");
runningarea.appendChild(iframe);
wb.kissstart = new Date().getTime();
};
// 需要根据一次批量执行整合所有文件的覆盖率情况
//function covcalc() {
// function covmerge(cc, covinfo) {
// for (var key in covinfo) {//key :每个文件
// for (var idx in covinfo[key]) {
// if (idx != 'source') {
//
// cc[key] = cc[key] || [];
// cc[key][idx] = (cc[key][idx] || 0) + covinfo[key][idx];
// }
// }
// }
// return cc;
// }
//
// var cc = {};
// var brkisses = window.brtest.kisses;
// for (var key in window.brtest.kisscov) {
// covmerge(cc, window.brtest.kisscov[key]);//key:每个用例
//// brkisses[kiss]= brkisses[kiss] + ',' + key;
// }
// var file;
// var files = [];
// var filter = '';
// var ls = location.search.split('&');
// for (var i = 0; i < ls.length; i++) {
// if (ls[i].indexOf('filter') != -1) {
// filter = ls[i].split('=')[1];
// }
//
// }
// for (file in cc) {
// if (!cc.hasOwnProperty(file)) {
// continue;
// }
// if (file.indexOf(filter) != -1)
// files.push(file);
// }
// files.sort();
// for (var f = 0; f < files.length; f++) {
// file = files[f];
// var lineNumber;
// var num_statements = 0;
// var num_executed = 0;
// var missing = [];
// var fileCC = cc[file];
// var length = fileCC.length;
// var currentConditionalEnd = 0;
// var conditionals = null;
//
// if (fileCC.conditionals) {
// conditionals = fileCC.conditionals;
// }
// var recordCovForBrowser = null;//
// for (lineNumber = 0; lineNumber < length; lineNumber++) {
// var n = fileCC[lineNumber];
//
// if (lineNumber === currentConditionalEnd) {
// currentConditionalEnd = 0;
// } else if (currentConditionalEnd === 0 && conditionals
// && conditionals[lineNumber]) {
// currentConditionalEnd = conditionals[lineNumber];
// }
//
// if (currentConditionalEnd !== 0) {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '2') : (recordCovForBrowser += ',2');
//
// continue;
// }
//
// if (n === undefined || n === null) {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '2') : (recordCovForBrowser += ',2');
// continue;
// }
//
// if (n === 0) {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '0') : (recordCovForBrowser += ',0');
// missing.push(lineNumber);
// } else {
// (recordCovForBrowser == null) ? (recordCovForBrowser = '1') : (recordCovForBrowser += ',1');
// num_executed++;
// }
// num_statements++;
// }
//
// var percentage = (num_statements === 0 ? 0 : ( 100 * num_executed / num_statements ).toFixed(1));
// var kiss = file.replace('.js', '');
// // 统计所有用例的覆盖率信息和测试结果
//
// if (brkisses[kiss] == undefined)
// brkisses[kiss] = '0;0;_;0;0';
// var info = brkisses[kiss].split(';_;');// 覆盖率的处理在最后环节加入到用例的测试结果中
// brkisses[kiss] = info[0] + ';' + percentage + ';' + info[1] + ';' + recordCovForBrowser;
// }
//}
window.onload =
function () {
if (location.href.search("[?&,]batchrun=true") > 0
|| document.getElementById('id_control_runnext').checked) {
run(document.getElementById('id_testlist').getElementsByTagName('a')[0].getAttribute('title'), true);
}
};
\ No newline at end of file
/**
* Created with JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午5:34
* To change this template use File | Settings | File Templates.
*/
function hasClass(obj, cls) {
return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(ele,cls) {
if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}
function removeClass(obj, cls) {
var clsArray= cls.split( " ");
for(var i=0;i<clsArray.length;i++){
if (hasClass(obj, clsArray[i])) {
var reg = new RegExp('(\\s|^)' + clsArray[i] + '(\\s|$)');
obj.className = obj.className.replace(reg, ' ');
}
}
}
function empty(obj){
var childs = obj.childNodes;
if(childs.length==0)return obj;
for(var i=0;i<childs.length;i++){
obj.removeChild(childs[i]);
}
return obj
}
function slideToggle(obj){
//todo 先写个大意,待完成
if(obj.style.display=='none'){
}else{
obj.style.display='block';
}
}
var triggerEvent = function () {
this.listeners = [];
this.customOne = function (type, listener) {
this.listeners[type] = listener;
for (var i = 0, l = this.listeners.length; i < l; i++) {
if (this.listeners[i] === this.listeners[type]) {
this.listeners.splice(i, 1);
i--;
}
}
},
this.customTrigger = function (type,arguments) {
if(this.listeners[type]){
return this.listeners[type].apply(this, arguments);
}
return false;
}
};
@echo off
jscoverage.exe --encoding=UTF-8 ../../../src ../../coverage
\ No newline at end of file
Copyright (c) 2008-2011 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed.
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
#HTMLReporter a { text-decoration: none; }
#HTMLReporter a:hover { text-decoration: underline; }
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
#HTMLReporter .version { color: #aaaaaa; }
#HTMLReporter .banner { margin-top: 14px; }
#HTMLReporter .duration { color: #aaaaaa; float: right; }
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
#HTMLReporter .passingAlert { background-color: #a6b779; }
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
#HTMLReporter .failingAlert { background-color: #cf867e; }
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
#HTMLReporter .results { margin-top: 14px; }
#HTMLReporter #details { display: none; }
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter.showDetails .summary { display: none; }
#HTMLReporter.showDetails #details { display: block; }
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter .summary { margin-top: 14px; }
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
#HTMLReporter .description + .suite { margin-top: 0; }
#HTMLReporter .suite { margin-top: 14px; }
#HTMLReporter .suite a { color: #333333; }
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
#HTMLReporter .resultMessage span.result { display: block; }
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
#TrivialReporter .runner.running { background-color: yellow; }
#TrivialReporter .options { text-align: right; font-size: .8em; }
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
#TrivialReporter .suite .suite { margin: 5px; }
#TrivialReporter .suite.passed { background-color: #dfd; }
#TrivialReporter .suite.failed { background-color: #fdd; }
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
#TrivialReporter .spec.skipped { background-color: #bbb; }
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
#TrivialReporter .passed { background-color: #cfc; display: none; }
#TrivialReporter .failed { background-color: #fbb; }
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
#TrivialReporter .resultMessage .mismatch { color: black; }
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
This diff is collapsed.
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-11
* Time: 下午5:17
* To change this template use File | Settings | File Templates.
*/
header( "Content-type: text/html; charset=utf-8" );
$filter = array_key_exists( 'filter' , $_GET ) ? $_GET[ 'filter' ] : '*';
$quirk = array_key_exists( 'quirk' , $_GET );
$cov = array_key_exists( 'cov' , $_GET );
if ( !$quirk ) {
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<?php } ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Kity Test Index Page</title>
<script type="text/javascript" src="js/tools.js"></script>
<!-- <script type="text/javascript" src="js/UserAction.js"></script>-->
<script type="text/javascript" src="js/run.js"></script>
<link media="screen" href="css/test.css" type="text/css"
rel="stylesheet"/>
</head>
<body>
<div id="title">
<h1>Kity Test Index Page</h1>
</div>
<!--浏览器插件,可调用windows api-->
<div>
<object id="plugin" type="application/x-plugintest" width="1" height="1">
<param name="onload" value="pluginLoaded"/>
</object>
</div>
<div id="id_control" class="control">
<input id="id_control_runnext" type="checkbox"/>自动下一个
<input id="id_control_breakonerror" type="checkbox"/>出错时终止
<input id="id_control_clearstatus" type="button" value="清除用例状态"
onclick="removeClass(document.getElementById('id_testlist'),'running_case pass_case fail_case');"/>
</div>
<div>
<a id="id_testlist_status" class="button"> <span
onclick="slideToggle(document.getElementById('id_testlist');"> 折叠用例 </span> </a>
<a id="id_srconly" class="button"><span
onclick="slideToggle(document.getElementById('id_runningarea');">折叠执行</span> </a>
</div>
<div style="clear: both"></div>
<div id="id_testlist" class="testlist">
<?php
/*分析所有源码与测试代码js文件一一对应的文件并追加到当前列表中*/
require_once "caseSource.php";
Kiss::listcase( $filter ,$cov);
?>
<div style="clear: both; overflow: hidden"></div>
</div>
<div id="id_runningarea" class="runningarea"
style="border: solid; display: none"></div>
<div id="id_reportarea" class="reportarea" style="display: none;"></div>
<div class='clear'></div>
<div id="id_showSrcOnly" class="testlist" style="display: none;">
<?php
require_once "caseSource.php";
Kiss::listSrcOnly( true );
?>
<div class="clear"></div>
</div>
</body>
</html>
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-17
* Time: 下午6:28
* To change this template use File | Settings | File Templates.
*/
error_reporting(E_ERROR|E_WARNING);
function report()
{
return;
}
report();
\ No newline at end of file
<?php
/**
* Created by JetBrains PhpStorm.
* User: dongyancen
* Date: 13-10-10
* Time: 上午1:17
* To change this template use File | Settings | File Templates.
*/
header( "Content-type: text/html; charset=utf-8" );
header( "Cache-Control: no-cache, max-age=10, must-revalidate" );
if ( !array_key_exists( 'quirk' , $_GET ) ) {
print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
}
;
require_once "caseSource.php";
$c = new Kiss( $_GET[ 'case' ] );
$title = $c->name;
$cov = array_key_exists( 'cov' , $_GET );
?>
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.3.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.3.0/jasmine.css">
<script type="text/javascript" src="lib/jasmine-1.3.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.3.0/jasmine-html.js"></script>
<script type="text/javascript" src="js/ext_jasmine.js"></script>
<?php $c->print_js($cov); ?>
</head>
<script type="text/javascript">
//todo
// if (parent && parent.brtest) {
// parent.$(parent.brtest).trigger('done', [ new Date().getTime(), {
// failed : args[0],
// passed : args[1],
// detail:args[2]
// }, window._$jscoverage || null ]);
// }
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
// jasmineEnv.beforeEach(function(){console.log(12)});
// jasmine.Suite.beforeEach(function(){console.log(123)});
// console.log(jasmineEnv.currentSpec);
// jasmineEnv.currentSpec.start=function(){console.log(123)};
jasmineEnv.execute();
}
})();
</script>
<body>
</body>
</html>
\ No newline at end of file
测试要点
1. 操作模式
1.1 常规模式
1.1.1 只在该模式允许的操作:`节点选择`、`创建新节点`、`拖动到父节点`
1.2 拖动模式
1.1.2 只在该模式允许的操作:`画布拖放`
1.3 文本编辑模式
1.1.3 只在该模式允许的操作:`文本框选`、`文本编辑`
1.4 模式切换
1.4.1 常规模式下,在单个选中的节点上点击文字区域(多选的情况下不算),进入文本编辑模式,并且光标定在点击的位置上
1.4.2 常规模式下,在任意节点上双击文字区域,进入文本编辑模式,并且文本被选中
1.4.3 常规模式下,创建了新节点的时候,进入文本编辑模式,新节点文本被选中
1.4.4 常规模式下,有唯一选中的节点,按下字母和数字的按键会进入文本编辑模式,并且文字变为刚输入的字母或数字,或是弹出输入法框
1.4.5 文本编辑模式下,按 Tab 和 Enter 退出文本编辑模式,回到常规模式
1.4.6 文本编辑模式下,点击非文本区域的任何位置,退出文本编辑模式,回到常规模式
1.4.7 常规模式下,按 Space 或点击 UI 上的拖动图标进入拖动模式
1.4.8 拖动模式下,按 Space 或点击 UI 上的拖动图标退出拖动模式,回到常规模式
2. `节点选择` 交互
2.1 该交互只在常规模式下有效
2.2 点击任意未被选中的节点,会使其选中
2.3 点击空白处,会取消节点的选择
2.4 按着 Shift 键,点击的节点会切换选择状态
2.5 在空白处按下鼠标并移动10像素后,会显示选框;当选框跟节点有重合的时候,节点会被选中,没有重合的节点不被选中
2.6 按键盘方向键的时候:
2.6.1 对于一个节点“方向”的定义为:
2.6.1.1 以节点为坐标原点的直角坐标系顺时针旋转45度,第一象限为“上”,第二象限为“左”,第三象限为“右”,第四象限为“下”
2.6.2 假如当前没有节点被选中,任何方向键都将选中根节点
2.6.3 假如当前有唯一选中的节点,将导航至指定方向区域的最近的节点
2.6.4 假如有多个选择的节点,以选择顺序第一个节点为参照,导航至其指定方向区域的最近的节点
2.6.5 假如被导航的区域中没有节点,选区保持不变
3. `创建新节点` 交互
3.1 目标节点定义为:
3.1.1 如果有唯一选中的节点,其为目标节点
3.1.2 如果有多个选中的节点,则首个(时间上)被选中的节点为目标节点
3.2 如果存在目标节点:
3.2.1 按下键盘的 Tab 键,会创建一个目标节点的子节点,并且新节点在唯一选中状态,模式变为文本编辑模式
3.2.2 按下键盘的 Enter 键,并且目标节点不是根节点,会创建一个目标节点的兄弟节点(紧邻的位置上),并且新节点在唯一选中,模式变为文本编辑模式
3.3 如果存在目标节点:
3.3.1 创建子节点的 UI 是可用的,否则不可用
3.3.2 如果目标节点是根节点,则创建兄弟节点的 UI 是不可用的,否则是可用的
3.4 该交互只在常规模式下有效
4. `拖放到父节点` 交互
4.1 该交互只在常规模式下有效
4.2 在任意节点上 mousedown,并且移动10像素以上,确定拖放对象:
4.2.1 如果节点没被选中,则节点被选中,并且作为拖动对象
4.2.2 如果节点是被选中的,则所有选中的节点作为拖放对象
4.3 排除无效拖放对象:
4.3.1 如果存在一个拖放对象A和另一个拖放对象B,A是B的祖先,则B被排除
4.3.2 排除后剩余的对象成为真正的拖放对象
4.4 拖放对象表示为一个拖放图形,并且显示拖放对象的数量
4.5 拖放图形随鼠标移动,并且每次移动会判断是否遇到拖放目标:
4.5.1 拖放对象本身以及整棵子树都不能作为拖放目标
4.5.2 如果拖放图形和拖放目标的图形有重合,拖放目标会高亮,否则不会高亮
4.6 如果在遇到拖放目标的时候释放鼠标(mouseup),会让拖放对象成为拖放目标的子节点,并且:
4.6.1 保持之前拖放目标的选中状态
4.6.2 保证拖放目标的顺序与拖放之前保持一致
5. `画布导航` 交互
5.1 该交互只在拖动模式下有效
5.2 在任意位置鼠标按下(mousedown)之后画布可以随鼠标移动
5.3 鼠标释放(mouseup)之后画布不再随鼠标移动
5.4 按下方向键会让画布用动画朝反方向移动一定的距离
6. `画布缩放` 交互
6.1 在非文本编辑模式下,点击 `+` 和 `-` 分别可以拉近视野(放大画布)和拉远视野(缩小画布)
6.2 在任意模式下,使用鼠标滚轮可以缩放视野
6.2.1 往上滚动拉近视野
6.2.3 往下滚动拉远视野
6.3 在任意模式下,UI 上的 zoom-in 和 zoom-out 分别可以拉近视野和拉远视野
6.4 视野拉远和拉近都有最值,不能无限操作;当每个操作不可用的时候,UI 上的按钮呈不可用状态
7. `文本框选` 和 `文本编辑` 和默认行为一致即可
8. `字体样式` 功能
8.1 该功能在 `拖放模式` 下不可用
8.2 包括的子功能:
8.2.1 加粗
8.2.2 斜体
8.2.3 字体
8.2.4 字号
8.2.5 颜色
8.3 所有的子功能以节点为单位设置和读取
8.4 对于选中的节点在 UI 上应该反映当前的样式状态
8.5 UI 上设置样式针对所有选中的节点生效
8.6 没有选中节点的时候,UI 上的功能按钮应该呈不可用状态
9. `子节点收缩功能`
9.1 在一级节点及以上,如果存在子节点,显示收缩功能的图标,否则不显示
9.2 收缩图标显示 `-` 的时候,子节点显示;收缩图标显示 `+` 的时候,子节点不显示;点击图标切换这两种状态
10. `节点删除功能`
10.1 目标节点的计算方法同拖放到父节点的拖放目标的计算方法
10.2 如果目标节点包含根,把根从目标节点中移除
10.3 如果包含删除目标,删除操作的 UI 是可用的,否则是不可用的
10.4 把所有目标节点从其父节点中移除
11. `标签功能`
11.1 对于选中的节点,点击优先级标签和完成度标签可以在节点文本前添加标签图形
11.2 对于同一类的标签,只能添加一个标签
11.3 选中单个节点的时候,标签面板显示选中节点的当前标签;
11.4 多选的情况下,如果标签一致以任意一个节点为准来显示状态;标签不一致显示所有包含的状态
12. `导入导出功能`
12.1 导出数据应该能下载一个文件
12.2 下载的文件拖动到画布上,可以还原原来的数据
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment