SJRK-268: generalized custom theme tests to work for any custom theme #39
Changes from 9 commits
ef00953
53fc4fb
886574c
750481d
c19ab4b
7c70738
8ec0d88
bfe9e21
c27b52e
bf1ae0d
8509372
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,28 +109,16 @@ sjrk.storyTelling.loadBrowse = function (clientConfig, options) { | |
}; | ||
|
||
/* Gets the current theme from the server and loads associated files if and | ||
* only if the current theme is not set to the base theme. Once complete, the | ||
* provided callback function is called and the theme name is passed into it. | ||
* - "callback": a function to call once everything has completed. Will be called | ||
* regardless of whether theme information was specified or retrieved | ||
* only if the current theme is not set to the base theme. Returns a promise. | ||
* If the promise resolves, it will contain the clientConfig information. | ||
*/ | ||
sjrk.storyTelling.loadThemedPage = function (callback) { | ||
sjrk.storyTelling.loadTheme = function () { | ||
var loadPromise = fluid.promise(); | ||
|
||
var callbackFunction = typeof callback === "function" ? callback : fluid.getGlobalValue(callback); | ||
|
||
$.get("/clientConfig").then(function (data) { | ||
if (data.theme !== data.baseTheme) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if this condition is needed, it seems that you do the same thing in |
||
sjrk.storyTelling.loadCustomThemeFiles(callbackFunction, data).then(function () { | ||
loadPromise.resolve(data); | ||
}, function (jqXHR, textStatus, errorThrown) { | ||
loadPromise.reject({ | ||
isError: true, | ||
message: errorThrown | ||
}); | ||
}); | ||
fluid.promise.follow(sjrk.storyTelling.loadCustomThemeFiles(data), loadPromise); | ||
} else { | ||
callbackFunction(data); | ||
loadPromise.resolve(data); | ||
} | ||
}, function (jqXHR, textStatus, errorThrown) { | ||
|
@@ -144,36 +132,39 @@ sjrk.storyTelling.loadThemedPage = function (callback) { | |
}; | ||
|
||
/* Loads CSS and JavaScript files for the provided theme into the page markup. | ||
* If JavaScript file loading is successful, the callback function is called. | ||
* - "callback": a function to call once everything has completed | ||
* Returns a promise. If the promise resolves, it will contain the clientConfig. | ||
* - "clientConfig": a collection of client config values consisting of | ||
* - "theme": the current theme of the site | ||
* - "baseTheme": the base theme of the site | ||
* - "authoringEnabled": indicates whether story saving and editing are enabled | ||
*/ | ||
sjrk.storyTelling.loadCustomThemeFiles = function (callback, clientConfig) { | ||
sjrk.storyTelling.loadCustomThemeFiles = function (clientConfig) { | ||
var loadPromise = fluid.promise(); | ||
|
||
var cssUrl = fluid.stringTemplate("/css/%theme.css", {theme: clientConfig.theme}); | ||
var scriptUrl = fluid.stringTemplate("/js/%theme.js", {theme: clientConfig.theme}); | ||
if (clientConfig.theme !== clientConfig.baseTheme) { | ||
var cssUrl = fluid.stringTemplate("/css/%theme.css", {theme: clientConfig.theme}); | ||
var scriptUrl = fluid.stringTemplate("/js/%theme.js", {theme: clientConfig.theme}); | ||
|
||
$("<link/>", { | ||
rel: "stylesheet", | ||
type: "text/css", | ||
href: cssUrl | ||
}).appendTo("head"); | ||
$("<link/>", { | ||
rel: "stylesheet", | ||
type: "text/css", | ||
href: cssUrl | ||
}).appendTo("head"); | ||
|
||
$.getScript(scriptUrl, function () { | ||
if (typeof callback === "function") { | ||
var callbackResult = callback(clientConfig); | ||
loadPromise.resolve(callbackResult); | ||
} | ||
}).fail(function (jqXHR, textStatus, errorThrown) { | ||
loadPromise.reject({ | ||
isError: true, | ||
message: errorThrown | ||
// TODO: This method of loading produces a potential race condition | ||
// See SJRK-272: https://issues.fluidproject.org/browse/SJRK-272 | ||
$.getScript(scriptUrl, function () { | ||
loadPromise.resolve(clientConfig); | ||
}).fail(function (jqXHR, textStatus, errorThrown) { | ||
loadPromise.reject({ | ||
isError: true, | ||
message: errorThrown | ||
}); | ||
}); | ||
}); | ||
} else { | ||
// The theme is the base theme, no custom files need to be loaded | ||
loadPromise.resolve(clientConfig); | ||
} | ||
|
||
return loadPromise; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,98 +69,94 @@ https://raw.githubusercontent.com/fluid-project/sjrk-story-telling/master/LICENS | |
}); | ||
}); | ||
|
||
var loadThemedPageTestCases = { | ||
base: { | ||
theme: "base", | ||
baseTheme: "base", | ||
authoringEnabled: true | ||
}, | ||
learningReflections: { | ||
theme: "learningReflections", | ||
baseTheme: "base", | ||
authoringEnabled: true | ||
} | ||
}; | ||
|
||
fluid.defaults("sjrk.storyTelling.storyTellingServerUiTester", { | ||
gradeNames: ["fluid.test.testCaseHolder"], | ||
gradeNames: ["fluid.modelComponent", "fluid.test.testCaseHolder"], | ||
baseTestCase: { | ||
clientConfig: { | ||
theme: "base", | ||
baseTheme: "base", | ||
authoringEnabled: true | ||
} | ||
}, | ||
members: { | ||
clientConfig: { | ||
theme: "customTheme", | ||
baseTheme: "base", | ||
authoringEnabled: true | ||
} | ||
}, | ||
modules: [{ | ||
name: "Test Storytelling Server UI code", | ||
tests: [{ | ||
name: "Test themed page loading functions", | ||
expect: 6, | ||
name: "Test themed page loading functions with mock values", | ||
expect: 1, | ||
sequence: [{ | ||
// call the load themed page function, forcing the base theme response | ||
task: "sjrk.storyTelling.storyTellingServerUiTester.loadThemedPageSingleTest", | ||
args: ["sjrk.storyTelling.testUtils.callbackVerificationFunction", loadThemedPageTestCases.base.theme], | ||
resolve: "jqUnit.assertDeepEq", | ||
resolveArgs: ["The themed page load resolved as expected", loadThemedPageTestCases.base, "{arguments}.0"] | ||
funcName: "sjrk.storyTelling.storyTellingServerUiTester.setupMockServer", | ||
args: ["/clientConfig", "{that}.options.baseTestCase.clientConfig", "application/json"] | ||
},{ | ||
// call the load themed page function, forcing the Learning Reflections theme response | ||
task: "sjrk.storyTelling.storyTellingServerUiTester.loadThemedPageSingleTest", | ||
args: ["sjrk.storyTelling.testUtils.callbackVerificationFunction", loadThemedPageTestCases.learningReflections.theme], | ||
task: "sjrk.storyTelling.loadTheme", | ||
resolve: "jqUnit.assertDeepEq", | ||
resolveArgs: ["The themed page load resolved as expected", loadThemedPageTestCases.learningReflections, "{arguments}.0"] | ||
resolveArgs: ["The themed page load resolved as expected", "{that}.options.baseTestCase.clientConfig", "{arguments}.0"] | ||
},{ | ||
funcName: "sjrk.storyTelling.storyTellingServerUiTester.assertCustomCssLoaded", | ||
args: ["learningReflections.css", 1] | ||
funcName: "sjrk.storyTelling.storyTellingServerUiTester.teardownMockServer" | ||
}] | ||
},{ | ||
name: "Test themed page loading functions with server config values", | ||
expect: 3, | ||
sequence: [{ | ||
task: "$.get", | ||
args: ["/clientConfig"], | ||
resolve: "fluid.set", | ||
resolveArgs: ["{that}", "clientConfig", "{arguments}.0"] | ||
},{ | ||
// test the CSS/JS injection function directly | ||
funcName: "sjrk.storyTelling.loadCustomThemeFiles", | ||
args: ["sjrk.storyTelling.testUtils.callbackVerificationFunction", {"theme": "learningReflections"}] | ||
task: "sjrk.storyTelling.loadTheme", | ||
resolve: "jqUnit.assertEquals", | ||
resolveArgs: ["The themed page load resolved as expected", "{that}.clientConfig.theme", "{arguments}.0.theme"] | ||
},{ | ||
funcName: "sjrk.storyTelling.storyTellingServerUiTester.assertCustomCssLoaded", | ||
args: ["learningReflections.css", 2] | ||
funcName: "sjrk.storyTelling.storyTellingServerUiTester.verifyCustomCssLoaded", | ||
args: ["{that}.clientConfig", 1] | ||
},{ | ||
task: "sjrk.storyTelling.loadCustomThemeFiles", | ||
args: ["{that}.clientConfig"], | ||
resolve: "sjrk.storyTelling.storyTellingServerUiTester.verifyCustomCssLoaded", | ||
resolveArgs: ["{that}.clientConfig", 2] | ||
}] | ||
}] | ||
}] | ||
}); | ||
|
||
sjrk.storyTelling.storyTellingServerUiTester.loadThemedPageSingleTest = function (callback, expectedTheme) { | ||
var loadPromise = fluid.promise(); | ||
|
||
sjrk.storyTelling.storyTellingServerUiTester.setupMockServer("/clientConfig", JSON.stringify({ | ||
theme: expectedTheme, | ||
baseTheme: "base", | ||
authoringEnabled: true | ||
})); | ||
sjrk.storyTelling.storyTellingServerUiTester.loadClientConfigFromServer = function (url) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see this function being used anywhere. I think it's usage was removed in some of the refactoring and this can probably be dropped. |
||
var configPromise = fluid.promise(); | ||
|
||
sjrk.storyTelling.loadThemedPage(callback).then(function (clientConfig) { | ||
loadPromise.resolve(clientConfig); | ||
}, function () { | ||
loadPromise.reject(); | ||
$.get(url).then(function (data) { | ||
configPromise.resolve(data); | ||
}, function (jqXHR, textStatus, errorThrown) { | ||
configPromise.reject({ | ||
isError: true, | ||
message: errorThrown | ||
}); | ||
}); | ||
|
||
sjrk.storyTelling.storyTellingServerUiTester.teardownMockServer(); | ||
|
||
return loadPromise; | ||
return configPromise; | ||
}; | ||
|
||
sjrk.storyTelling.storyTellingServerUiTester.setupMockServer = function (url, responseData) { | ||
sjrk.storyTelling.storyTellingServerUiTester.setupMockServer = function (url, clientConfig) { | ||
mockServer = sinon.createFakeServer(); | ||
mockServer.respondImmediately = true; | ||
|
||
mockServer.respondWith(url, [200, { "Content-Type": "application/json" }, responseData]); | ||
mockServer.respondWith(url, [200, { "Content-Type": "application/json"}, JSON.stringify(clientConfig)]); | ||
}; | ||
|
||
sjrk.storyTelling.storyTellingServerUiTester.teardownMockServer = function () { | ||
mockServer.restore(); | ||
}; | ||
|
||
sjrk.storyTelling.storyTellingServerUiTester.assertCustomCssLoaded = function (expectedFileName, expectedInstanceCount) { | ||
var cssFilesLinked = fluid.transform(fluid.getMembers($("link"), "href"), function (fileUrl) { | ||
return fileUrl.split("/css/")[1]; | ||
}); | ||
|
||
var actualInstanceCount = 0; | ||
|
||
fluid.each(cssFilesLinked, function (fileName) { | ||
if (fileName === expectedFileName) { | ||
actualInstanceCount++; | ||
} | ||
}); | ||
sjrk.storyTelling.storyTellingServerUiTester.verifyCustomCssLoaded = function (clientConfig, expectedCssInstanceCount) { | ||
if (clientConfig.theme === clientConfig.baseTheme) { | ||
expectedCssInstanceCount = 0; // if no custom theme is set, we actually expect zero custom files | ||
} | ||
|
||
jqUnit.assertEquals("Linked CSS files include the expected custom theme file the expected number of instances", expectedInstanceCount, actualInstanceCount); | ||
var actualInstanceCount = $("link[href$=\"" + clientConfig.theme + ".css\"]").length; | ||
jqUnit.assertEquals("Custom theme CSS file is linked the expected number of instances", expectedCssInstanceCount, actualInstanceCount); | ||
}; | ||
|
||
fluid.defaults("sjrk.storyTelling.storyTellingServerUiTest", { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,7 +95,7 @@ h3:empty { | |
align-items: center; | ||
position: relative; | ||
flex-wrap: wrap; | ||
top: 1.75rem; | ||
/* top: 1.75rem; */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this be removed? |
||
justify-content: flex-end; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,5 +7,5 @@ | |
<li><a href="storyBrowse.html">{{localizedMessages.link_browse_text}}</a></li> | ||
</ul> | ||
</nav> | ||
<a class="sjrk-st-edit-link" href="{{localizedMessages.editor_url}}">{{localizedMessages.link_edit_text}}</a> | ||
{{!--<a class="sjrk-st-edit-link" href="{{localizedMessages.editor_url}}">{{localizedMessages.link_edit_text}}</a>--}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should remove the commented out code, or provide a comment for why it is needed. |
||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably be a bit more readable/descriptive if the argument is called
clientConfig
instead ofdata
.