mirror of
https://github.com/bringout/oca-ocb-test.git
synced 2026-04-22 11:02:04 +02:00
19.0 vanilla
This commit is contained in:
parent
38c6088dcc
commit
d9452d2060
243 changed files with 30797 additions and 10815 deletions
|
|
@ -0,0 +1,15 @@
|
|||
import { Interaction } from "@web/public/interaction";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
|
||||
export class TestError extends Interaction {
|
||||
static selector = ".rpc_error a";
|
||||
dynamicContent = {
|
||||
_root: { "t-on-click.prevent": () => rpc(this.el.getAttribute("href")) },
|
||||
}
|
||||
}
|
||||
|
||||
registry
|
||||
.category("public.interactions")
|
||||
.add("test_website.test_error", TestError);
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
odoo.define('website_forum.test_error', function (require) {
|
||||
'use strict';
|
||||
|
||||
var publicWidget = require('web.public.widget');
|
||||
|
||||
publicWidget.registry.testError = publicWidget.Widget.extend({
|
||||
selector: '.rpc_error',
|
||||
events: {
|
||||
'click a': '_onRpcErrorClick',
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Handlers
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* make a rpc call with the href of the DOM element clicked
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_onRpcErrorClick: function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
return this._rpc({
|
||||
route: $link.attr('href'),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { FileSelectorControlPanel } from '@web_editor/components/media_dialog/file_selector';
|
||||
import { getFixture, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { HtmlField } from '@web_editor/js/backend/html_field';
|
||||
import {registry} from '@web/core/registry';
|
||||
import testUtils from 'web.test_utils';
|
||||
import { uploadService } from '@web_editor/components/upload_progress_toast/upload_service';
|
||||
import { unsplashService } from '@web_unsplash/services/unsplash_service';
|
||||
import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
|
||||
import weTestUtils from 'web_editor.test_utils';
|
||||
import Wysiwyg from 'web_editor.wysiwyg';
|
||||
|
||||
const { useEffect } = owl;
|
||||
|
||||
QUnit.module('field html file upload', {
|
||||
beforeEach: function () {
|
||||
this.data = weTestUtils.wysiwygData({
|
||||
'mail.compose.message': {
|
||||
fields: {
|
||||
display_name: {
|
||||
string: "Displayed name",
|
||||
type: "char"
|
||||
},
|
||||
body: {
|
||||
string: "Message Body inline (to send)",
|
||||
type: "html"
|
||||
},
|
||||
attachment_ids: {
|
||||
string: "Attachments",
|
||||
type: "many2many",
|
||||
relation: "ir.attachment",
|
||||
}
|
||||
},
|
||||
records: [{
|
||||
id: 1,
|
||||
display_name: "Some Composer",
|
||||
body: "Hello",
|
||||
attachment_ids: [],
|
||||
}],
|
||||
},
|
||||
});
|
||||
},
|
||||
}, function () {
|
||||
QUnit.test('media dialog: upload', async function (assert) {
|
||||
assert.expect(4);
|
||||
const onAttachmentChangeTriggered = testUtils.makeTestPromise();
|
||||
patchWithCleanup(HtmlField.prototype, {
|
||||
'_onAttachmentChange': function (event) {
|
||||
this._super(event);
|
||||
onAttachmentChangeTriggered.resolve(true);
|
||||
}
|
||||
});
|
||||
const defFileSelector = testUtils.makeTestPromise();
|
||||
const onChangeTriggered = testUtils.makeTestPromise();
|
||||
patchWithCleanup(FileSelectorControlPanel.prototype, {
|
||||
setup() {
|
||||
this._super();
|
||||
useEffect(() => {
|
||||
defFileSelector.resolve(true);
|
||||
}, () => []);
|
||||
},
|
||||
async onChangeFileInput() {
|
||||
this._super();
|
||||
onChangeTriggered.resolve(true);
|
||||
}
|
||||
});
|
||||
// create and load form view
|
||||
const serviceRegistry = registry.category("services");
|
||||
serviceRegistry.add("upload", uploadService);
|
||||
serviceRegistry.add("unsplash", unsplashService);
|
||||
const serverData = {
|
||||
models: this.data,
|
||||
};
|
||||
serverData.actions = {
|
||||
1: {
|
||||
id: 1,
|
||||
name: "test",
|
||||
res_model: "mail.compose.message",
|
||||
type: "ir.actions.act_window",
|
||||
views: [[false, "form"]],
|
||||
},
|
||||
};
|
||||
serverData.views = {
|
||||
"mail.compose.message,false,search": "<search></search>",
|
||||
"mail.compose.message,false,form": `
|
||||
<form>
|
||||
<field name="body" type="html"/>
|
||||
<field name="attachment_ids" widget="many2many_binary"/>
|
||||
</form>`,
|
||||
};
|
||||
const mockRPC = (route, args) => {
|
||||
if (route === "/web_editor/attachment/add_data") {
|
||||
return Promise.resolve({"id": 5, "name": "test.jpg", "description": false, "mimetype": "image/jpeg", "checksum": "7951a43bbfb08fd742224ada280913d1897b89ab",
|
||||
"url": false, "type": "binary", "res_id": 1, "res_model": "note.note", "public": false, "access_token": false,
|
||||
"image_src": "/web/image/1-a0e63e61/test.jpg", "image_width": 1, "image_height": 1, "original_id": false
|
||||
});
|
||||
}
|
||||
else if (route === "/web/dataset/call_kw/ir.attachment/generate_access_token") {
|
||||
return Promise.resolve(["129a52e1-6bf2-470a-830e-8e368b022e13"]);
|
||||
}
|
||||
};
|
||||
const webClient = await createWebClient({ serverData, mockRPC });
|
||||
await doAction(webClient, 1);
|
||||
//trigger wysiwyg mediadialog
|
||||
const fixture = getFixture();
|
||||
const formField = fixture.querySelector('.o_field_html[name="body"]');
|
||||
const textInput = formField.querySelector('.note-editable p');
|
||||
textInput.innerText = "test";
|
||||
const pText = $(textInput).contents()[0];
|
||||
Wysiwyg.setRange(pText, 1, pText, 2);
|
||||
await new Promise((resolve) => setTimeout(resolve)); //ensure fully set up
|
||||
const wysiwyg = $(textInput.parentElement).data('wysiwyg');
|
||||
wysiwyg.openMediaDialog();
|
||||
assert.ok(await Promise.race([defFileSelector, new Promise((res, _) => setTimeout(() => res(false), 400))]), "File Selector did not mount");
|
||||
// upload test
|
||||
const fileInputs = document.querySelectorAll(".o_select_media_dialog input.d-none.o_file_input");
|
||||
const fileB64 = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigD//2Q==';
|
||||
const fileBytes = new Uint8Array(atob(fileB64).split('').map(char => char.charCodeAt(0)));
|
||||
// redefine 'files' so we can put mock data in through js
|
||||
fileInputs.forEach((input) => Object.defineProperty(input, 'files', {
|
||||
value: [new File(fileBytes, "test.jpg", { type: 'image/jpeg' })],
|
||||
}));
|
||||
fileInputs.forEach(input => {
|
||||
input.dispatchEvent(new Event('change', {}));
|
||||
});
|
||||
|
||||
assert.ok(await Promise.race([onChangeTriggered, new Promise((res, _) => setTimeout(() => res(false), 400))]),
|
||||
"File change event was not triggered");
|
||||
assert.ok(await Promise.race([onAttachmentChangeTriggered, new Promise((res, _) => setTimeout(() => res(false), 400))]),
|
||||
"_onAttachmentChange was not called with the new attachment, necessary for unsused upload cleanup on backend");
|
||||
|
||||
// wait to check that dom is properly updated
|
||||
await new Promise((res, _) => setTimeout(() => res(false), 400));
|
||||
assert.ok(fixture.querySelector('.o_attachment[title="test.jpg"]'));
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
odoo.define('test_website.custom_snippets', function (require) {
|
||||
'use strict';
|
||||
|
||||
const wTourUtils = require('website.tour_utils');
|
||||
import { insertSnippet, registerWebsitePreviewTour } from "@website/js/tours/tour_utils";
|
||||
|
||||
/**
|
||||
* The purpose of this tour is to check the custom snippets flow:
|
||||
|
|
@ -11,8 +8,8 @@ const wTourUtils = require('website.tour_utils');
|
|||
* -> customize banner (set text)
|
||||
* -> save banner as custom snippet
|
||||
* -> confirm save
|
||||
* -> ensure custom snippet is available
|
||||
* -> drag custom snippet
|
||||
* -> ensure custom snippet is available in the "add snippet" dialog
|
||||
* -> add custom snippet into the page
|
||||
* -> ensure block appears as banner
|
||||
* -> ensure block appears as custom banner
|
||||
* -> rename custom banner
|
||||
|
|
@ -22,87 +19,89 @@ const wTourUtils = require('website.tour_utils');
|
|||
* -> ensure it was deleted
|
||||
*/
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_custom_snippet', {
|
||||
registerWebsitePreviewTour('test_custom_snippet', {
|
||||
url: '/',
|
||||
edition: true,
|
||||
test: true,
|
||||
}, [
|
||||
}, () => [
|
||||
...insertSnippet({
|
||||
id: 's_banner',
|
||||
name: 'Banner',
|
||||
groupName: "Intro",
|
||||
}),
|
||||
{
|
||||
content: "drop a snippet",
|
||||
trigger: ".oe_snippet[name='Banner'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
moveTrigger: ".oe_drop_zone",
|
||||
run: "drag_and_drop iframe #wrap",
|
||||
content: "Customize snippet",
|
||||
trigger: ":iframe #wrapwrap .s_banner h1",
|
||||
run: "editor Test",
|
||||
},
|
||||
{
|
||||
content: "customize snippet",
|
||||
trigger: "iframe #wrapwrap .s_banner h1",
|
||||
run: "text",
|
||||
consumeEvent: "input",
|
||||
content: "Save custom snippet",
|
||||
trigger: "div[data-container-title='Banner'] .oe_snippet_save",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "save custom snippet",
|
||||
trigger: ".snippet-option-SnippetSave we-button",
|
||||
content: "Confirm reload",
|
||||
trigger: ".modal-dialog button:contains('Save')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "confirm reload",
|
||||
trigger: ".modal-dialog button span:contains('Save and Reload')",
|
||||
content: "Click on the block tab",
|
||||
trigger: ".o-snippets-tabs button[data-name='blocks']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure custom snippet appeared",
|
||||
trigger: "#oe_snippets.o_loaded .oe_snippet[name='Custom Banner']",
|
||||
run: function () {
|
||||
$("#oe_snippets .oe_snippet[name='Custom Banner'] .o_rename_btn").attr("style", "display: block;");
|
||||
// hover is needed for rename button to appear
|
||||
},
|
||||
content: "Click on the Custom category block",
|
||||
trigger: ".o_block_tab:not(.o_we_ongoing_insertion) #snippet_groups .o_snippet[name='Custom'].o_draggable .o_snippet_thumbnail .o_snippet_thumbnail_area",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "rename custom snippet",
|
||||
trigger: ".oe_snippet[name='Custom Banner'] we-button.o_rename_btn",
|
||||
extra_trigger: ".oe_snippet[name='Custom Banner'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
content: "Ensure custom snippet preview appeared in the dialog",
|
||||
trigger: ":iframe .o_snippet_preview_wrap[data-snippet-id^='s_banner_'] section[data-name='Custom Banner']",
|
||||
},
|
||||
{
|
||||
content: "set name",
|
||||
trigger: ".oe_snippet[name='Custom Banner'] input",
|
||||
run: "text Bruce Banner",
|
||||
content: "Rename custom snippet",
|
||||
trigger: ":iframe .o_custom_snippet_edit > button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "confirm rename",
|
||||
trigger: ".oe_snippet[name='Custom Banner'] we-button.o_we_confirm_btn",
|
||||
content: "Set name",
|
||||
trigger: ".modal-dialog:not(.o_inactive_modal body) input[id='inputConfirmation']",
|
||||
run: "edit Bruce Banner",
|
||||
},
|
||||
{
|
||||
content: "drop custom snippet",
|
||||
trigger: ".oe_snippet[name='Bruce Banner'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
extra_trigger: "iframe body.editor_enable",
|
||||
moveTrigger: ".oe_drop_zone",
|
||||
run: "drag_and_drop iframe #wrap",
|
||||
content: "Confirm rename",
|
||||
trigger: ".modal-dialog:not(.o_inactive_modal body) footer .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure banner section exists",
|
||||
trigger: "iframe #wrap section[data-name='Banner']",
|
||||
run: function () {}, // check
|
||||
content: "Click on the 'Bruce Banner' snippet",
|
||||
trigger: ":iframe .o_snippet_preview_wrap[data-snippet-id^='s_banner_']:has(section[data-name='Bruce Banner'])",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure custom banner section exists",
|
||||
trigger: "iframe #wrap section[data-name='Bruce Banner']",
|
||||
run: function () {
|
||||
$("#oe_snippets .oe_snippet[name='Bruce Banner'] .o_delete_btn").attr("style", "display: block;");
|
||||
// hover is needed for delete button to appear
|
||||
},
|
||||
content: "Ensure banner section exists",
|
||||
trigger: ":iframe #wrap section[data-name='Banner']",
|
||||
},
|
||||
{
|
||||
content: "delete custom snippet",
|
||||
trigger: ".oe_snippet[name='Bruce Banner'] we-button.o_delete_btn",
|
||||
extra_trigger: ".oe_snippet[name='Bruce Banner'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
content: "Ensure custom banner section exists",
|
||||
trigger: ":iframe #wrap section[data-name='Bruce Banner']",
|
||||
},
|
||||
{
|
||||
content: "confirm delete",
|
||||
trigger: ".modal-dialog button:has(span:contains('Yes'))",
|
||||
content: "Click on the Custom category block",
|
||||
trigger: ".o_block_tab:not(.o_we_ongoing_insertion) #snippet_groups .o_snippet[name='Custom'].o_draggable .o_snippet_thumbnail .o_snippet_thumbnail_area",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure custom snippet disappeared",
|
||||
trigger: "#oe_snippets:not(:has(.oe_snippet[name='Bruce Banner']))",
|
||||
run: function () {}, // check
|
||||
content: "Delete custom snippet",
|
||||
trigger: ":iframe .o_custom_snippet_edit > button + button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Confirm delete",
|
||||
trigger: ".modal-dialog button:contains('Yes')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Ensure custom snippet disappeared",
|
||||
trigger: ":iframe .o_add_snippets_preview:not(:has(section[data-name='Bruce Banner']))",
|
||||
},
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,56 +1,81 @@
|
|||
odoo.define('test_website.error_views', function (require) {
|
||||
'use strict';
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
|
||||
tour.register('test_error_website', {
|
||||
test: true,
|
||||
registry.category("web_tour.tours").add('test_error_website', {
|
||||
url: '/test_error_view',
|
||||
},
|
||||
[
|
||||
steps: () => [
|
||||
// RPC ERROR
|
||||
{
|
||||
content: "trigger rpc user error",
|
||||
trigger: 'a[href="/test_user_error_json"]',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_notification:contains("This is a user rpc test")',
|
||||
},
|
||||
{
|
||||
content: "rpc user error modal has message",
|
||||
extra_trigger: 'div.o_notification_content:contains("This is a user rpc test")',
|
||||
trigger: 'button.o_notification_close',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "trigger rpc access error",
|
||||
trigger: 'a[href="/test_access_error_json"]',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_notification:contains("This is an access rpc test")',
|
||||
},
|
||||
{
|
||||
content: "rpc access error modal has message",
|
||||
extra_trigger: 'div.o_notification_content:contains("This is an access rpc test")',
|
||||
trigger: 'button.o_notification_close',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "trigger validation rpc error",
|
||||
trigger: 'a[href="/test_validation_error_json"]',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_notification:contains("This is a validation rpc test")',
|
||||
},
|
||||
{
|
||||
content: "rpc validation error modal has message",
|
||||
extra_trigger: 'div.o_notification_content:contains("This is a validation rpc test")',
|
||||
trigger: 'button.o_notification_close',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "trigger rpc missing error",
|
||||
trigger: 'a[href="/test_missing_error_json"]',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_notification:contains("This is a missing rpc test")',
|
||||
},
|
||||
{
|
||||
content: "rpc missing error modal has message",
|
||||
extra_trigger: 'div.o_notification_content:contains("This is a missing rpc test")',
|
||||
trigger: 'button.o_notification_close',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "trigger rpc error 403",
|
||||
trigger: 'a[href="/test_access_denied_json"]',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_notification:contains("This is an access denied rpc test")',
|
||||
},
|
||||
{
|
||||
content: "rpc error 403 modal has message",
|
||||
extra_trigger: 'div.o_notification_content:contains("This is an access denied rpc test")',
|
||||
trigger: 'button.o_notification_close',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "trigger rpc error 500",
|
||||
trigger: 'a[href="/test_internal_error_json"]',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div.o_error_dialog.modal-content",
|
||||
},
|
||||
{
|
||||
content: "rpc error 500 modal is an ErrorDialog",
|
||||
extra_trigger: 'div.o_dialog_error.modal-content div.alert.alert-warning',
|
||||
trigger: '.modal-footer button.btn.btn-primary',
|
||||
run: "click",
|
||||
},
|
||||
// HTTP ERROR
|
||||
{
|
||||
|
|
@ -59,94 +84,139 @@ tour.register('test_error_website', {
|
|||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_user_error_http?debug=0';
|
||||
},
|
||||
}, {
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("Something went wrong.")',
|
||||
},
|
||||
{
|
||||
content: "http user error page has title and message",
|
||||
extra_trigger: 'h1:contains("Something went wrong.")',
|
||||
trigger: 'div.container pre:contains("This is a user http test")',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_user_error_http?debug=1';
|
||||
},
|
||||
}, {
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("Something went wrong.")',
|
||||
},
|
||||
{
|
||||
content: "http user error page debug has title and message open",
|
||||
extra_trigger: 'h1:contains("Something went wrong.")',
|
||||
trigger: 'div#error_main.collapse.show pre:contains("This is a user http test")',
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "http user error page debug has traceback closed",
|
||||
trigger: 'body:has(div#error_traceback.collapse:not(.show) pre#exception_traceback)',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_validation_error_http?debug=0';
|
||||
},
|
||||
}, {
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("Something went wrong.")',
|
||||
},
|
||||
{
|
||||
content: "http validation error page has title and message",
|
||||
extra_trigger: 'h1:contains("Something went wrong.")',
|
||||
trigger: 'div.container pre:contains("This is a validation http test")',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_validation_error_http?debug=1';
|
||||
},
|
||||
}, {
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("Something went wrong.")',
|
||||
},
|
||||
{
|
||||
content: "http validation error page debug has title and message open",
|
||||
extra_trigger: 'h1:contains("Something went wrong.")',
|
||||
trigger: 'div#error_main.collapse.show pre:contains("This is a validation http test")',
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "http validation error page debug has traceback closed",
|
||||
trigger: 'body:has(div#error_traceback.collapse:not(.show) pre#exception_traceback)',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_access_error_http?debug=0';
|
||||
},
|
||||
}, {
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("403: Forbidden")',
|
||||
},
|
||||
{
|
||||
content: "http access error page has title and message",
|
||||
extra_trigger: 'h1:contains("403: Forbidden")',
|
||||
trigger: 'div.container pre:contains("This is an access http test")',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_access_error_http?debug=1';
|
||||
},
|
||||
}, {
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("403: Forbidden")',
|
||||
},
|
||||
{
|
||||
content: "http access error page debug has title and message open",
|
||||
extra_trigger: 'h1:contains("403: Forbidden")',
|
||||
trigger: 'div#error_main.collapse.show pre:contains("This is an access http test")',
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "http access error page debug has traceback closed",
|
||||
trigger: 'body:has(div#error_traceback.collapse:not(.show) pre#exception_traceback)',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_view_access_error?debug=0';
|
||||
},
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("403: Forbidden")',
|
||||
},
|
||||
{
|
||||
content: "http access error page has title and message",
|
||||
trigger: 'div.container pre:contains("Uh-oh! Looks like you have stumbled upon some top-secret records.")',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_view_access_error?debug=1';
|
||||
},
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("403: Forbidden")',
|
||||
},
|
||||
{
|
||||
content: "http access error page debug has title and message open",
|
||||
trigger: 'div#error_main.collapse.show pre:contains("Uh-oh! Looks like you have stumbled upon some top-secret records.")',
|
||||
}, {
|
||||
content: "http access error page debug has traceback closed",
|
||||
trigger: 'body:has(div#error_traceback.collapse:not(.show) pre#exception_traceback)',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_missing_error_http?debug=0';
|
||||
},
|
||||
}, {
|
||||
content: "http missing error page has title and message",
|
||||
extra_trigger: 'h1:contains("Something went wrong.")',
|
||||
trigger: 'div.container pre:contains("This is a missing http test")',
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("Error 404")',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_missing_error_http?debug=1';
|
||||
},
|
||||
}, {
|
||||
content: "http missing error page debug has title and message open",
|
||||
extra_trigger: 'h1:contains("Something went wrong.")',
|
||||
trigger: 'div#error_main.collapse.show pre:contains("This is a missing http test")',
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "http missing error page debug has traceback closed",
|
||||
trigger: 'body:has(div#error_traceback.collapse:not(.show) pre#exception_traceback)',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_access_denied_http?debug=0';
|
||||
},
|
||||
}, {
|
||||
content: "http error 403 page has title but no message",
|
||||
extra_trigger: 'h1:contains("403: Forbidden")',
|
||||
trigger: 'div#wrap:not(:has(pre:contains("This is an access denied http test"))', //See ir_http.py handle_exception, the exception is replaced so there is no message !
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("Error 404")',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_access_denied_http?debug=1';
|
||||
},
|
||||
}, {
|
||||
content: "http 403 error page debug has title but no message",
|
||||
extra_trigger: 'h1:contains("403: Forbidden")',
|
||||
trigger: 'div#debug_infos:not(:has(#error_main))',
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "http 403 error page debug has traceback open",
|
||||
trigger: 'body:has(div#error_traceback.collapse.show pre#exception_traceback)',
|
||||
run: function () {},
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
{
|
||||
trigger: 'h1:contains("403: Forbidden")',
|
||||
},
|
||||
{
|
||||
content: "http error 403 page has title but no message",
|
||||
// See http.py _transactionning, the exception is replaced so there is no message !
|
||||
trigger: 'div#wrap:not(:has(pre:contains("Traceback"))',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_access_denied_http?debug=1';
|
||||
},
|
||||
expectUnloadPage: true,
|
||||
},
|
||||
{
|
||||
trigger: 'h1:contains("403: Forbidden")',
|
||||
},
|
||||
{
|
||||
content: "http 403 error page debug has title but no message",
|
||||
trigger: 'div#wrap:not(:has(pre:contains("Traceback"))',
|
||||
},
|
||||
]});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
import {
|
||||
clickOnEditAndWaitEditMode,
|
||||
clickOnSave,
|
||||
registerWebsitePreviewTour,
|
||||
changeOptionInPopover,
|
||||
} from "@website/js/tours/tour_utils";
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"test_form_conditional_visibility_record_field",
|
||||
{
|
||||
url: "/test_website/model_item/1",
|
||||
edition: true,
|
||||
},
|
||||
() => [
|
||||
{
|
||||
content: "Select name field",
|
||||
trigger: ":iframe .s_website_form .s_website_form_input[name=name]",
|
||||
run: "click",
|
||||
},
|
||||
...changeOptionInPopover("Field", "Visibility", "Visible only if"),
|
||||
{
|
||||
content: "Open model selector",
|
||||
trigger: "button[id='hidden_condition_record_opt']:contains('Test Tag')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Set model to tag #2",
|
||||
trigger: ".o_popover div.o-dropdown-item:contains('Test Tag #2')",
|
||||
run: "click",
|
||||
},
|
||||
...clickOnSave(),
|
||||
{
|
||||
content: "Name field is hidden",
|
||||
trigger: ":iframe .s_website_form:has(.s_website_form_field_hidden_if.d-none)",
|
||||
},
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
|
||||
{
|
||||
content: "Select name field",
|
||||
trigger: ":iframe .s_website_form .s_website_form_input[name=name]",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open comparator dropdown",
|
||||
trigger: "button[id='hidden_condition_record_opt']:contains('Is equal to')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Set comparator to Is not equal",
|
||||
trigger: ".o_popover div.o-dropdown-item:contains('Is not equal to')",
|
||||
run: "click",
|
||||
},
|
||||
...clickOnSave(),
|
||||
{
|
||||
content: "Name field is shown",
|
||||
trigger: ":iframe .s_website_form:has(.s_website_form_field_hidden_if:not(.d-none))",
|
||||
},
|
||||
],
|
||||
);
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import wTourUtils from 'website.tour_utils';
|
||||
import { insertSnippet, registerWebsitePreviewTour } from '@website/js/tours/tour_utils';
|
||||
|
||||
/**
|
||||
* The purpose of this tour is to check the link on image flow.
|
||||
|
|
@ -8,78 +6,81 @@ import wTourUtils from 'website.tour_utils';
|
|||
|
||||
const selectImageSteps = [{
|
||||
content: "select block",
|
||||
trigger: "iframe #wrapwrap .s_text_image",
|
||||
trigger: ":iframe #wrapwrap .s_text_image",
|
||||
async run(helpers) {
|
||||
await helpers.click();
|
||||
const el = this.anchor;
|
||||
const sel = el.ownerDocument.getSelection();
|
||||
sel.collapse(el, 0);
|
||||
el.focus();
|
||||
},
|
||||
}, {
|
||||
content: "check link popover disappeared",
|
||||
trigger: "iframe body:not(:has(.o_edit_menu_popover))",
|
||||
run: () => {}, // check
|
||||
trigger: ":iframe body:not(:has(.o_edit_menu_popover))",
|
||||
}, {
|
||||
content: "select image",
|
||||
trigger: "iframe #wrapwrap .s_text_image img",
|
||||
trigger: ":iframe #wrapwrap .s_text_image img",
|
||||
run: "click",
|
||||
}];
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_image_link', {
|
||||
test: true,
|
||||
registerWebsitePreviewTour('test_image_link', {
|
||||
url: '/',
|
||||
edition: true,
|
||||
}, [
|
||||
wTourUtils.dragNDrop({
|
||||
}, () => [
|
||||
...insertSnippet({
|
||||
id: 's_text_image',
|
||||
name: 'Text - Image',
|
||||
groupName: "Content",
|
||||
}),
|
||||
...selectImageSteps,
|
||||
{
|
||||
content: "enable link",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-customizeblock-option:has(we-title:contains(Media)) we-button.fa-link",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] button[data-action-id='setLink']",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "enter site URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "text odoo.com",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] div[data-action-id='setUrl'] input",
|
||||
run: "edit odoo.com && click body",
|
||||
},
|
||||
...selectImageSteps,
|
||||
{
|
||||
content: "check popover content has site URL",
|
||||
trigger: "iframe .o_edit_menu_popover a.o_we_url_link[href='http://odoo.com/']:contains(http://odoo.com/)",
|
||||
run: () => {}, // check
|
||||
trigger: ".o-we-linkpopover a.o_we_url_link[href='http://odoo.com']:contains(http://odoo.com)",
|
||||
}, {
|
||||
content: "remove URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "remove_text",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] div[data-action-id='setUrl'] input",
|
||||
run: "clear && click body",
|
||||
},
|
||||
...selectImageSteps,
|
||||
{
|
||||
content: "check popover content has no URL",
|
||||
trigger: "iframe .o_edit_menu_popover a.o_we_url_link:not([href]):contains(No URL specified)",
|
||||
run: () => {}, // check
|
||||
trigger: ".o-we-linkpopover .o_we_href_input_link:value()",
|
||||
}, {
|
||||
content: "enter email URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "text mailto:test@test.com",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] div[data-action-id='setUrl'] input",
|
||||
run: "edit mailto:test@test.com && click body",
|
||||
},
|
||||
...selectImageSteps,
|
||||
{
|
||||
content: "check popover content has mail URL",
|
||||
trigger: "iframe .o_edit_menu_popover:has(.fa-envelope-o) a.o_we_url_link[href='mailto:test@test.com']:contains(mailto:test@test.com)",
|
||||
run: () => {}, // check
|
||||
trigger: ".o-we-linkpopover:has(.fa-envelope-o) a.o_we_url_link[href='mailto:test@test.com']:contains(mailto:test@test.com)",
|
||||
}, {
|
||||
content: "enter phone URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "text tel:555-2368",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] div[data-action-id='setUrl'] input",
|
||||
run: "edit tel:555-2368 && click body",
|
||||
},
|
||||
...selectImageSteps,
|
||||
{
|
||||
content: "check popover content has phone URL",
|
||||
trigger: "iframe .o_edit_menu_popover:has(.fa-phone) a.o_we_url_link[href='tel:555-2368']:contains(tel:555-2368)",
|
||||
run: () => {}, // check
|
||||
trigger: ".o-we-linkpopover:has(.fa-phone) a.o_we_url_link[href='tel:555-2368']:contains(tel:555-2368)",
|
||||
}, {
|
||||
content: "remove URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "remove_text",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] div[data-action-id='setUrl'] input",
|
||||
run: "clear && click body",
|
||||
},
|
||||
...selectImageSteps,
|
||||
{
|
||||
content: "check popover content has no URL",
|
||||
trigger: "iframe .o_edit_menu_popover a.o_we_url_link:not([href]):contains(No URL specified)",
|
||||
run: () => {}, // check
|
||||
trigger: ".o-we-linkpopover .o_we_href_input_link:value()",
|
||||
},
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
odoo.define('test_website.image_upload_progress', function (require) {
|
||||
'use strict';
|
||||
import { insertSnippet, registerWebsitePreviewTour } from "@website/js/tours/tour_utils";
|
||||
|
||||
const wTourUtils = require('website.tour_utils');
|
||||
|
||||
const { FileSelectorControlPanel } = require('@web_editor/components/media_dialog/file_selector');
|
||||
const { patch, unpatch } = require('web.utils');
|
||||
import { FileSelectorControlPanel } from "@html_editor/main/media/media_dialog/file_selector";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
let patchWithError = false;
|
||||
const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, 'test_website.mock_image_widgets', {
|
||||
const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, {
|
||||
async onChangeFileInput() {
|
||||
const getFileFromB64 = (fileData) => {
|
||||
const binary = atob(fileData[2]);
|
||||
|
|
@ -37,46 +34,50 @@ const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, 'test_w
|
|||
}
|
||||
});
|
||||
|
||||
const unpatchMediaDialog = () => unpatch(FileSelectorControlPanel.prototype, 'test_website.mock_image_widgets');
|
||||
let unpatchMediaDialog = null;
|
||||
|
||||
const setupSteps = [{
|
||||
content: "reload to load patch",
|
||||
trigger: ".o_website_preview",
|
||||
run: () => {
|
||||
patchMediaDialog();
|
||||
},
|
||||
}, {
|
||||
content: "drop a snippet",
|
||||
trigger: "#oe_snippets .oe_snippet[name='Text - Image'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
moveTrigger: "iframe .oe_drop_zone",
|
||||
run: "drag_and_drop iframe #wrap",
|
||||
}, {
|
||||
content: "drop a snippet",
|
||||
trigger: "#oe_snippets .oe_snippet[name='Image Gallery'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
extra_trigger: "body.editor_has_snippets",
|
||||
moveTrigger: ".oe_drop_zone",
|
||||
run: "drag_and_drop iframe #wrap",
|
||||
}];
|
||||
const setupSteps = function () {
|
||||
return [
|
||||
{
|
||||
content: "reload to load patch",
|
||||
trigger: ".o_website_preview",
|
||||
run() {
|
||||
unpatchMediaDialog = patchMediaDialog();
|
||||
},
|
||||
},
|
||||
...insertSnippet({
|
||||
id: "s_text_image",
|
||||
name: "Text - Image",
|
||||
groupName: "Content",
|
||||
}),
|
||||
...insertSnippet({
|
||||
id: "s_image_gallery",
|
||||
name: "Image Gallery",
|
||||
groupName: "Images",
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
const formatErrorMsg = "format is not supported. Try with: .gif, .jpe, .jpeg, .jpg, .png, .svg";
|
||||
const formatErrorMsg = "format is not supported. Try with: .gif, .jpe, .jpeg, .jpg, .png, .svg, .webp";
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_image_upload_progress', {
|
||||
registerWebsitePreviewTour('test_image_upload_progress', {
|
||||
url: '/test_image_progress',
|
||||
test: true,
|
||||
edition: true,
|
||||
}, [
|
||||
...setupSteps,
|
||||
}, () => [
|
||||
...setupSteps(),
|
||||
// 1. Check multi image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_image_gallery .img",
|
||||
trigger: ":iframe #wrap .s_image_gallery .img",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "click on add images to open image dialog (in multi mode)",
|
||||
trigger: 'we-customizeblock-option [data-add-images]',
|
||||
trigger: "button[data-action-id='addImage']",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "manually trigger input change",
|
||||
trigger: ".o_select_media_dialog .o_upload_media_button",
|
||||
run: () => {
|
||||
run() {
|
||||
// This will trigger upload of dummy files for test purpose, as a
|
||||
// test can't select local files to upload into the input.
|
||||
document.body.querySelector('.o_select_media_dialog .o_file_input').dispatchEvent(new Event('change'));
|
||||
|
|
@ -84,52 +85,50 @@ wTourUtils.registerWebsitePreviewTour('test_image_upload_progress', {
|
|||
}, {
|
||||
content: "check upload progress bar is correctly shown (1)",
|
||||
trigger: `.o_we_progressbar:contains('icon.ico'):contains('${formatErrorMsg}')`,
|
||||
in_modal: false,
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check upload progress bar is correctly shown (2)",
|
||||
trigger: `.o_we_progressbar:contains('image.webp'):contains('${formatErrorMsg}')`,
|
||||
in_modal: false,
|
||||
run: function () {}, // it's a check
|
||||
trigger: ".o_we_progressbar:contains('image.webp'):contains('File has been uploaded')",
|
||||
}, {
|
||||
content: "check upload progress bar is correctly shown (3)",
|
||||
trigger: ".o_we_progressbar:contains('image.png'):contains('File has been uploaded')",
|
||||
in_modal: false,
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "check upload progress bar is correctly shown (4)",
|
||||
trigger: ".o_we_progressbar:contains('image.jpeg'):contains('File has been uploaded')",
|
||||
in_modal: false,
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "there should only have one notification toaster",
|
||||
},
|
||||
{
|
||||
trigger: ".o_notification",
|
||||
in_modal: false,
|
||||
run: () => {
|
||||
const notificationCount = $('.o_notification').length;
|
||||
},
|
||||
{
|
||||
content: "there should only have one notification toaster",
|
||||
trigger: "body",
|
||||
run() {
|
||||
const notificationCount = document.querySelectorAll(".o_notification").length;
|
||||
if (notificationCount !== 1) {
|
||||
console.error("There should be one noficiation toaster opened, and only one.");
|
||||
throw new Error(`There should be one notification toaster opened, and only one, found ${notificationCount}.`);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
content: "close notification",
|
||||
trigger: '.o_notification_close',
|
||||
in_modal: false,
|
||||
run: "click",
|
||||
}, {
|
||||
content: "close media dialog",
|
||||
trigger: '.modal-footer .btn-secondary',
|
||||
run: "click",
|
||||
},
|
||||
// 2. Check success single image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_text_image .img",
|
||||
trigger: ":iframe #wrap .s_text_image .img",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "click on replace media to open image dialog",
|
||||
trigger: 'we-customizeblock-option [data-replace-media]',
|
||||
trigger: "button[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "manually trigger input change",
|
||||
trigger: ".o_select_media_dialog .o_upload_media_button",
|
||||
run: () => {
|
||||
run() {
|
||||
// This will trigger upload of dummy files for test purpose, as a
|
||||
// test can't select local files to upload into the input.
|
||||
document.body.querySelector('.o_select_media_dialog .o_file_input').dispatchEvent(new Event('change'));
|
||||
|
|
@ -137,43 +136,38 @@ wTourUtils.registerWebsitePreviewTour('test_image_upload_progress', {
|
|||
}, {
|
||||
content: "check upload progress bar is correctly shown",
|
||||
trigger: ".o_we_progressbar:contains('image.png')",
|
||||
in_modal: false,
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "there should only have one notification toaster",
|
||||
trigger: ".o_notification",
|
||||
in_modal: false,
|
||||
run: () => {
|
||||
const notificationCount = $('.o_notification').length;
|
||||
run() {
|
||||
const notificationCount = document.querySelectorAll(".o_notification").length;
|
||||
if (notificationCount !== 1) {
|
||||
console.error("There should be one noficiation toaster opened, and only one.");
|
||||
throw new Error(`There should be one notification toaster opened, and only one, found ${notificationCount}.`);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
content: "media dialog has closed after the upload",
|
||||
trigger: 'body:not(:has(.o_select_media_dialog))',
|
||||
run: () => {}, // It's a check.
|
||||
}, {
|
||||
content: "the upload progress toast was updated",
|
||||
trigger: ".o_we_progressbar:contains('image.png'):contains('File has been uploaded')",
|
||||
run: () => {}, // It's a check.
|
||||
}, {
|
||||
content: "toaster should disappear after a few seconds if the uploaded image is successful",
|
||||
trigger: "body:not(:has(.o_we_progressbar))",
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
// 3. Check error single image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_text_image .img",
|
||||
trigger: ":iframe #wrap .s_text_image .img",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "click on replace media to open image dialog",
|
||||
trigger: 'we-customizeblock-option [data-replace-media]',
|
||||
trigger: "button[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "manually trigger input change",
|
||||
trigger: ".o_select_media_dialog .o_upload_media_button",
|
||||
in_modal: false,
|
||||
run: () => {
|
||||
run() {
|
||||
patchWithError = true;
|
||||
// This will trigger upload of dummy files for test purpose, as a
|
||||
// test can't select local files to upload into the input.
|
||||
|
|
@ -183,18 +177,16 @@ wTourUtils.registerWebsitePreviewTour('test_image_upload_progress', {
|
|||
}, {
|
||||
content: "check upload progress bar is correctly shown",
|
||||
trigger: `.o_we_progressbar:contains('icon.ico'):contains('${formatErrorMsg}')`,
|
||||
in_modal: false,
|
||||
run: function () {
|
||||
run() {
|
||||
patchWithError = false;
|
||||
},
|
||||
}, {
|
||||
content: "there should only have one notification toaster",
|
||||
trigger: ".o_notification",
|
||||
in_modal: false,
|
||||
run: () => {
|
||||
const notificationCount = $('.o_notification').length;
|
||||
run() {
|
||||
const notificationCount = document.querySelectorAll(".o_notification").length;
|
||||
if (notificationCount !== 1) {
|
||||
console.error("There should be one noficiation toaster opened, and only one.");
|
||||
throw new Error(`There should be one noficiation toaster opened, and only one, found ${notificationCount}.`);
|
||||
}
|
||||
unpatchMediaDialog();
|
||||
}
|
||||
|
|
@ -202,44 +194,45 @@ wTourUtils.registerWebsitePreviewTour('test_image_upload_progress', {
|
|||
]);
|
||||
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_image_upload_progress_unsplash', {
|
||||
registerWebsitePreviewTour('test_image_upload_progress_unsplash', {
|
||||
url: '/test_image_progress',
|
||||
test: true,
|
||||
edition: true,
|
||||
}, [
|
||||
...setupSteps,
|
||||
}, () => [
|
||||
...setupSteps(),
|
||||
// 1. Check multi image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_image_gallery .img",
|
||||
trigger: ":iframe #wrap .s_image_gallery .img",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "click on replace media to open image dialog",
|
||||
trigger: 'we-customizeblock-option [data-replace-media]',
|
||||
trigger: "button[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "search 'fox' images",
|
||||
trigger: ".o_we_search",
|
||||
run: "text fox",
|
||||
run: "edit fox",
|
||||
}, {
|
||||
content: "click on unsplash result", // note that unsplash is mocked
|
||||
trigger: "img[alt~=fox]"
|
||||
}, {
|
||||
trigger: ".o_we_media_dialog_img_wrapper:has(img[alt~=fox]) + .o_button_area",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_notification_close",
|
||||
},
|
||||
{
|
||||
content: "check that the upload progress bar is correctly shown",
|
||||
// ensure it is there so we are sure next step actually test something
|
||||
extra_trigger: '.o_notification_close',
|
||||
trigger: ".o_we_progressbar:contains('fox'):contains('File has been uploaded')",
|
||||
in_modal: false,
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "notification should close after 3 seconds",
|
||||
trigger: 'body:not(:has(.o_notification_close))',
|
||||
in_modal: false,
|
||||
run: "click",
|
||||
}, {
|
||||
content: "unsplash image (mocked to logo) should have been used",
|
||||
trigger: "iframe #wrap .s_image_gallery .img[data-original-src^='/unsplash/HQqIOc8oYro/fox']",
|
||||
run: () => {
|
||||
trigger: ":iframe #wrap .s_image_gallery img[data-original-src^='/unsplash/HQqIOc8oYro/fox']",
|
||||
run() {
|
||||
unpatchMediaDialog();
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
odoo.define('test_website.json_auth', function (require) {
|
||||
'use strict';
|
||||
import { registry } from "@web/core/registry";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
var session = require('web.session')
|
||||
|
||||
tour.register('test_json_auth', {
|
||||
test: true,
|
||||
}, [{
|
||||
registry.category("web_tour.tours").add('test_json_auth', {
|
||||
steps: () => [{
|
||||
trigger: 'body',
|
||||
run: async function () {
|
||||
await session.rpc('/test_get_dbname').then( function (result){
|
||||
return session.rpc("/web/session/authenticate", {
|
||||
await rpc('/test_get_dbname').then( function (result){
|
||||
return rpc("/web/session/authenticate", {
|
||||
db: result,
|
||||
login: 'admin',
|
||||
password: 'admin'
|
||||
|
|
@ -18,9 +14,8 @@ tour.register('test_json_auth', {
|
|||
});
|
||||
window.location.href = window.location.origin;
|
||||
},
|
||||
expectUnloadPage: true,
|
||||
}, {
|
||||
trigger: 'span:contains(Mitchell Admin), span:contains(Administrator)',
|
||||
run: function () {},
|
||||
}
|
||||
]);
|
||||
});
|
||||
]});
|
||||
|
|
|
|||
|
|
@ -1,77 +1,87 @@
|
|||
/** @odoo-module **/
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
tour.register('test_website_page_manager', {
|
||||
test: true,
|
||||
url: '/web#action=test_website.action_test_model_multi_website',
|
||||
}, [
|
||||
registry.category("web_tour.tours").add('test_website_page_manager', {
|
||||
url: '/odoo/action-test_website.action_test_model_multi_website',
|
||||
steps: () => [
|
||||
// Part 1: check that the website filter is working
|
||||
{
|
||||
content: "Check that we see records from My Website",
|
||||
trigger: ".o_list_table .o_data_row .o_data_cell[name=name]:contains('Test Multi Model Website 1') " +
|
||||
"~ .o_data_cell[name=website_id]:contains('My Website')",
|
||||
run: () => null, // it's a check
|
||||
}, {
|
||||
content: "Check that there is only 2 records in the pager",
|
||||
trigger: ".o_pager .o_pager_value:contains('1-2')",
|
||||
run: () => null, // it's a check
|
||||
}, {
|
||||
content: "Click on the 'Select all records' checkbox",
|
||||
trigger: "thead .o_list_record_selector",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Check that there is only 2 records selected",
|
||||
trigger: ".o_list_selection_box:contains('2 selected')",
|
||||
run: () => null, // it's a check
|
||||
trigger: ".o_selection_box:contains(2):contains(selected)",
|
||||
}, {
|
||||
content: "Click on My Website search filter",
|
||||
trigger: "button.dropdown-toggle:contains('My Website')",
|
||||
content: "Click on the 'Select all records' checkbox again to unselect all records and see the search bar",
|
||||
trigger: "thead .o_list_record_selector",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Select My Website 2",
|
||||
trigger: ".dropdown-menu.show > .dropdown-item:contains('My Website 2')",
|
||||
content: "Click on the search options",
|
||||
trigger: ".o_searchview_dropdown_toggler",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Remove 'My Website' filter",
|
||||
trigger: ".o_filter_menu .o-dropdown-item:contains('My Website')",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Select 'My Website 2' filter",
|
||||
trigger: ".o_filter_menu .o-dropdown-item:contains('My Website 2')",
|
||||
run: "click",
|
||||
}, {
|
||||
// This step is just here to ensure there is more records than the 2
|
||||
// available on website 1, to ensure the test is actually testing something.
|
||||
content: "Check that we see records from My Website 2",
|
||||
trigger: ".o_list_table .o_data_row .o_data_cell[name=name]:contains('Test Model Multi Website 2') " +
|
||||
"~ .o_data_cell[name=website_id]:contains('My Website 2')",
|
||||
run: () => null, // it's a check
|
||||
},
|
||||
// Part 2: ensure Kanban View is working / not crashing
|
||||
{
|
||||
content: "Click on Kanban View",
|
||||
trigger: '.o_cp_switch_buttons .o_kanban',
|
||||
}, {
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_kanban_renderer",
|
||||
},
|
||||
{
|
||||
content: "Click on List View",
|
||||
extra_trigger: '.o_kanban_renderer',
|
||||
trigger: '.o_cp_switch_buttons .o_list',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Wait for List View to be loaded",
|
||||
trigger: '.o_list_renderer',
|
||||
run: () => null, // it's a check
|
||||
}]);
|
||||
}]
|
||||
});
|
||||
|
||||
tour.register('test_website_page_manager_js_class_bug', {
|
||||
test: true,
|
||||
url: '/web#action=test_website.action_test_model_multi_website_js_class_bug',
|
||||
}, [{
|
||||
registry.category("web_tour.tours").add('test_website_page_manager_js_class_bug', {
|
||||
url: '/odoo/action-test_website.action_test_model_multi_website_js_class_bug',
|
||||
steps: () => [
|
||||
{
|
||||
content: "Click on Kanban View",
|
||||
trigger: '.o_cp_switch_buttons .o_kanban',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Wait for Kanban View to be loaded",
|
||||
trigger: '.o_kanban_renderer',
|
||||
run: () => null, // it's a check
|
||||
}]);
|
||||
}]
|
||||
});
|
||||
|
||||
tour.register('test_website_page_manager_no_website_id', {
|
||||
test: true,
|
||||
url: '/web#action=test_website.action_test_model',
|
||||
}, [{
|
||||
registry.category("web_tour.tours").add('test_website_page_manager_no_website_id', {
|
||||
url: '/odoo/action-test_website.action_test_model',
|
||||
steps: () => [
|
||||
{
|
||||
content: "Click on Kanban View",
|
||||
trigger: '.o_cp_switch_buttons .o_kanban',
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Wait for Kanban View to be loaded",
|
||||
trigger: '.o_kanban_renderer',
|
||||
run: () => null, // it's a check
|
||||
}]);
|
||||
|
||||
}]
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { patch } from '@web/core/utils/patch';
|
||||
import { VideoSelector } from '@web_editor/components/media_dialog/video_selector';
|
||||
import wTourUtils from 'website.tour_utils';
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { VideoSelector } from "@html_editor/main/media/media_dialog/video_selector";
|
||||
import {
|
||||
changeOption,
|
||||
insertSnippet,
|
||||
registerWebsitePreviewTour,
|
||||
} from '@website/js/tours/tour_utils';
|
||||
|
||||
const VIDEO_URL = 'https://www.youtube.com/watch?v=Dpq87YCHmJc';
|
||||
|
||||
/**
|
||||
* The purpose of this tour is to check the media replacement flow.
|
||||
*/
|
||||
wTourUtils.registerWebsitePreviewTour('test_replace_media', {
|
||||
registerWebsitePreviewTour('test_replace_media', {
|
||||
url: '/',
|
||||
test: true,
|
||||
edition: true,
|
||||
}, [
|
||||
}, () => [
|
||||
{
|
||||
trigger: "body",
|
||||
run: function () {
|
||||
|
|
@ -23,138 +24,148 @@ wTourUtils.registerWebsitePreviewTour('test_replace_media', {
|
|||
// specific to an URL only, it is acceptable).
|
||||
// TODO if we ever give the possibility to upload its own videos,
|
||||
// this won't be necessary anymore.
|
||||
patch(VideoSelector.prototype, "Video selector patch", {
|
||||
patch(VideoSelector.prototype, {
|
||||
async _getVideoURLData(src, options) {
|
||||
if (src === VIDEO_URL || src === 'about:blank') {
|
||||
return {platform: 'youtube', embed_url: 'about:blank'};
|
||||
}
|
||||
return this._super(...arguments);
|
||||
return super._getVideoURLData(...arguments);
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "drop picture snippet",
|
||||
trigger: "#oe_snippets .oe_snippet[name='Picture'] .oe_snippet_thumbnail:not(.o_we_already_dragging)",
|
||||
moveTrigger: "iframe .oe_drop_zone",
|
||||
run: "drag_and_drop iframe #wrap",
|
||||
},
|
||||
...insertSnippet({
|
||||
name: 'Title - Image',
|
||||
id: 's_picture',
|
||||
groupName: "Images",
|
||||
}),
|
||||
{
|
||||
content: "select image",
|
||||
trigger: "iframe .s_picture figure img",
|
||||
trigger: ":iframe .s_picture figure img",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure image size is displayed",
|
||||
trigger: "#oe_snippets we-title:contains('Image') .o_we_image_weight:contains('kb')",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] .options-container-header:contains('kb')",
|
||||
},
|
||||
wTourUtils.changeOption("ImageTools", 'we-select[data-name="shape_img_opt"] we-toggler'),
|
||||
wTourUtils.changeOption("ImageTools", "we-button[data-set-img-shape]"),
|
||||
changeOption("Image", "[data-label='Shape'] .dropdown-toggle"),
|
||||
{
|
||||
content: "replace image",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
content: "Click on the first image shape",
|
||||
trigger: "button[data-action-id='setImageShape']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open MediaDialog from an image",
|
||||
trigger: "button[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select svg",
|
||||
trigger: ".o_select_media_dialog img[title='sample.svg']",
|
||||
trigger: ".o_select_media_dialog .o_button_area[aria-label='sample.svg']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure the svg doesn't have a shape",
|
||||
trigger: "iframe .s_picture figure img:not([data-shape])",
|
||||
run: function () {}, // check
|
||||
content: "ensure the svg does have a shape",
|
||||
trigger: ":iframe .s_picture figure img[data-shape]",
|
||||
},
|
||||
{
|
||||
content: "ensure image size is not displayed",
|
||||
trigger: "#oe_snippets we-title:contains('Image'):not(:has(.o_we_image_weight:visible))",
|
||||
run: function () {}, // check
|
||||
content: "ensure image size is displayed",
|
||||
trigger: ".o_customize_tab [data-container-title='Image'] span[title='Size']",
|
||||
},
|
||||
{
|
||||
content: "replace image",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
trigger: "button[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "go to pictogram tab",
|
||||
trigger: ".o_select_media_dialog .nav-link:contains('Icons')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select an icon",
|
||||
trigger: ".o_select_media_dialog:has(.nav-link.active:contains('Icons')) .tab-content span.fa-lemon-o",
|
||||
trigger: ".o_select_media_dialog:has(.nav-link.active:contains('Icons')) .tab-content span.fa-heart",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_customize_tab [data-container-title='Icon']",
|
||||
},
|
||||
{
|
||||
content: "select footer",
|
||||
trigger: "iframe footer",
|
||||
trigger: ":iframe footer",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select icon",
|
||||
trigger: "iframe .s_picture figure span.fa-lemon-o",
|
||||
trigger: ":iframe .s_picture figure span.fa-heart",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is still displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_customize_tab [data-container-title='Icon']",
|
||||
},
|
||||
{
|
||||
content: "replace icon",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
trigger: "button[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "go to video tab",
|
||||
trigger: ".o_select_media_dialog .nav-link:contains('Video')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "enter a video URL",
|
||||
trigger: ".o_select_media_dialog #o_video_text",
|
||||
// Design your first web page.
|
||||
run: `text ${VIDEO_URL}`,
|
||||
run: `edit ${VIDEO_URL}`,
|
||||
},
|
||||
{
|
||||
content: "wait for preview to appear",
|
||||
// "about:blank" because the VideoWidget was patched at the start of this tour
|
||||
trigger: ".o_select_media_dialog div.media_iframe_video iframe[src='about:blank']",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_select_media_dialog div.media_iframe_video [src='about:blank']:iframe body",
|
||||
},
|
||||
{
|
||||
content: "confirm selection",
|
||||
trigger: ".o_select_media_dialog .modal-footer .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure video option block is displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Video')",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_customize_tab [data-container-title='Video']",
|
||||
},
|
||||
{
|
||||
content: "replace image",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
trigger: ".btn-success[data-action-id='replaceMedia']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "go to pictogram tab",
|
||||
trigger: ".o_select_media_dialog .nav-link:contains('Icons')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select an icon",
|
||||
trigger: ".o_select_media_dialog:has(.nav-link.active:contains('Icons')) .tab-content span.fa-lemon-o",
|
||||
trigger: ".o_select_media_dialog:has(.nav-link.active:contains('Icons')) .tab-content span.fa-heart",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_customize_tab [data-container-title='Icon']",
|
||||
},
|
||||
{
|
||||
content: "select footer",
|
||||
trigger: "iframe footer",
|
||||
trigger: ":iframe footer",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select icon",
|
||||
trigger: "iframe .s_picture figure span.fa-lemon-o",
|
||||
trigger: ":iframe .s_picture figure span.fa-heart",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is still displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
trigger: ".o_customize_tab [data-container-title='Icon']",
|
||||
},
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
/* global ace */
|
||||
odoo.define('test_website.reset_views', function (require) {
|
||||
'use strict';
|
||||
|
||||
const wTourUtils = require('website.tour_utils');
|
||||
import { clickOnSave, registerWebsitePreviewTour } from "@website/js/tours/tour_utils";
|
||||
|
||||
var BROKEN_STEP = {
|
||||
// because saving a broken template opens a recovery page with no assets
|
||||
|
|
@ -10,98 +8,110 @@ var BROKEN_STEP = {
|
|||
// to properly wait for the page to be saved & reloaded in order to fix the
|
||||
// race condition of a tour ending on a side-effect (with the possible
|
||||
// exception of somehow telling the harness / browser to do it)
|
||||
trigger: 'body',
|
||||
run: function () {}
|
||||
trigger: "body",
|
||||
};
|
||||
wTourUtils.registerWebsitePreviewTour('test_reset_page_view_complete_flow_part1', {
|
||||
test: true,
|
||||
url: '/test_page_view',
|
||||
// 1. Edit the page through Edit Mode, it will COW the view
|
||||
edition: true,
|
||||
},
|
||||
[
|
||||
registerWebsitePreviewTour(
|
||||
"test_reset_page_view_complete_flow_part1",
|
||||
{
|
||||
url: "/test_page_view",
|
||||
// 1. Edit the page through Edit Mode, it will COW the view
|
||||
edition: true,
|
||||
},
|
||||
() => [
|
||||
{
|
||||
content: "drop a snippet",
|
||||
trigger: ".oe_snippet:has(.s_cover) .oe_snippet_thumbnail",
|
||||
content: "Drag the Intro snippet group and drop it in #oe_structure_test_website_page.",
|
||||
trigger:
|
||||
".o_block_tab:not(.o_we_ongoing_insertion) #snippet_groups .o_snippet[name='Intro'] .o_snippet_thumbnail .o_snippet_thumbnail_area",
|
||||
// id starting by 'oe_structure..' will actually create an inherited view
|
||||
run: "drag_and_drop iframe #oe_structure_test_website_page",
|
||||
run: "drag_and_drop :iframe #oe_structure_test_website_page",
|
||||
},
|
||||
{
|
||||
content: "save the page",
|
||||
extra_trigger: 'iframe #oe_structure_test_website_page.o_dirty',
|
||||
trigger: "button[data-action=save]",
|
||||
content: "Click on the s_cover snippet.",
|
||||
trigger: ':iframe .o_snippet_preview_wrap[data-snippet-id="s_cover"]',
|
||||
run: "click",
|
||||
},
|
||||
...clickOnSave(),
|
||||
// 2. Edit that COW'd view in the HTML editor to break it.
|
||||
{
|
||||
content: "open site menu",
|
||||
extra_trigger: "iframe body:not(.editor_enable)",
|
||||
trigger: 'button[data-menu-xmlid="website.menu_site"]',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "open html editor",
|
||||
trigger: 'a[data-menu-xmlid="website.menu_ace_editor"]',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "add a broken t-field in page DOM",
|
||||
trigger: 'div.ace_line .ace_xml:contains("placeholder")',
|
||||
run: function () {
|
||||
ace.edit('ace-view-editor').getSession().insert({row: 4, column: 1}, '<t t-field="not.exist"/>\n');
|
||||
run() {
|
||||
ace.edit(document.querySelector("#resource-editor div"))
|
||||
.getSession()
|
||||
.insert({row: 4, column: 1}, '<t t-field="not.exist"/>\n');
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "save the html editor",
|
||||
extra_trigger: '.ace_content:contains("not.exist")',
|
||||
trigger: ".o_ace_view_editor button[data-action=save]",
|
||||
trigger: '.ace_content:contains("not.exist")',
|
||||
},
|
||||
BROKEN_STEP
|
||||
{
|
||||
content: "save the html editor",
|
||||
trigger: ".o_resource_editor button:contains(Save)",
|
||||
run: "click",
|
||||
},
|
||||
BROKEN_STEP,
|
||||
]
|
||||
);
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_reset_page_view_complete_flow_part2', {
|
||||
test: true,
|
||||
url: '/test_page_view',
|
||||
},
|
||||
[
|
||||
registerWebsitePreviewTour(
|
||||
"test_reset_page_view_complete_flow_part2",
|
||||
{
|
||||
url: "/test_page_view",
|
||||
},
|
||||
() => [
|
||||
{
|
||||
content: "check that the view got fixed",
|
||||
trigger: 'iframe p:containsExact("Test Page View")',
|
||||
run: function () {}, // it's a check
|
||||
trigger: ":iframe p:text(Test Page View)",
|
||||
},
|
||||
{
|
||||
content: "check that the inherited COW view is still there (created during edit mode)",
|
||||
trigger: 'iframe #oe_structure_test_website_page .s_cover',
|
||||
run: function () {}, // it's a check
|
||||
trigger: ":iframe #oe_structure_test_website_page .s_cover",
|
||||
},
|
||||
//4. Now break the inherited view created when dropping a snippet
|
||||
{
|
||||
content: "open site menu",
|
||||
trigger: 'button[data-menu-xmlid="website.menu_site"]',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "open html editor",
|
||||
trigger: 'a[data-menu-xmlid="website.menu_ace_editor"]',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select oe_structure view",
|
||||
trigger: '#s2id_ace-view-list', // use select2 version
|
||||
run: function () {
|
||||
var viewId = $('#ace-view-list option:contains("oe_structure_test_website_page")').val();
|
||||
$('#ace-view-list').val(viewId).trigger('change');
|
||||
},
|
||||
trigger: ".o_resource_editor_title .o_select_menu_toggler",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select oe_structure view",
|
||||
trigger: ".o_select_menu_menu .o_select_menu_item:contains(Test Page View)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "add a broken t-field in page DOM",
|
||||
trigger: 'div.ace_line .ace_xml:contains("oe_structure_test_website_page")',
|
||||
run: function () {
|
||||
ace.edit('ace-view-editor').getSession().insert({row: 4, column: 1}, '<t t-field="not.exist"/>\n');
|
||||
run() {
|
||||
ace.edit(document.querySelector("#resource-editor div"))
|
||||
.getSession()
|
||||
.insert({row: 4, column: 1}, '<t t-field="not.exist"/>\n');
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "save the html editor",
|
||||
trigger: ".o_ace_view_editor button[data-action=save]",
|
||||
trigger: ".o_resource_editor button:contains(Save)",
|
||||
run: "click",
|
||||
},
|
||||
BROKEN_STEP
|
||||
BROKEN_STEP,
|
||||
]
|
||||
);
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
import {
|
||||
clickOnSave,
|
||||
clickOnEditAndWaitEditMode,
|
||||
clickOnExtraMenuItem,
|
||||
registerWebsitePreviewTour,
|
||||
insertSnippet
|
||||
} from '@website/js/tours/tour_utils';
|
||||
import { stepUtils } from "@web_tour/tour_utils";
|
||||
|
||||
const EDIT_BUTTON_SELECTOR = "body .o_menu_systray button.o-website-btn-custo-primary:contains(edit)";
|
||||
|
||||
const checkNoTranslate = {
|
||||
content: "Check there is no translate button",
|
||||
trigger: `${EDIT_BUTTON_SELECTOR}:not(.o-dropdown-toggle-custo)`,
|
||||
};
|
||||
const translate = [{
|
||||
content: "Open Edit menu",
|
||||
trigger: `${EDIT_BUTTON_SELECTOR}.o-dropdown-toggle-custo`,
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Click on translate button",
|
||||
trigger: ".o_popover .o_translate_website_dropdown_item:contains(translate)",
|
||||
run: "click",
|
||||
}];
|
||||
const closeErrorDialog = [{
|
||||
content: "Check has error dialog",
|
||||
trigger: ".modal:contains(error) .o_error_dialog.modal-content",
|
||||
}, {
|
||||
content: "Close error dialog",
|
||||
trigger: ".modal .modal-footer button.btn.btn-primary",
|
||||
run: "click",
|
||||
}, {
|
||||
trigger: "body:not(:has(.modal))",
|
||||
}];
|
||||
const switchTo = (lang) => [
|
||||
{
|
||||
content: `Switch to ${lang}`,
|
||||
trigger: `:iframe .js_change_lang[data-url_code='${lang}']`,
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: `Wait until ${lang} is applied`,
|
||||
trigger: `:iframe html[lang*="${lang}"]`,
|
||||
},
|
||||
stepUtils.waitIframeIsReady(),
|
||||
];
|
||||
const goToMenuItem = [
|
||||
clickOnExtraMenuItem({}, true),
|
||||
{
|
||||
content: "Navigate to model item page",
|
||||
trigger: ":iframe a[href='/test_website/model_item/1']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait to land on model item page",
|
||||
trigger: ':iframe a[href="/test_website/model_item/1"].nav-link.active:not(:visible)',
|
||||
},
|
||||
stepUtils.waitIframeIsReady(),
|
||||
];
|
||||
|
||||
registerWebsitePreviewTour('test_restricted_editor_only', {
|
||||
url: '/',
|
||||
}, () => [
|
||||
// Home
|
||||
checkNoTranslate,
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Check icons cannot be dragged",
|
||||
trigger: "#snippet_groups .o_snippet[name='Intro'].o_disabled",
|
||||
run: function () {
|
||||
if (document.querySelector("button.o_snippet_thumbnail_area")) {
|
||||
console.error(
|
||||
"The button to open the add snippet dialog should not be display for restricted editor."
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
...clickOnSave(),
|
||||
...switchTo('fr'),
|
||||
...translate,
|
||||
...closeErrorDialog,
|
||||
...switchTo('en'),
|
||||
// Model item
|
||||
{
|
||||
trigger: ":iframe body:contains(welcome to your)"
|
||||
},
|
||||
...goToMenuItem,
|
||||
checkNoTranslate,
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Check icons cannot be dragged",
|
||||
trigger: "#snippet_groups .o_snippet[name='Intro'].o_disabled",
|
||||
run: function () {
|
||||
if (document.querySelector("button.o_snippet_thumbnail_area")) {
|
||||
console.error(
|
||||
"The button to open the add snippet dialog should not be display for restricted editor."
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
...clickOnSave(),
|
||||
...switchTo('fr'),
|
||||
...translate,
|
||||
...closeErrorDialog,
|
||||
]);
|
||||
|
||||
registerWebsitePreviewTour('test_restricted_editor_test_admin', {
|
||||
url: '/',
|
||||
}, () => [
|
||||
// Home
|
||||
checkNoTranslate,
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Check icons cannot be dragged",
|
||||
trigger: "#snippet_groups .o_snippet[name='Intro'].o_disabled",
|
||||
},
|
||||
...clickOnSave(),
|
||||
...switchTo('fr'),
|
||||
...translate,
|
||||
...closeErrorDialog,
|
||||
...switchTo('en'),
|
||||
// Model item
|
||||
...goToMenuItem,
|
||||
checkNoTranslate,
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Check icons can be dragged",
|
||||
trigger: "#snippet_groups .o_snippet[name='Intro']:not(.o_disabled)",
|
||||
},
|
||||
...insertSnippet({ id: "s_banner", name: "Banner", groupName: "Intro" }),
|
||||
{
|
||||
content: "Change name",
|
||||
trigger: ":iframe [data-oe-expression='record.name']",
|
||||
run: "editor New value",
|
||||
},
|
||||
...clickOnSave(),
|
||||
...switchTo('fr'),
|
||||
...translate,
|
||||
{
|
||||
content: "Close the dialog",
|
||||
trigger: ".modal .modal-footer .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Assure the modal is well closed",
|
||||
trigger: "body:not(:has(.modal))",
|
||||
},
|
||||
{
|
||||
content: "Check that html fields are not content editable when translating",
|
||||
trigger: ":iframe [data-oe-expression='record.website_description']:not([contenteditable='true'])",
|
||||
},
|
||||
{
|
||||
content: "Translate name",
|
||||
trigger: ":iframe [data-oe-expression='record.name']",
|
||||
run: "editor Nouvelle valeur",
|
||||
},
|
||||
{
|
||||
content: "Translate some banner text",
|
||||
trigger: ":iframe [data-oe-expression='record.website_description'] strong",
|
||||
run: "editor potentiel.",
|
||||
},
|
||||
...clickOnSave(),
|
||||
]);
|
||||
|
||||
registerWebsitePreviewTour('test_restricted_editor_tester', {
|
||||
url: '/test_model/1',
|
||||
}, () => [
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Footer should not be be editable for restricted user",
|
||||
trigger: ":iframe :has(.o_editable) footer:not(.o_editable):not(:has(.o_editable))",
|
||||
},
|
||||
...clickOnSave(),
|
||||
]);
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { VideoSelector } from "@html_editor/main/media/media_dialog/video_selector";
|
||||
import { insertSnippet, registerWebsitePreviewTour } from "@website/js/tours/tour_utils";
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"snippet_background_video",
|
||||
{
|
||||
url: "/",
|
||||
edition: true,
|
||||
}, () => [
|
||||
{
|
||||
trigger: "body",
|
||||
run: function () {
|
||||
// Patch the VideoDialog so that it does not do external calls
|
||||
// during the test (note that we don't unpatch but as the patch
|
||||
// is only done after the execution of a test_website test, it
|
||||
// is acceptable).
|
||||
// TODO we should investigate to rather mock the external calls,
|
||||
// maybe not using a tour. Probably easier to discuss when the
|
||||
// new OWL editor will have been implemented.
|
||||
patch(VideoSelector.prototype, {
|
||||
async prepareVimeoPreviews() {
|
||||
// Ignore the super call and directly push a fake video
|
||||
this.state.vimeoPreviews.push({
|
||||
id: 1,
|
||||
// Those lead to 404 but it's fine for the test
|
||||
thumbnailSrc: "/hello/world.jpg",
|
||||
src: "/hello/world.mp4",
|
||||
});
|
||||
},
|
||||
async _getVideoURLData(src, options) {
|
||||
if (src === '/hello/world.mp4') {
|
||||
return {
|
||||
'platform': 'vimeo',
|
||||
'embed_url': 'about:blank',
|
||||
};
|
||||
}
|
||||
return super._getVideoURLData(...arguments);
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
...insertSnippet({
|
||||
id: "s_text_block",
|
||||
name: "Text",
|
||||
groupName: "Text",
|
||||
}),
|
||||
{
|
||||
content: "Click on the text block.",
|
||||
trigger: ":iframe #wrap section.s_text_block",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'Background Video' button option.",
|
||||
trigger: "button[data-action-id='toggleBgVideo']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click on the first sample video in the modal.",
|
||||
trigger: "#video-suggestion .o_sample_video",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check the video is select.",
|
||||
trigger: "textarea.is-valid",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'Add' button to apply the selected video as the background.",
|
||||
trigger: ".modal-footer button.btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Verify that the video is set as the background of the snippet.",
|
||||
trigger: ":iframe #wrap section.o_background_video",
|
||||
},
|
||||
{
|
||||
content: "Check that the video container is not editable.",
|
||||
trigger: ":iframe #wrap section.o_background_video > .o_bg_video_container[contenteditable=false]",
|
||||
},
|
||||
]
|
||||
);
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import wTourUtils from 'website.tour_utils';
|
||||
import {
|
||||
clickOnEditAndWaitEditMode,
|
||||
clickOnSave,
|
||||
registerWebsitePreviewTour,
|
||||
} from '@website/js/tours/tour_utils';
|
||||
import { stepUtils } from "@web_tour/tour_utils";
|
||||
|
||||
/**
|
||||
* The purpose of these tours is to check the systray visibility:
|
||||
|
|
@ -12,189 +16,209 @@ import wTourUtils from 'website.tour_utils';
|
|||
* - as an unrelated user (neither "tester" nor restricted editor)
|
||||
*/
|
||||
|
||||
const canPublish = [{
|
||||
content: 'Publish',
|
||||
const canPublish = () => [{
|
||||
content: "Publish",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Unpublished")',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Wait for Publish',
|
||||
content: "Wait for Publish",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Published"):not([data-processing])',
|
||||
run: () => {}, // This is a check.
|
||||
}, {
|
||||
content: 'Unpublish',
|
||||
content: "Unpublish",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Published")',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Wait for Unpublish',
|
||||
content: "Wait for Unpublish",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Unpublished"):not([data-processing])',
|
||||
run: () => {}, // This is a check.
|
||||
}];
|
||||
|
||||
const cannotPublish = [{
|
||||
content: 'Check has no Publish/Unpublish',
|
||||
const cannotPublish = () => [{
|
||||
content: "Check has no Publish/Unpublish",
|
||||
trigger: '.o_menu_systray:not(:has(.o_menu_systray_item:contains("ublished")))',
|
||||
run: () => {}, // This is a check.
|
||||
}];
|
||||
|
||||
const canToggleMobilePreview = [{
|
||||
content: 'Enable mobile preview',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_mobile_preview:not(.o_mobile_preview_active)',
|
||||
const canToggleMobilePreview = () => [{
|
||||
content: "Enable mobile preview",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_mobile_preview:not(.o_mobile_preview_active) span',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Disable mobile preview',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_mobile_preview.o_mobile_preview_active',
|
||||
content: "Disable mobile preview",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_mobile_preview.o_mobile_preview_active span',
|
||||
run: "click",
|
||||
}];
|
||||
|
||||
const cannotToggleMobilePreview = [{
|
||||
const cannotToggleMobilePreview = () => [{
|
||||
content: 'Enable mobile preview',
|
||||
trigger: '.o_menu_systray:not(:has(.o_menu_systray_item.o_mobile_preview))',
|
||||
run: () => {}, // This is a check.
|
||||
}];
|
||||
|
||||
// For non-website users, switching across website only works if the domains are
|
||||
// specified. Within the scope of test tours, this cannot be achieved.
|
||||
const canSwitchWebsiteNoCheck = [{
|
||||
const canSwitchWebsiteNoCheck = () => [{
|
||||
content: 'Open website switcher',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_website_switcher_container .dropdown-toggle:contains("My Website"):not(:contains("My Website 2"))',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Switch to other website',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_website_switcher_container .dropdown-item:contains("Other")',
|
||||
run: () => {}, // This is a check.
|
||||
content: 'Can switch to other website',
|
||||
trigger: '.o-dropdown--menu .dropdown-item:contains("Other")',
|
||||
}];
|
||||
|
||||
|
||||
const canSwitchWebsite = [{
|
||||
content: 'Open website switcher',
|
||||
const canSwitchWebsite = () => [{
|
||||
content: "Open website switcher",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_website_switcher_container .dropdown-toggle:contains("My Website"):not(:contains("My Website 2"))',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Switch to other website',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_website_switcher_container .dropdown-item:contains("Other")',
|
||||
content: "Switch to other website",
|
||||
trigger: '.o-dropdown--menu .dropdown-item:contains("Other")',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Wait for other website',
|
||||
trigger: 'iframe body:contains("Test Model") div:contains("Other")',
|
||||
run: () => {}, // This is a check.
|
||||
content: "Wait for other website",
|
||||
trigger: ':iframe body:contains("Test Model") div:contains("Other")',
|
||||
}];
|
||||
|
||||
const canAddNewContent = [{
|
||||
content: 'Open +New content',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_new_content_container',
|
||||
const canAddNewContent = () => [{
|
||||
content: "Open +New content",
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_new_content_container button',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Close +New content',
|
||||
trigger: '#o_new_content_menu_choices',
|
||||
content: "Close +New content",
|
||||
trigger: '.o_new_content_menu_choices',
|
||||
run: "click",
|
||||
}];
|
||||
|
||||
const cannotAddNewContent = [{
|
||||
const cannotAddNewContent = () => [{
|
||||
content: 'No +New content',
|
||||
trigger: '.o_menu_systray:not(:has(.o_menu_systray_item.o_new_content_container))',
|
||||
run: () => {}, // This is a check.
|
||||
}];
|
||||
|
||||
const canEditInBackEnd = [{
|
||||
content: 'Edit in backend',
|
||||
const canEditInBackEnd = () => [{
|
||||
content: "Edit in backend",
|
||||
trigger: '.o_menu_systray .o_website_edit_in_backend a',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Check that the form is editable',
|
||||
content: "Check that the form is editable",
|
||||
trigger: '.o_form_view_container .o_form_editable',
|
||||
run: () => {}, // This is a check.
|
||||
}, {
|
||||
content: 'Return to website',
|
||||
trigger: '.oe_button_box .fa-globe',
|
||||
content: "Return to website",
|
||||
trigger: '.o-form-buttonbox .fa-globe',
|
||||
run: "click",
|
||||
}];
|
||||
|
||||
const canViewInBackEnd = [{
|
||||
content: 'Go to backend',
|
||||
const canViewInBackEnd = () => [{
|
||||
content: "Go to backend",
|
||||
trigger: '.o_menu_systray .o_website_edit_in_backend a',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Check that the form is read-only',
|
||||
content: "Check that the form is read-only",
|
||||
trigger: '.o_form_view_container .o_form_readonly',
|
||||
run: () => {}, // This is a check.
|
||||
}, {
|
||||
content: 'Return to website',
|
||||
trigger: '.oe_button_box .fa-globe',
|
||||
content: "Return to website",
|
||||
trigger: '.o-form-buttonbox .fa-globe',
|
||||
run: "click",
|
||||
}];
|
||||
|
||||
const canEdit = [
|
||||
...wTourUtils.clickOnEditAndWaitEditMode(),
|
||||
const canEdit = () => [
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: 'Click on name',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"][contenteditable="true"]',
|
||||
content: "Click on name",
|
||||
trigger: ':iframe span[data-oe-expression="test_model.name"][contenteditable="true"]',
|
||||
run: "click",
|
||||
}, {
|
||||
content: 'Change name',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"][contenteditable="true"]',
|
||||
run: 'text Better name',
|
||||
content: "Change name",
|
||||
trigger: ':iframe span[data-oe-expression="test_model.name"][contenteditable="true"]',
|
||||
run: "editor Better name",
|
||||
}, {
|
||||
content: 'Check that field becomes dirty',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"].o_dirty',
|
||||
run: () => {}, // This is a check.
|
||||
content: "Check that field becomes dirty",
|
||||
trigger: ':iframe span[data-oe-expression="test_model.name"].o_dirty',
|
||||
},
|
||||
...wTourUtils.clickOnSave(),
|
||||
...clickOnSave(),
|
||||
{
|
||||
content: 'Check whether name is saved',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"]:contains("Better name")',
|
||||
run: () => {}, // This is a check.
|
||||
content: "Check whether name is saved",
|
||||
trigger: ':iframe span[data-oe-expression="test_model.name"]:contains("Better name")',
|
||||
},
|
||||
];
|
||||
|
||||
const cannotEdit = [{
|
||||
content: 'Check Edit is not available',
|
||||
const cannotEdit = () => [stepUtils.waitIframeIsReady(), {
|
||||
content: "Check Edit is not available",
|
||||
trigger: '.o_menu_systray:not(:has(.o_edit_website_container))',
|
||||
run: () => {}, // This is a check.
|
||||
}];
|
||||
|
||||
const canEditButCannotChange = [
|
||||
...wTourUtils.clickOnEditAndWaitEditMode(),
|
||||
const canEditButCannotChange = () => [
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: 'Cannot change name',
|
||||
trigger: 'iframe main:not(:has([data-oe-expression])):contains("Test Model")',
|
||||
run: () => {}, // This is a check.
|
||||
trigger: ':iframe main:not(:has([data-oe-expression])):contains("Test Model")',
|
||||
},
|
||||
];
|
||||
|
||||
const ensureWebsiteSwitcherIsNotVisible = [
|
||||
{
|
||||
content: "Ensure website switcher is hidden when only one website exists",
|
||||
trigger: ".o_menu_systray:not(:has(.o_website_switcher_container))",
|
||||
},
|
||||
];
|
||||
|
||||
const ensureWebsiteSwitcherIsVisible = [
|
||||
{
|
||||
content: "Ensure website switcher is present when multiple website exists",
|
||||
trigger: ".o_menu_systray:has(.o_website_switcher_container)",
|
||||
},
|
||||
];
|
||||
|
||||
const register = (title, steps) => {
|
||||
wTourUtils.registerWebsitePreviewTour(title, {
|
||||
url: '/test_model/1',
|
||||
test: true,
|
||||
registerWebsitePreviewTour(title, {
|
||||
url: "/test_model/1",
|
||||
}, steps);
|
||||
};
|
||||
|
||||
register('test_systray_admin', [
|
||||
...canPublish,
|
||||
...canToggleMobilePreview,
|
||||
...canSwitchWebsite,
|
||||
...canAddNewContent,
|
||||
...canEditInBackEnd,
|
||||
...canEdit,
|
||||
register("test_systray_admin", () => [
|
||||
...canPublish(),
|
||||
...canToggleMobilePreview(),
|
||||
...canSwitchWebsite(),
|
||||
...canAddNewContent(),
|
||||
...canEditInBackEnd(),
|
||||
...canEdit(),
|
||||
]);
|
||||
|
||||
register('test_systray_reditor_tester', [
|
||||
...canPublish,
|
||||
...canToggleMobilePreview,
|
||||
...canSwitchWebsite,
|
||||
...canAddNewContent,
|
||||
...canEditInBackEnd,
|
||||
...canEdit,
|
||||
register("test_systray_reditor_tester", () => [
|
||||
...canPublish(),
|
||||
...canToggleMobilePreview(),
|
||||
...canSwitchWebsite(),
|
||||
...canAddNewContent(),
|
||||
...canEditInBackEnd(),
|
||||
...canEdit(),
|
||||
]);
|
||||
|
||||
register('test_systray_reditor_not_tester', [
|
||||
...cannotPublish,
|
||||
...canToggleMobilePreview,
|
||||
...canSwitchWebsite,
|
||||
...canAddNewContent,
|
||||
...canViewInBackEnd,
|
||||
...canEditButCannotChange,
|
||||
register("test_systray_reditor_not_tester", () => [
|
||||
...cannotPublish(),
|
||||
...canToggleMobilePreview(),
|
||||
...canSwitchWebsite(),
|
||||
...canAddNewContent(),
|
||||
...canViewInBackEnd(),
|
||||
...canEditButCannotChange(),
|
||||
]);
|
||||
|
||||
register('test_systray_not_reditor_tester', [
|
||||
...canPublish,
|
||||
...cannotToggleMobilePreview,
|
||||
...canSwitchWebsiteNoCheck,
|
||||
...cannotAddNewContent,
|
||||
...canEditInBackEnd,
|
||||
...cannotEdit,
|
||||
register("test_systray_not_reditor_tester", () => [
|
||||
...canPublish(),
|
||||
...cannotToggleMobilePreview(),
|
||||
...canSwitchWebsiteNoCheck(),
|
||||
...cannotAddNewContent(),
|
||||
...canEditInBackEnd(),
|
||||
...cannotEdit(),
|
||||
]);
|
||||
|
||||
register('test_systray_not_reditor_not_tester', [
|
||||
...cannotPublish,
|
||||
...cannotToggleMobilePreview,
|
||||
...canSwitchWebsiteNoCheck,
|
||||
...cannotAddNewContent,
|
||||
...canViewInBackEnd,
|
||||
...cannotEdit,
|
||||
register("test_systray_not_reditor_not_tester", () => [
|
||||
...cannotPublish(),
|
||||
...cannotToggleMobilePreview(),
|
||||
...canSwitchWebsiteNoCheck(),
|
||||
...cannotAddNewContent(),
|
||||
...canViewInBackEnd(),
|
||||
...cannotEdit(),
|
||||
{
|
||||
trigger: ":iframe main:contains(test model)",
|
||||
},
|
||||
]);
|
||||
|
||||
register("test_systray_single_website", () => ensureWebsiteSwitcherIsNotVisible);
|
||||
|
||||
register("test_systray_multi_website", () => ensureWebsiteSwitcherIsVisible);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,499 @@
|
|||
import {
|
||||
clickOnEditAndWaitEditMode,
|
||||
clickOnSave,
|
||||
insertSnippet,
|
||||
registerWebsitePreviewTour,
|
||||
} from "@website/js/tours/tour_utils";
|
||||
import { stepUtils } from "@web_tour/tour_utils";
|
||||
import { translationIsReady } from "@web/core/l10n/translation";
|
||||
|
||||
function createNewPage() {
|
||||
return [
|
||||
{
|
||||
content: "Open +New content",
|
||||
trigger: ".o_menu_systray .o_menu_systray_item.o_new_content_container button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Create a New page",
|
||||
trigger: `button.o_new_content_element img[src="/website/static/description/icon.png"]`,
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Select Blank page",
|
||||
trigger: ".o_page_template:has(div.text-muted) .o_button_area:not(:visible)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Page name",
|
||||
trigger: ".modal-dialog .o_website_dialog input",
|
||||
run: "edit Test",
|
||||
},
|
||||
{
|
||||
content: "Confirm creation",
|
||||
trigger: ".modal-dialog .o_website_dialog .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_builder_sidebar_open",
|
||||
timeout: 20000,
|
||||
},
|
||||
...insertSnippet({
|
||||
id: "s_banner",
|
||||
name: "Banner",
|
||||
groupName: "Intro",
|
||||
}),
|
||||
{
|
||||
content: "Click on the link",
|
||||
trigger: ":iframe main section.s_banner a",
|
||||
async run(helpers) {
|
||||
await helpers.click();
|
||||
const el = this.anchor;
|
||||
const sel = el.ownerDocument.getSelection();
|
||||
sel.collapse(el, 0);
|
||||
el.focus();
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click on Edit link",
|
||||
trigger: ".o_we_edit_link",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Replace URL",
|
||||
trigger: ".o-we-linkpopover .o_we_href_input_link",
|
||||
run: "edit /test_view",
|
||||
},
|
||||
{
|
||||
content: "Apply",
|
||||
trigger: ".o-we-linkpopover .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
...clickOnSave("bottom", 50000, false),
|
||||
];
|
||||
}
|
||||
|
||||
function openHtmlEditor() {
|
||||
return [
|
||||
{
|
||||
content: "Open Site menu",
|
||||
trigger: ".o_menu_sections [data-menu-xmlid='website.menu_site']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open HTML editor",
|
||||
trigger: ".o-overlay-item .dropdown-item[data-menu-xmlid='website.menu_ace_editor']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Edit anyway",
|
||||
trigger: ".o_resource_editor_wrapper [role='alert'] button.btn-link",
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function saveHtmlEditor() {
|
||||
return [
|
||||
{
|
||||
content: "Save the html editor",
|
||||
trigger: ".o_resource_editor button.btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Close the html editor",
|
||||
trigger: ".o_resource_editor button.btn-secondary",
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function singleLanguage() {
|
||||
return [
|
||||
{
|
||||
content: "Ensure single language site",
|
||||
trigger: ":iframe body:not(:has(.js_language_selector))",
|
||||
},
|
||||
// new page
|
||||
...createNewPage(),
|
||||
...openHtmlEditor(),
|
||||
{
|
||||
content: "Change text",
|
||||
trigger: 'div.ace_line .ace_xml:contains("oe_structure")',
|
||||
run() {
|
||||
window.ace.edit(document.querySelector("#resource-editor div"))
|
||||
.getSession()
|
||||
.insert({row: 8, column: 1}, '<p>More text</p>\n');
|
||||
},
|
||||
},
|
||||
...saveHtmlEditor(),
|
||||
{
|
||||
content: "Ensure page is updated",
|
||||
trigger: ":iframe body:contains(More text)",
|
||||
},
|
||||
// xml record
|
||||
{
|
||||
content: "Go to test_view page",
|
||||
trigger: ":iframe main section.s_banner a",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait until page is reached",
|
||||
trigger: ":iframe body:contains(Test View)",
|
||||
},
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Edit template text",
|
||||
trigger: ":iframe main p.o_editable[data-oe-field='arch'][contenteditable='true']",
|
||||
run: "editor Modified Text",
|
||||
},
|
||||
...clickOnSave("bottom", 50000, false),
|
||||
...openHtmlEditor(),
|
||||
{
|
||||
content: "Change text",
|
||||
trigger: 'div.ace_line .ace_xml:contains("test_website.test_view")',
|
||||
run() {
|
||||
window.ace.edit(document.querySelector("#resource-editor div"))
|
||||
.getSession()
|
||||
.insert({row: 2, column: 36}, 'Further ');
|
||||
},
|
||||
},
|
||||
...saveHtmlEditor(),
|
||||
{
|
||||
content: "Ensure view is updated",
|
||||
trigger: ":iframe body:contains(Further Modified Text)",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const ensureFrUser = {
|
||||
content: "Ensure FR user",
|
||||
trigger: ".o_website_systray:contains(Publié)",
|
||||
};
|
||||
|
||||
const ensureEnUser = {
|
||||
content: "Ensure EN user",
|
||||
trigger: ".o_website_systray:contains(Published)",
|
||||
};
|
||||
|
||||
const ensureFrSite = {
|
||||
content: "Ensure FR site",
|
||||
trigger: ":iframe .o_main_nav:contains(Accueil)",
|
||||
};
|
||||
|
||||
const ensureEnSite = {
|
||||
content: "Ensure EN site",
|
||||
trigger: ":iframe .o_main_nav:contains(Home)",
|
||||
};
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_single_language_fr_user_fr_site",
|
||||
{
|
||||
url: "/",
|
||||
},
|
||||
() => [
|
||||
ensureFrUser,
|
||||
ensureFrSite,
|
||||
...singleLanguage(),
|
||||
]
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_single_language_en_user_fr_site",
|
||||
{
|
||||
url: "/",
|
||||
},
|
||||
() => [
|
||||
ensureEnUser,
|
||||
ensureFrSite,
|
||||
...singleLanguage(),
|
||||
]
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_single_language_fr_user_en_site",
|
||||
{
|
||||
url: "/",
|
||||
},
|
||||
() => [
|
||||
ensureFrUser,
|
||||
ensureEnSite,
|
||||
...singleLanguage(),
|
||||
]
|
||||
);
|
||||
|
||||
function switchLanguage(lang, timeout = 50000) {
|
||||
return [
|
||||
{
|
||||
content: "Ensure was in other language",
|
||||
trigger: `:iframe .o_header_language_selector:contains(${lang !== "fr" ? "Français" : "English"})`,
|
||||
timeout,
|
||||
}, {
|
||||
content: "Open language dropdown",
|
||||
trigger: ":iframe .o_header_language_selector .dropdown-toggle",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Select language",
|
||||
trigger: `:iframe .o_header_language_selector .js_change_lang[data-url_code=${lang}]`,
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Wait until target page is loaded",
|
||||
trigger: `:iframe .o_header_language_selector:contains(${lang === "fr" ? "Français" : "English"})`,
|
||||
timeout,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// TODO Such a step should not be needed, but test randomly fails without it.
|
||||
const awaitTranslationIsReady = {
|
||||
content: "Await translationIsReady",
|
||||
trigger: "body",
|
||||
run: async () => {
|
||||
await translationIsReady;
|
||||
},
|
||||
};
|
||||
|
||||
function openTranslate(timeout = 50000) {
|
||||
return [
|
||||
stepUtils.waitIframeIsReady(),
|
||||
awaitTranslationIsReady,
|
||||
{
|
||||
content: "Open edit dropdown",
|
||||
trigger: ".o_edit_website_container button",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Enter translate mode",
|
||||
trigger: ".o_translate_website_dropdown_item",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Effect's 200ms setTimeout passed",
|
||||
trigger: ".o_builder_open .o_main_navbar.d-none:not(:visible)",
|
||||
}, {
|
||||
content: "Translatable text became highlighted",
|
||||
trigger: ":iframe [data-oe-translation-state=to_translate]",
|
||||
timeout,
|
||||
}, {
|
||||
content: "Confirm popup",
|
||||
trigger: ".o_website_dialog .btn-secondary",
|
||||
run: "click",
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function saveTranslation(timeout = 50000) {
|
||||
return [
|
||||
{
|
||||
content: "Save translation",
|
||||
trigger: ".o-website-builder_sidebar button[data-action=save]",
|
||||
run: "click",
|
||||
}, {
|
||||
content: "Back to preview mode",
|
||||
trigger: ".o_edit_website_container button",
|
||||
timeout,
|
||||
}, {
|
||||
trigger: "body:not(.o_builder_open)",
|
||||
noPrepend: true,
|
||||
timeout,
|
||||
},
|
||||
stepUtils.waitIframeIsReady(),
|
||||
awaitTranslationIsReady,
|
||||
];
|
||||
}
|
||||
|
||||
function multiLanguage(mainLanguage, secondLanguage) {
|
||||
return [
|
||||
{
|
||||
content: "Ensure multi language site",
|
||||
trigger: ":iframe body:has(.js_language_selector)",
|
||||
},
|
||||
// new page
|
||||
...createNewPage(),
|
||||
...switchLanguage(secondLanguage),
|
||||
...openTranslate(),
|
||||
{
|
||||
content: "Translate some text",
|
||||
trigger: ":iframe h1 [data-oe-translation-state=to_translate]",
|
||||
run: "editor Some translated text",
|
||||
},
|
||||
...saveTranslation(),
|
||||
{
|
||||
content: "Check translation is displayed",
|
||||
trigger: ":iframe h1:contains(Some translated text)",
|
||||
},
|
||||
...openHtmlEditor(),
|
||||
{
|
||||
content: "Change text",
|
||||
trigger: 'div.ace_line .ace_xml:contains("oe_structure")',
|
||||
run() {
|
||||
window.ace.edit(document.querySelector("#resource-editor div"))
|
||||
.getSession()
|
||||
.insert({row: 6, column: 50}, "more text ");
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Pollute old DOM to detect reload",
|
||||
trigger: ":iframe body",
|
||||
run() {
|
||||
this.anchor.dataset.reloaded = false;
|
||||
},
|
||||
},
|
||||
...saveHtmlEditor(),
|
||||
{
|
||||
content: "Ensure page is NOT updated",
|
||||
trigger: ":iframe body:not([data-reloaded=false]) h1:not(:contains(more text))",
|
||||
},
|
||||
...switchLanguage(mainLanguage),
|
||||
{
|
||||
content: "Ensure French page IS updated",
|
||||
trigger: ":iframe h1:contains(more text)",
|
||||
},
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Change text again",
|
||||
trigger: ":iframe h1",
|
||||
run: "editor Yet another version of the text.",
|
||||
},
|
||||
...clickOnSave("bottom", 50000, false),
|
||||
...switchLanguage(secondLanguage),
|
||||
{
|
||||
content: "Ensure English page is NOT updated",
|
||||
trigger: ":iframe h1:not(:contains(Yet another))",
|
||||
},
|
||||
...openTranslate(),
|
||||
{
|
||||
content: "Ensure English page is updated",
|
||||
trigger: ":iframe h1:contains(Yet another)",
|
||||
},
|
||||
{
|
||||
content: "Translate again",
|
||||
trigger: ":iframe h1 [data-oe-translation-state=to_translate]",
|
||||
run: "editor Yet another translated text",
|
||||
},
|
||||
...saveTranslation(),
|
||||
{
|
||||
content: "Check translation is displayed",
|
||||
trigger: ":iframe h1:contains(Yet another translated text)",
|
||||
},
|
||||
// xml record
|
||||
{
|
||||
content: "Go to test_view page",
|
||||
trigger: ":iframe main section.s_banner a",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait until page is reached",
|
||||
trigger: ":iframe body:contains(Test View)",
|
||||
},
|
||||
...switchLanguage(mainLanguage),
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Edit template text",
|
||||
trigger: ":iframe main p.o_editable[contenteditable='true']",
|
||||
run: "editor Modified View",
|
||||
},
|
||||
...clickOnSave("bottom", 50000, false),
|
||||
...switchLanguage(secondLanguage),
|
||||
...openTranslate(),
|
||||
{
|
||||
content: "Translate test view",
|
||||
trigger: ":iframe main > p > span[data-oe-translation-state=to_translate]",
|
||||
run: "editor Some translated view",
|
||||
},
|
||||
...saveTranslation(),
|
||||
{
|
||||
content: "Check translation is displayed",
|
||||
trigger: ":iframe p:contains(Some translated view)",
|
||||
},
|
||||
...switchLanguage(mainLanguage),
|
||||
...openHtmlEditor(),
|
||||
{
|
||||
content: "Change text",
|
||||
trigger: 'div.ace_line .ace_xml:contains("test_website.test_view")',
|
||||
run() {
|
||||
window.ace.edit(document.querySelector("#resource-editor div"))
|
||||
.getSession()
|
||||
.insert({row: 2, column: 36}, 'Further ');
|
||||
},
|
||||
},
|
||||
...saveHtmlEditor(),
|
||||
{
|
||||
content: "Ensure view is updated",
|
||||
trigger: ":iframe body:contains(Further Modified View)",
|
||||
},
|
||||
...clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: "Edit template text",
|
||||
trigger: ":iframe main p.o_editable[data-oe-field='arch'][contenteditable='true']",
|
||||
run: "editor Even more modified Text",
|
||||
},
|
||||
...clickOnSave("bottom", 50000, false),
|
||||
...switchLanguage(secondLanguage),
|
||||
{
|
||||
content: "Check old translation is displayed",
|
||||
trigger: ":iframe p:contains(Some translated view)",
|
||||
},
|
||||
...openTranslate(),
|
||||
{
|
||||
content: "Check new original is displayed",
|
||||
trigger: ":iframe p:contains(Even more modified text)",
|
||||
},
|
||||
{
|
||||
content: "Translate test view",
|
||||
trigger: ":iframe main > p > span[data-oe-translation-state=to_translate]",
|
||||
run: "editor Even more translated text",
|
||||
},
|
||||
...saveTranslation(),
|
||||
{
|
||||
content: "Check new translation is displayed",
|
||||
trigger: ":iframe p:contains(Even more translated text)",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_multi_language_fr_user_fr_en_site",
|
||||
{
|
||||
url: "/fr",
|
||||
},
|
||||
() => [
|
||||
ensureFrUser,
|
||||
ensureFrSite,
|
||||
...multiLanguage("fr", "en"),
|
||||
]
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_multi_language_fr_user_en_fr_site",
|
||||
{
|
||||
url: "/en",
|
||||
},
|
||||
() => [
|
||||
ensureFrUser,
|
||||
ensureEnSite,
|
||||
...multiLanguage("en", "fr"),
|
||||
]
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_multi_language_en_user_fr_en_site",
|
||||
{
|
||||
url: "/fr",
|
||||
},
|
||||
() => [
|
||||
ensureEnUser,
|
||||
ensureFrSite,
|
||||
...multiLanguage("fr", "en"),
|
||||
]
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"translation_multi_language_en_user_en_fr_site",
|
||||
{
|
||||
url: "/en",
|
||||
},
|
||||
() => [
|
||||
ensureEnUser,
|
||||
ensureEnSite,
|
||||
...multiLanguage("en", "fr"),
|
||||
]
|
||||
);
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import {
|
||||
clickOnSave,
|
||||
registerWebsitePreviewTour,
|
||||
changeOptionInPopover,
|
||||
} from "@website/js/tours/tour_utils";
|
||||
|
||||
function assertEqual(actual, expected) {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`Assert failed: expected: ${expected} ; got: ${actual}`);
|
||||
}
|
||||
}
|
||||
|
||||
registerWebsitePreviewTour('website_controller_page_listing_layout', {
|
||||
url: '/model/exposed-model',
|
||||
edition: true,
|
||||
}, () => [
|
||||
{
|
||||
content: "website is in preview mode",
|
||||
trigger: '.o_website_preview',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "records are listed in grid mode by default",
|
||||
trigger: ':iframe .o_website_grid',
|
||||
run() {
|
||||
const iframeDocument = document.querySelector(".o_website_preview iframe").contentDocument;
|
||||
// grid option is selected by default in the switch
|
||||
assertEqual(iframeDocument.querySelector(".listing_layout_switcher #o_wstudio_apply_grid").checked, true);
|
||||
assertEqual([...iframeDocument.querySelectorAll(".test_record_listing")].length, 2);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "open customize tab",
|
||||
trigger: ":iframe .listing_layout_switcher",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o-snippets-menu .o_customize_tab",
|
||||
},
|
||||
...changeOptionInPopover("Layout", "Default Layout", "list"),
|
||||
{
|
||||
content: "records are now displayed in list mode",
|
||||
trigger: ':iframe .o_website_list',
|
||||
run() {
|
||||
const iframeDocument = document.querySelector(".o_website_preview iframe").contentDocument;
|
||||
// list option is now selected in the switch
|
||||
assertEqual(iframeDocument.querySelector(".listing_layout_switcher #o_wstudio_apply_list").checked, true);
|
||||
},
|
||||
},
|
||||
...clickOnSave(),
|
||||
]);
|
||||
|
||||
registerWebsitePreviewTour('website_controller_page_default_page_check', {
|
||||
url: '/model/exposed-model',
|
||||
}, () => [
|
||||
{
|
||||
content: "records are listed in list mode by default",
|
||||
trigger: ':iframe [is-ready=true] .o_website_list',
|
||||
run() {
|
||||
const iframeDocument = document.querySelector(".o_website_preview iframe").contentDocument;
|
||||
// list option is selected by default in the switch
|
||||
assertEqual(iframeDocument.querySelector(".listing_layout_switcher #o_wstudio_apply_list").checked, true);
|
||||
assertEqual([...iframeDocument.querySelectorAll(".test_record_listing")].length, 2);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import { clickOnSave, registerWebsitePreviewTour } from "@website/js/tours/tour_utils";
|
||||
|
||||
// As admin, add a YouTube video iframe in a `sanitize_overridable` HTML field.
|
||||
registerWebsitePreviewTour("website_designer_iframe_video",
|
||||
{
|
||||
url: "/test_website/model_item/1",
|
||||
edition: true,
|
||||
},
|
||||
() => [
|
||||
{
|
||||
content: "As administrator, add a video block to the description field",
|
||||
trigger: `.o_block_tab:not(.o_we_ongoing_insertion) #snippet_content .o_snippet[name="Video"].o_draggable .o_snippet_thumbnail`,
|
||||
run: "drag_and_drop :iframe .o_test_website_description",
|
||||
},
|
||||
{
|
||||
content: "Add a video URL",
|
||||
trigger: ".o_select_media_dialog #o_video_text",
|
||||
run: `edit https://www.youtube.com/watch?v=G8b4UZIcTfg`,
|
||||
},
|
||||
{
|
||||
content: "Add the video",
|
||||
trigger: ".o_select_media_dialog .modal-footer .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
...clickOnSave(),
|
||||
{
|
||||
content: "Check that the video was correctly saved",
|
||||
trigger: ":iframe .media_iframe_video[data-oe-expression*='G8b4UZIcTfg']",
|
||||
run: () => {},
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// Check that a restricted editor can edit the field content (even with
|
||||
// a video iframe).
|
||||
registerWebsitePreviewTour("website_restricted_editor_iframe_video", {
|
||||
url: "/test_website/model_item/1",
|
||||
edition: true,
|
||||
},
|
||||
() => [
|
||||
{
|
||||
content: "Check that the video iframe was correctly restored after saving the changes",
|
||||
trigger:
|
||||
":iframe [data-oe-field]:not([data-oe-sanitize-prevent-edition]) .media_iframe_video[data-oe-expression*='G8b4UZIcTfg']",
|
||||
run: () => {},
|
||||
},
|
||||
{
|
||||
content: "As a restricted editor, edit the HTML field content",
|
||||
trigger: ":iframe .o_test_website_description",
|
||||
run: "editor I can still edit the HTML field",
|
||||
},
|
||||
...clickOnSave(),
|
||||
{
|
||||
content: "Check that the HTML content (with a video iframe) was correctly updated",
|
||||
trigger:
|
||||
":iframe .o_test_website_description:contains('I can still edit the HTML field')",
|
||||
run: () => {},
|
||||
},
|
||||
]
|
||||
);
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
import {
|
||||
assertPathName,
|
||||
clickOnSave,
|
||||
getClientActionUrl,
|
||||
registerWebsitePreviewTour,
|
||||
} from "@website/js/tours/tour_utils";
|
||||
import { stepUtils } from "@web_tour/tour_utils";
|
||||
|
||||
const openPagePropertiesDialog = [
|
||||
{
|
||||
content: "Open Site backend menu",
|
||||
trigger: '[data-menu-xmlid="website.menu_site"]',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open page properties dialog",
|
||||
trigger: '[data-menu-xmlid="website.menu_page_properties"]',
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
|
||||
const clickOnSaveButtonStep = [
|
||||
{
|
||||
content: "Click on Save & Close",
|
||||
trigger: ".o_form_button_save:enabled",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait",
|
||||
trigger: "body:not(.modal-open)",
|
||||
}
|
||||
];
|
||||
|
||||
const openCreatePageDialog = [
|
||||
{
|
||||
content: "Open create content menu",
|
||||
trigger: ".o_new_content_container button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Create a new page",
|
||||
trigger: 'button[aria-label="New Page"]',
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
|
||||
function assertPageCanonicalUrlIs(url) {
|
||||
return [
|
||||
{
|
||||
content: `Verify page canonical url is ${url}`,
|
||||
trigger: `:iframe head:hidden link[rel="canonical"][href$="${url}"]`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function checkIsTemplate(isTemplate, pageTitle = undefined) {
|
||||
return [
|
||||
...openCreatePageDialog,
|
||||
{
|
||||
trigger: 'button[data-id="custom"]',
|
||||
},
|
||||
{
|
||||
content: "Go to custom section",
|
||||
trigger: 'button[data-id="custom"]',
|
||||
run: "click",
|
||||
},
|
||||
...(isTemplate
|
||||
? [
|
||||
{
|
||||
content: `Verify template ${pageTitle} exists`,
|
||||
trigger: `.o_page_template .o_page_name:contains(${pageTitle}):hidden`,
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
trigger: ".o_website_page_templates_pane .alert-info",
|
||||
},
|
||||
{
|
||||
content: `Verify custom templates section is empty`,
|
||||
trigger: `.o_website_page_templates_pane:not(:has(.o_page_template))`,
|
||||
},
|
||||
]
|
||||
),
|
||||
{
|
||||
content: "Exit dialog",
|
||||
trigger: ".modal-header .btn-close",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Exit new content backdrop",
|
||||
trigger: "body",
|
||||
run: "press escape",
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function testCommonProperties(url, canPublish, modifiedUrl = undefined) {
|
||||
if (!modifiedUrl) {
|
||||
modifiedUrl = url;
|
||||
}
|
||||
|
||||
const steps = {
|
||||
setup: [
|
||||
{
|
||||
content: "Open Edit Menu dialog",
|
||||
trigger: '.o_field_widget[name="is_in_menu"] + .btn-link',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check that menu editor was opened",
|
||||
trigger: ".oe_menu_editor",
|
||||
},
|
||||
{
|
||||
content: "Close Edit Menu dialog",
|
||||
trigger: ".modal:has(.oe_menu_editor) .btn-close",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Add to menu",
|
||||
trigger: "#is_in_menu_0",
|
||||
run: "check",
|
||||
},
|
||||
{
|
||||
content: "Set as homepage",
|
||||
trigger: "#is_homepage_0",
|
||||
run: "check",
|
||||
},
|
||||
],
|
||||
check: [
|
||||
{
|
||||
content: "Verify is in menu",
|
||||
trigger: `:visible :iframe #top_menu a[href="${modifiedUrl}"]`,
|
||||
},
|
||||
stepUtils.goToUrl(getClientActionUrl("/")),
|
||||
...assertPageCanonicalUrlIs(modifiedUrl),
|
||||
stepUtils.goToUrl(getClientActionUrl(modifiedUrl)),
|
||||
],
|
||||
teardown: [
|
||||
{
|
||||
content: "Remove from menu",
|
||||
trigger: "#is_in_menu_0",
|
||||
run: "uncheck",
|
||||
},
|
||||
{
|
||||
content: "Unset as homepage",
|
||||
trigger: "#is_homepage_0",
|
||||
run: "uncheck",
|
||||
},
|
||||
],
|
||||
checkTorndown: [
|
||||
{
|
||||
content: "Verify is not in menu",
|
||||
trigger: `:visible :iframe #top_menu:not(:has(a[href="${url}"]))`,
|
||||
},
|
||||
stepUtils.goToUrl(getClientActionUrl("/")),
|
||||
...assertPageCanonicalUrlIs("/"),
|
||||
stepUtils.goToUrl(getClientActionUrl(url)),
|
||||
],
|
||||
finalize() {
|
||||
return [
|
||||
...openPagePropertiesDialog,
|
||||
...this.setup,
|
||||
...clickOnSaveButtonStep,
|
||||
...this.check,
|
||||
...openPagePropertiesDialog,
|
||||
...this.teardown,
|
||||
...clickOnSaveButtonStep,
|
||||
...this.checkTorndown,
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
if (canPublish) {
|
||||
steps.setup.push({
|
||||
content: "Publish",
|
||||
trigger: "#is_published_0",
|
||||
run: "check",
|
||||
});
|
||||
steps.check.push({
|
||||
content: "Verify is published",
|
||||
trigger: '[data-hotkey="p"] .form-check input:checked',
|
||||
});
|
||||
steps.teardown.push({
|
||||
content: "Unpublish",
|
||||
trigger: "#is_published_0",
|
||||
run: "uncheck",
|
||||
});
|
||||
steps.checkTorndown.push({
|
||||
content: "Verify is not published",
|
||||
trigger: '[data-hotkey="p"] .form-check input:not(:checked)',
|
||||
});
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
function testWebsitePageProperties() {
|
||||
const steps = testCommonProperties("/new-page", true, "/cool-page");
|
||||
steps.setup.unshift(
|
||||
{
|
||||
content: "Change page title",
|
||||
trigger: "#name_0",
|
||||
run: "edit Cool Page",
|
||||
},
|
||||
{
|
||||
content: `Change url to /cool-page`,
|
||||
trigger: "#url_0",
|
||||
run: `edit cool-page && press Enter`,
|
||||
},
|
||||
{
|
||||
content: "Enable old url redirect",
|
||||
trigger: "#redirect_old_url_0",
|
||||
run: "check",
|
||||
},
|
||||
{
|
||||
content: "Open redirect type popup",
|
||||
trigger: "#redirect_type_0",
|
||||
run: "click"
|
||||
},
|
||||
{
|
||||
content: "Set redirect type to temporary",
|
||||
trigger: ".o-dropdown-item[data-choice-index='1']",
|
||||
run: "click"
|
||||
},
|
||||
{
|
||||
// TODO: this needs to be tested
|
||||
content: "Change date published",
|
||||
trigger: "#date_publish_0",
|
||||
run: "edit 02/01/2005 01:00:00 && press enter",
|
||||
},
|
||||
{
|
||||
content: "Don't index",
|
||||
trigger: "#website_indexed_0",
|
||||
run: "uncheck",
|
||||
},
|
||||
{
|
||||
content: "Open visibility popup",
|
||||
trigger: "#visibility_0",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
// TODO: this needs to be tested
|
||||
content: "Make visible with password only",
|
||||
trigger: ".o-dropdown-item[data-choice-index='3']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Set password to 123",
|
||||
trigger: "#visibility_password_display_0",
|
||||
run: "edit 123",
|
||||
},
|
||||
{
|
||||
content: "Make it a template",
|
||||
trigger: "#is_new_page_template_0",
|
||||
run: "check",
|
||||
},
|
||||
);
|
||||
steps.check.push(
|
||||
{
|
||||
content: "Verify page title",
|
||||
trigger: ":iframe head:hidden title:contains(/Cool Page/)",
|
||||
},
|
||||
...assertPageCanonicalUrlIs("/cool-page"),
|
||||
stepUtils.goToUrl(getClientActionUrl("/new-page")),
|
||||
assertPathName("/cool-page", "body"),
|
||||
{
|
||||
content: "Verify no index",
|
||||
trigger: ':iframe head:hidden meta[name="robots"][content="noindex"]',
|
||||
},
|
||||
...checkIsTemplate(true, "Cool Page"),
|
||||
);
|
||||
steps.teardown.unshift(
|
||||
{
|
||||
content: "Reset page title",
|
||||
trigger: "#name_0",
|
||||
run: `edit New Page`,
|
||||
},
|
||||
{
|
||||
content: `Change url back to /new-page`,
|
||||
trigger: "#url_0",
|
||||
run: `edit new-page && press Enter`,
|
||||
},
|
||||
{
|
||||
content: "Open date published popup",
|
||||
trigger: "#date_publish_0",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Reset date published",
|
||||
trigger: "button[title='Clear']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Do index",
|
||||
trigger: "#website_indexed_0",
|
||||
run: "check",
|
||||
},
|
||||
{
|
||||
content: "Open visibility popup",
|
||||
trigger: "#visibility_0",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Make visible public",
|
||||
trigger: ".o-dropdown-item[data-choice-index='0']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Remove from templates",
|
||||
trigger: "#is_new_page_template_0",
|
||||
run: "uncheck",
|
||||
},
|
||||
);
|
||||
steps.checkTorndown.push(
|
||||
{
|
||||
content: "Verify page title",
|
||||
trigger: ":iframe head:hidden title:contains(/New Page/)",
|
||||
},
|
||||
...assertPageCanonicalUrlIs("/new-page"),
|
||||
stepUtils.goToUrl(getClientActionUrl("/new-page")),
|
||||
assertPathName("/new-page", "body"),
|
||||
{
|
||||
content: "Verify is indexed",
|
||||
trigger: ':iframe head:hidden:not(:has(meta[name="robots"][content="noindex"]))',
|
||||
},
|
||||
...checkIsTemplate(false),
|
||||
);
|
||||
return steps;
|
||||
}
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"website_page_properties_common",
|
||||
{
|
||||
url: "/test_view",
|
||||
},
|
||||
() => [...testCommonProperties("/test_view", false).finalize()],
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"website_page_properties_can_publish",
|
||||
{
|
||||
url: "/test_website/model_item/1",
|
||||
},
|
||||
() => [...testCommonProperties("/test_website/model_item/1", true).finalize()],
|
||||
);
|
||||
|
||||
registerWebsitePreviewTour(
|
||||
"website_page_properties_website_page",
|
||||
{
|
||||
url: "/",
|
||||
},
|
||||
() => [
|
||||
...openCreatePageDialog,
|
||||
{
|
||||
content: "Use blank template",
|
||||
trigger: ".o_page_template .o_button_area:hidden",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Name page",
|
||||
trigger: ".modal-body input",
|
||||
run: "edit New Page",
|
||||
},
|
||||
{
|
||||
content: "Don't add to menu",
|
||||
trigger: ".modal-body .o_switch",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click on Create button",
|
||||
trigger: ".modal-footer .btn-primary",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait for editor to open",
|
||||
trigger: ":iframe body.editor_enable",
|
||||
timeout: 30000,
|
||||
},
|
||||
...clickOnSave(),
|
||||
...testWebsitePageProperties().finalize(),
|
||||
],
|
||||
);
|
||||
|
|
@ -1,49 +1,39 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import tour from "web_tour.tour";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { stepUtils } from "@web_tour/tour_utils";
|
||||
|
||||
const websiteName = "Website Test Settings";
|
||||
|
||||
tour.register("website_settings_m2o_dirty", {
|
||||
test: true,
|
||||
url: "/web",
|
||||
},
|
||||
[
|
||||
tour.stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
content: "open settings",
|
||||
trigger: ".o_app[data-menu-xmlid='base.menu_administration'",
|
||||
}, {
|
||||
content: "open website settings",
|
||||
trigger: ".settings_tab .tab[data-key='website']",
|
||||
}, {
|
||||
content: "check that the 'Shared Customers Accounts' setting is checked",
|
||||
trigger: "input#shared_user_account:checked",
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "open website switcher",
|
||||
trigger: "input#website_id",
|
||||
}, {
|
||||
content: `select ${websiteName} in the website switcher`,
|
||||
trigger: `li:has(.dropdown-item:contains('${websiteName}'))`,
|
||||
}, {
|
||||
content: `check that the settings of ${websiteName} are loaded (Shared Customers Accounts)`,
|
||||
trigger: "input#shared_user_account:not(:checked)",
|
||||
run: function () {}, // it's a check
|
||||
}, {
|
||||
content: "click on the fake website setting after checking the edited website",
|
||||
trigger: "button[name='action_website_test_setting']",
|
||||
}, {
|
||||
content: "check that we are on '/'",
|
||||
trigger: "iframe body div#wrap",
|
||||
run: function () {
|
||||
if (window.location.pathname !== "/") {
|
||||
// If this fails, it's probably because the change of website
|
||||
// in the settings dirty the record and so there is a dialog
|
||||
// save/discard displayed. This test ensure that does not happen
|
||||
// because it makes actions unreachable in multi website.
|
||||
console.error("We should be on '/' the settings didn't work");
|
||||
}
|
||||
}
|
||||
},
|
||||
]);
|
||||
registry.category("web_tour.tours").add("website_settings_m2o_dirty", {
|
||||
url: "/odoo",
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
content: "open settings",
|
||||
trigger: ".o_app[data-menu-xmlid='base.menu_administration']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "open website settings",
|
||||
trigger: ".settings_tab .tab[data-key='website']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "check that the 'Shared Customers Accounts' setting is checked",
|
||||
trigger: "input[id^='shared_user_account']:checked",
|
||||
},
|
||||
{
|
||||
content: "open website switcher",
|
||||
trigger: "input[id^='website_id']",
|
||||
run: `edit ${websiteName}`,
|
||||
},
|
||||
{
|
||||
content: `select ${websiteName} in the website switcher`,
|
||||
trigger: `li:has(.dropdown-item:contains('${websiteName}'))`,
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: `check that the settings of ${websiteName} are loaded (Shared Customers Accounts)`,
|
||||
trigger: "input[id^='shared_user_account']:not(:checked)",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue