diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 0a3f717740f..a6d8f2982f9 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -179,6 +179,7 @@ class Website(openerp.addons.web.controllers.main.Home): result.append({ 'name': v.inherit_option_id.name, 'id': v.id, + 'xml_id': v.xml_id, 'inherit_id': v.inherit_id.id, 'header': True, 'active': False @@ -187,6 +188,7 @@ class Website(openerp.addons.web.controllers.main.Home): result.append({ 'name': v.name, 'id': v.id, + 'xml_id': v.xml_id, 'inherit_id': v.inherit_id.id, 'header': False, 'active': (v.inherit_id.id == v.inherit_option_id.id) or (not optional and v.inherit_id.id) diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index fab9dbcc4a7..1e8246366a9 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -414,6 +414,7 @@ openerp.jsonRpc('/website/customize_template_get', 'call', { 'xml_id': view_name }).then( function(result) { _.each(result, function (item) { + if (item.xml_id === "website.debugger" && !window.location.search.match(/[&?]debug(&|$)/)) return; if (item.header) { menu.append(''); } else { diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 7965c4b88f0..e45bee9685b 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -9,7 +9,7 @@ var self = this; $("[data-oe-model]").on('click', function (event) { var $this = $(event.srcElement); - var tag = $this[0].tagName.toLowerCase(); + var tag = $this[0] && $this[0].tagName.toLowerCase(); if (!(tag === 'a' || tag === "button") && !$this.parents("a, button").length) { self.$('[data-action="edit"]').parent().effect('bounce', {distance: 18, times: 5}, 250); } @@ -419,12 +419,18 @@ // reset snippet for rte $target.removeData("snippet-editor"); - $target.removeData("overlay"); + if ($target.data("overlay")) { + $target.data("overlay").remove(); + $target.removeData("overlay"); + } self.create_overlay($target); $target.find("[data-snippet-id]").each(function () { var $snippet = $(this); $snippet.removeData("snippet-editor"); - $snippet.removeData("overlay"); + if ($snippet.data("overlay")) { + $snippet.data("overlay").remove(); + $snippet.removeData("overlay"); + } self.create_overlay($snippet); }); // end diff --git a/addons/website/static/src/js/website.tests.js b/addons/website/static/src/js/website.tests.js deleted file mode 100644 index 977dc8e1848..00000000000 --- a/addons/website/static/src/js/website.tests.js +++ /dev/null @@ -1,40 +0,0 @@ -var tests = {}; -var droptest = function () { - var errors = []; - for (var snippet_id in tests) { - if (!tests[snippet_id]['activated'] || !tests[snippet_id]['dropped']){ - console.log("Can't dropped or activated snippet: " + snippet_id); - } - } - if (errors.length) { - console.log(tests); - throw new Error("Can't dropped or activated at least one snippet"); - } - $("#oe_snippets").off('snippet-activated snippet-dropped'); -}; -var droptesttime = setTimeout(droptest,0); - -$("#oe_snippets").off('snippet-activated snippet-dropped') - .on('snippet-activated', function (event, dom) { - tests[$(dom).data('src-snippet-id')]['activated'] = true; - clearTimeout(droptesttime); - droptesttime = setTimeout(droptest,0); - }) - .on('snippet-dropped', function (event, dom, src_snipped_id) { - tests[$(dom).data('src-snippet-id')]['dropped'] = true; - clearTimeout(droptesttime); - droptesttime = setTimeout(droptest,0); - }); -var $thumbnails = $('#oe_snippets div.oe_snippet[data-snippet-id] .oe_snippet_thumbnail'); -$thumbnails.each(function () { - var $thumbnail = $(this); - tests[$thumbnail.parent().data('snippet-id')] = {}; - var position = $thumbnail.position(); - $thumbnail.trigger( $.Event( "mousedown", { which: 1, pageX: position.left, pageY: position.top } ) ); - $thumbnail.trigger( $.Event( "mousemove", { which: 1, pageX: position.left+100, pageY: position.top+100 } ) ); - $first_drop = $(".oe_drop_zone").first(); - position = $first_drop.position(); - $first_drop.trigger( $.Event( "mouseup", { which: 1, pageX: position.left+20, pageY: position.top+20 } ) ); - clearTimeout(droptesttime); - droptesttime = setTimeout(droptest,0); -}); diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js index b079c4a670c..c5b04091b40 100644 --- a/addons/website/static/src/js/website.tour.banner.js +++ b/addons/website/static/src/js/website.tour.banner.js @@ -2,113 +2,112 @@ 'use strict'; var website = openerp.website; + var _t = openerp._t; website.EditorBar.include({ start: function () { - this.registerTour(new website.BannerTour(this)); + this.registerTour(new website.Tour.Banner(this)); return this._super(); }, }); - website.BannerTour = website.Tour.extend({ + website.Tour.Banner = website.Tour.extend({ id: 'banner', name: "Insert a banner", path: '/', - init: function (editor) { + init: function () { var self = this; self.steps = [ { - title: "Welcome to your website!", - content: "This tutorial will guide you to build your home page. We will start by adding a banner.", - template: self.popover({ next: "Start Tutorial", end: "Skip It" }), - backdrop: true, + title: _t("Welcome to your website!"), + content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."), + popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, }, { waitNot: '.popover.tour', element: 'button[data-action=edit]', placement: 'bottom', - title: "Edit this page", - content: "Every page of your website can be modified through the Edit button.", - template: self.popover({ fixed: true }), + title: _t("Edit this page"), + content: _t("Every page of your website can be modified through the Edit button."), + popover: { fixed: true }, }, { element: 'button[data-action=snippet]', placement: 'bottom', - title: "Insert building blocks", - content: "To add content in a page, you can insert building blocks.", - template: self.popover({ fixed: true }), + title: _t("Insert building blocks"), + content: _t("To add content in a page, you can insert building blocks."), + popover: { fixed: true }, }, { snippet: 'carousel', placement: 'bottom', - title: "Drag & Drop a Banner", - content: "Drag the Banner block and drop it in your page.", - template: self.popover({ fixed: true }), + title: _t("Drag & Drop a Banner"), + content: _t("Drag the Banner block and drop it in your page."), + popover: { fixed: true }, }, { waitFor: '.oe_overlay_options .oe_options:visible', element: '#wrap [data-snippet-id=carousel]:first .carousel-caption', - sampleText: 'My Title', placement: 'top', - title: "Customize banner's text", - content: "Click in the text and start editing it. Click continue once it's done.", - template: self.popover({ next: "Continue" }), + title: _t("Customize banner's text"), + content: _t("Click in the text and start editing it. Click continue once it's done."), + popover: { next: _t("Continue") }, }, { element: '.oe_overlay_options .oe_options', placement: 'left', - title: "Customize the banner", - content: "Customize any block through this menu. Try to change the background of the banner.", - template: self.popover({ next: "Continue" }), + title: _t("Customize the banner"), + content: _t("Customize any block through this menu. Try to change the background of the banner."), + popover: { next: _t("Continue") }, }, { waitNot: '.popover.tour', element: 'button[data-action=snippet]', placement: 'bottom', - title: "Add Another Block", - content: "Let's add another building block to your page.", - template: self.popover({ fixed: true }), + title: _t("Add Another Block"), + content: _t("Let's add another building block to your page."), + popover: { fixed: true }, }, { snippet: 'three-columns', placement: 'bottom', - title: "Drag & Drop a Block", - content: "Drag the '3 Columns' block and drop it below the banner.", - template: self.popover({ fixed: true }), + title: _t("Drag & Drop a Block"), + content: _t("Drag the '3 Columns' block and drop it below the banner."), + popover: { fixed: true }, }, { waitFor: '.oe_overlay_options .oe_options:visible', element: 'button[data-action=save]', placement: 'right', - title: "Save your modifications", - content: "Publish your page by clicking on the 'Save' button.", - template: self.popover({ fixed: true }), + title: _t("Save your modifications"), + content: _t("Publish your page by clicking on the 'Save' button."), + popover: { fixed: true }, }, { waitFor: 'button[data-action=edit]:visible', - title: "Congratulation!", - content: "Your homepage has been updated.", - template: self.popover({ next: "Continue" }), + title: _t("Congratulation!"), + content: _t("Your homepage has been updated."), + popover: { next: _t("Continue") }, }, { waitNot: '.popover.tour', element: 'a[data-action=show-mobile-preview]', placement: 'bottom', - title: "Test Your Mobile Version", - content: "Let's check how your homepage looks like on mobile devices.", - template: self.popover({ fixed: true }), + title: _t("Test Your Mobile Version"), + content: _t("Let's check how your homepage looks like on mobile devices."), + popover: { fixed: true }, }, { element: 'button[data-dismiss=modal]', placement: 'right', - title: "Close Mobile Preview", - content: "Scroll in the mobile preview to test the rendering. Once it's ok, close this dialog.", + title: _t("Close Mobile Preview"), + content: _t("Scroll in the mobile preview to test the rendering. Once it's ok, close this dialog."), }, { waitNot: '.modal', - title: "Congrats", - content: "Congratulation. This tour is finished.", - template: self.popover({ fixed: true, next: "Close Tutorial" }), + title: _t("Congrats"), + content: _t("Congratulation. This tour is finished."), + popover: { fixed: true, next: _t("Close Tutorial") }, }, ]; return this._super(); diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js index 1db813e4cd4..408a4c01539 100644 --- a/addons/website/static/src/js/website.tour.js +++ b/addons/website/static/src/js/website.tour.js @@ -2,8 +2,11 @@ 'use strict'; var website = openerp.website; + +if (typeof QWeb2 !== "undefined") website.add_template_file('/website/static/src/xml/website.tour.xml'); +if (website.EditorBar) website.EditorBar.include({ tours: [], start: function () { @@ -17,31 +20,11 @@ website.EditorBar.include({ }); menu.append($menuItem); }); - - this.waitRTEReady = false; - this.on('rte:called', this, function () {self.waitRTEReady = true; }); - this.on('rte:ready', this, function () {self.waitRTEReady = false;}); - - var res = this._super(); - website.Tour.waitReady.call(this, this.testRunning); - return res; + return this._super(); }, registerTour: function (tour) { website.Tour.add(tour); this.tours.push(tour); - }, - testRunning: function () { - if (this.waitRTEReady) { - this.on('rte:ready', this, function () { - website.Tour.each(function () { - this.running(); - }); - }); - } else { - website.Tour.each(function () { - this.running(); - }); - } } }); @@ -78,23 +61,12 @@ $.ajaxSetup({ } }); - website.Tour = openerp.Class.extend({ steps: [], defaultDelay: 50, //ms + defaultOverLaps: 5000, //ms localStorage: window.localStorage, - init: function (url) { - this.tour = new Tour({ - name: this.id, - storage: this.tourStorage, - keyboard: false, - template: this.popover(), - onHide: function () { - window.scrollTo(0, 0); - } - }); - this.registerSteps(); - }, + init: function () {}, run: function (automatic) { this.reset(); @@ -105,9 +77,8 @@ website.Tour = openerp.Class.extend({ website.Tour.busy = true; - if (automatic) { - this.localStorage.setItem("tour-"+this.id+"-test-automatic", true); - } + this.localStorage.setItem("tour-"+this.id+"-test-automatic", automatic); + this.automatic = automatic; if (this.path) { // redirect to begin of the tour in function of the language @@ -123,12 +94,13 @@ website.Tour = openerp.Class.extend({ website.Tour.waitReady.call(this, function () {self._running();}); }, running: function () { + var self = this; if (+this.localStorage.getItem("tour-"+this.id+"-test") >= this.steps.length-1) { this.endTour(); return; } - if (website.Tour.is_busy() || !this.testPathUrl()) return; + if (website.Tour.is_busy()) return; // launch tour with url this.checkRunningUrl(); @@ -136,6 +108,21 @@ website.Tour = openerp.Class.extend({ // mark tour as busy (only one test running) if (this.localStorage.getItem("tour-"+this.id+"-test") != null) { website.Tour.busy = true; + this.automatic = !!this.localStorage.getItem("tour-"+this.id+"-test-automatic"); + } + + if (!this.testPathUrl()) { + if (this.automatic) { + this.timer = setTimeout(function () { + self.reset(); + throw new Error("Wrong url for running " + self.id + + '\ntestPath: ' + self.testPath + + '\nhref: ' + window.location.href + + "\nreferrer: " + document.referrer + ); + },this.defaultOverLaps); + } + return; } var self = this; @@ -143,14 +130,10 @@ website.Tour = openerp.Class.extend({ }, _running: function () { var stepId = this.localStorage.getItem("tour-"+this.id+"-test"); - var automatic = !!this.localStorage.getItem("tour-"+this.id+"-test-automatic"); - + if (stepId != null) { - if (!this.check(this.step(stepId))) { - var step = this.next(stepId); - stepId = step ? step.stepId : stepId; - } - this.nextStep(stepId, automatic ? this.autoNextStep : null, automatic ? 5000 : null); + this.registerTour(); + this.nextStep(stepId, this.automatic ? this.autoNextStep : null, this.automatic ? this.defaultOverLaps : null); } }, @@ -187,20 +170,35 @@ website.Tour = openerp.Class.extend({ } }, + registerTour: function () { + this.tour = new Tour({ + name: this.id, + storage: this.tourStorage, + keyboard: false, + template: this.popover(), + onHide: function () { + window.scrollTo(0, 0); + } + }); + this.registerSteps(); + }, registerSteps: function () { for (var index=0, len=this.steps.length; index 0 && $(this.steps[index-1].template).has("button[data-role='next']").size()) { - step.waitNot = '.popover.tour'; + if (!step.waitNot && index > 0 && this.steps[index-1] && + this.steps[index-1].popover && this.steps[index-1].popover.next) { + step.waitNot = '.popover.tour:visible'; } if (!step.waitFor && index > 0 && this.steps[index-1].snippet) { step.waitFor = '.oe_overlay_options .oe_options:visible'; } - step._title = step.title; - step.title = openerp.qweb.render('website.tour_popover_title', { title: step.title }); + step._title = step._title || step.title; + step.title = this.popoverTitle({ title: step._title }); + step.template = step.template || this.popover( step.popover ); + if (!step.element) step.orphan = true; if (step.snippet) { step.element = '#oe_snippets div.oe_snippet[data-snippet-id="'+step.snippet+'"] .oe_snippet_thumbnail'; @@ -208,9 +206,10 @@ website.Tour = openerp.Class.extend({ } - if ($(this.steps[index-1].template).has("button[data-role='next']").size()) { + if (this.steps[index-1] && + this.steps[index-1].popover && this.steps[index-1].popover.next) { var step = { - stepId: index, + stepId: ""+index, waitNot: '.popover.tour:visible' }; this.steps.push(step); @@ -219,8 +218,21 @@ website.Tour = openerp.Class.extend({ this.tour.addSteps(this.steps); }, + popoverTitle: function (options) { + try { + return openerp.qweb.render('website.tour_popover_title', options); + } catch (e) { + if (!this.automatic) throw e; + return options.title; + } + }, popover: function (options) { - return openerp.qweb.render('website.tour_popover', options); + try { + return openerp.qweb.render('website.tour_popover', options); + } catch (e) { + if (!this.automatic) throw e; + return ""; + } }, timer: null, @@ -268,7 +280,12 @@ website.Tour = openerp.Class.extend({ self.timer = setTimeout(checkNext, self.defaultDelay); } else { self.reset(); - throw new Error("Time overlaps to arrive to step " + step.stepId + ": '" + step._title + "'"); + throw new Error("Time overlaps to arrive to step " + step.stepId + ": '" + step._title + "'" + + '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) + + '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size()) + + '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size()) + + '\n\n' + $("body").html() + ); } } checkNext(); @@ -291,7 +308,7 @@ website.Tour = openerp.Class.extend({ $(".popover.tour").remove(); // go to step in bootstrap tour this.tour.goto(index); - if (step.callback) step.callback(); + if (step.onload) step.onload(); next = steps.shift(); break; } @@ -358,7 +375,10 @@ website.Tour = openerp.Class.extend({ } else if (step.sampleText) { $element.trigger($.Event("keydown", { srcElement: $element })); - if ($element.is("select") || $element.is("input") ) { + if ($element.is("input") ) { + $element.val(step.sampleText); + } if ($element.is("select")) { + $element.find("[value='"+step.sampleText+"'], option:contains('"+step.sampleText+"')").attr("selected", true); $element.val(step.sampleText); } else { $element.html(step.sampleText); @@ -404,7 +424,10 @@ website.Tour.busy = false; website.Tour.add = function (tour) { website.Tour.waitReady(function () { tour = tour.id ? tour : new tour(); - website.Tour.tours[tour.id] = tour; + if (!website.Tour.tours[tour.id]) { + website.Tour.tours[tour.id] = tour; + tour.running(); + } }); }; website.Tour.get = function (id) { @@ -420,7 +443,7 @@ website.Tour.each = function (callback) { website.Tour.waitReady = function (callback) { var self = this; $(document).ready(function () { - if ($.ajaxBusy == null || $.ajaxBusy) { + if ($.ajaxBusy) { $(document).ajaxStop(function() { setTimeout(function () { callback.call(self); @@ -435,18 +458,20 @@ website.Tour.waitReady = function (callback) { }); }; website.Tour.run_test = function (id) { - website.Tour.get(id).run(true); + website.Tour.waitReady(function () { + if (!website.Tour.is_busy()) { + website.Tour.tours[id].run(true); + } + }); }; website.Tour.is_busy = function () { for (var k in this.localStorage) { if (!k.indexOf("tour-")) { - return true; + return k; } } return website.Tour.busy; }; - - }()); diff --git a/addons/website/static/src/js/website.tour.test.admin.js b/addons/website/static/src/js/website.tour.test.admin.js new file mode 100644 index 00000000000..787f05beb23 --- /dev/null +++ b/addons/website/static/src/js/website.tour.test.admin.js @@ -0,0 +1,106 @@ +(function () { + 'use strict'; + + var website = openerp.website; + + website.Tour.LoginEdit = website.Tour.extend({ + id: 'login_edit', + name: "Try to log as admin and check editor", + path: '/', + init: function () { + var self = this; + self.steps = [ + { + title: "click login", + element: '#top_menu a[href*="/web/login"]', + }, + { + title: "insert login", + element: '.oe_login_form input[name="login"]', + sampleText: "admin", + }, + { + title: "insert password", + waitFor: '.oe_login_form input[name="login"][value!=""]', + element: '.oe_login_form input[name="password"]', + sampleText: "admin", + }, + { + title: "select 2 Standard tickets", + waitFor: '.oe_login_form input[name="password"][value!=""]', + element: '.oe_login_form button', + }, + { + title: "go back to website from backend", + element: 'a[data-action-model="ir.actions.act_url"]:contains("Website")', + }, + { + title: 'try to edit', + waitNot: '#wrap .carousel', + element: 'button[data-action=edit]:visible', + }, + { + title: 'check edit mode', + waitFor: 'button[data-action=save]:visible', + }, + { + title: 'check branding', + waitFor: '#wrap[data-oe-model="ir.ui.view"]', + }, + { + title: 'check rte', + waitFor: '#oe_rte_toolbar', + }, + { + title: 'check insert block button', + element: '[data-action="snippet"]:visible', + }, + { + title: 'add snippets', + snippet: 'carousel', + }, + { + title: 'try to save', + waitFor: '.oe_overlay_options .oe_options:visible', + element: 'button[data-action=save]:visible', + }, + { + title: 'check saved', + waitFor: '#wrap div.carousel', + element: 'button[data-action=edit]:visible', + }, + { + title: 'try to re-edit', + waitFor: 'button[data-action=save]:visible', + element: '#wrap .carousel', + }, + { + title: 'remove snippet', + element: '.oe_snippet_remove', + }, + { + title: 'try to re-save', + waitNot: '#wrap .carousel', + element: 'button[data-action=save]:visible', + }, + { + title: "click admin", + waitFor: 'button[data-action=edit]:visible', + element: 'a:contains("Administrator")', + }, + { + title: "click logout", + element: '#top_menu a[href*="/logout"]', + }, + { + title: "check logout", + waitFor: '#top_menu a[href*="/web/login"]', + }, + ]; + return this._super(); + }, + }); + // for test without editor bar + website.Tour.add(website.Tour.LoginEdit); + +}()); diff --git a/addons/website/static/src/js/website.tour.test.js b/addons/website/static/src/js/website.tour.test.js new file mode 100644 index 00000000000..3e85ce20dae --- /dev/null +++ b/addons/website/static/src/js/website.tour.test.js @@ -0,0 +1,34 @@ +(function () { + +function LoadScript(src) { + xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if(xmlHttp.readyState == 4) { + if (xmlHttp.status == 200 || xmlHttp.status == 304) { + new Function(xmlHttp.responseText)(); + } else { + throw new Error("Can't load JavaScript.\nhref: " + window.location.href + "\nsrc: " + src); + } + } + }; + xmlHttp.open("GET", src, false); + xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xmlHttp.send(null); +} + +if (typeof jQuery === "undefined") + LoadScript("/web/static/lib/jquery/jquery.js"); +if (typeof _ === "undefined") + LoadScript("/web/static/lib/underscore/underscore.js"); +if (typeof openerp === "undefined") { + LoadScript("/web/static/lib/qweb/qweb2.js"); + LoadScript("/web/static/src/js/openerpframework.js"); +} +if (typeof openerp === "undefined" || !openerp.website || !openerp.website.add_template_file) + LoadScript("/website/static/src/js/website.js"); +if (typeof Tour === "undefined") + LoadScript("/website/static/lib/bootstrap-tour/bootstrap-tour.js"); +if (typeof openerp === "undefined" || !openerp.website.Tour) + LoadScript("/website/static/src/js/website.tour.js"); + +})(); \ No newline at end of file diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py index 96484882577..e79a2eb13ec 100644 --- a/addons/website/tests/test_ui.py +++ b/addons/website/tests/test_ui.py @@ -41,7 +41,7 @@ class WebsiteUiSuite(unittest.TestSuite): # timeout in seconds def __init__(self, testfile, options, timeout=60.0): self._testfile = testfile - self._timeout = timeout + self._timeout = timeout + 5.0 self._options = options self._test = None self._ignore_filters = [ @@ -58,7 +58,6 @@ class WebsiteUiSuite(unittest.TestSuite): return iter([self]) def run(self, result): - return # clean slate if sql_db._Pool is not None: sql_db._Pool.close_all(sql_db.dsn(tools.config['db_name'])) @@ -79,18 +78,25 @@ class WebsiteUiSuite(unittest.TestSuite): del result._exc_info_to_string def _run(self, result): - self._test = WebsiteUiTest(self._testfile) + self._test = WebsiteUiTest("%s (as %s)" % + (self._testfile, self._options.get('user') or "Anonymous" if 'user' in self._options else "admin" )) start_time = time.time() last_check_time = time.time() self._options['timeout'] = self._timeout self._options['port'] = tools.config.get('xmlrpc_port', 80) self._options['db'] = tools.config.get('db_name', '') - self._options['user'] = 'admin' - self._options['password'] = tools.config.get('admin_passwd', 'admin') + # FIX for runbot test + if hasattr(os, 'uname') and os.uname()[1].startswith('runbot.'): + self._options['host'] = tools.config.get('db_name', '') + ".runbot.openerp.com" + + if 'user' not in self._options: + self._options['user'] = 'admin' + self._options['password'] = 'admin' phantom = subprocess.Popen([ 'phantomjs', + #'--debug=true', self._testfile, json.dumps(self._options) ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -148,6 +154,7 @@ def full_path(pyfile, filename): def load_tests(loader, base, _): base.addTest(WebsiteUiSuite(full_path(__file__, 'dummy_test.js'), {}, 5.0)) + base.addTest(WebsiteUiSuite(full_path(__file__, 'login_test.js'), {'path': '/', 'user': None}, 60.0)) base.addTest(WebsiteUiSuite(full_path(__file__, 'simple_dom_test.js'), {'redirect': '/page/website.homepage'}, 60.0)) base.addTest(WebsiteUiSuite(full_path(__file__, 'homepage_test.js'), {'redirect': '/page/website.homepage'}, 60.0)) return base diff --git a/addons/website/tests/ui_suite/homepage_test.js b/addons/website/tests/ui_suite/homepage_test.js index 2560e5af4d5..9c7375589a6 100644 --- a/addons/website/tests/ui_suite/homepage_test.js +++ b/addons/website/tests/ui_suite/homepage_test.js @@ -1,17 +1,3 @@ var testRunner = require('./ui_test_runner.js'); -var waitFor = testRunner.waitFor; - -testRunner.run(function homepageTest (page, timeout) { - page.evaluate(function () { localStorage.clear(); }); - waitFor(function clientReady () { - return page.evaluate(function () { - return window.$ && window.openerp && window.openerp.website - && window.openerp.website.Tour; - }); - }, function executeTest () { - page.evaluate(function () { - window.openerp.website.Tour.run_test('banner'); - }); - }, timeout); -}); +testRunner.run_test('banner'); \ No newline at end of file diff --git a/addons/website/tests/ui_suite/login_test.js b/addons/website/tests/ui_suite/login_test.js new file mode 100644 index 00000000000..3ac403e586d --- /dev/null +++ b/addons/website/tests/ui_suite/login_test.js @@ -0,0 +1,7 @@ +var testRunner = require('./ui_test_runner.js'); + +testRunner.run_test('login_edit', { + "inject": [ + "./../../../website/static/src/js/website.tour.test.js", + "./../../../website/static/src/js/website.tour.test.admin.js"] + }); \ No newline at end of file diff --git a/addons/website/tests/ui_suite/ui_test_runner.js b/addons/website/tests/ui_suite/ui_test_runner.js index 507a8ca1e72..745adc15f0c 100644 --- a/addons/website/tests/ui_suite/ui_test_runner.js +++ b/addons/website/tests/ui_suite/ui_test_runner.js @@ -19,15 +19,15 @@ function waitFor (ready, callback, timeout, timeoutMessageCallback) { }, 100); } -function run (test) { +function run (test, onload, inject) { var options = JSON.parse(phantom.args); - var timeout = options.timeout ? Math.round(parseFloat(options.timeout)*1000) : 60000; + var timeout = options.timeout ? Math.round(parseFloat(options.timeout)*1000-5000) : 60000; var scheme = options.scheme ? options.scheme+'://' : 'http://'; var host = options.host ? options.host : 'localhost'; var port = options.port ? ':'+options.port : ''; - var path = options.path ? options.path : '/login'; + var path = options.path ? options.path : '/web/login'; var queryParams = []; if (options.db) queryParams.push('db='+options.db); @@ -56,24 +56,52 @@ function run (test) { }; page.onConsoleMessage = function(message) { console.log(message); + try { + var result = JSON.parse(message); + if (result.event === 'success') { + phantom.exit(0); + } else if (result.event === 'console') { + return; + } else { + phantom.exit(1); + } + } catch (exception) { + phantom.exit(1); + } }; page.onCallback = function(data) { if (data.event && data.event === 'start') { - test(page, timeout); + if (test) test(page, timeout, options); + } + }; + page.onLoadFinished = function(status) { + if (status === "success") { + if (inject) { + if (!inject instanceof Array) { + inject = [inject]; + } + for (var k in inject) { + if(!page.injectJs(inject[k])) { + console.log("Can't inject "+inject[k]); + phantom.exit(1); + } + } + } + if (onload) onload(page, timeout, options); } }; var maxRetries = 10; var retryDelay = 1000; // ms - var tries = 0; + var tries = 0; page.open(url, function openPage (status) { if (status !== 'success') { tries++; if (tries < maxRetries) { - setTimeout(function () { - page.open(url, openPage); - }, retryDelay); + setTimeout(function () { + page.open(url, openPage); + }, retryDelay); } else { console.log('{ "event": "error", "message": "'+url+' failed to load '+tries+' times ('+status+')"}'); phantom.exit(1); @@ -85,9 +113,45 @@ function run (test) { } }); + + setTimeout(function () { + page.evaluate(function (timeout) { + var message = ("Timeout after " +(timeout/1000)+ " s" + + "\nhref: " + window.location.href + + "\nreferrer: " + document.referrer + + "\n\n" + document.body.innerHTML).replace(/[^a-z0-9\s~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, "*"); + console.log(JSON.stringify({ "event": "error", "message": message})); + phantom.exit(1); + },timeout); + }, timeout); +} + +function run_test (testname, options) { + options = options || {}; + run( + function start (page, timeout) { + page.evaluate(function () { localStorage.clear(); }); + }, + function onload (page, timeout) { + waitFor(function clientReady () { + return page.evaluate(function () { + return window.$ + && window.openerp + && window.openerp.website + && window.openerp.website.Tour; + }); + }, function executeTest () { + page.evaluate(function (testname) { + window.openerp.website.Tour.run_test(testname); + }, testname); + }, timeout); + }, + options.inject || null + ); } module.exports = { waitFor: waitFor, - run: run + run: run, + run_test: run_test } diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 0f77d7e2914..bf61f64a1b9 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -284,6 +284,13 @@ + +