Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Eugene Shen
todomvc
Commits
4a4016ff
Commit
4a4016ff
authored
11 years ago
by
Pascal Hartig
Browse files
Options
Download
Email Patches
Plain Diff
Update browser-tests JS style
parent
d7be11ee
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
841 additions
and
819 deletions
+841
-819
browser-tests/Gruntfile.js
browser-tests/Gruntfile.js
+14
-15
browser-tests/allTests.js
browser-tests/allTests.js
+46
-27
browser-tests/knownIssues.js
browser-tests/knownIssues.js
+87
-87
browser-tests/page.js
browser-tests/page.js
+146
-146
browser-tests/pageLaxMode.js
browser-tests/pageLaxMode.js
+19
-19
browser-tests/test.js
browser-tests/test.js
+371
-370
browser-tests/testOperations.js
browser-tests/testOperations.js
+158
-155
No files found.
browser-tests/Gruntfile.js
View file @
4a4016ff
module
.
exports
=
function
(
grunt
)
{
grunt
.
loadNpmTasks
(
'
grunt-simple-mocha
'
);
'
use strict
'
;
grunt
.
loadNpmTasks
(
'
grunt-simple-mocha
'
);
var
gruntConfig
=
{
simplemocha
:
{
options
:
{
reporter
:
'
mocha-known-issues-reporter
'
},
files
:
{
src
:
'
allTests.js
'
}
}
};
grunt
.
initConfig
(
gruntConfig
);
grunt
.
initConfig
({
simplemocha
:
{
options
:
{
reporter
:
'
mocha-known-issues-reporter
'
},
files
:
{
src
:
'
allTests.js
'
}
}
});
// build tasks
grunt
.
registerTask
(
'
test
'
,
[
'
simplemocha
'
]);
// build tasks
grunt
.
registerTask
(
'
test
'
,
[
'
simplemocha
'
]);
};
This diff is collapsed.
Click to expand it.
browser-tests/allTests.js
View file @
4a4016ff
var
testSuite
=
require
(
'
./test.js
'
),
fs
=
require
(
'
fs
'
),
argv
=
require
(
'
optimist
'
).
default
(
'
laxMode
'
,
false
).
argv
,
rootUrl
=
"
http://localhost:8000/
"
,
frameworkNamePattern
=
/^
[
a-z-_
]
+$/
;
'
use strict
'
;
// collect together the framework names from each of the subfolders
var
list
=
fs
.
readdirSync
(
"
../architecture-examples/
"
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
"
architecture-examples/
"
+
folderName
}
});
list
=
list
.
concat
(
fs
.
readdirSync
(
"
../labs/architecture-examples/
"
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
"
labs/architecture-examples/
"
+
folderName
}
}));
list
=
list
.
concat
(
fs
.
readdirSync
(
"
../labs/dependency-examples/
"
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
"
labs/dependency-examples/
"
+
folderName
}
}));
var
testSuite
=
require
(
'
./test.js
'
);
var
fs
=
require
(
'
fs
'
);
var
argv
=
require
(
'
optimist
'
).
default
(
'
laxMode
'
,
false
).
argv
;
var
rootUrl
=
'
http://localhost:8000/
'
;
var
frameworkNamePattern
=
/^
[
a-z-_
]
+$/
;
list
=
list
.
concat
(
fs
.
readdirSync
(
"
../dependency-examples/
"
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
"
dependency-examples/
"
+
folderName
}
}));
// collect together the framework names from each of the subfolders
var
list
=
fs
.
readdirSync
(
'
../architecture-examples/
'
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
'
architecture-examples/
'
+
folderName
};
})
.
concat
(
fs
.
readdirSync
(
'
../labs/architecture-examples/
'
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
'
labs/architecture-examples/
'
+
folderName
};
})
)
.
concat
(
fs
.
readdirSync
(
'
../labs/dependency-examples/
'
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
'
labs/dependency-examples/
'
+
folderName
};
})
)
.
concat
(
fs
.
readdirSync
(
'
../dependency-examples/
'
)
.
map
(
function
(
folderName
)
{
return
{
name
:
folderName
,
path
:
'
dependency-examples/
'
+
folderName
};
})
);
// apps that are not hosted at the root of their folder need to be handled explicitly
var
exceptions
=
[
{
name
:
"
chaplin-brunch
"
,
path
:
"
labs/dependency-examples/chaplin-brunch/public
"
}
{
name
:
'
chaplin-brunch
'
,
path
:
'
labs/dependency-examples/chaplin-brunch/public
'
}
];
list
=
list
.
map
(
function
(
framework
)
{
var
exception
=
exceptions
.
filter
(
function
(
exFramework
)
{
return
exFramework
.
name
===
framework
.
name
});
return
exception
.
length
>
0
?
exception
[
0
]
:
framework
;
list
=
list
.
map
(
function
(
framework
)
{
var
exception
=
exceptions
.
filter
(
function
(
exFramework
)
{
return
exFramework
.
name
===
framework
.
name
;
});
return
exception
.
length
>
0
?
exception
[
0
]
:
framework
;
});
// filter out any folders that are not frameworks (.e.g hidden files)
list
=
list
.
filter
(
function
(
framework
)
{
return
frameworkNamePattern
.
test
(
framework
.
name
);
});
list
=
list
.
filter
(
function
(
framework
)
{
return
frameworkNamePattern
.
test
(
framework
.
name
);
});
// if a specific framework has been named, just run this one
if
(
argv
.
framework
)
{
list
=
list
.
filter
(
function
(
framework
)
{
return
framework
.
name
===
argv
.
framework
});
if
(
argv
.
framework
)
{
list
=
list
.
filter
(
function
(
framework
)
{
return
framework
.
name
===
argv
.
framework
;
});
}
// run the tests for each framework
var
testIndex
=
1
;
list
.
forEach
(
function
(
framework
)
{
testSuite
.
todoMVCTest
(
framework
.
name
,
rootUrl
+
framework
.
path
+
"
/index.html
"
,
argv
.
speedMode
,
argv
.
laxMode
);
list
.
forEach
(
function
(
framework
)
{
testSuite
.
todoMVCTest
(
framework
.
name
,
rootUrl
+
framework
.
path
+
'
/index.html
'
,
argv
.
speedMode
,
argv
.
laxMode
);
});
This diff is collapsed.
Click to expand it.
browser-tests/knownIssues.js
View file @
4a4016ff
module
.
exports
=
[
// the following are covered by the following issue:
// https://github.com/tastejs/todomvc/issues/789
"
TodoMVC - agilityjs, Editing, should cancel edits on escape
"
,
"
TodoMVC - angularjs-perf, Editing, should cancel edits on escape
"
,
"
TodoMVC - closure, Editing, should cancel edits on escape
"
,
"
TodoMVC - jquery, Editing, should cancel edits on escape
"
,
"
TodoMVC - knockback, Editing, should cancel edits on escape
"
,
"
TodoMVC - spine, Editing, should cancel edits on escape
"
,
"
TodoMVC - yui, Editing, should cancel edits on escape
"
,
// the following are covered by the following issue:
// https://github.com/tastejs/todomvc/issues/789
'
TodoMVC - agilityjs, Editing, should cancel edits on escape
'
,
'
TodoMVC - angularjs-perf, Editing, should cancel edits on escape
'
,
'
TodoMVC - closure, Editing, should cancel edits on escape
'
,
'
TodoMVC - jquery, Editing, should cancel edits on escape
'
,
'
TodoMVC - knockback, Editing, should cancel edits on escape
'
,
'
TodoMVC - spine, Editing, should cancel edits on escape
'
,
'
TodoMVC - yui, Editing, should cancel edits on escape
'
,
// all the following are covered by this issue:
// https://github.com/tastejs/todomvc/issues/790
// these implementations filter the view rather than the model when routing
"
TodoMVC - agilityjs, Routing, should allow me to display active items
"
,
"
TodoMVC - agilityjs, Routing, should allow me to display completed items
"
,
"
TodoMVC - backbone, Routing, should allow me to display active items
"
,
"
TodoMVC - backbone, Routing, should allow me to display completed items
"
,
"
TodoMVC - maria, Routing, should allow me to display active items
"
,
"
TodoMVC - maria, Routing, should allow me to display completed items
"
,
"
TodoMVC - dojo, Routing, should allow me to display active items
"
,
"
TodoMVC - dojo, Routing, should allow me to display completed items
"
,
// all the following are covered by this issue:
// https://github.com/tastejs/todomvc/issues/790
// these implementations filter the view rather than the model when routing
'
TodoMVC - agilityjs, Routing, should allow me to display active items
'
,
'
TodoMVC - agilityjs, Routing, should allow me to display completed items
'
,
'
TodoMVC - backbone, Routing, should allow me to display active items
'
,
'
TodoMVC - backbone, Routing, should allow me to display completed items
'
,
'
TodoMVC - maria, Routing, should allow me to display active items
'
,
'
TodoMVC - maria, Routing, should allow me to display completed items
'
,
'
TodoMVC - dojo, Routing, should allow me to display active items
'
,
'
TodoMVC - dojo, Routing, should allow me to display completed items
'
,
// the following are covered by this issue:
// https://github.com/tastejs/todomvc/issues/795
"
TodoMVC - spine, Mark all as completed, complete all checkbox should update state when items are completed / cleared
"
,
"
TodoMVC - angularjs-perf, Mark all as completed, complete all checkbox should update state when items are completed / cleared
"
,
// the following are covered by this issue:
// https://github.com/tastejs/todomvc/issues/795
'
TodoMVC - spine, Mark all as completed, complete all checkbox should update state when items are completed / cleared
'
,
'
TodoMVC - angularjs-perf, Mark all as completed, complete all checkbox should update state when items are completed / cleared
'
,
// the following implementations do not support routing
"
TodoMVC - jquery, Routing, should allow me to display active items
"
,
"
TodoMVC - jquery, Routing, should allow me to display completed items
"
,
"
TodoMVC - jquery, Routing, should allow me to display all items
"
,
"
TodoMVC - jquery, Routing, should highlight the currently applied filter
"
,
// the following implementations do not support routing
'
TodoMVC - jquery, Routing, should allow me to display active items
'
,
'
TodoMVC - jquery, Routing, should allow me to display completed items
'
,
'
TodoMVC - jquery, Routing, should allow me to display all items
'
,
'
TodoMVC - jquery, Routing, should highlight the currently applied filter
'
,
// ----------------- Test framework issues -----------
// ----------------- Test framework issues -----------
// for some reason the persistence test fails for knockout, even though persistence is working
// just fine. Perhaps there is something asynchronous going on that is causing the assert
// to be executed early?
"
TodoMVC - knockoutjs, Persistence, should persist its data
"
,
// for some reason the persistence test fails for knockout, even though persistence is working
// just fine. Perhaps there is something asynchronous going on that is causing the assert
// to be executed early?
'
TodoMVC - knockoutjs, Persistence, should persist its data
'
,
// ----------------- Unsupported implementations!! -----------
// ----------------- Unsupported implementations!! -----------
// the following are TodoMVC implementations that are not supported by the autoated UI
// tests, and as a result have numerous failures.
// the following are TodoMVC implementations that are not supported by the autoated UI
// tests, and as a result have numerous failures.
// polymer - does not follow the HTML spec
"
TodoMVC - polymer, New Todo, should allow me to add todo items
"
,
"
TodoMVC - polymer, New Todo, should clear text input field when an item is added
"
,
"
TodoMVC - polymer, New Todo, should trim text input
"
,
"
TodoMVC - polymer, New Todo, should show #main and #footer when items added
"
,
"
TodoMVC - polymer, Mark all as completed, should allow me to mark all items as completed
"
,
"
TodoMVC - polymer, Mark all as completed, should allow me to clear the completion state of all items
"
,
"
TodoMVC - polymer, Mark all as completed, complete all checkbox should update state when items are completed / cleared
"
,
"
TodoMVC - polymer, Item, should allow me to mark items as complete
"
,
"
TodoMVC - polymer, Item, should allow me to un-mark items as complete
"
,
"
TodoMVC - polymer, Item, should allow me to edit an item
"
,
"
TodoMVC - polymer, Editing, should hide other controls when editing
"
,
"
TodoMVC - polymer, Editing, should save edits on enter
"
,
"
TodoMVC - polymer, Editing, should save edits on blur
"
,
"
TodoMVC - polymer, Editing, should trim entered text
"
,
"
TodoMVC - polymer, Editing, should remove the item if an empty text string was entered
"
,
"
TodoMVC - polymer, Editing, should cancel edits on escape
"
,
"
TodoMVC - polymer, Counter, should display the current number of todo items
"
,
"
TodoMVC - polymer, Clear completed button, should display the number of completed items
"
,
"
TodoMVC - polymer, Clear completed button, should remove completed items when clicked
"
,
"
TodoMVC - polymer, Clear completed button, should be hidden when there are no items that are completed
"
,
"
TodoMVC - polymer, Persistence, should persist its data
"
,
"
TodoMVC - polymer, Routing, should allow me to display active items
"
,
"
TodoMVC - polymer, Routing, should allow me to display completed items
"
,
"
TodoMVC - polymer, Routing, should allow me to display all items
"
,
"
TodoMVC - polymer, Routing, should highlight the currently applied filter
"
,
// polymer - does not follow the HTML spec
'
TodoMVC - polymer, New Todo, should allow me to add todo items
'
,
'
TodoMVC - polymer, New Todo, should clear text input field when an item is added
'
,
'
TodoMVC - polymer, New Todo, should trim text input
'
,
'
TodoMVC - polymer, New Todo, should show #main and #footer when items added
'
,
'
TodoMVC - polymer, Mark all as completed, should allow me to mark all items as completed
'
,
'
TodoMVC - polymer, Mark all as completed, should allow me to clear the completion state of all items
'
,
'
TodoMVC - polymer, Mark all as completed, complete all checkbox should update state when items are completed / cleared
'
,
'
TodoMVC - polymer, Item, should allow me to mark items as complete
'
,
'
TodoMVC - polymer, Item, should allow me to un-mark items as complete
'
,
'
TodoMVC - polymer, Item, should allow me to edit an item
'
,
'
TodoMVC - polymer, Editing, should hide other controls when editing
'
,
'
TodoMVC - polymer, Editing, should save edits on enter
'
,
'
TodoMVC - polymer, Editing, should save edits on blur
'
,
'
TodoMVC - polymer, Editing, should trim entered text
'
,
'
TodoMVC - polymer, Editing, should remove the item if an empty text string was entered
'
,
'
TodoMVC - polymer, Editing, should cancel edits on escape
'
,
'
TodoMVC - polymer, Counter, should display the current number of todo items
'
,
'
TodoMVC - polymer, Clear completed button, should display the number of completed items
'
,
'
TodoMVC - polymer, Clear completed button, should remove completed items when clicked
'
,
'
TodoMVC - polymer, Clear completed button, should be hidden when there are no items that are completed
'
,
'
TodoMVC - polymer, Persistence, should persist its data
'
,
'
TodoMVC - polymer, Routing, should allow me to display active items
'
,
'
TodoMVC - polymer, Routing, should allow me to display completed items
'
,
'
TodoMVC - polymer, Routing, should allow me to display all items
'
,
'
TodoMVC - polymer, Routing, should highlight the currently applied filter
'
,
// gwt - does not follow the HTML spec closely eough for testing
"
TodoMVC - gwt, New Todo, should allow me to add todo items
"
,
"
TodoMVC - gwt, New Todo, should trim text input
"
,
"
TodoMVC - gwt, Mark all as completed, should allow me to mark all items as completed
"
,
"
TodoMVC - gwt, Mark all as completed, should allow me to clear the completion state of all items
"
,
"
TodoMVC - gwt, Mark all as completed, complete all checkbox should update state when items are completed / cleared
"
,
"
TodoMVC - gwt, Item, should allow me to mark items as complete
"
,
"
TodoMVC - gwt, Item, should allow me to un-mark items as complete
"
,
"
TodoMVC - gwt, Item, should allow me to edit an item
"
,
"
TodoMVC - gwt, Editing, should hide other controls when editing
"
,
"
TodoMVC - gwt, Editing, should save edits on enter
"
,
"
TodoMVC - gwt, Editing, should save edits on blur
"
,
"
TodoMVC - gwt, Editing, should trim entered text
"
,
"
TodoMVC - gwt, Editing, should remove the item if an empty text string was entered
"
,
"
TodoMVC - gwt, Editing, should cancel edits on escape
"
,
"
TodoMVC - gwt, Clear completed button, should display the number of completed items
"
,
"
TodoMVC - gwt, Clear completed button, should remove completed items when clicked
"
,
"
TodoMVC - gwt, Clear completed button, should be hidden when there are no items that are completed
"
,
"
TodoMVC - gwt, Persistence, should persist its data
"
,
"
TodoMVC - gwt, Routing, should allow me to display active items
"
,
"
TodoMVC - gwt, Routing, should allow me to display completed items
"
,
"
TodoMVC - gwt, Routing, should allow me to display all items
"
,
"
TodoMVC - gwt, Routing, should highlight the currently applied filter
"
,
];
\ No newline at end of file
// gwt - does not follow the HTML spec closely eough for testing
'
TodoMVC - gwt, New Todo, should allow me to add todo items
'
,
'
TodoMVC - gwt, New Todo, should trim text input
'
,
'
TodoMVC - gwt, Mark all as completed, should allow me to mark all items as completed
'
,
'
TodoMVC - gwt, Mark all as completed, should allow me to clear the completion state of all items
'
,
'
TodoMVC - gwt, Mark all as completed, complete all checkbox should update state when items are completed / cleared
'
,
'
TodoMVC - gwt, Item, should allow me to mark items as complete
'
,
'
TodoMVC - gwt, Item, should allow me to un-mark items as complete
'
,
'
TodoMVC - gwt, Item, should allow me to edit an item
'
,
'
TodoMVC - gwt, Editing, should hide other controls when editing
'
,
'
TodoMVC - gwt, Editing, should save edits on enter
'
,
'
TodoMVC - gwt, Editing, should save edits on blur
'
,
'
TodoMVC - gwt, Editing, should trim entered text
'
,
'
TodoMVC - gwt, Editing, should remove the item if an empty text string was entered
'
,
'
TodoMVC - gwt, Editing, should cancel edits on escape
'
,
'
TodoMVC - gwt, Clear completed button, should display the number of completed items
'
,
'
TodoMVC - gwt, Clear completed button, should remove completed items when clicked
'
,
'
TodoMVC - gwt, Clear completed button, should be hidden when there are no items that are completed
'
,
'
TodoMVC - gwt, Persistence, should persist its data
'
,
'
TodoMVC - gwt, Routing, should allow me to display active items
'
,
'
TodoMVC - gwt, Routing, should allow me to display completed items
'
,
'
TodoMVC - gwt, Routing, should allow me to display all items
'
,
'
TodoMVC - gwt, Routing, should highlight the currently applied filter
'
,
];
This diff is collapsed.
Click to expand it.
browser-tests/page.js
View file @
4a4016ff
var
webdriver
=
require
(
'
selenium-webdriver
'
)
;
'
use strict
'
;
function
Page
(
browser
,
laxMode
)
{
var
webdriver
=
require
(
'
selenium-webdriver
'
);
// ----------------- utility methods
module
.
exports
=
function
Page
(
browser
)
{
this
.
xPathForItemAtIndex
=
function
(
index
)
{
// why is XPath the only language silly enough to be 1-indexed?
return
"
//ul[@id='todo-list']/li[
"
+
(
index
+
1
)
+
"
]
"
;
}
// ----------------- try / get methods
// unfortunately webdriver does not have a decent API for determining if an
// element exists. The standard approach is to obtain an array of elements
// and test that the length is zero. These methods are used to obtain
// elements which *might* be present in the DOM, hence the try/get name.
this
.
tryGetMainSectionElement
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
"
//section[@id='main']
"
));
}
this
.
tryGetFooterElement
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
"
//footer[@id='footer']
"
));
}
this
.
tryGetClearCompleteButton
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
"
//button[@id='clear-completed']
"
));
}
this
.
tryGetToggleForItemAtIndex
=
function
(
index
)
{
var
xpath
=
this
.
xPathForItemAtIndex
(
index
)
+
"
//input[contains(@class,'toggle')]
"
;
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
xpath
));
}
this
.
tryGetItemLabelAtIndex
=
function
(
index
)
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
this
.
xPathForItemAtIndex
(
index
)
+
"
//label
"
));
}
// ----------------- DOM element access methods
this
.
getEditInputForItemAtIndex
=
function
(
index
)
{
var
xpath
=
this
.
xPathForItemAtIndex
(
index
)
+
"
//input[contains(@class,'edit')]
"
;
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
xpath
));
}
this
.
getItemInputField
=
function
()
{
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
"
//input[@id='new-todo']
"
));
}
this
.
getMarkAllCompletedCheckBox
=
function
()
{
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
"
//input[@id='toggle-all']
"
));
}
this
.
getItemElements
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
"
//ul[@id='todo-list']/li
"
));
}
this
.
getNonCompletedItemElements
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
"
//ul[@id='todo-list']/li[not(contains(@class,'completed'))]
"
));
}
this
.
getItemsCountElement
=
function
()
{
return
browser
.
findElement
(
webdriver
.
By
.
id
(
"
todo-count
"
));
}
this
.
getItemLabelAtIndex
=
function
(
index
)
{
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
this
.
xPathForItemAtIndex
(
index
)
+
"
//label
"
));
}
this
.
getFilterElements
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
"
//ul[@id='filters']//a
"
));
}
// ----------------- page actions
this
.
clickMarkAllCompletedCheckBox
=
function
()
{
return
this
.
getMarkAllCompletedCheckBox
().
then
(
function
(
checkbox
){
checkbox
.
click
();
});
}
this
.
clickClearCompleteButton
=
function
()
{
return
this
.
tryGetClearCompleteButton
().
then
(
function
(
elements
)
{
var
button
=
elements
[
0
];
button
.
click
();
});
}
this
.
enterItem
=
function
(
itemText
)
{
var
textField
=
this
.
getItemInputField
();
textField
.
sendKeys
(
itemText
);
textField
.
sendKeys
(
webdriver
.
Key
.
ENTER
);
};
this
.
toggleItemAtIndex
=
function
(
index
)
{
return
this
.
tryGetToggleForItemAtIndex
(
index
).
then
(
function
(
elements
)
{
var
toggleElement
=
elements
[
0
];
toggleElement
.
click
();
});
}
this
.
editItemAtIndex
=
function
(
index
,
itemText
)
{
return
this
.
getEditInputForItemAtIndex
(
index
)
.
then
(
function
(
itemEditField
)
{
// send 50 delete keypresses, just to be sure the item text is deleted
var
deleteKeyPresses
=
""
;
for
(
var
i
=
0
;
i
<
50
;
i
++
)
{
deleteKeyPresses
+=
webdriver
.
Key
.
BACK_SPACE
}
itemEditField
.
sendKeys
(
deleteKeyPresses
);
// update the item with the new text.
itemEditField
.
sendKeys
(
itemText
);
});
};
this
.
doubleClickItemAtIndex
=
function
(
index
)
{
return
this
.
getItemLabelAtIndex
(
index
).
then
(
function
(
itemLabel
)
{
// double click is not 'natively' supported, so we need to send the event direct to the element
// see: http://stackoverflow.com/questions/3982442/selenium-2-webdriver-how-to-double-click-a-table-row-which-opens-a-new-window
browser
.
executeScript
(
"
var evt = document.createEvent('MouseEvents');
"
+
"
evt.initMouseEvent('dblclick',true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);
"
+
"
arguments[0].dispatchEvent(evt);
"
,
itemLabel
);
});
}
this
.
filterByActiveItems
=
function
(
index
)
{
return
this
.
getFilterElements
().
then
(
function
(
filters
)
{
filters
[
1
].
click
();
});
}
this
.
filterByCompletedItems
=
function
(
index
)
{
return
this
.
getFilterElements
().
then
(
function
(
filters
)
{
filters
[
2
].
click
();
});
}
this
.
filterByAllItems
=
function
(
index
)
{
return
this
.
getFilterElements
().
then
(
function
(
filters
)
{
filters
[
0
].
click
();
});
}
}
module
.
exports
=
Page
;
\ No newline at end of file
// ----------------- utility methods
this
.
xPathForItemAtIndex
=
function
(
index
)
{
// why is XPath the only language silly enough to be 1-indexed?
return
'
//ul[@id="todo-list"]/li[
'
+
(
index
+
1
)
+
'
]
'
;
};
// ----------------- try / get methods
// unfortunately webdriver does not have a decent API for determining if an
// element exists. The standard approach is to obtain an array of elements
// and test that the length is zero. These methods are used to obtain
// elements which *might* be present in the DOM, hence the try/get name.
this
.
tryGetMainSectionElement
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
'
//section[@id="main"]
'
));
};
this
.
tryGetFooterElement
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
'
//footer[@id="footer"]
'
));
};
this
.
tryGetClearCompleteButton
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
'
//button[@id="clear-completed"]
'
));
};
this
.
tryGetToggleForItemAtIndex
=
function
(
index
)
{
var
xpath
=
this
.
xPathForItemAtIndex
(
index
)
+
'
//input[contains(@class,"toggle")]
'
;
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
xpath
));
};
this
.
tryGetItemLabelAtIndex
=
function
(
index
)
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
this
.
xPathForItemAtIndex
(
index
)
+
'
//label
'
));
};
// ----------------- DOM element access methods
this
.
getEditInputForItemAtIndex
=
function
(
index
)
{
var
xpath
=
this
.
xPathForItemAtIndex
(
index
)
+
'
//input[contains(@class,"edit")]
'
;
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
xpath
));
};
this
.
getItemInputField
=
function
()
{
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
'
//input[@id="new-todo"]
'
));
};
this
.
getMarkAllCompletedCheckBox
=
function
()
{
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
'
//input[@id="toggle-all"]
'
));
};
this
.
getItemElements
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
'
//ul[@id="todo-list"]/li
'
));
};
this
.
getNonCompletedItemElements
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
'
//ul[@id="todo-list"]/li[not(contains(@class,"completed"))]
'
));
};
this
.
getItemsCountElement
=
function
()
{
return
browser
.
findElement
(
webdriver
.
By
.
id
(
'
todo-count
'
));
};
this
.
getItemLabelAtIndex
=
function
(
index
)
{
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
this
.
xPathForItemAtIndex
(
index
)
+
'
//label
'
));
};
this
.
getFilterElements
=
function
()
{
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
'
//ul[@id="filters"]//a
'
));
};
// ----------------- page actions
this
.
clickMarkAllCompletedCheckBox
=
function
()
{
return
this
.
getMarkAllCompletedCheckBox
().
then
(
function
(
checkbox
)
{
checkbox
.
click
();
});
};
this
.
clickClearCompleteButton
=
function
()
{
return
this
.
tryGetClearCompleteButton
().
then
(
function
(
elements
)
{
var
button
=
elements
[
0
];
button
.
click
();
});
};
this
.
enterItem
=
function
(
itemText
)
{
var
textField
=
this
.
getItemInputField
();
textField
.
sendKeys
(
itemText
);
textField
.
sendKeys
(
webdriver
.
Key
.
ENTER
);
};
this
.
toggleItemAtIndex
=
function
(
index
)
{
return
this
.
tryGetToggleForItemAtIndex
(
index
).
then
(
function
(
elements
)
{
var
toggleElement
=
elements
[
0
];
toggleElement
.
click
();
});
};
this
.
editItemAtIndex
=
function
(
index
,
itemText
)
{
return
this
.
getEditInputForItemAtIndex
(
index
)
.
then
(
function
(
itemEditField
)
{
// send 50 delete keypresses, just to be sure the item text is deleted
var
deleteKeyPresses
=
''
;
for
(
var
i
=
0
;
i
<
50
;
i
++
)
{
deleteKeyPresses
+=
webdriver
.
Key
.
BACK_SPACE
;
}
itemEditField
.
sendKeys
(
deleteKeyPresses
);
// update the item with the new text.
itemEditField
.
sendKeys
(
itemText
);
});
};
this
.
doubleClickItemAtIndex
=
function
(
index
)
{
return
this
.
getItemLabelAtIndex
(
index
).
then
(
function
(
itemLabel
)
{
// double click is not 'natively' supported, so we need to send the
// event direct to the element see:
// http://stackoverflow.com/questions/3982442/selenium-2-webdriver-how-to-double-click-a-table-row-which-opens-a-new-window
browser
.
executeScript
(
'
var evt = document.createEvent("MouseEvents");
'
+
'
evt.initMouseEvent("dblclick",true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);
'
+
'
arguments[0].dispatchEvent(evt);
'
,
itemLabel
);
});
};
this
.
filterByActiveItems
=
function
()
{
return
this
.
getFilterElements
().
then
(
function
(
filters
)
{
filters
[
1
].
click
();
});
};
this
.
filterByCompletedItems
=
function
()
{
return
this
.
getFilterElements
().
then
(
function
(
filters
)
{
filters
[
2
].
click
();
});
};
this
.
filterByAllItems
=
function
()
{
return
this
.
getFilterElements
().
then
(
function
(
filters
)
{
filters
[
0
].
click
();
});
};
};
This diff is collapsed.
Click to expand it.
browser-tests/pageLaxMode.js
View file @
4a4016ff
var
webdriver
=
require
(
'
selenium-webdriver
'
),
Page
=
require
(
"
./page
"
);
'
use strict
'
;
function
PageLaxMode
(
browser
)
{
Page
.
apply
(
this
,
[
browser
]
);
var
webdriver
=
require
(
'
selenium-webdriver
'
);
var
Page
=
require
(
'
./page
'
);
this
.
tryGetToggleForItemAtIndex
=
function
(
index
)
{
// the specification dictates that the checkbox should have the 'toggle' CSS class. Some implementations deviate from
// this, hence in lax mode we simply look for any checkboxes within the specified 'li'.
var
xpath
=
this
.
xPathForItemAtIndex
(
index
)
+
"
//input[@type='checkbox']
"
;
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
xpath
));
}
module
.
exports
=
function
PageLaxMode
(
browser
)
{
Page
.
apply
(
this
,
[
browser
]);
this
.
getEditInputForItemAtIndex
=
function
(
index
)
{
// the specification dictates that the input element that allows the user to edit a todo item should have a CSS
// class of 'edit'. In lax mode, we also look for an input of type 'text'.
this
.
tryGetToggleForItemAtIndex
=
function
(
index
)
{
// the specification dictates that the checkbox should have the 'toggle' CSS class. Some implementations deviate from
// this, hence in lax mode we simply look for any checkboxes within the specified 'li'.
var
xpath
=
this
.
xPathForItemAtIndex
(
index
)
+
'
//input[@type="checkbox"]
'
;
return
browser
.
findElements
(
webdriver
.
By
.
xpath
(
xpath
));
};
var
xpath
=
"
(
"
+
this
.
xPathForItemAtIndex
(
index
)
+
"
//input[@type='text']
"
+
"
|
"
+
this
.
xPathForItemAtIndex
(
index
)
+
"
//input[contains(@class,'edit')]
"
+
"
)
"
;
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
xpath
));
}
}
this
.
getEditInputForItemAtIndex
=
function
(
index
)
{
// the specification dictates that the input element that allows the user to edit a todo item should have a CSS
// class of 'edit'. In lax mode, we also look for an input of type 'text'.
module
.
exports
=
PageLaxMode
;
\ No newline at end of file
var
xpath
=
'
(
'
+
this
.
xPathForItemAtIndex
(
index
)
+
'
//input[@type="text"]
'
+
'
|
'
+
this
.
xPathForItemAtIndex
(
index
)
+
'
//input[contains(@class,"edit")]
'
+
'
)
'
;
return
browser
.
findElement
(
webdriver
.
By
.
xpath
(
xpath
));
};
};
This diff is collapsed.
Click to expand it.
browser-tests/test.js
View file @
4a4016ff
This diff is collapsed.
Click to expand it.
browser-tests/testOperations.js
View file @
4a4016ff
var
assert
=
require
(
"
assert
"
);
'
use strict
'
;
var
assert
=
require
(
'
assert
'
);
function
TestOperations
(
page
)
{
// unfortunately webdriver does not have a decent API for determining if an
// element exists. The standard approach is to obtain an array of elements
// and test that the length is zero. In this case the item is hidden if
// it is either not in the DOM, or is in the DOM but not visible.
function
testIsHidden
(
elements
)
{
if
(
elements
.
length
===
1
)
{
elements
[
0
].
isDisplayed
().
then
(
function
(
isDisplayed
)
{
assert
(
!
isDisplayed
);
})
}
}
function
testIsVisible
(
elements
)
{
assert
.
equal
(
1
,
elements
.
length
);
elements
[
0
].
isDisplayed
().
then
(
function
(
isDisplayed
)
{
assert
(
isDisplayed
);
});
}
this
.
assertClearCompleteButtonIsHidden
=
function
()
{
page
.
tryGetClearCompleteButton
().
then
(
function
(
element
)
{
testIsHidden
(
element
);
});
}
this
.
assertClearCompleteButtonIsVisible
=
function
()
{
page
.
tryGetClearCompleteButton
().
then
(
function
(
element
)
{
testIsVisible
(
element
);
});
}
this
.
assertItemCount
=
function
(
itemCount
)
{
page
.
getItemElements
().
then
(
function
(
toDoItems
){
assert
.
equal
(
itemCount
,
toDoItems
.
length
);
});
}
this
.
assertClearCompleteButtonText
=
function
(
buttonText
)
{
page
.
tryGetClearCompleteButton
().
then
(
function
(
elements
)
{
var
button
=
elements
[
0
];
button
.
getText
().
then
(
function
(
text
)
{
assert
.
equal
(
buttonText
,
text
);
});
});
}
this
.
assertMainSectionIsHidden
=
function
()
{
page
.
tryGetMainSectionElement
().
then
(
function
(
mainSection
)
{
testIsHidden
(
mainSection
);
});
}
this
.
assertFooterIsHidden
=
function
()
{
page
.
tryGetFooterElement
().
then
(
function
(
footer
)
{
testIsHidden
(
footer
);
});
}
this
.
assertMainSectionIsVisible
=
function
()
{
page
.
tryGetMainSectionElement
().
then
(
function
(
mainSection
)
{
testIsVisible
(
mainSection
);
});
}
this
.
assertItemToggleIsHidden
=
function
()
{
page
.
tryGetToggleForItemAtIndex
().
then
(
function
(
toggleItem
)
{
testIsHidden
(
toggleItem
);
});
}
this
.
assertItemLabelIsHidden
=
function
()
{
page
.
tryGetItemLabelAtIndex
().
then
(
function
(
toggleItem
)
{
testIsHidden
(
toggleItem
);
});
}
this
.
assertFooterIsVisible
=
function
()
{
page
.
tryGetFooterElement
().
then
(
function
(
footer
)
{
testIsVisible
(
footer
);
});
}
this
.
assertItemInputFieldText
=
function
(
text
)
{
page
.
getItemInputField
().
getText
().
then
(
function
(
inputFieldText
)
{
assert
.
equal
(
text
,
inputFieldText
);
});
}
this
.
assertItemText
=
function
(
itemIndex
,
textToAssert
)
{
page
.
getItemLabelAtIndex
(
itemIndex
).
getText
().
then
(
function
(
text
)
{
assert
.
equal
(
textToAssert
,
text
.
trim
());
});
}
this
.
assertItemCountText
=
function
(
textToAssert
)
{
page
.
getItemsCountElement
().
getText
().
then
(
function
(
text
)
{
assert
.
equal
(
textToAssert
,
text
.
trim
());
});
}
// tests for the presence of the 'completed' CSS class for the item at the given index
this
.
assertItemAtIndexIsCompleted
=
function
(
index
)
{
page
.
getItemElements
().
then
(
function
(
toDoItems
)
{
toDoItems
[
index
].
getAttribute
(
"
class
"
).
then
(
function
(
cssClass
)
{
assert
(
cssClass
.
indexOf
(
"
completed
"
)
!==
-
1
);
});
});
}
this
.
assertItemAtIndexIsNotCompleted
=
function
(
index
)
{
page
.
getItemElements
().
then
(
function
(
toDoItems
)
{
toDoItems
[
index
].
getAttribute
(
"
class
"
).
then
(
function
(
cssClass
)
{
// the maria implementation uses an 'incompleted' CSS class which is redundant
// TODO: this should really be moved into the pageLaxMode
assert
(
cssClass
.
indexOf
(
"
completed
"
)
===
-
1
||
cssClass
.
indexOf
(
"
incompleted
"
)
!==
-
1
);
});
});
}
function
isSelected
(
cssClass
)
{
return
cssClass
.
indexOf
(
"
selected
"
)
!==
-
1
;
}
this
.
assertFilterAtIndexIsSelected
=
function
(
index
)
{
page
.
getFilterElements
().
then
(
function
(
filterElements
)
{
filterElements
[
0
].
getAttribute
(
"
class
"
).
then
(
function
(
cssClass
)
{
assert
(
index
==
0
?
isSelected
(
cssClass
)
:
!
isSelected
(
cssClass
));
});
filterElements
[
1
].
getAttribute
(
"
class
"
).
then
(
function
(
cssClass
)
{
assert
(
index
==
1
?
isSelected
(
cssClass
)
:
!
isSelected
(
cssClass
));
});
filterElements
[
2
].
getAttribute
(
"
class
"
).
then
(
function
(
cssClass
)
{
assert
(
index
==
2
?
isSelected
(
cssClass
)
:
!
isSelected
(
cssClass
));
});
});
}
this
.
assertCompleteAllIsClear
=
function
()
{
page
.
getMarkAllCompletedCheckBox
().
then
(
function
(
markAllCompleted
)
{
markAllCompleted
.
isSelected
().
then
(
function
(
isSelected
){
assert
(
!
isSelected
);
})
});
}
this
.
assertCompleteAllIsChecked
=
function
()
{
page
.
getMarkAllCompletedCheckBox
().
then
(
function
(
markAllCompleted
)
{
markAllCompleted
.
isSelected
().
then
(
function
(
isSelected
){
assert
(
isSelected
);
})
});
}
// unfortunately webdriver does not have a decent API for determining if an
// element exists. The standard approach is to obtain an array of elements
// and test that the length is zero. In this case the item is hidden if
// it is either not in the DOM, or is in the DOM but not visible.
function
testIsHidden
(
elements
)
{
if
(
elements
.
length
===
1
)
{
elements
[
0
].
isDisplayed
().
then
(
function
(
isDisplayed
)
{
assert
(
!
isDisplayed
);
});
}
}
function
testIsVisible
(
elements
)
{
assert
.
equal
(
1
,
elements
.
length
);
elements
[
0
].
isDisplayed
().
then
(
function
(
isDisplayed
)
{
assert
(
isDisplayed
);
});
}
this
.
assertClearCompleteButtonIsHidden
=
function
()
{
page
.
tryGetClearCompleteButton
().
then
(
function
(
element
)
{
testIsHidden
(
element
);
});
};
this
.
assertClearCompleteButtonIsVisible
=
function
()
{
page
.
tryGetClearCompleteButton
().
then
(
function
(
element
)
{
testIsVisible
(
element
);
});
};
this
.
assertItemCount
=
function
(
itemCount
)
{
page
.
getItemElements
().
then
(
function
(
toDoItems
)
{
assert
.
equal
(
itemCount
,
toDoItems
.
length
);
});
};
this
.
assertClearCompleteButtonText
=
function
(
buttonText
)
{
page
.
tryGetClearCompleteButton
().
then
(
function
(
elements
)
{
var
button
=
elements
[
0
];
button
.
getText
().
then
(
function
(
text
)
{
assert
.
equal
(
buttonText
,
text
);
});
});
};
this
.
assertMainSectionIsHidden
=
function
()
{
page
.
tryGetMainSectionElement
().
then
(
function
(
mainSection
)
{
testIsHidden
(
mainSection
);
});
};
this
.
assertFooterIsHidden
=
function
()
{
page
.
tryGetFooterElement
().
then
(
function
(
footer
)
{
testIsHidden
(
footer
);
});
};
this
.
assertMainSectionIsVisible
=
function
()
{
page
.
tryGetMainSectionElement
().
then
(
function
(
mainSection
)
{
testIsVisible
(
mainSection
);
});
};
this
.
assertItemToggleIsHidden
=
function
()
{
page
.
tryGetToggleForItemAtIndex
().
then
(
function
(
toggleItem
)
{
testIsHidden
(
toggleItem
);
});
};
this
.
assertItemLabelIsHidden
=
function
()
{
page
.
tryGetItemLabelAtIndex
().
then
(
function
(
toggleItem
)
{
testIsHidden
(
toggleItem
);
});
};
this
.
assertFooterIsVisible
=
function
()
{
page
.
tryGetFooterElement
().
then
(
function
(
footer
)
{
testIsVisible
(
footer
);
});
};
this
.
assertItemInputFieldText
=
function
(
text
)
{
page
.
getItemInputField
().
getText
().
then
(
function
(
inputFieldText
)
{
assert
.
equal
(
text
,
inputFieldText
);
});
};
this
.
assertItemText
=
function
(
itemIndex
,
textToAssert
)
{
page
.
getItemLabelAtIndex
(
itemIndex
).
getText
().
then
(
function
(
text
)
{
assert
.
equal
(
textToAssert
,
text
.
trim
());
});
};
this
.
assertItemCountText
=
function
(
textToAssert
)
{
page
.
getItemsCountElement
().
getText
().
then
(
function
(
text
)
{
assert
.
equal
(
textToAssert
,
text
.
trim
());
});
};
// tests for the presence of the 'completed' CSS class for the item at the given index
this
.
assertItemAtIndexIsCompleted
=
function
(
index
)
{
page
.
getItemElements
().
then
(
function
(
toDoItems
)
{
toDoItems
[
index
].
getAttribute
(
'
class
'
).
then
(
function
(
cssClass
)
{
assert
(
cssClass
.
indexOf
(
'
completed
'
)
!==
-
1
);
});
});
};
this
.
assertItemAtIndexIsNotCompleted
=
function
(
index
)
{
page
.
getItemElements
().
then
(
function
(
toDoItems
)
{
toDoItems
[
index
].
getAttribute
(
'
class
'
).
then
(
function
(
cssClass
)
{
// the maria implementation uses an 'incompleted' CSS class which is redundant
// TODO: this should really be moved into the pageLaxMode
assert
(
cssClass
.
indexOf
(
'
completed
'
)
===
-
1
||
cssClass
.
indexOf
(
'
incompleted
'
)
!==
-
1
);
});
});
};
function
isSelected
(
cssClass
)
{
return
cssClass
.
indexOf
(
'
selected
'
)
!==
-
1
;
}
this
.
assertFilterAtIndexIsSelected
=
function
(
index
)
{
page
.
getFilterElements
().
then
(
function
(
filterElements
)
{
filterElements
[
0
].
getAttribute
(
'
class
'
).
then
(
function
(
cssClass
)
{
assert
(
index
===
0
?
isSelected
(
cssClass
)
:
!
isSelected
(
cssClass
));
});
filterElements
[
1
].
getAttribute
(
'
class
'
).
then
(
function
(
cssClass
)
{
assert
(
index
===
1
?
isSelected
(
cssClass
)
:
!
isSelected
(
cssClass
));
});
filterElements
[
2
].
getAttribute
(
'
class
'
).
then
(
function
(
cssClass
)
{
assert
(
index
===
2
?
isSelected
(
cssClass
)
:
!
isSelected
(
cssClass
));
});
});
};
this
.
assertCompleteAllIsClear
=
function
()
{
page
.
getMarkAllCompletedCheckBox
().
then
(
function
(
markAllCompleted
)
{
markAllCompleted
.
isSelected
().
then
(
function
(
isSelected
)
{
assert
(
!
isSelected
);
});
});
};
this
.
assertCompleteAllIsChecked
=
function
()
{
page
.
getMarkAllCompletedCheckBox
().
then
(
function
(
markAllCompleted
)
{
markAllCompleted
.
isSelected
().
then
(
function
(
isSelected
)
{
assert
(
isSelected
);
});
});
};
}
module
.
exports
=
TestOperations
;
\ No newline at end of file
module
.
exports
=
TestOperations
;
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment