mirror of
https://github.com/bringout/oca-ocb-test.git
synced 2026-04-20 01:42:03 +02:00
Initial commit: Test packages
This commit is contained in:
commit
080accd21c
338 changed files with 32413 additions and 0 deletions
|
|
@ -0,0 +1,137 @@
|
|||
/** @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"]'));
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
odoo.define('test_website.custom_snippets', function (require) {
|
||||
'use strict';
|
||||
|
||||
const wTourUtils = require('website.tour_utils');
|
||||
|
||||
/**
|
||||
* The purpose of this tour is to check the custom snippets flow:
|
||||
*
|
||||
* -> go to edit mode
|
||||
* -> drag a banner into page content
|
||||
* -> customize banner (set text)
|
||||
* -> save banner as custom snippet
|
||||
* -> confirm save
|
||||
* -> ensure custom snippet is available
|
||||
* -> drag custom snippet
|
||||
* -> ensure block appears as banner
|
||||
* -> ensure block appears as custom banner
|
||||
* -> rename custom banner
|
||||
* -> verify rename took effect
|
||||
* -> delete custom snippet
|
||||
* -> confirm delete
|
||||
* -> ensure it was deleted
|
||||
*/
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_custom_snippet', {
|
||||
url: '/',
|
||||
edition: true,
|
||||
test: true,
|
||||
}, [
|
||||
{
|
||||
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: "text",
|
||||
consumeEvent: "input",
|
||||
},
|
||||
{
|
||||
content: "save custom snippet",
|
||||
trigger: ".snippet-option-SnippetSave we-button",
|
||||
},
|
||||
{
|
||||
content: "confirm reload",
|
||||
trigger: ".modal-dialog button span:contains('Save and Reload')",
|
||||
},
|
||||
{
|
||||
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: "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: "set name",
|
||||
trigger: ".oe_snippet[name='Custom Banner'] input",
|
||||
run: "text Bruce Banner",
|
||||
},
|
||||
{
|
||||
content: "confirm rename",
|
||||
trigger: ".oe_snippet[name='Custom Banner'] we-button.o_we_confirm_btn",
|
||||
},
|
||||
{
|
||||
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: "ensure banner section exists",
|
||||
trigger: "iframe #wrap section[data-name='Banner']",
|
||||
run: function () {}, // check
|
||||
},
|
||||
{
|
||||
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: "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: "confirm delete",
|
||||
trigger: ".modal-dialog button:has(span:contains('Yes'))",
|
||||
},
|
||||
{
|
||||
content: "ensure custom snippet disappeared",
|
||||
trigger: "#oe_snippets:not(:has(.oe_snippet[name='Bruce Banner']))",
|
||||
run: function () {}, // check
|
||||
},
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
odoo.define('test_website.error_views', function (require) {
|
||||
'use strict';
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
|
||||
tour.register('test_error_website', {
|
||||
test: true,
|
||||
url: '/test_error_view',
|
||||
},
|
||||
[
|
||||
// RPC ERROR
|
||||
{
|
||||
content: "trigger rpc user error",
|
||||
trigger: 'a[href="/test_user_error_json"]',
|
||||
}, {
|
||||
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',
|
||||
}, {
|
||||
content: "trigger rpc access error",
|
||||
trigger: 'a[href="/test_access_error_json"]',
|
||||
}, {
|
||||
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',
|
||||
}, {
|
||||
content: "trigger validation rpc error",
|
||||
trigger: 'a[href="/test_validation_error_json"]',
|
||||
}, {
|
||||
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',
|
||||
}, {
|
||||
content: "trigger rpc missing error",
|
||||
trigger: 'a[href="/test_missing_error_json"]',
|
||||
}, {
|
||||
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',
|
||||
}, {
|
||||
content: "trigger rpc error 403",
|
||||
trigger: 'a[href="/test_access_denied_json"]',
|
||||
}, {
|
||||
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',
|
||||
}, {
|
||||
content: "trigger rpc error 500",
|
||||
trigger: 'a[href="/test_internal_error_json"]',
|
||||
}, {
|
||||
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',
|
||||
},
|
||||
// HTTP ERROR
|
||||
{
|
||||
content: "trigger http user error",
|
||||
trigger: 'body',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/test_user_error_http?debug=0';
|
||||
},
|
||||
}, {
|
||||
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';
|
||||
},
|
||||
}, {
|
||||
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';
|
||||
},
|
||||
}, {
|
||||
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';
|
||||
},
|
||||
}, {
|
||||
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';
|
||||
},
|
||||
}, {
|
||||
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';
|
||||
},
|
||||
}, {
|
||||
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_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")',
|
||||
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 !
|
||||
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 () {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import wTourUtils from 'website.tour_utils';
|
||||
|
||||
/**
|
||||
* The purpose of this tour is to check the link on image flow.
|
||||
*/
|
||||
|
||||
const selectImageSteps = [{
|
||||
content: "select block",
|
||||
trigger: "iframe #wrapwrap .s_text_image",
|
||||
}, {
|
||||
content: "check link popover disappeared",
|
||||
trigger: "iframe body:not(:has(.o_edit_menu_popover))",
|
||||
run: () => {}, // check
|
||||
}, {
|
||||
content: "select image",
|
||||
trigger: "iframe #wrapwrap .s_text_image img",
|
||||
}];
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_image_link', {
|
||||
test: true,
|
||||
url: '/',
|
||||
edition: true,
|
||||
}, [
|
||||
wTourUtils.dragNDrop({
|
||||
id: 's_text_image',
|
||||
name: 'Text - Image',
|
||||
}),
|
||||
...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",
|
||||
}, {
|
||||
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",
|
||||
},
|
||||
...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
|
||||
}, {
|
||||
content: "remove URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "remove_text",
|
||||
},
|
||||
...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
|
||||
}, {
|
||||
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",
|
||||
},
|
||||
...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
|
||||
}, {
|
||||
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",
|
||||
},
|
||||
...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
|
||||
}, {
|
||||
content: "remove URL",
|
||||
trigger: "#oe_snippets we-customizeblock-options:has(we-title:contains('Image')) we-input:contains(Your URL) input",
|
||||
run: "remove_text",
|
||||
},
|
||||
...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
|
||||
},
|
||||
]);
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
odoo.define('test_website.image_upload_progress', function (require) {
|
||||
'use strict';
|
||||
|
||||
const wTourUtils = require('website.tour_utils');
|
||||
|
||||
const { FileSelectorControlPanel } = require('@web_editor/components/media_dialog/file_selector');
|
||||
const { patch, unpatch } = require('web.utils');
|
||||
|
||||
let patchWithError = false;
|
||||
const patchMediaDialog = () => patch(FileSelectorControlPanel.prototype, 'test_website.mock_image_widgets', {
|
||||
async onChangeFileInput() {
|
||||
const getFileFromB64 = (fileData) => {
|
||||
const binary = atob(fileData[2]);
|
||||
let len = binary.length;
|
||||
const arr = new Uint8Array(len);
|
||||
while (len--) {
|
||||
arr[len] = binary.charCodeAt(len);
|
||||
}
|
||||
return new File([arr], fileData[1], {type: fileData[0]});
|
||||
};
|
||||
|
||||
let files = [
|
||||
getFileFromB64(['image/vnd.microsoft.icon', 'icon.ico', "AAABAAEAAQEAAAEAIAAwAAAAFgAAACgAAAABAAAAAgAAAAEAIAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA=="]),
|
||||
getFileFromB64(['image/webp', 'image.webp', "UklGRhwAAABXRUJQVlA4TBAAAAAvE8AEAAfQhuh//wMR0f8A"]),
|
||||
getFileFromB64(['image/png', 'image.png', "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAApElEQVR42u3RAQ0AAAjDMO5fNCCDkC5z0HTVrisFCBABASIgQAQEiIAAAQJEQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAREQIAICBABASIgQAQECBAgAgJEQIAIyPcGFY7HnV2aPXoAAAAASUVORK5CYII="]),
|
||||
getFileFromB64(['image/jpeg', 'image.jpeg', "/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAA0NDQ0ODQ4QEA4UFhMWFB4bGRkbHi0gIiAiIC1EKjIqKjIqRDxJOzc7STxsVUtLVWx9aWNpfZeHh5e+tb75+f8BDQ0NDQ4NDhAQDhQWExYUHhsZGRseLSAiICIgLUQqMioqMipEPEk7NztJPGxVS0tVbH1pY2l9l4eHl761vvn5///CABEIAEsASwMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAABv/aAAgBAQAAAACHAAAAAAAAAAAAAAAAH//EABUBAQEAAAAAAAAAAAAAAAAAAAAH/9oACAECEAAAAKYAAAB//8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/2gAIAQMQAAAAngAAAf/EABQQAQAAAAAAAAAAAAAAAAAAAGD/2gAIAQEAAT8ASf/EABQRAQAAAAAAAAAAAAAAAAAAAED/2gAIAQIBAT8AT//EABQRAQAAAAAAAAAAAAAAAAAAAED/2gAIAQMBAT8AT//Z"]),
|
||||
];
|
||||
|
||||
if (!this.props.multiSelect) {
|
||||
if (patchWithError) {
|
||||
files = [files[0]];
|
||||
} else {
|
||||
files = [files[2]];
|
||||
}
|
||||
}
|
||||
await this.props.uploadFiles(files);
|
||||
}
|
||||
});
|
||||
|
||||
const unpatchMediaDialog = () => unpatch(FileSelectorControlPanel.prototype, 'test_website.mock_image_widgets');
|
||||
|
||||
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 formatErrorMsg = "format is not supported. Try with: .gif, .jpe, .jpeg, .jpg, .png, .svg";
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_image_upload_progress', {
|
||||
url: '/test_image_progress',
|
||||
test: true,
|
||||
edition: true,
|
||||
}, [
|
||||
...setupSteps,
|
||||
// 1. Check multi image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_image_gallery .img",
|
||||
}, {
|
||||
content: "click on add images to open image dialog (in multi mode)",
|
||||
trigger: 'we-customizeblock-option [data-add-images]',
|
||||
}, {
|
||||
content: "manually trigger input change",
|
||||
trigger: ".o_select_media_dialog .o_upload_media_button",
|
||||
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'));
|
||||
},
|
||||
}, {
|
||||
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
|
||||
}, {
|
||||
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;
|
||||
if (notificationCount !== 1) {
|
||||
console.error("There should be one noficiation toaster opened, and only one.");
|
||||
}
|
||||
}
|
||||
}, {
|
||||
content: "close notification",
|
||||
trigger: '.o_notification_close',
|
||||
in_modal: false,
|
||||
}, {
|
||||
content: "close media dialog",
|
||||
trigger: '.modal-footer .btn-secondary',
|
||||
},
|
||||
// 2. Check success single image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_text_image .img",
|
||||
}, {
|
||||
content: "click on replace media to open image dialog",
|
||||
trigger: 'we-customizeblock-option [data-replace-media]',
|
||||
}, {
|
||||
content: "manually trigger input change",
|
||||
trigger: ".o_select_media_dialog .o_upload_media_button",
|
||||
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'));
|
||||
},
|
||||
}, {
|
||||
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;
|
||||
if (notificationCount !== 1) {
|
||||
console.error("There should be one noficiation toaster opened, and only one.");
|
||||
}
|
||||
}
|
||||
}, {
|
||||
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",
|
||||
}, {
|
||||
content: "click on replace media to open image dialog",
|
||||
trigger: 'we-customizeblock-option [data-replace-media]',
|
||||
}, {
|
||||
content: "manually trigger input change",
|
||||
trigger: ".o_select_media_dialog .o_upload_media_button",
|
||||
in_modal: false,
|
||||
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.
|
||||
document.body.querySelector('.o_select_media_dialog .o_file_input').dispatchEvent(new Event('change'));
|
||||
|
||||
},
|
||||
}, {
|
||||
content: "check upload progress bar is correctly shown",
|
||||
trigger: `.o_we_progressbar:contains('icon.ico'):contains('${formatErrorMsg}')`,
|
||||
in_modal: false,
|
||||
run: function () {
|
||||
patchWithError = false;
|
||||
},
|
||||
}, {
|
||||
content: "there should only have one notification toaster",
|
||||
trigger: ".o_notification",
|
||||
in_modal: false,
|
||||
run: () => {
|
||||
const notificationCount = $('.o_notification').length;
|
||||
if (notificationCount !== 1) {
|
||||
console.error("There should be one noficiation toaster opened, and only one.");
|
||||
}
|
||||
unpatchMediaDialog();
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_image_upload_progress_unsplash', {
|
||||
url: '/test_image_progress',
|
||||
test: true,
|
||||
edition: true,
|
||||
}, [
|
||||
...setupSteps,
|
||||
// 1. Check multi image upload
|
||||
{
|
||||
content: "click on dropped snippet",
|
||||
trigger: "iframe #wrap .s_image_gallery .img",
|
||||
}, {
|
||||
content: "click on replace media to open image dialog",
|
||||
trigger: 'we-customizeblock-option [data-replace-media]',
|
||||
}, {
|
||||
content: "search 'fox' images",
|
||||
trigger: ".o_we_search",
|
||||
run: "text fox",
|
||||
}, {
|
||||
content: "click on unsplash result", // note that unsplash is mocked
|
||||
trigger: "img[alt~=fox]"
|
||||
}, {
|
||||
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,
|
||||
}, {
|
||||
content: "unsplash image (mocked to logo) should have been used",
|
||||
trigger: "iframe #wrap .s_image_gallery .img[data-original-src^='/unsplash/HQqIOc8oYro/fox']",
|
||||
run: () => {
|
||||
unpatchMediaDialog();
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
odoo.define('test_website.json_auth', function (require) {
|
||||
'use strict';
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
var session = require('web.session')
|
||||
|
||||
tour.register('test_json_auth', {
|
||||
test: true,
|
||||
}, [{
|
||||
trigger: 'body',
|
||||
run: async function () {
|
||||
await session.rpc('/test_get_dbname').then( function (result){
|
||||
return session.rpc("/web/session/authenticate", {
|
||||
db: result,
|
||||
login: 'admin',
|
||||
password: 'admin'
|
||||
});
|
||||
});
|
||||
window.location.href = window.location.origin;
|
||||
},
|
||||
}, {
|
||||
trigger: 'span:contains(Mitchell Admin), span:contains(Administrator)',
|
||||
run: function () {},
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
tour.register('test_website_page_manager', {
|
||||
test: true,
|
||||
url: '/web#action=test_website.action_test_model_multi_website',
|
||||
}, [
|
||||
// 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",
|
||||
}, {
|
||||
content: "Check that there is only 2 records selected",
|
||||
trigger: ".o_list_selection_box:contains('2 selected')",
|
||||
run: () => null, // it's a check
|
||||
}, {
|
||||
content: "Click on My Website search filter",
|
||||
trigger: "button.dropdown-toggle:contains('My Website')",
|
||||
}, {
|
||||
content: "Select My Website 2",
|
||||
trigger: ".dropdown-menu.show > .dropdown-item:contains('My Website 2')",
|
||||
}, {
|
||||
// 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',
|
||||
}, {
|
||||
content: "Click on List View",
|
||||
extra_trigger: '.o_kanban_renderer',
|
||||
trigger: '.o_cp_switch_buttons .o_list',
|
||||
}, {
|
||||
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',
|
||||
}, [{
|
||||
content: "Click on Kanban View",
|
||||
trigger: '.o_cp_switch_buttons .o_kanban',
|
||||
}, {
|
||||
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',
|
||||
}, [{
|
||||
content: "Click on Kanban View",
|
||||
trigger: '.o_cp_switch_buttons .o_kanban',
|
||||
}, {
|
||||
content: "Wait for Kanban View to be loaded",
|
||||
trigger: '.o_kanban_renderer',
|
||||
run: () => null, // it's a check
|
||||
}]);
|
||||
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/** @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';
|
||||
|
||||
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', {
|
||||
url: '/',
|
||||
test: true,
|
||||
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 and
|
||||
// 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", {
|
||||
async _getVideoURLData(src, options) {
|
||||
if (src === VIDEO_URL || src === 'about:blank') {
|
||||
return {platform: 'youtube', embed_url: 'about:blank'};
|
||||
}
|
||||
return this._super(...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",
|
||||
},
|
||||
{
|
||||
content: "select image",
|
||||
trigger: "iframe .s_picture figure img",
|
||||
},
|
||||
{
|
||||
content: "ensure image size is displayed",
|
||||
trigger: "#oe_snippets we-title:contains('Image') .o_we_image_weight:contains('kb')",
|
||||
run: function () {}, // check
|
||||
},
|
||||
wTourUtils.changeOption("ImageTools", 'we-select[data-name="shape_img_opt"] we-toggler'),
|
||||
wTourUtils.changeOption("ImageTools", "we-button[data-set-img-shape]"),
|
||||
{
|
||||
content: "replace image",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
},
|
||||
{
|
||||
content: "select svg",
|
||||
trigger: ".o_select_media_dialog img[title='sample.svg']",
|
||||
},
|
||||
{
|
||||
content: "ensure the svg doesn't have a shape",
|
||||
trigger: "iframe .s_picture figure img:not([data-shape])",
|
||||
run: function () {}, // check
|
||||
},
|
||||
{
|
||||
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: "replace image",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
},
|
||||
{
|
||||
content: "go to pictogram tab",
|
||||
trigger: ".o_select_media_dialog .nav-link:contains('Icons')",
|
||||
},
|
||||
{
|
||||
content: "select an icon",
|
||||
trigger: ".o_select_media_dialog:has(.nav-link.active:contains('Icons')) .tab-content span.fa-lemon-o",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
},
|
||||
{
|
||||
content: "select footer",
|
||||
trigger: "iframe footer",
|
||||
},
|
||||
{
|
||||
content: "select icon",
|
||||
trigger: "iframe .s_picture figure span.fa-lemon-o",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is still displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
},
|
||||
{
|
||||
content: "replace icon",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
},
|
||||
{
|
||||
content: "go to video tab",
|
||||
trigger: ".o_select_media_dialog .nav-link:contains('Video')",
|
||||
},
|
||||
{
|
||||
content: "enter a video URL",
|
||||
trigger: ".o_select_media_dialog #o_video_text",
|
||||
// Design your first web page.
|
||||
run: `text ${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
|
||||
},
|
||||
{
|
||||
content: "confirm selection",
|
||||
trigger: ".o_select_media_dialog .modal-footer .btn-primary",
|
||||
},
|
||||
{
|
||||
content: "ensure video option block is displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Video')",
|
||||
run: function () {}, // check
|
||||
},
|
||||
{
|
||||
content: "replace image",
|
||||
trigger: "#oe_snippets we-button[data-replace-media]",
|
||||
},
|
||||
{
|
||||
content: "go to pictogram tab",
|
||||
trigger: ".o_select_media_dialog .nav-link:contains('Icons')",
|
||||
},
|
||||
{
|
||||
content: "select an icon",
|
||||
trigger: ".o_select_media_dialog:has(.nav-link.active:contains('Icons')) .tab-content span.fa-lemon-o",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
},
|
||||
{
|
||||
content: "select footer",
|
||||
trigger: "iframe footer",
|
||||
},
|
||||
{
|
||||
content: "select icon",
|
||||
trigger: "iframe .s_picture figure span.fa-lemon-o",
|
||||
},
|
||||
{
|
||||
content: "ensure icon block is still displayed",
|
||||
trigger: "#oe_snippets we-customizeblock-options we-title:contains('Icon')",
|
||||
run: function () {}, // check
|
||||
},
|
||||
]);
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/* global ace */
|
||||
odoo.define('test_website.reset_views', function (require) {
|
||||
'use strict';
|
||||
|
||||
const wTourUtils = require('website.tour_utils');
|
||||
|
||||
var BROKEN_STEP = {
|
||||
// because saving a broken template opens a recovery page with no assets
|
||||
// there's no way for the tour to resume on the new page, and thus no way
|
||||
// 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 () {}
|
||||
};
|
||||
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,
|
||||
},
|
||||
[
|
||||
{
|
||||
content: "drop a snippet",
|
||||
trigger: ".oe_snippet:has(.s_cover) .oe_snippet_thumbnail",
|
||||
// id starting by 'oe_structure..' will actually create an inherited view
|
||||
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]",
|
||||
},
|
||||
// 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"]',
|
||||
},
|
||||
{
|
||||
content: "open html editor",
|
||||
trigger: 'a[data-menu-xmlid="website.menu_ace_editor"]',
|
||||
},
|
||||
{
|
||||
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');
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "save the html editor",
|
||||
extra_trigger: '.ace_content:contains("not.exist")',
|
||||
trigger: ".o_ace_view_editor button[data-action=save]",
|
||||
},
|
||||
BROKEN_STEP
|
||||
]
|
||||
);
|
||||
|
||||
wTourUtils.registerWebsitePreviewTour('test_reset_page_view_complete_flow_part2', {
|
||||
test: true,
|
||||
url: '/test_page_view',
|
||||
},
|
||||
[
|
||||
{
|
||||
content: "check that the view got fixed",
|
||||
trigger: 'iframe p:containsExact("Test Page View")',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
{
|
||||
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
|
||||
},
|
||||
//4. Now break the inherited view created when dropping a snippet
|
||||
{
|
||||
content: "open site menu",
|
||||
trigger: 'button[data-menu-xmlid="website.menu_site"]',
|
||||
},
|
||||
{
|
||||
content: "open html editor",
|
||||
trigger: 'a[data-menu-xmlid="website.menu_ace_editor"]',
|
||||
},
|
||||
{
|
||||
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');
|
||||
},
|
||||
},
|
||||
{
|
||||
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');
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "save the html editor",
|
||||
trigger: ".o_ace_view_editor button[data-action=save]",
|
||||
},
|
||||
BROKEN_STEP
|
||||
]
|
||||
);
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import wTourUtils from 'website.tour_utils';
|
||||
|
||||
/**
|
||||
* The purpose of these tours is to check the systray visibility:
|
||||
*
|
||||
* - as an administrator
|
||||
* - as a restricted editor with "tester" right
|
||||
* - as a restricted editor without "tester" right
|
||||
* - as a "tester" who is not a restricted editor
|
||||
* - as an unrelated user (neither "tester" nor restricted editor)
|
||||
*/
|
||||
|
||||
const canPublish = [{
|
||||
content: 'Publish',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Unpublished")',
|
||||
}, {
|
||||
content: 'Wait for Publish',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Published"):not([data-processing])',
|
||||
run: () => {}, // This is a check.
|
||||
}, {
|
||||
content: 'Unpublish',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item:contains("Published")',
|
||||
}, {
|
||||
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',
|
||||
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)',
|
||||
}, {
|
||||
content: 'Disable mobile preview',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_mobile_preview.o_mobile_preview_active',
|
||||
}];
|
||||
|
||||
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 = [{
|
||||
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"))',
|
||||
}, {
|
||||
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.
|
||||
}];
|
||||
|
||||
|
||||
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"))',
|
||||
}, {
|
||||
content: 'Switch to other website',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_website_switcher_container .dropdown-item:contains("Other")',
|
||||
}, {
|
||||
content: 'Wait for other website',
|
||||
trigger: 'iframe body:contains("Test Model") div:contains("Other")',
|
||||
run: () => {}, // This is a check.
|
||||
}];
|
||||
|
||||
const canAddNewContent = [{
|
||||
content: 'Open +New content',
|
||||
trigger: '.o_menu_systray .o_menu_systray_item.o_new_content_container',
|
||||
}, {
|
||||
content: 'Close +New content',
|
||||
trigger: '#o_new_content_menu_choices',
|
||||
}];
|
||||
|
||||
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',
|
||||
trigger: '.o_menu_systray .o_website_edit_in_backend a',
|
||||
}, {
|
||||
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',
|
||||
}];
|
||||
|
||||
const canViewInBackEnd = [{
|
||||
content: 'Go to backend',
|
||||
trigger: '.o_menu_systray .o_website_edit_in_backend a',
|
||||
}, {
|
||||
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',
|
||||
}];
|
||||
|
||||
const canEdit = [
|
||||
...wTourUtils.clickOnEditAndWaitEditMode(),
|
||||
{
|
||||
content: 'Click on name',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"][contenteditable="true"]',
|
||||
}, {
|
||||
content: 'Change name',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"][contenteditable="true"]',
|
||||
run: 'text Better name',
|
||||
}, {
|
||||
content: 'Check that field becomes dirty',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"].o_dirty',
|
||||
run: () => {}, // This is a check.
|
||||
},
|
||||
...wTourUtils.clickOnSave(),
|
||||
{
|
||||
content: 'Check whether name is saved',
|
||||
trigger: 'iframe span[data-oe-expression="test_model.name"]:contains("Better name")',
|
||||
run: () => {}, // This is a check.
|
||||
},
|
||||
];
|
||||
|
||||
const cannotEdit = [{
|
||||
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(),
|
||||
{
|
||||
content: 'Cannot change name',
|
||||
trigger: 'iframe main:not(:has([data-oe-expression])):contains("Test Model")',
|
||||
run: () => {}, // This is a check.
|
||||
},
|
||||
];
|
||||
|
||||
const register = (title, steps) => {
|
||||
wTourUtils.registerWebsitePreviewTour(title, {
|
||||
url: '/test_model/1',
|
||||
test: true,
|
||||
}, steps);
|
||||
};
|
||||
|
||||
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_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_not_tester', [
|
||||
...cannotPublish,
|
||||
...cannotToggleMobilePreview,
|
||||
...canSwitchWebsiteNoCheck,
|
||||
...cannotAddNewContent,
|
||||
...canViewInBackEnd,
|
||||
...cannotEdit,
|
||||
]);
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import tour from "web_tour.tour";
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
},
|
||||
]);
|
||||
Loading…
Add table
Add a link
Reference in a new issue