define(function (require, exports, module) { "use strict"; var defineComponent = require("flight").component; var withAutomaticTeardownOnContentUpdate = require("app-modules/utils/mixins/ui/with-automatic-teardown-on-content-update"); var withAjax = require("app-modules/utils/mixins/data/with-ajax"); var varsRegistry = require("app-modules/core/vars-registry"); var appConfig = require("app/config"); var _ = require("lodash"); var $ = require("jquery"); var logger = require("logger"); var myDebug = !false; // Exports: component definition module.exports = defineComponent(ajaxPostWriting, withAutomaticTeardownOnContentUpdate, withAjax); myDebug && logger.debug(module.id, "Component on the bridge, captain!"); function ajaxPostWriting() { this.defaultAttrs({ closeBtSelector: ".frame-tools .bt-close", minimizeBtSelector: ".frame-tools .bt-minimize", cancelMinimizeBtSelector: ".frame-tools .bt-cancel-minimize", fullscreenBtSelector: ".frame-tools .bt-fullscreen", cancelFullscreenBtSelector: ".frame-tools .bt-cancel-fullscreen" }); this.statesClasses = "state-normal state-minimized state-fullscreen"; this.onAjaxTopicWritingRequest = function (ev, data) { var parentForumId = data.forumId; myDebug && logger.debug(module.id, "Ajax Topic writing requested for Forum n°", parentForumId); this.$node.empty().show(); this.loadNewTopicWidgetContent(parentForumId); }; this.onAjaxPostWritingRequest = function (ev, data) { var parentTopicId = data.topicId; myDebug && logger.debug(module.id, "Ajax Post writing requested for Topic n°", parentTopicId); this.$node.empty().show(); this.loadNewPostWidgetContent(parentTopicId); }; this.onCloseBtClick = function (ev, data) { this.close(); }; this.onMinimizeBtClick = function (ev, data) { this.$node.removeClass(this.statesClasses).addClass("state-minimized"); }; this.onCancelMinimizeBtClick = function (ev, data) { this.$node.removeClass(this.statesClasses).addClass("state-normal"); }; this.onFullscreenBtClick = function (ev, data) { this.$node.removeClass(this.statesClasses).addClass("state-fullscreen"); }; this.onCancelFullscreenBtClick = function (ev, data) { this.$node.removeClass(this.statesClasses).addClass("state-normal"); }; this.close = function () { this.$node.fadeOut("fast"); }; this.loadNewTopicWidgetContent = function (forumId) { this.$node.addClass("ajax-loading"); this.clearEventsBindings(); this.ajaxPromise({ url: appConfig["base_url"] + "/ajax-post-writing/forum/"+forumId+"/new-topic/widget" }) .then( _.bind(this.onWidgetContentRetrieved, this) ); }; this.loadNewPostWidgetContent = function (topicId) { this.$node.addClass("ajax-loading"); this.clearEventsBindings(); this.ajaxPromise({ url: appConfig["base_url"] + "/ajax-post-writing/topic/"+topicId+"/new-post/widget" }) .then( _.bind(this.onWidgetContentRetrieved, this) ); }; this.onWidgetContentRetrieved = function (data) { this.$node.removeClass("ajax-loading"); this.$node.html(data); var mySelector = "#" + this.$node.attr("id"); this.trigger(document, "widgetsSearchRequested", {selector: mySelector}); this.trigger(document, "uiContentUpdated", { target: mySelector }); _.defer( _.bind(function () { var $contentWritingForm = this.$node.find("form"); $contentWritingForm .on("submit.ajax-post-writing", _.bind(this.onFormSubmit, this)); }, this) ); this.initEventsBindings(); }; this.onFormSubmit = function (e) { // Let's wait for Ajax content loading result... this.on(document, "ajaxContentLoadingDone", this.onAjaxContentLoadingAfterFormSubmit); this.on(document, "ajaxContentLoadingError", this.onAjaxContentLoadingErrorAfterFormSubmit); }; this.onAjaxContentLoadingAfterFormSubmit = function (ev, data) { // All right, it seems that our form has been successfully sent. // Let's close this Topic/Post writing widget! this.close(); this.$node.find("form").off("submit.ajax-post-writing"); this.off(document, "ajaxContentLoadingDone", this.onAjaxContentLoadingAfterFormSubmit); this.off(document, "ajaxContentLoadingError", this.onAjaxContentLoadingAfterFormSubmit); }; this.onAjaxContentLoadingErrorAfterFormSubmit = function (ev, data) { // Too bad! logger.warn("Ajax Topic/Post writing form failed!"); this.$node.find("form").off("submit.ajax-post-writing"); this.off(document, "ajaxContentLoadingDone", this.onAjaxContentLoadingAfterFormSubmit); this.off(document, "ajaxContentLoadingError", this.onAjaxContentLoadingAfterFormSubmit); }; this.initEventsBindings = function () { this.on(this.select("minimizeBtSelector"), "click", this.onMinimizeBtClick); this.on(this.select("cancelMinimizeBtSelector"), "click", this.onCancelMinimizeBtClick); this.on(this.select("fullscreenBtSelector"), "click", this.onFullscreenBtClick); this.on(this.select("cancelFullscreenBtSelector"), "click", this.onCancelFullscreenBtClick); this.on(this.select("closeBtSelector"), "click", this.onCloseBtClick); }; this.clearEventsBindings = function () { this.off(this.select("minimizeBtSelector"), "click", this.onMinimizeBtClick); this.off(this.select("cancelMinimizeBtSelector"), "click", this.onCancelMinimizeBtClick); this.off(this.select("fullscreenBtSelector"), "click", this.onFullscreenBtClick); this.off(this.select("cancelFullscreenBtSelector"), "click", this.onCancelFullscreenBtClick); this.off(this.select("closeBtSelector"), "click", this.onCloseBtClick); }; // Component initialization this.after("initialize", function() { this.$node.addClass("state-normal flight-component flight-component-attached"); this.on(document, "uiNeedsAjaxTopicWriting", this.onAjaxTopicWritingRequest); this.on(document, "uiNeedsAjaxPostWriting", this.onAjaxPostWritingRequest); }); } });
module.exports = function (register) { var _ = require('underscore') , Backbone = require('backbone') , App = require('App') , Logger = require('logger') Logger.debug('Testing plugin'); init(); register( { id: 'xemware.nimblescript.plugin.testing', about: function () { return "Adds Test menu" }, version: function () { return "0.0.1" } } ); function init() { addToMenu(); } function addToMenu() { // return; var menuManager = App.request('menu:getmanager'); var helpMenu = menuManager.findMenu('help'); var helpPosition = menuManager.collection.models.indexOf(helpMenu); menuManager.collection.add([ { "id": "Test", "label": "Test", "href": "#", "subitems": new Backbone.Collection( [ { "id": "test.components", "label": "Components", "href": "#", "submenu": true, "subitems": new Backbone.Collection( [ { "id": "test.component.folderbrowser", "label": "Directory Browser", "href": "#", "command": "test:component:folderbrowser:create" }, { "id": "test.component.folderbrowsermodal", "label": "Folder Browser Modal", "href": "#", "command": "test:component:folderbrowsermodal:create" }, { "id": "test.component.datatable", "label": "DataTable", "href": "#", "command": "test:component:datatable:create" }, { "id": "test.component.fileexplorer", "label": "File Explorer", "href": "#", "command": "test:component:fileexplorer:create" }, { "id": "test.component.fileexplorermodal.openfile", "label": "File Explorer Modal - Open File", "href": "#", "command": "test:component:fileexplorermodal:openfile" }, { "id": "test.component.fileexplorermodal.savefile", "label": "File Explorer Modal - Save File", "href": "#", "command": "test:component:fileexplorermodal:savefile" }, { "id": "test.component.repositoryexplorermodal.openfile", "label": "Repository Explorer Modal - Open File", "href": "#", "command": "test:component:repositoryexplorermodal:open" }, { "id": "test.component.repositoryexplorermodal.savefile", "label": "Repository Explorer Modal - Save File", "href": "#", "command": "test:component:repositoryexplorermodal:save" }, { "id": "test.component.repositorybrowser", "label": "Script Browser", "href": "#", "command": "test:component:repositorybrowser:create" }, { "id": "test.component.repositorybrowsermodal", "label": "Script Browser Modal", "href": "#", "command": "test:component:repositorybrowser:modal" }, { "id": "test.component.filelist", "label": "File List", "href": "#", "command": "test:component:filelist:create" }, { "id": "test.component.filelisteditor", "label": "File List Editor", "href": "#", "command": "test:component:filelisteditor:create" }, { "id": "test.component.scriptrunner", "label": "Script Runner", "href": "#", "command": "test:component:scriptrunner:create" }, { "id": "test.component.scriptsummarybuilder", "label": "Script Summary Builder", "href": "#", "command": "test:component:scriptsummarybuilder:create" }, { "id": "test.component.scriptparametersbuilder", "label": "Script Parameters Builder", "href": "#", "command": "test:component:scriptparametersbuilder:create" }, { "id": "test.component.adddocument", "label": "Add Document", "href": "#", "command": "test:document:add" }, { "id": "test.modalhelper.prompt", "label": "Modal Prompt", "href": "#", "command": "test:modalhelper:prompt" }, { "id": "test.component.templatebrowsermodal", "label": "Template Browser Modal", "href": "#", "command": "test:component:templatebrowsermodal:create" }, { "id": "test.component.publishscript.modal", "label": "Publish Script Modal", "href": "#", "command": "test:component:publishscript:modal" }, { "id": "test.openscript.fail", "label": "Open Script Fail", "href": "#", "command": "test:component:openscriptdocument:fail" } ]) } ]) } ], { at: helpPosition + 1 }); } App.commands.setHandler('test:component:datatable:create', function () { App.execute('components:get', ['xemware.nimblescript.component.datatable'], function (err, Components) { var columns = [{ name: "id", // The key of the model attribute label: "ID", // The name to display in the header editable: false, // By default every cell in a column is editable, but *ID* shouldn't be // Defines a cell type, and ID is displayed as an integer without the ',' separating 1000s. cell: "string" }, { name: "name", label: "Name", // The cell type can be a reference of a Backgrid.Cell subclass, any Backgrid.Cell subclass instances like *id* above, or a string cell: "string" // This is converted to "StringCell" and a corresponding class in the Backgrid package namespace is looked up }]; var coll = new Backbone.Collection(); for (var i = 0; i < 100; i++) coll.add({ id: i, name: 'smee' }) var view = Components[0].createView({ columns: columns, collection: coll }); App.main.show(view); // view.updateColumnSizing(); }); }); App.commands.setHandler('test:component:folderbrowser:create', function () { App.execute('components:get', ['xemware.nimblescript.component.folderbrowser'], function (err, Components) { var view = Components[0].createView({ restricted: false }); App.main.show(view); view.listenTo(view, 'node', function () { }); }); }); App.commands.setHandler('test:component:fileexplorer:create', function () { App.execute('components:get', ['xemware.nimblescript.component.fileexplorer'], function (err, Components) { var view = Components[0].createView({ anchorToWindow: true, initialPath: 'C:/Development/Assemblies' }); App.main.show(view); }); }); App.commands.setHandler('test:component:repositorybrowser:create', function () { App.execute('components:get', ['xemware.nimblescript.component.repositorybrowser'], function (err, Components) { var view = Components[0].createView(); App.main.show(view); view.listenTo(view, 'all', function () { }) }); }); App.commands.setHandler('test:component:repositorybrowser:modal', function () { App.execute('components:get', ['xemware.nimblescript.component.repositorybrowser'], function (err, Components) { require(['modalhelper'], function (ModalHelper) { var view = Components[0].createView(); var modalHelper = new ModalHelper(); modalHelper.view({ view: view }); }); }); }); App.commands.setHandler('test:component:filelist:create', function () { App.execute('components:get', ['xemware.nimblescript.component.filelist'], function (err, Components) { var view = Components[0].createView(); App.main.show(view); view.listenTo(view, 'all', function () { }) }); }); App.commands.setHandler('test:modalhelper:prompt', function () { require(['modalhelper'], function (ModalHelper) { var modal; new ModalHelper().prompt({ title: 'Save as...', text: 'Please enter a valid filename:', onButton: function (text) { if (text == 'OK') { var name = modal.find('input.active').val(); var r = /[A-Za-z\-_\s0-9]+/; if (true) new ModalHelper().alert({ title: 'Error...', text: 'Only following characters are supported:<br/> A-Z, a-z, 0-9, _, -, and spaces' }); } return false; }, onCreate: function (m) { modal = m; } }); }); }); App.commands.setHandler('test:component:filelisteditor:create', function () { App.execute('components:get', ['xemware.nimblescript.component.filelisteditor'], function (err, Components) { var view = Components[0].createView(); App.main.show(view); }); }); App.commands.setHandler('test:component:fileexplorermodal:savefile', function () { App.execute('components:get', ['xemware.nimblescript.component.fileexplorer'], function (err, Components) { var modal = Components[0].showModal({ mode: 'saveFile', overwritePrompt: true, // initialFilename: 'smoo.js', initialPath: 'C:/Development/Assemblies', allowedItems: ['file'], onOK: function (selectedItems) { console.log(modal.getFilename()); console.log(modal.getDirectory()); console.log(selectedItems[0].key); return true; } }); }); }); App.commands.setHandler('test:component:fileexplorermodal:openfile', function () { App.execute('components:get', ['xemware.nimblescript.component.fileexplorer'], function (err, Components) { var modal = Components[0].showModal({ mode: 'openFile', deleteConfirm: true, // initialFilename: 'smoo.js', initialPath: 'U:/Archive/Development', allowedItems: ['file'], onOK: function (selectedItems) { console.log(modal.getFilename()); console.log(modal.getDirectory()); console.log(selectedItems[0].key); return true; } }); }); }); App.commands.setHandler('test:component:repositoryexplorermodal:save', function () { App.execute('components:get', ['xemware.nimblescript.component.repositoryexplorer'], function (err, Components) { var modal = Components[0].showModal({ mode: 'save', overwritePrompt: true, // initialFilename: 'smoo.js', onOK: function (selectedItems) { console.log(modal.getFilename()); console.log(modal.getDirectory()); console.log(selectedItems); return true; } }); }); }); App.commands.setHandler('test:component:repositoryexplorermodal:open', function () { App.execute('components:get', ['xemware.nimblescript.component.repositoryexplorer'], function (err, Components) { var modal = Components[0].showModal({ mode: 'open', deleteConfirm: true, onOK: function (selectedItems) { console.log(modal.getFilename()); console.log(modal.getDirectory()); console.log(selectedItems); return true; } }); }); }); App.commands.setHandler('test:component:templatebrowsermodal:create', function () { App.execute('components:get', ['xemware.nimblescript.component.templatebrowser'], function (err, Components) { Components[0].showModal({ title: 'New Script...', onOK: function (content) { return true; } }); }); }); App.commands.setHandler('test:component:folderbrowsermodal:create', function () { App.execute('components:get', ['xemware.nimblescript.component.folderbrowser'], function (err, Components) { Components[0].showModal({ selectionMode: 'multiple', onOK: function (selectedItems) { alert(selectedItems[0].key); return true; } }); }); }); App.commands.setHandler('test:component:scriptsummarybuilder:create', function () { App.execute('components:get', ['xemware.nimblescript.component.scriptsummarybuilder'], function (err, Components) { Components[0].showModal(); }); }); App.commands.setHandler('test:component:scriptparametersbuilder:create', function () { App.execute('components:get', ['xemware.nimblescript.component.scriptparametersbuilder'], function (err, Components) { Components[0].showModal(); }); }); App.commands.setHandler('test:component:scriptrunner:create', function () { App.execute('components:get', ['xemware.nimblescript.component.scriptrunner'], function (err, Components) { Components[0].showModal(); }); }); App.commands.setHandler('test:component:publishscript:modal', function () { App.execute('components:get', ['xemware.nimblescript.component.publishscript'], function (err, Components) { Components[0].showModal({ scriptPath: 'local*C:/Users/tshnaider/AppData/Roaming/xemware/nimbleScript/repository/Balsamiq thumbnail PDF exporter.ns' }); }); }); App.commands.setHandler('test:component:openscriptdocument:fail', function () { App.request('scripts:getmanager').openScript('local*C:/Users/tshnaider/AppData/Roaming/xemware/nimbleScript/repository/nS Test Script3.ns'); }); App.commands.setHandler('test:document:add', function () { require(['document'], function (Document) { var MyDoc = Document.extend({ title: 'My Document', renderContent: function (callback) { callback($('<div>Hello</div>')); } }); var myDoc = new MyDoc(); var documentManager = App.request('documents:getmanager'); documentManager.addDocument(myDoc); }); }) }
error: function(_data) { LOGGER.debug(__FILE__+"ACS.registerAndroid @error"); LOGGER.debug(__FILE__+JSON.stringify(_data)); }
return app.schedule(description, f).addErrback(function(e) { logger.error('Exception from "%s": %s', description, e); logger.debug('%s', e.stack); });
function(e) { logger.debug('Ignoring Exception from "%s": %s', description, e); //logger.debug('%s', e.stack); });
wdSandbox.promise.ControlFlow.EventType.IDLE, function() { logger.debug('The sandbox control flow has gone idle, history: %j', this.sandboxApp_.getHistory()); }.bind(this));
this.body = 'Unexpected error'; } if (process.env.NODE_ENV !== 'prod') { logger.error(err); } } this.response.type = 'application/vnd.api+json'; }); const cache = require('lru-cache')({ maxAge: 30000 // global max age }); app.use(require('koa-cash')({ get(key) { logger.debug('Getting the cache key: %s', key); return cache.get(key); }, set(key, value) { logger.debug('Setting in cache. key: %s, value: ', key, value); cache.set(key, value); }, hash(_this) { logger.debug('Hash by: ', _this.request.originalUrl); return _this.request.originalUrl; } })); // load custom validator app.use(validate());
function() { logger.debug('Stub Builder.build() called'); return fakeDriver; });
it('should work overall with Chrome - start, run, stop', function() { // This is a long test that does a full run. It goes like this: // * General stubs/fakes/spies. // * First view: // * Verify we clear the cache, run, then keep our WD. // * Repeat view: // * Verify we keep our cache, run, then quit/stop WD. // // We do this as a single test, because the WebDriverServer state after // the first view is crucial for the repeat view, and because some of the // stubs/spies remain the same from the first view into the repeat view. // * General stubs/fakes/spies. var chromedriver = '/gaga/chromedriver'; // Stub out spawning chromedriver, verify at the end. var isFirstRun = true; var launcherStubs = stubBrowserLauncher(function() { should.ok(isFirstRun); // Only spawn WD on first run. }); var startChromeStub = launcherStubs.startChromeStub; var killStub = launcherStubs.killStub; // Stub out IPC, verify at the end. var sendStub = sandbox.stub(wd_server.process, 'send'); var disconnectStub = sandbox.stub(wd_server.process, 'disconnect'); // Connect DevTools. test_utils.stubHttpGet(sandbox, /^http:\/\/localhost:\d+\/json$/, '[{"webSocketDebuggerUrl": "ws://gaga"}]'); var stubWebSocket = sandbox.stub(devtools, 'WebSocket', FakeWebSocket); var idleSpy = sandbox.spy(); app.on(webdriver.promise.ControlFlow.EventType.IDLE, idleSpy); // * First view. logger.debug('First run of WD server'); wd_server.process.emit('message', { cmd: 'run', isCacheWarm: false, exitWhenDone: false, flags: {chromedriver: chromedriver}, task: {url: 'http://gaga.com/ulala', timeline: 1} }); // Do not use tickUntilIdle -- it will fail, because we actually stall // on the DevTools WebSocket connection, and we want to inject a bunch // of stuff before proceeding. sandbox.clock.tick(wd_server.WAIT_AFTER_ONLOAD_MS + webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY * 10); var fakeWs = stubWebSocket.firstCall.thisValue; // The DevTools WebSocket. // Simulate Chrome generating profiling messages as the page loads. var pageMessage = {method: 'Page.gaga'}; var networkMessage = {method: 'Network.ulala'}; var timelineMessage = {method: 'Timeline.tutu'}; var pageLoadedMessage = {method: 'Page.loadEventFired'}; // Verify that messages get ignored before the page load starts fakeWs.emit('message', JSON.stringify(networkMessage), {}); // Emit DevTools events after the test has started -- Page.navigate fired. function onPageNavigate(message) { if (/"method"\s*:\s*"Page.navigate"/.test(message)) { var m = message.match(/"url":"([^"]+)"/); var url = (m ? m[1] : ''); if ('http://gaga.com/ulala' === url) { fakeWs.removeListener('message', onPageNavigate); // Fire only once. fakeWs.emit('message', JSON.stringify(pageMessage), {}); fakeWs.emit('message', JSON.stringify(networkMessage), {}); fakeWs.emit('message', JSON.stringify(timelineMessage), {}); fakeWs.emit('message', JSON.stringify(pageLoadedMessage), {}); } else { url.should.match(/^data:text/); // ignore blank } } } fakeWs.on('message', onPageNavigate); test_utils.tickUntilIdle(app, sandbox); // * Verify we clear the cache, run, then keep our WD. should.ok(startChromeStub.calledOnce); should.equal('chrome', startChromeStub.firstCall.args[0].browserName); should.ok(stubWebSocket.calledOnce); should.ok('ws://gaga', stubWebSocket.firstCall.args[0]); fakeWs.commands.should.eql([ 'Timeline.start', 'Network.clearBrowserCache', 'Network.clearBrowserCookies', 'Page.navigate', 'Network.enable', 'Page.enable', 'Page.navigate', 'Page.captureScreenshot' ]); fakeWs.commands = []; // Reset for the next verification. should.ok(sendStub.calledOnce); var doneIpcMsg = sendStub.firstCall.args[0]; should.equal(doneIpcMsg.cmd, 'done'); doneIpcMsg.devToolsMessages.should.eql( [pageMessage, networkMessage, timelineMessage, pageLoadedMessage]); doneIpcMsg.screenshots.map(function(s) { return s.fileName; }).should.eql( ['screen.jpg']); should.equal(1, writeFileStub.callCount); // We expect a kill Chrome and keep our agent. should.ok(killStub.calledOnce); should.ok(disconnectStub.notCalled); // * Repeat view logger.debug('Second run of WD server'); wd_server.process.emit('message', { cmd: 'run', isCacheWarm: true, exitWhenDone: true, flags: {chromedriver: chromedriver}, task: {url: 'http://gaga.com/ulala', pngScreenshot: 1} }); // Verify that messages get ignored between runs fakeWs.emit('message', JSON.stringify(networkMessage), {}); // Do not use tickUntilIdle -- see comment above for run 1. sandbox.clock.tick(wd_server.WAIT_AFTER_ONLOAD_MS + webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY * 20 + 1000); should.ok(stubWebSocket.calledTwice); fakeWs = stubWebSocket.secondCall.thisValue; // The DevTools WebSocket. // Simulate page load finish. fakeWs.emit('message', JSON.stringify(pageLoadedMessage), {}); test_utils.tickUntilIdle(app, sandbox); // * Verify we keep our cache, run, then quit/stop WD. // Make sure we re-spawned Chrome but didn't reconnect to our agent. should.ok(startChromeStub.calledTwice); // These things get called for the second time on the repeat view. fakeWs.commands.should.eql([ 'Page.navigate', // To blank page. 'Network.enable', 'Page.enable', 'Page.navigate', // To the real page. 'Page.captureScreenshot' ]); should.ok(sendStub.calledTwice); doneIpcMsg = sendStub.secondCall.args[0]; should.equal(doneIpcMsg.cmd, 'done'); doneIpcMsg.devToolsMessages.should.eql([pageLoadedMessage]); doneIpcMsg.screenshots.map(function(s) { return s.fileName; }).should.eql( ['screen.png']); should.equal(2, writeFileStub.callCount); // The cleanup occurs only on the repeat view. should.ok(killStub.calledTwice); should.ok(disconnectStub.calledOnce); });
function(e) { logger.error('Exception from "%s": %s', description, e); logger.debug('%s', e.stack); });
it('should work overall with WD - start, run, stop', function() { // This is a long test that does a full run. It goes like this: // * General stubs/fakes/spies. // * First view: // * Verify we clear the cache, run, and quit/stop WD. // * Repeat view: // * Verify we clear the cache, run, and quit/stop WD. // // We do this as a single test, because the WebDriverServer state after // the first view is crucial for the repeat view, and because some of the // stubs/spies remain the same from the first view into the repeat view. // * General stubs/fakes/spies. var chromedriver = '/gaga/chromedriver'; // Stub out spawning chromedriver, verify at the end. var isFirstRun = true; var launcherStubs = stubBrowserLauncher(function() { should.ok(isFirstRun); // Only spawn WD on first run. }); var startWdServerStub = launcherStubs.startWdServerStub; var killStub = launcherStubs.killStub; // Stub out IPC, verify at the end. var sendStub = sandbox.stub(wd_server.process, 'send'); var disconnectStub = sandbox.stub(wd_server.process, 'disconnect'); stubServerReadyHttp(); // Fake a WebDriver instance, stub Builder.build() to return it. var driverExecuteScriptSpy = sinon.spy(); var driverGetSpy = sinon.spy(); var driverQuitSpy = sinon.spy(); var logsGetMock = sandbox.stub(); var fakeDriver = { getSession: function() { return webdriver.promise.fullyResolved('fake session'); }, executeScript: function(script) { return app.schedule('Fake WebDriver.executeScript(' + script + ')', driverExecuteScriptSpy.bind(fakeDriver, script)); }, get: function(url) { return app.schedule('Fake WebDriver.get(' + url + ')', driverGetSpy.bind(fakeDriver, url)); }, manage: function() { return { logs: function() { return { get: function(type) { return app.schedule('Fake WebDriver.Logs.get(' + type + ')', logsGetMock.bind(logsGetMock, type)); } }; } }; }, takeScreenshot: function() { return app.schedule('Fake WebDriver.takeScreenshot()', function() { return 'Z2FnYQ=='; // Base64 for 'gaga'. }.bind(fakeDriver)); }, quit: function() { return app.schedule('Fake WebDriver.quit()', driverQuitSpy.bind(fakeDriver)); } }; var wdBuildStub = sandbox.stub(webdriver.Builder.prototype, 'build', function() { logger.debug('Stub Builder.build() called'); return fakeDriver; }); // Simulate Chrome generating profiling messages as the page loads. var pageMessage = {method: 'Page.gaga'}; var networkMessage = {method: 'Network.ulala'}; var timelineMessage = {method: 'Timeline.tutu'}; function wdLogEntryFromMessage(devToolsMessage) { return { level: 'INFO', timestamp: 123, message: JSON.stringify({webview: 'gaga', message: devToolsMessage}) }; } logsGetMock.withArgs('performance').returns([ wdLogEntryFromMessage(pageMessage), wdLogEntryFromMessage(networkMessage), wdLogEntryFromMessage(timelineMessage) ]); var idleSpy = sandbox.spy(); app.on(webdriver.promise.ControlFlow.EventType.IDLE, idleSpy); // * First view. logger.debug('First run of WD server'); wd_server.process.emit('message', { cmd: 'run', isCacheWarm: false, exitWhenDone: false, flags: {chromedriver: chromedriver}, task: {script: 'new webdriver.Builder().build();'} }); test_utils.tickUntilIdle(app, sandbox, 500); // * Verify we clear the cache, run, and quit/stop WD. // Should spawn the chromedriver process on port 4444. should.ok(startWdServerStub.calledOnce); should.equal('chrome', startWdServerStub.firstCall.args[0].browserName); should.ok(wdBuildStub.calledOnce); should.ok(sendStub.calledOnce); var doneIpcMsg = sendStub.firstCall.args[0]; should.equal(doneIpcMsg.cmd, 'done'); doneIpcMsg.devToolsMessages.should.eql( [pageMessage, networkMessage, timelineMessage]); doneIpcMsg.screenshots.map(function(s) { return s.fileName; }).should.eql( ['screen.jpg']); should.equal(1, writeFileStub.callCount); // We do not clean up between runs in webdriver mode. should.ok(driverQuitSpy.notCalled); should.ok(killStub.notCalled); should.ok(disconnectStub.notCalled); // * Repeat view. logger.debug('Second run of WD server'); logsGetMock.withArgs('performance').returns([ wdLogEntryFromMessage(networkMessage) ]); wd_server.process.emit('message', { cmd: 'run', isCacheWarm: true, exitWhenDone: true, flags: {chromedriver: chromedriver}, task: {pngScreenshot: 1, script: 'new webdriver.Builder().build();'} }); test_utils.tickUntilIdle(app, sandbox); // * Verify we clear the cache, run, and quit/stop WD. // Make sure we spawned the WD server etc. should.ok(startWdServerStub.calledOnce); should.ok(wdBuildStub.calledOnce); // These things get called for the second time on the repeat view. should.ok(sendStub.calledTwice); doneIpcMsg = sendStub.secondCall.args[0]; should.equal(doneIpcMsg.cmd, 'done'); doneIpcMsg.devToolsMessages.should.eql([networkMessage]); doneIpcMsg.screenshots.map(function(s) { return s.fileName; }).should.eql( ['screen.png']); should.equal(2, writeFileStub.callCount); // The disconnect occurs only on the repeat view. should.ok(driverQuitSpy.calledOnce); should.ok(killStub.calledOnce); should.ok(disconnectStub.calledOnce); });
this.trafficShaper_('clear').addErrback(function(/*e*/) { logger.debug('Ignoring failed trafficShaper clear'); }.bind(this));
define(function (require, exports, module) { "use strict"; var defineComponent = require("flight").component; var withUrlNormalization = require("app-modules/utils/mixins/data/with-url-normalization"); var withHttpStatusManagement = require("app-modules/utils/mixins/data/with-http-status-management"); var $ = require("jquery"); var logger = require("logger"); var myDebug = false; // Exports: component definition module.exports = defineComponent(ajaxBreadcrumbHandler, withUrlNormalization, withHttpStatusManagement); myDebug && logger.debug(module.id, "Component on the bridge, captain!"); function ajaxBreadcrumbHandler() { this.onBreadcrumbUpdateRequested = function(ev, data) { var newBreadcrumbContent; if (data.fromSelector) { var $newBreadcrumbContainer = $(data.fromSelector); newBreadcrumbContent = $newBreadcrumbContainer.html(); $newBreadcrumbContainer.remove(); } else if (data.content) { newBreadcrumbContent = data.content; } this.$node.html(newBreadcrumbContent); }; this.onUiContentUpdated = function (ev, data) { // If this is the first page content, we restore its breadcrumb content if (this.firstPageUrl && this.firstPageBreadcrumb && data.url === this.firstPageUrl) { this.$node.html(this.firstPageBreadcrumb); myDebug && logger.debug(module.id, "First page breadcrumb restored."); } }; this.storeInitialBradcrumb = function () { if (this.isCurrentPageAnError()) { // Don't handle anything if the current page is a error page return; } this.firstPageUrl = this.normalizeUrl(document.location); myDebug && logger.debug(module.id, "First page breadcrumb is stored for later use."); this.firstPageBreadcrumb = this.$node.html(); }; // Component initialization this.after("initialize", function() { this.storeInitialBradcrumb(); this.on(document, "uiNeedsBreadcrumbUpdate", this.onBreadcrumbUpdateRequested); this.on(document, "uiContentUpdated", this.onUiContentUpdated); }); } });
process.nextTick(function () { worker = cluster.fork(); logger.debug('Http重启服务器,新进程:' + worker.process.pid); });
this.app_.schedule('Video record started', function() { logger.debug('Video record start succeeded'); this.videoFile_ = videoFile; }.bind(this));
var PlaylistManager = function() { this.currentSongIndex = -1; this.playlists = []; this.queue = []; events.EventEmitter.call(this); this.files = getAudioFiles('.mp3', 0, config.musicDir); logger.debug(util.format('Found %s files in: %s', this.files.length, config.musicDir)); allFiles = this.files; this.dirname = config.playstlistDir; if (this.dirname.length < 1) { this.dirname = path.join(process.cwd(), 'playlist'); fs.mkdir(this.dirname, function(err) { // Directory already exists }); } // Create default playlist which contains all songs var defaultPlaylist = new Playlist('All songs'); try { defaultPlaylist.load(this.dirname); } catch (err) { console.log(err); logger.info('Default playlist not found, creating...'); this.files.forEach(function(file) { defaultPlaylist.paths.push(file.path); }); defaultPlaylist.save(this.dirname); logger.info('Default playlist created'); } defaultPlaylist.locked = true; if (defaultPlaylist.paths.length !== this.files.length) { console.log('playlist is missing files'); } this.playlists.push(defaultPlaylist); // Load all playlists var self = this; var files = fs.readdirSync(this.dirname); files.forEach(function(fileName) { // Default playlist is already created if (fileName != defaultPlaylistName && ignoreFiles.indexOf(fileName) < 0) { var filePath = path.join(self.dirname, fileName); if (!fs.lstatSync(filePath).isDirectory()) { // Could be playlist try { var p = new Playlist(fileName); p.load(self.dirname); self.playlists.push(p); if (p.autoShuffle) { self.shuffle(p.id); } } catch (err) { logger.error(util.format('Cannot load playlist from "%s"', filePath)); } } } }); this.updateQueue(); if (config.commercial.enable && undefined !== config.commercial.dir && undefined !== config.commercial.frequency) { try { commercialQueue = getAudioFiles('.mp3', 0, config.commercial.dir); commercialFrequency = config.commercial.frequency.split(':')[0]; commercialsInRow = config.commercial.frequency.split(':')[1]; if (commercialQueue.length > 0) { logger.info(util.format('Found %s commercial(s)', commercialQueue.length)); commercialsEnabled = true; } } catch (err) { commercialsEnabled = false; logger.error(util.format('Cannot enable commercials: %s', err)); } } logger.info('Playlist manager started'); };
this.app_.schedule('Packet capture started', function() { logger.debug('Packet capture start succeeded'); this.pcapFile_ = pcapFile; }.bind(this));
this.adb_.adb(['uninstall', this.chromePackage_]).addErrback(function() { logger.debug('Ignoring failed uninstall'); }.bind(this));
function(job, resultFile, fields, callback) { logger.debug('stub postResultFile_ f=%j fields=%j', resultFile, fields); filesSubmitted += 1; callback(); });
function(alloc) { logger.debug('Selected WD port ' + alloc.port); this.serverPortLock_ = alloc; this.serverPort_ = alloc.port; }.bind(this));
return app.schedule(cmd, function() { logger.debug('Exec with timeout(%d): %s', timeout, cmd); // Create output buffers var stdout = ''; var stderr = ''; function newMsg(desc, code, signal) { function crop(s, n) { return (s.length <= n ? s : s.substring(0, n - 3) + '...'); } var ret = [desc, code && 'code ' + code, signal && 'signal ' + signal, stdout && 'stdout[' + stdout.length + '] ' + crop(stdout, 1024), stderr && 'stderr[' + stderr.length + '] ' + crop(stderr, 1024)]; // Comma-separated elements of ret, except the undefined ones. return ret.filter(function(v) { return !!v; }).join(', '); } function newError(desc, code, signal) { var ret = new Error(newMsg(desc, code, signal)); // Attach the stdout/stderr/etc to the Error ret.stdout = stdout; ret.stderr = stderr; ret.code = code; ret.signal = signal; return ret; } // Spawn var proc = child_process.spawn(command, args, options); var done = new webdriver.promise.Deferred(); // Start timer var timerId = global.setTimeout(function() { timerId = undefined; // Reset it before the close listener gets called. try { proc.kill(); } catch (e) { logger.error('Error killing %s: %s', cmd, e); } // The kill() call normally triggers the close listener, but we reject // the promise here instead of the close listener, because we don't really // know if and when it's going to be killed at OS level. // In the future we may want to restart the adb server here as a recovery // for wedged adb connections, or use a relay board for device recovery. done.reject( newError(cmd + ' timeout after ' + (timeout / 1000) + ' seconds')); }, timeout); // Listen for stdout/err proc.stdout.on('data', function(data) { stdout += data; }); proc.stderr.on('data', function(data) { stderr += data; }); // Listen for 'close' not 'exit', otherwise we might miss some output. proc.on('close', function(code, signal, e) { if (timerId) { // Our timer is still ticking, so we didn't timeout. global.clearTimeout(timerId); if (e) { done.reject(e); } else if (code || signal) { done.reject(newError(cmd + ' failed', code, signal)); } else { logger.debug(newMsg()); // TODO webdriver's fulfill only saves the first argument, so we can // only return the stdout. For now our clients only need the stdout. done.fulfill(stdout);//, stderr, code, signal); } } else { // The timer has expired, which means that we're already killed our // process and rejected our promise. logger.debug('%s close on timeout kill', cmd); } }); // Somehow, I can't figure out how, if I don't set an 'error' handler on the // process, any spawn error throws an uncaught exception and never calls // the 'close' handler (or at least before it calls the 'close' handler), // which in turn preempts my civilized promise logic in the 'close' handler. proc.on('error', function(e) { logger.error('%s failed with exception: %s', cmd, e.message); }); return done.promise; });
.then(function(alloc) { logger.debug('Selected DevTools port ' + alloc.port); this.devtoolsPortLock_ = alloc; this.devToolsPort_ = alloc.port; }.bind(this));
return app.schedule(description, function() { logger.debug('Calling %s', description); f.apply(undefined, args); return done.promise; });
this.app_.on(webdriver.promise.ControlFlow.EventType.IDLE, function() { logger.debug('The main control flow has gone idle, history: %j', this.app_.getHistory()); }.bind(this));
app.schedule(description, function() { logger.debug('Killing %s: %s', proc.pid, formatForMessage( proc.command, proc.args)); var cmd = system_commands.get('kill', [proc.pid]).split(/\s+/); exports.scheduleExec(app, cmd.shift(), cmd).addErrback(function() { }); });
this.devToolsCommand_(message).then(function() { logger.debug('Started tracing to ' + traceFile); }, function(e) {
progress: function(msg) { log.debug(msg); },
function(e) { logger.debug('Ignoring close error: ' + e.message); }); // Don't wait for close; we've already flushed.
registerDevice(function() { LOGGER.debug(__FILE__+"PUSH.init @success"); // Subscribe everyone to the news channel exports.subscribeToChannel('news'); });
define(function (require, exports, module) { "use strict"; /* jshint multistr:true */ var defineComponent = require("flight").component; var _ = require("lodash"); var logger = require("logger"); var myDebug = false; // Exports: component definition module.exports = defineComponent(ajaxAdvancedPerfsDebugInfo); myDebug && logger.debug(module.id, "Component on the bridge, captain!"); function ajaxAdvancedPerfsDebugInfo() { this.onjQueryAjaxSuccess = function(ev, data, jqXHR) { this.$node.find(".current-action-url").text(jqXHR.type + " " + jqXHR.url); // Lets handle our specific "X-Perfs-*" headers! var headersDomSelectorsMaping = { "X-Perfs-Elapsed-Time-Now": ".perfs-elapsed-time-now", "X-Perfs-Elapsed-Time-Bootstrap": ".perfs-elapsed-time-bootstrap", "X-Perfs-Elapsed-Time-Plugins-Init": ".perfs-elapsed-time-plugins-init", "X-Perfs-Nb-Included-Files-Now": ".perfs-nb-included-files-now", "X-Perfs-Nb-Included-Files-Bootstrap": ".perfs-nb-included-files-bootstrap", "X-Perfs-Nb-Included-Files-Plugins-Init": ".perfs-nb-included-files-plugins-init", "X-Perfs-Nb-Included-Templates-Now": ".perfs-nb-included-templates-now", "X-Perfs-Nb-Included-Packs-Now": ".perfs-nb-included-packs-now", "X-Perfs-Nb-Plugins": ".nb-plugins", "X-Perfs-Nb-Plugins-Permanently-Disabled": ".nb-plugins-permanently-disabled", "X-Perfs-Nb-Plugins-Disabled-For-Current-URL": ".nb-plugins-disabled-for-current-url", "X-Perfs-Nb-Actions-Registered": ".nb-actions-registered", "X-Perfs-Session-Content": ".session-content", "X-Perfs-SQL-Nb-Queries": ".nb-sql-queries", "X-Perfs-View-Rendering-Duration": ".view-rendering-duration", "X-Perfs-QueryPath-Duration": ".query-path-duration" }; _.forEach(headersDomSelectorsMaping, _.bind(function(domSelector, headerName) { this.$node.find(domSelector).text( data.getResponseHeader(headerName) || "" ) .closest("li").removeClass("hidden"); }, this)); // X-Perfs-SQL-Queries var sqlQueries = data.getResponseHeader("X-Perfs-SQL-Queries"); if (sqlQueries) { sqlQueries = JSON.parse(sqlQueries); var sqlQueriesHtml = ""; _.forEach(sqlQueries, function(query) { sqlQueriesHtml += "\ <li>\ <b>"+query.time+"</b>ms. :\ <i>"+query.query+"</i>\ - bindings: <i>"+JSON.stringify(query.bindings)+"</i>\ </li>"; }); this.$node.find(".sql-queries") .html(sqlQueriesHtml); } else { this.$node.find(".sql-queries") .empty(); } }; // Component initialization this.after("initialize", function() { this.on(document, "ajaxSuccess", this.onjQueryAjaxSuccess); }); } });