summaryrefslogtreecommitdiff
path: root/addons/web/static/tests/widgets/data_export_tests.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/tests/widgets/data_export_tests.js')
-rw-r--r--addons/web/static/tests/widgets/data_export_tests.js421
1 files changed, 421 insertions, 0 deletions
diff --git a/addons/web/static/tests/widgets/data_export_tests.js b/addons/web/static/tests/widgets/data_export_tests.js
new file mode 100644
index 00000000..2e2cae1c
--- /dev/null
+++ b/addons/web/static/tests/widgets/data_export_tests.js
@@ -0,0 +1,421 @@
+odoo.define('web.data_export_tests', function (require) {
+"use strict";
+
+const data = require('web.data');
+const framework = require('web.framework');
+const ListView = require('web.ListView');
+const testUtils = require('web.test_utils');
+
+const cpHelpers = testUtils.controlPanel;
+const createView = testUtils.createView;
+
+QUnit.module('widgets', {
+ beforeEach: function () {
+ this.data = {
+ 'partner': {
+ fields: {
+ foo: {string: "Foo", type: "char"},
+ bar: {string: "Bar", type: "char"},
+ unexportable: {string: "Unexportable", type: "boolean", exportable: false},
+ },
+ records: [
+ {
+ id: 1,
+ foo: "yop",
+ bar: "bar-blup",
+ }, {
+ id: 2,
+ foo: "yop",
+ bar: "bar-yop",
+ }, {
+ id: 3,
+ foo: "blup",
+ bar: "bar-blup",
+ }
+ ]
+ },
+ 'ir.exports': {
+ fields: {
+ name: {string: "Name", type: "char"},
+ },
+ records: [],
+ },
+ };
+ this.mockSession = {
+ async user_has_group(g) { return g === 'base.group_allow_export'; }
+ }
+ this.mockDataExportRPCs = function (route) {
+ if (route === '/web/export/formats') {
+ return Promise.resolve([
+ {tag: 'csv', label: 'CSV'},
+ {tag: 'xls', label: 'Excel'},
+ ]);
+ }
+ if (route === '/web/export/get_fields') {
+ return Promise.resolve([
+ {
+ field_type: "one2many",
+ string: "Activities",
+ required: false,
+ value: "activity_ids/id",
+ id: "activity_ids",
+ params: {"model": "mail.activity", "prefix": "activity_ids", "name": "Activities"},
+ relation_field: "res_id",
+ children: true,
+ }, {
+ children: false,
+ field_type: 'char',
+ id: "foo",
+ relation_field: null,
+ required: false,
+ string: 'Foo',
+ value: "foo",
+ }
+ ]);
+ }
+ return this._super.apply(this, arguments);
+ };
+ }
+}, function () {
+
+ QUnit.module('Data Export');
+
+
+ QUnit.test('exporting all data in list view', async function (assert) {
+ assert.expect(8);
+
+ var blockUI = framework.blockUI;
+ var unblockUI = framework.unblockUI;
+ framework.blockUI = function () {
+ assert.step('block UI');
+ };
+ framework.unblockUI = function () {
+ assert.step('unblock UI');
+ };
+
+ var list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: '<tree><field name="foo"/></tree>',
+ viewOptions: {
+ hasActionMenus: true,
+ },
+ mockRPC: this.mockDataExportRPCs,
+ session: {
+ ...this.mockSession,
+ get_file: function (params) {
+ assert.step(params.url);
+ params.complete();
+ },
+ },
+ });
+
+
+ await testUtils.dom.click(list.$('thead th.o_list_record_selector input'));
+
+ await cpHelpers.toggleActionMenu(list);
+ await cpHelpers.toggleMenuItem(list, 'Export');
+
+ assert.strictEqual($('.modal').length, 1, "a modal dialog should be open");
+ assert.strictEqual($('div.o_tree_column:contains(Activities)').length, 1,
+ "the Activities field should be in the list of exportable fields");
+ assert.strictEqual($('.modal .o_export_field').length, 1, "There should be only one export field");
+ assert.strictEqual($('.modal .o_export_field').data('field_id'), 'foo', "There should be only one export field");
+
+ // select the field Description, click on add, then export and close
+ await testUtils.dom.click($('.modal .o_tree_column:contains(Foo) .o_add_field'));
+ await testUtils.dom.click($('.modal span:contains(Export)'));
+ await testUtils.dom.click($('.modal span:contains(Close)'));
+ list.destroy();
+ framework.blockUI = blockUI;
+ framework.unblockUI = unblockUI;
+ assert.verifySteps([
+ 'block UI',
+ '/web/export/csv',
+ 'unblock UI',
+ ]);
+ });
+
+ QUnit.test('exporting data in list view (multi pages)', async function (assert) {
+ assert.expect(4);
+
+ let expectedData;
+ const list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: '<tree limit="2"><field name="foo"/></tree>',
+ domain: [['id', '<', 1000]],
+ viewOptions: {
+ hasActionMenus: true,
+ },
+ mockRPC: this.mockDataExportRPCs,
+ session: {
+ ...this.mockSession,
+ get_file: function (params) {
+ const data = JSON.parse(params.data.data);
+ assert.deepEqual({ids: data.ids, domain: data.domain}, expectedData);
+ params.complete();
+ },
+ },
+ });
+
+ // select all records (first page) and export
+ expectedData = {
+ ids: [1, 2],
+ domain: [['id', '<', 1000]],
+ };
+ await testUtils.dom.click(list.$('thead th.o_list_record_selector input'));
+
+ await cpHelpers.toggleActionMenu(list);
+ await cpHelpers.toggleMenuItem(list, 'Export');
+
+ assert.containsOnce(document.body, '.modal');
+
+ await testUtils.dom.click($('.modal span:contains(Export)'));
+ await testUtils.dom.click($('.modal span:contains(Close)'));
+
+ // select all domain and export
+ expectedData = {
+ ids: false,
+ domain: [['id', '<', 1000]],
+ };
+ await testUtils.dom.click(list.$('.o_list_selection_box .o_list_select_domain'));
+
+ await cpHelpers.toggleActionMenu(list);
+ await cpHelpers.toggleMenuItem(list, 'Export');
+
+ assert.containsOnce(document.body, '.modal');
+
+ await testUtils.dom.click($('.modal span:contains(Export)'));
+ await testUtils.dom.click($('.modal span:contains(Close)'));
+
+ list.destroy();
+ });
+
+ QUnit.test('exporting view with non-exportable field', async function (assert) {
+ assert.expect(0);
+
+ var list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: '<tree><field name="unexportable"/></tree>',
+ viewOptions: {
+ hasActionMenus: true,
+ },
+ mockRPC: this.mockDataExportRPCs,
+ session: {
+ ...this.mockSession,
+ get_file: function (params) {
+ assert.step(params.url);
+ params.complete();
+ },
+ },
+ });
+
+ await testUtils.dom.click(list.$('thead th.o_list_record_selector input'));
+
+ await cpHelpers.toggleActionMenu(list);
+ await cpHelpers.toggleMenuItem(list, 'Export');
+
+ list.destroy();
+ });
+
+ QUnit.test('saving fields list when exporting data', async function (assert) {
+ assert.expect(4);
+
+ var create = data.DataSet.prototype.create;
+
+ data.DataSet.prototype.create = function () {
+ assert.step('create');
+ return Promise.resolve([]);
+ };
+
+ var list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: '<tree><field name="foo"/></tree>',
+ viewOptions: {
+ hasActionMenus: true,
+ },
+ session: this.mockSession,
+ mockRPC: this.mockDataExportRPCs,
+ });
+
+
+ // Open the export modal
+ await testUtils.dom.click(list.$('thead th.o_list_record_selector input'));
+ await cpHelpers.toggleActionMenu(list);
+ await cpHelpers.toggleMenuItem(list, 'Export');
+
+ assert.strictEqual($('.modal').length, 1,
+ "a modal dialog should be open");
+
+ // Select 'Activities' in fields to export
+ await testUtils.dom.click($('.modal .o_export_tree_item:contains(Activities) .o_add_field'));
+ assert.strictEqual($('.modal .o_fields_list .o_export_field').length, 2,
+ "there should be two items in the fields list");
+ // Save as template
+ await testUtils.fields.editAndTrigger($('.modal .o_exported_lists_select'), 'new_template', ['change']);
+ await testUtils.fields.editInput($('.modal .o_save_list .o_save_list_name'), 'fields list');
+ await testUtils.dom.click($('.modal .o_save_list .o_save_list_btn'));
+
+ assert.verifySteps(['create'],
+ "create should have been called");
+
+ // Close the modal and destroy list
+ await testUtils.dom.click($('.modal button span:contains(Close)'));
+ list.destroy();
+
+ // restore create function
+ data.DataSet.prototype.create = create;
+ });
+
+ QUnit.test('Export dialog UI test', async function (assert) {
+ assert.expect(5);
+ var list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: '<tree><field name="foo"/></tree>',
+ viewOptions: {
+ hasActionMenus: true,
+ },
+ session: this.mockSession,
+ mockRPC: this.mockDataExportRPCs,
+ });
+
+
+ // Open the export modal
+ await testUtils.dom.click(list.$('thead th.o_list_record_selector input'));
+ await cpHelpers.toggleActionMenu(list);
+ await cpHelpers.toggleMenuItem(list, 'Export');
+
+ assert.strictEqual($('.modal .o_export_tree_item:visible').length, 2, "There should be only two items visible");
+ await testUtils.dom.click($('.modal .o_export_search_input'));
+ $('.modal .o_export_search_input').val('Activities').trigger($.Event('input', {
+ keyCode: 65,
+ }));
+ assert.strictEqual($('.modal .o_export_tree_item:visible').length, 1, "Only match item visible");
+ // Add field
+ await testUtils.dom.click($('.modal div:contains(Activities) .o_add_field'));
+ assert.strictEqual($('.modal .o_fields_list li').length, 2, "There should be two fields in export field list.");
+ assert.strictEqual($('.modal .o_fields_list li:eq(1)').text(), "Activities",
+ "string of second field in export list should be 'Activities'");
+ // Remove field
+ await testUtils.dom.click($('.modal .o_fields_list li:first .o_remove_field'));
+ assert.strictEqual($('.modal .o_fields_list li').length, 1, "There should be only one field in list");
+ list.destroy();
+ });
+
+ QUnit.test('Direct export button invisible', async function (assert) {
+ assert.expect(1)
+
+ let list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: `<tree export_xlsx="0"><field name="foo"/></tree>`,
+ session: this.mockSession,
+ });
+ assert.containsNone(list, '.o_list_export_xlsx')
+ list.destroy();
+ });
+
+ QUnit.test('Direct export list ', async function (assert) {
+ assert.expect(2);
+
+ let list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: `
+ <tree export_xlsx="1">
+ <field name="foo"/>
+ <field name="bar"/>
+ </tree>`,
+ domain: [['bar', '!=', 'glou']],
+ session: {
+ ...this.mockSession,
+ get_file(args) {
+ let data = JSON.parse(args.data.data);
+ assert.strictEqual(args.url, '/web/export/xlsx', "should call get_file with the correct url");
+ assert.deepEqual(data, {
+ context: {},
+ model: 'partner',
+ domain: [['bar', '!=', 'glou']],
+ groupby: [],
+ ids: false,
+ import_compat: false,
+ fields: [{
+ name: 'foo',
+ label: 'Foo',
+ type: 'char',
+ }, {
+ name: 'bar',
+ label: 'Bar',
+ type: 'char',
+ }]
+ }, "should be called with correct params");
+ args.complete();
+ },
+ },
+ });
+
+ // Download
+ await testUtils.dom.click(list.$buttons.find('.o_list_export_xlsx'));
+
+ list.destroy();
+ });
+
+ QUnit.test('Direct export grouped list ', async function (assert) {
+ assert.expect(2);
+
+ let list = await createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: `
+ <tree>
+ <field name="foo"/>
+ <field name="bar"/>
+ </tree>`,
+ groupBy: ['foo', 'bar'],
+ domain: [['bar', '!=', 'glou']],
+ session: {
+ ...this.mockSession,
+ get_file(args) {
+ let data = JSON.parse(args.data.data);
+ assert.strictEqual(args.url, '/web/export/xlsx', "should call get_file with the correct url");
+ assert.deepEqual(data, {
+ context: {},
+ model: 'partner',
+ domain: [['bar', '!=', 'glou']],
+ groupby: ['foo', 'bar'],
+ ids: false,
+ import_compat: false,
+ fields: [{
+ name: 'foo',
+ label: 'Foo',
+ type: 'char',
+ }, {
+ name: 'bar',
+ label: 'Bar',
+ type: 'char',
+ }]
+ }, "should be called with correct params");
+ args.complete();
+ },
+ },
+ });
+
+ await testUtils.dom.click(list.$buttons.find('.o_list_export_xlsx'));
+
+ list.destroy();
+ });
+});
+
+});