Skip to content

Commit 4682151

Browse files
fix autogenerated paths to be relative to #ember-testing div, filter out non user given id mutations
1 parent d0a102c commit 4682151

File tree

4 files changed

+44
-43
lines changed

4 files changed

+44
-43
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ If you don't want an element to be recorded, and any of its children add this cl
3434

3535
Avoid making multiple button clicks (or other interactions that cause asynchronous) updates until DOM has
3636
finished updating. This will allow code generated by the mutations observer to be placed in the in the
37-
generated code. This happens outside of the ember run loop.ImpIm
37+
generated code. This happens outside of the ember run loop.
3838

3939

4040
## Roadmap

app/components/test-recorder.js

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Ember from 'ember';
22

33
export default Ember.Component.extend({
4-
classNames: ['dont'],
4+
classNames: ['dont'], //this is the output code, we don't want to generate any code form changes in this
55

66
MUTATIONS_PLACEHOLDER: "[MUTATIONS_PLACEHOLDER]", //holds text to be added from mutations
77

@@ -23,8 +23,7 @@ export default Ember.Component.extend({
2323
console.log("destroying");
2424
this.get("mutationObserversArr").forEach(function (observer) {
2525
observer.disconnect();
26-
})
27-
//var rect = obj.getBoundingClientRect();
26+
});
2827
},
2928

3029
/**
@@ -53,15 +52,6 @@ export default Ember.Component.extend({
5352
},
5453

5554
onCurrentRouteNameChange: Ember.observer('currentRouteName', function () {
56-
//console.log(this.get("currentRouteName"));
57-
58-
/* //todo alternative?
59-
window.onhashchange = function locationHashChanged() {
60-
};
61-
window.addEventListener('popstate', function locationHashChanged(e) {
62-
});
63-
* */
64-
//todo have a timing mechanism or wait for all promises are fulfilled
6555
this.set("routeHasChanged", true);
6656
}),
6757

@@ -80,10 +70,10 @@ export default Ember.Component.extend({
8070
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
8171

8272
//listen to clicks on ember items, apart from
83-
//the test recorder UI
73+
//the test recorder UI (the dont class)
8474
var emberSelector = '[id^=ember]:not(.dont),[data-ember-action]';
8575
var self = this;
86-
var indendation = ' ';//2 spaces
76+
var indentation = ' ';//2 spaces
8777
var currentNestedLevel = 0; //tracks the nesting level for mutations
8878

8979
Ember.$.fn.extend({
@@ -94,7 +84,9 @@ export default Ember.Component.extend({
9484
}
9585

9686
var path, node = this;
97-
while (node.length) {
87+
//this is just to get the path if the user interacts with a non user given id object
88+
//we stop at body as qunit tests find statement is relative to the #ember-testing div
89+
while (node.length && node[0].localName !== 'body') {
9890
var realNode = node[0], name = realNode.localName;
9991
if (!name) {
10092
break;
@@ -125,13 +117,21 @@ export default Ember.Component.extend({
125117
var $emberTarget = $target.is(emberSelector) ? $target : $target.parent(emberSelector);
126118

127119
if ($emberTarget.length) {
128-
var pathPrint = e.target.id ? "#" + e.target.id : $emberTarget.path();
120+
// we don't want to output a click (#ember123) as this is not reliable
121+
var hasEmberIdRegex = /ember[\d]+/;
122+
if (e.target.id && !hasEmberIdRegex.test(e.target.id)) {
123+
var pathPrint = "#" + e.target.id;
124+
} else {
125+
//print the nasty DOM path instead, to avoid give your element its own id
126+
var pathPrint = $emberTarget.path();
127+
}
128+
129+
129130
var newTestPrint = 'click("' + pathPrint + '");<br/>' + 'andThen(function () {' + '<br/>';
130131

131132
//TEST 1 - > Assert the route is what it a changed to
132-
// todo hook this to afterModel in the final route
133133
if (self.get("routeHasChanged")) {
134-
newTestPrint += indendation + 'assert.equal(currentRouteName(), "' +
134+
newTestPrint += indentation + 'assert.equal(currentRouteName(), "' +
135135
self.get("currentRouteName") +
136136
'", "The page navigates to ' + self.get("currentRouteName") +
137137
' on button click");<br/>'; //todo make reason more dynamic
@@ -141,15 +141,13 @@ export default Ember.Component.extend({
141141
//TEST 2 - > Place holder that will be replaced with dom visibility Assertions
142142
// the last one of these is replaced each time the mutation observes are run
143143
newTestPrint += self.get("MUTATIONS_PLACEHOLDER") + '<br/>' +
144-
145144
//Close the and then block
146145
'});<br/><br/>'
147146
// console.log(testLinePrint);
148147

149148
//add to exisiting tests
150149
self.set("generatedScript", self.get("generatedScript") + newTestPrint);
151150

152-
//todo hack to fill in mutations
153151
var withReplacement = self.get("generatedScript").replace(self.get("MUTATIONS_PLACEHOLDER"), self.get("pendingGeneratedDomChangedScript"));
154152
self.set("generatedScript", withReplacement);
155153
self.set("pendingGeneratedDomChangedScript", "") //clear
@@ -165,9 +163,9 @@ export default Ember.Component.extend({
165163
* @param target
166164
*/
167165
function addObserverForTarget(target) {
168-
//todo, fix this hack -> this will fire before the onClick of jquery so we cache the generated text here for now
169-
var observer = new MutationObserver(function (mutations) {
170166

167+
168+
var observer = new MutationObserver(function (mutations) {
171169
mutations.forEach(function (mutation) {
172170

173171
var addedNodesTestText = "";
@@ -195,21 +193,9 @@ export default Ember.Component.extend({
195193
})
196194

197195
//this array is used to generate the source code, we ignore anything with no ID
198-
addedNodesArray = addedNodesArray.filter(function (node) {
199-
var classListArray = node.classList && Array.prototype.slice.call(node.classList);
200-
//var isEmberView = classListArray ? (classListArray.indexOf("ember-view") === -1) : false;
201-
var hasDoNotRecordClass = classListArray ? (classListArray.indexOf("doNotRecord") !== -1) : false;
202-
203-
return node.nodeType !== 3 && node.id && !hasDoNotRecordClass;
204-
});
205-
206-
removedNodesArray = removedNodesArray.filter(function (node) {
207-
var classListArray = node.classList && Array.prototype.slice.call(node.classList);
208-
//var isEmberView = classListArray ? (classListArray.indexOf("ember-view") === -1) : false;
209-
var hasDoNotRecordClass = classListArray ? (classListArray.indexOf("doNotRecord") !== -1) : false;
210196

211-
return node.nodeType !== 3 && node.id && !hasDoNotRecordClass;
212-
});
197+
addedNodesArray = addedNodesArray.filter(unwantedNodesFilter);
198+
removedNodesArray = removedNodesArray.filter(unwantedNodesFilter);
213199

214200
if (!addedNodesArray.length && !removedNodesArray.length) {
215201
//no point continuing in this iteration if nothing of interest
@@ -223,11 +209,11 @@ export default Ember.Component.extend({
223209
}
224210

225211
addedNodesArray.forEach(function (node) {
226-
addedNodesTestText += indendation + 'assert.equal(find("#' + node.id + '").length, 1, "' + node.id + ' shown AFTER user [INSERT REASON]");' + '<br/>';
212+
addedNodesTestText += indentation + 'assert.equal(find("#' + node.id + '").length, 1, "' + node.id + ' shown AFTER user [INSERT REASON]");' + '<br/>';
227213
});
228214

229215
removedNodesArray.forEach(function (node) {
230-
removedNodesTestText += indendation + 'assert.equal(find("#' + node.id + '").length, 0, "' + node.id + ' removed AFTER user [INSERT REASON]");' + '<br/>';
216+
removedNodesTestText += indentation + 'assert.equal(find("#' + node.id + '").length, 0, "' + node.id + ' removed AFTER user [INSERT REASON]");' + '<br/>';
231217
});
232218

233219
self.set("pendingGeneratedDomChangedScript", self.get("pendingGeneratedDomChangedScript") + (addedNodesTestText || removedNodesTestText));
@@ -275,3 +261,17 @@ export default Ember.Component.extend({
275261
}
276262
});
277263

264+
function unwantedNodesFilter(node) {
265+
var classListArray = node.classList && Array.prototype.slice.call(node.classList);
266+
//var isEmberView = classListArray ? (classListArray.indexOf("ember-view") === -1) : false;
267+
var hasDoNotRecordClass = classListArray ? (classListArray.indexOf("doNotRecord") !== -1) : false;
268+
269+
//the check here is we don't want to record
270+
// 1 whitespace
271+
// 2 things with no id
272+
// 3 things that have a hasDoNotRecordClass
273+
// 4 things with an ember id, (where a user has not given one but ember needs to add an id)
274+
var hasEmberIdRegex = /ember[\d]+/;
275+
276+
return node.nodeType !== 3 && node.id && !hasDoNotRecordClass && !hasEmberIdRegex.test(node.id);
277+
}

tests/acceptance/test-playback-test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ module('Acceptance: TestPlayback', {
2424
*/
2525
test('Playback code', function (assert) {
2626
//assume that the user starts on index
27-
visit('inputs');
27+
visit('/');
28+
click("div:eq(0)>header>button:eq(0)");
2829
andThen(function () {
29-
30+
assert.equal(currentRouteName(), "login", "The page navigates to login on button click");
31+
assert.equal(find("#login-foo-component-with-nested-components").length, 1, "login-foo-component-with-nested-components shown AFTER user [INSERT REASON]");
3032

3133
});
3234

33-
stop();
3435
});

tests/dummy/app/templates/application.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<h1>Buttons</h1>
33
<button type="button" {{action 'goToLoginView'}}
44
class=""
5-
id="btnLogin">
5+
>
66
<span class=""></span>&nbsp;Log in
77
</button>
88
<!--this has no id to check if test recorder prints out html path for selector-->

0 commit comments

Comments
 (0)