Skip to content

Commit

Permalink
FLUID-5633: Fix and test case for failure to deregister IoC Testing f…
Browse files Browse the repository at this point in the history
…ramework listener that was registered via IoCSS
  • Loading branch information
amb26 committed Feb 20, 2018
1 parent eb2448d commit 7a9ffdd
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 23 deletions.
38 changes: 27 additions & 11 deletions tests/test-core/testTests/js/IoCTestingTests.js
Expand Up @@ -290,6 +290,16 @@ fluid.defaults("fluid.tests.onTestCaseStart.tree", {
components: {
targetTree: {
type: "fluid.component",
options: {
events: {
"hearIt": null
},
listeners: {
"onCreate.hearIt": {
listener: "{that}.events.hearIt.fire"
}
}
},
createOnEvent: "{testCases}.events.onTestCaseStart"
},
testCases: {
Expand All @@ -307,14 +317,20 @@ fluid.defaults("fluid.tests.fluid5559Tree", {
name: "FLUID-5559 Double firing of onTestCaseStart",
tests: [{
name: "FLUID-5559 sequence",
expect: 2,
sequence: [ {
expect: 3,
sequence: [{
// Must use IoCSS here - see discussion on FLUID-4929 - must avoid triggering construction
event: "{fluid5559Tree targetTree}.events.onCreate",
listener: "fluid.tests.onTestCaseStart.assertOnce"
event: "{fluid5559Tree targetTree}.events.hearIt",
listener: "fluid.tests.onTestCaseStart.assertValue"
}, {
func: "fluid.tests.onTestCaseStart.assertOnce",
func: "fluid.tests.onTestCaseStart.assertValue",
args: "{targetTree}"
}, { // Try firing the event again in order to test FLUID-5633
func: "{fluid5559Tree}.targetTree.events.hearIt.fire",
args: 5
}, {
event: "{fluid5559Tree targetTree}.events.hearIt",
listener: "fluid.tests.onTestCaseStart.assertValue"
}]
}]
}]
Expand All @@ -323,7 +339,7 @@ fluid.defaults("fluid.tests.fluid5559Tree", {
}
});

fluid.tests.onTestCaseStart.assertOnce = function (arg) {
fluid.tests.onTestCaseStart.assertValue = function (arg) {
jqUnit.assertValue("Received value", arg);
};

Expand Down Expand Up @@ -353,7 +369,7 @@ fluid.defaults("fluid.tests.fluid5575Tree", {
triggerable: null // used in "activePassive" case
},
listeners: {
onCreate: "fluid.tests.onTestCaseStart.assertOnce"
onCreate: "fluid.tests.onTestCaseStart.assertValue"
}
}
},
Expand All @@ -371,7 +387,7 @@ fluid.defaults("fluid.tests.fluid5575Tree", {
fluid.tests.onTestCaseStart.singleActive = {
expect: 2,
sequence: [{
func: "fluid.tests.onTestCaseStart.assertOnce",
func: "fluid.tests.onTestCaseStart.assertValue",
args: "{targetTree}"
}]
};
Expand All @@ -384,10 +400,10 @@ fluid.defaults("fluid.tests.fluid5575Tree.singleActive", {
fluid.tests.onTestCaseStart.doubleActive = {
expect: 3,
sequence: [{
func: "fluid.tests.onTestCaseStart.assertOnce",
func: "fluid.tests.onTestCaseStart.assertValue",
args: "{targetTree}"
}, {
func: "fluid.tests.onTestCaseStart.assertOnce",
func: "fluid.tests.onTestCaseStart.assertValue",
args: "{targetTree}"
}]
};
Expand All @@ -406,7 +422,7 @@ fluid.tests.onTestCaseStart.activePassive = {
args: "{targetTree}"
}, {
event: "{targetTree}.events.triggerable",
listener: "fluid.tests.onTestCaseStart.assertOnce"
listener: "fluid.tests.onTestCaseStart.assertValue"
}]
};

Expand Down
72 changes: 60 additions & 12 deletions tests/test-core/utils/js/IoCTestUtils.js
Expand Up @@ -325,6 +325,21 @@ var fluid_3_0_0 = fluid_3_0_0 || {};
return that;
};

// Queries for the tail section of an IoCSS selector which has previously been sent to fluid.extractSelectorHead.
// Note that for this purpose, the selector head needs to be *completely* removed since the head matching has now been
// achieved. TODO: We need to integrate this utility with fluid.queryIoCSelector once FLUID-5556 is resolved
fluid.test.queryPartialSelector = function (root, selector) {
var togo = [];
var parsed = fluid.copy(selector);
parsed.shift();
fluid.visitComponentsForMatching(root, {}, function (that, thatStack, contextHashes, memberNames, i) {
if (fluid.matchIoCSelector(parsed, thatStack, contextHashes, memberNames, i)) {
togo.push(that);
}
});
return togo;
};

// TODO: This will eventually go into the core framework for "Luke Skywalker Event Binding"
fluid.analyseTarget = function (testCaseState, material, expectedPrefix) {
if (fluid.isIoCReference(material)) {
Expand All @@ -341,12 +356,26 @@ var fluid_3_0_0 = fluid_3_0_0 || {};
if (segs.length < 2 || segs[0] !== expectedPrefix) {
fluid.fail("Error in test case selector ", material, " must start with path " + expectedPrefix);
}
return {selector: selector, head: head, path: segs.slice(1)};
var query = function () {
return fluid.test.queryPartialSelector(head, selector);
};
return {selector: selector, head: head, query: query, path: segs.slice(1)};
}
}
return {resolved: testCaseState.expand(material)};
};

// Because of listener instance removal code driven by fluid.event.resolveListenerRecord, the id assigned
// on registration of a listener via IoC may not agree with its raw id - this is so that the same listener
// handle can be distributed to the same function via multiple declarative blocks. Therefore here we need to
// search for the assigned id since we mean to do something untypical - programmatically remove a listener
// which was registered declaratively.
fluid.test.findListenerId = function (event, listener) {
return fluid.find(event.byId, function (lisRec, key) {
return lisRec.listener === listener ? key : undefined;
}, fluid.event.identifyListener(listener));
};

fluid.test.decoders.event = function (testCaseState, fixture) {
var analysed = fluid.analyseTarget(testCaseState, fixture.event, "events");
var listener = fluid.test.decodeListener(testCaseState, fixture);
Expand All @@ -365,19 +394,38 @@ var fluid_3_0_0 = fluid_3_0_0 || {};
var id;

bind = function (wrapped) {
var options = {};
fluid.set(options, ["listeners"].concat(analysed.path), {
listener: wrapped,
args: fixture.args,
namespace: fixture.namespace,
priority: fixture.priority
});
id = fluid.pushDistributions(analysed.head, analysed.selector, fixture.event,
[{options: options, recordType: "distribution", priority: fluid.mergeRecordTypes.distribution}]
);
var existent = analysed.query();
if (existent.length === 0) {
// If it be not now, yet it will come
var options = {};
fluid.event.identifyListener(wrapped);
fluid.set(options, ["listeners"].concat(analysed.path), {
listener: wrapped,
args: fixture.args,
namespace: fixture.namespace,
priority: fixture.priority
});
id = fluid.pushDistributions(analysed.head, analysed.selector, fixture.event,
[{options: options, recordType: "distribution", priority: fluid.mergeRecordTypes.distribution}]
);
} else if (existent.length === 1) {
// If it be now, 'tis not to come
var event = fluid.getForComponent(existent[0], ["events"].concat(analysed.path));
event.addListener(wrapped, fixture.namespace, priority);
} else {
fluid.fail("Error in listening fixture ", fixture, " selector " + fixture.event + " matched more than one component during bind: ", existent);
}
};
unbind = function () {
unbind = function (wrapped) {
fluid.clearDistribution(analysed.head, id);
var existent = analysed.query();
if (existent.length === 1) {
var event = fluid.getForComponent(existent[0], ["events"].concat(analysed.path));
var identified = fluid.test.findListenerId(event, wrapped);
event.removeListener(identified);
} else if (existent.length > 1) {
fluid.fail("Error in listening fixture ", fixture, " selector " + fixture.event + " matched more than one component during unbind: ", existent);
}
};
} else {
fluid.fail("Error decoding event fixture ", fixture, ": must be able to look up member \"event\" to one or more events");
Expand Down

0 comments on commit 7a9ffdd

Please sign in to comment.