[IMP] web: benchmark: revive benchmark suite
The benchmark suite has been broken for a while, by several refactorings (e.g. use of native Promise). This commit makes it work again. We do not use it much, but maybe we should as it can be useful to track changes (mostly in view renderers) that impact performances.
This commit is contained in:
@@ -1,94 +1,98 @@
|
||||
odoo.define('web.form_benchmarks', function (require) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
var FormView = require('web.FormView');
|
||||
var testUtils = require('web.test_utils');
|
||||
const FormView = require('web.FormView');
|
||||
const testUtils = require('web.test_utils');
|
||||
|
||||
var createView = testUtils.createView;
|
||||
const { createView } = testUtils;
|
||||
|
||||
QUnit.module('Form View', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
many2many: { string: "bar", type: "many2many", relation: 'bar'},
|
||||
QUnit.module('Form View', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
foo: {string: "Foo", type: "char"},
|
||||
many2many: { string: "bar", type: "many2many", relation: 'bar'},
|
||||
},
|
||||
records: [
|
||||
{ id: 1, foo: "bar", many2many: []},
|
||||
],
|
||||
onchanges: {}
|
||||
},
|
||||
records: [
|
||||
{ id: 1, many2many: []},
|
||||
],
|
||||
onchanges: {}
|
||||
},
|
||||
bar: {
|
||||
fields: {
|
||||
char: {string: "char", type: "char"},
|
||||
many2many: { string: "pokemon", type: "many2many", relation: 'pokemon'},
|
||||
bar: {
|
||||
fields: {
|
||||
char: {string: "char", type: "char"},
|
||||
many2many: { string: "pokemon", type: "many2many", relation: 'pokemon'},
|
||||
},
|
||||
records: [],
|
||||
onchanges: {}
|
||||
},
|
||||
records: [],
|
||||
onchanges: {}
|
||||
},
|
||||
pokemon: {
|
||||
fields: {
|
||||
name: {string: "Name", type: "char"},
|
||||
pokemon: {
|
||||
fields: {
|
||||
name: {string: "Name", type: "char"},
|
||||
},
|
||||
records: [],
|
||||
onchanges: {}
|
||||
},
|
||||
records: [],
|
||||
onchanges: {}
|
||||
},
|
||||
};
|
||||
this.arch = null;
|
||||
this.run = function (assert, done, cb) {
|
||||
var data = this.data;
|
||||
var arch = this.arch;
|
||||
new Benchmark.Suite({})
|
||||
.add('form', function () {
|
||||
var list = createView({
|
||||
View: FormView,
|
||||
model: 'foo',
|
||||
data: data,
|
||||
arch: arch,
|
||||
res_id: 1,
|
||||
});
|
||||
if (cb) {
|
||||
cb(list);
|
||||
}
|
||||
list.destroy();
|
||||
})
|
||||
.on('cycle', function(event) {
|
||||
assert.ok(true, String(event.target));
|
||||
})
|
||||
.on('complete', done)
|
||||
.run({ 'async': true });
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
QUnit.test('x2many with 250 rows, 2 fields (with many2many_tags, and modifiers), onchanges, and edition', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
|
||||
this.data.foo.onchanges.many2many = function (obj) {
|
||||
obj.many2many = [5].concat(obj.many2many);
|
||||
};
|
||||
for (var i = 2; i < 500; i) {
|
||||
this.data.bar.records.push({
|
||||
id: i,
|
||||
char: "automated data",
|
||||
});
|
||||
this.data.foo.records[0].many2many.push(i);
|
||||
};
|
||||
this.arch = null;
|
||||
this.run = function (assert, viewParams, cb) {
|
||||
const data = this.data;
|
||||
const arch = this.arch;
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite({})
|
||||
.add('form', {
|
||||
defer: true,
|
||||
fn: async (deferred) => {
|
||||
const form = await createView(Object.assign({
|
||||
View: FormView,
|
||||
model: 'foo',
|
||||
data,
|
||||
arch,
|
||||
}, viewParams));
|
||||
if (cb) {
|
||||
await cb(form);
|
||||
}
|
||||
form.destroy();
|
||||
deferred.resolve();
|
||||
},
|
||||
})
|
||||
.on('cycle', event => {
|
||||
assert.ok(true, String(event.target));
|
||||
})
|
||||
.on('complete', resolve)
|
||||
.run({ async: true });
|
||||
});
|
||||
};
|
||||
}
|
||||
this.arch =
|
||||
'<form string="Partners">' +
|
||||
'<field name="many2many">' +
|
||||
'<tree editable="top" limit="250">' +
|
||||
'<field name="char"/>' +
|
||||
'<field name="many2many" widget="many2many_tags" attrs="{\'readonly\': [(\'char\', \'==\', \'toto\')]}"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</form>';
|
||||
this.run(assert, done, function (form) {
|
||||
testUtils.form.clickEdit(form);
|
||||
form.$('.o_data_cell:first').click();
|
||||
form.$('input:first').val("tralala").trigger('input');
|
||||
}, function () {
|
||||
QUnit.test('x2many with 250 rows, 2 fields (with many2many_tags, and modifiers), onchanges, and edition', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
this.data.foo.onchanges.many2many = function (obj) {
|
||||
obj.many2many = [5].concat(obj.many2many);
|
||||
};
|
||||
for (let i = 2; i < 500; i++) {
|
||||
this.data.bar.records.push({
|
||||
id: i,
|
||||
char: "automated data",
|
||||
});
|
||||
this.data.foo.records[0].many2many.push(i);
|
||||
}
|
||||
this.arch = `
|
||||
<form>
|
||||
<field name="many2many">
|
||||
<tree editable="top" limit="250">
|
||||
<field name="char"/>
|
||||
<field name="many2many" widget="many2many_tags" attrs="{'readonly': [('char', '==', 'toto')]}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</form>`;
|
||||
return this.run(assert, { res_id: 1 }, async form => {
|
||||
await testUtils.form.clickEdit(form);
|
||||
await testUtils.dom.click(form.$('.o_data_cell:first'));
|
||||
await testUtils.fields.editInput(form.$('input:first'), "tralala");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,83 +1,92 @@
|
||||
odoo.define('web.kanban_benchmarks', function (require) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
var KanbanView = require('web.KanbanView');
|
||||
var testUtils = require('web.test_utils');
|
||||
const KanbanView = require('web.KanbanView');
|
||||
const { createView } = require('web.test_utils');
|
||||
|
||||
var createView = testUtils.createView;
|
||||
|
||||
QUnit.module('Kanban View', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
foo: {string: "Foo", type: "char"},
|
||||
bar: {string: "Bar", type: "boolean"},
|
||||
int_field: {string: "int_field", type: "integer", sortable: true},
|
||||
qux: {string: "my float", type: "float"},
|
||||
QUnit.module('Kanban View', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
foo: {string: "Foo", type: "char"},
|
||||
bar: {string: "Bar", type: "boolean"},
|
||||
int_field: {string: "int_field", type: "integer", sortable: true},
|
||||
qux: {string: "my float", type: "float"},
|
||||
},
|
||||
records: [
|
||||
{ id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4},
|
||||
{id: 2, bar: true, foo: "blip", int_field: 9, qux: 13},
|
||||
]
|
||||
},
|
||||
records: [
|
||||
{ id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4},
|
||||
{id: 2, bar: true, foo: "blip", int_field: 9, qux: 13},
|
||||
]
|
||||
},
|
||||
};
|
||||
this.arch = null;
|
||||
this.run = function (assert, done) {
|
||||
var data = this.data;
|
||||
var arch = this.arch;
|
||||
new Benchmark.Suite({})
|
||||
.add('kanban', function () {
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'foo',
|
||||
data: data,
|
||||
arch: arch,
|
||||
});
|
||||
kanban.destroy();
|
||||
})
|
||||
.on('cycle', function(event) {
|
||||
assert.ok(true, String(event.target));
|
||||
})
|
||||
.on('complete', done)
|
||||
.run({ 'async': true });
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
QUnit.test('simple kanban view with 2 records', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
|
||||
this.arch = '<kanban class="o_kanban_test"><templates><t t-name="kanban-box">' +
|
||||
'<div>' +
|
||||
'<t t-esc="record.foo.value"/>' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</t></templates></kanban>';
|
||||
|
||||
this.run(assert, done);
|
||||
});
|
||||
|
||||
QUnit.test('simple kanban view with 200 records', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
|
||||
for (var i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data" + i,
|
||||
});
|
||||
};
|
||||
this.arch = null;
|
||||
this.run = function (assert) {
|
||||
const data = this.data;
|
||||
const arch = this.arch;
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite({})
|
||||
.add('kanban', {
|
||||
defer: true,
|
||||
fn: async (deferred) => {
|
||||
const kanban = await createView({
|
||||
View: KanbanView,
|
||||
model: 'foo',
|
||||
data,
|
||||
arch,
|
||||
});
|
||||
kanban.destroy();
|
||||
deferred.resolve();
|
||||
},
|
||||
})
|
||||
.on('cycle', event => {
|
||||
assert.ok(true, String(event.target));
|
||||
})
|
||||
.on('complete', resolve)
|
||||
.run({ async: true });
|
||||
});
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
QUnit.test('simple kanban view with 2 records', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
this.arch = '<kanban class="o_kanban_test"><templates><t t-name="kanban-box">' +
|
||||
'<div>' +
|
||||
'<t t-esc="record.foo.value"/>' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</t></templates></kanban>';
|
||||
this.arch = `
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div>
|
||||
<t t-esc="record.foo.value"/>
|
||||
<field name="foo"/>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>`;
|
||||
return this.run(assert);
|
||||
});
|
||||
|
||||
this.run(assert, done);
|
||||
QUnit.test('simple kanban view with 200 records', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
for (let i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: `automated data ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
this.arch = `
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div>
|
||||
<t t-esc="record.foo.value"/>
|
||||
<field name="foo"/>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>`;
|
||||
return this.run(assert);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
odoo.define('web.list_benchmarks', function (require) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
var ListView = require('web.ListView');
|
||||
var testUtils = require('web.test_utils');
|
||||
const ListView = require('web.ListView');
|
||||
const { createView } = require('web.test_utils');
|
||||
|
||||
var createView = testUtils.createView;
|
||||
|
||||
QUnit.module('List View', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
foo: {string: "Foo", type: "char"},
|
||||
bar: {string: "Bar", type: "boolean"},
|
||||
int_field: {string: "int_field", type: "integer", sortable: true},
|
||||
qux: {string: "my float", type: "float"},
|
||||
QUnit.module('List View', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
foo: {string: "Foo", type: "char"},
|
||||
bar: {string: "Bar", type: "boolean"},
|
||||
int_field: {string: "int_field", type: "integer", sortable: true},
|
||||
qux: {string: "my float", type: "float"},
|
||||
},
|
||||
records: [
|
||||
{id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4},
|
||||
{id: 2, bar: true, foo: "blip", int_field: 9, qux: 13},
|
||||
]
|
||||
},
|
||||
records: [
|
||||
{ id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4},
|
||||
{id: 2, bar: true, foo: "blip", int_field: 9, qux: 13},
|
||||
]
|
||||
},
|
||||
};
|
||||
this.arch = null;
|
||||
this.run = function (assert, done, cb) {
|
||||
var data = this.data;
|
||||
var arch = this.arch;
|
||||
new Benchmark.Suite({})
|
||||
.add('list', function () {
|
||||
var list = createView({
|
||||
View: ListView,
|
||||
model: 'foo',
|
||||
data: data,
|
||||
arch: arch,
|
||||
});
|
||||
if (cb) {
|
||||
cb(list);
|
||||
}
|
||||
list.destroy();
|
||||
})
|
||||
.on('cycle', function(event) {
|
||||
assert.ok(true, String(event.target));
|
||||
})
|
||||
.on('complete', done)
|
||||
.run({ 'async': true });
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
QUnit.test('simple readonly list with 2 rows and 2 fields', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
|
||||
this.arch ='<tree><field name="foo"/><field name="int_field"/></tree>';
|
||||
this.run(assert, done);
|
||||
});
|
||||
|
||||
QUnit.test('simple readonly list with 200 rows and 2 fields', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
|
||||
for (var i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data",
|
||||
int_field: 10 * i,
|
||||
});
|
||||
};
|
||||
this.arch = null;
|
||||
this.run = function (assert, cb) {
|
||||
const data = this.data;
|
||||
const arch = this.arch;
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite({})
|
||||
.add('list', {
|
||||
defer: true,
|
||||
fn: async (deferred) => {
|
||||
const list = await createView({
|
||||
View: ListView,
|
||||
model: 'foo',
|
||||
data,
|
||||
arch,
|
||||
});
|
||||
if (cb) {
|
||||
cb(list);
|
||||
}
|
||||
list.destroy();
|
||||
deferred.resolve();
|
||||
},
|
||||
})
|
||||
.on('cycle', event => {
|
||||
assert.ok(true, String(event.target));
|
||||
})
|
||||
.on('complete', resolve)
|
||||
.run({ async: true });
|
||||
});
|
||||
};
|
||||
}
|
||||
this.arch ='<tree><field name="foo"/><field name="int_field"/></tree>';
|
||||
this.run(assert, done);
|
||||
});
|
||||
}, function () {
|
||||
QUnit.test('simple readonly list with 2 rows and 2 fields', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
QUnit.test('simple readonly list with 200 rows and 2 fields (with widgets)', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
this.arch = '<tree><field name="foo"/><field name="int_field"/></tree>';
|
||||
return this.run(assert);
|
||||
});
|
||||
|
||||
for (var i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data",
|
||||
int_field: 10 * i,
|
||||
QUnit.test('simple readonly list with 200 rows and 2 fields', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
for (let i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data",
|
||||
int_field: 10 * i,
|
||||
});
|
||||
}
|
||||
this.arch = '<tree><field name="foo"/><field name="int_field"/></tree>';
|
||||
return this.run(assert);
|
||||
});
|
||||
|
||||
QUnit.test('simple readonly list with 200 rows and 2 fields (with widgets)', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
for (let i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data",
|
||||
int_field: 10 * i,
|
||||
});
|
||||
}
|
||||
this.arch = '<tree><field name="foo" widget="char"/><field name="int_field" widget="integer"/></tree>';
|
||||
return this.run(assert);
|
||||
});
|
||||
|
||||
QUnit.test('editable list with 200 rows 4 fields', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
for (let i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data",
|
||||
int_field: 10 * i,
|
||||
bar: i % 2 === 0,
|
||||
});
|
||||
}
|
||||
this.arch = `
|
||||
<tree editable="bottom">
|
||||
<field name="foo" attrs="{'readonly': [['bar', '=', True]]}"/>
|
||||
<field name="int_field"/>
|
||||
<field name="bar"/>
|
||||
<field name="qux"/>
|
||||
</tree>`;
|
||||
return this.run(assert, list => {
|
||||
list.$('.o_list_button_add').click();
|
||||
list.$('.o_list_button_discard').click();
|
||||
});
|
||||
}
|
||||
this.arch = '<tree><field name="foo" widget="char"/><field name="int_field" widget="integer"/></tree>';
|
||||
this.run(assert, done);
|
||||
});
|
||||
|
||||
QUnit.test('editable list with 200 rows 4 fields', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
|
||||
for (var i = 2; i < 200; i++) {
|
||||
this.data.foo.records.push({
|
||||
id: i,
|
||||
foo: "automated data",
|
||||
int_field: 10 * i,
|
||||
bar: i % 2 === 0,
|
||||
});
|
||||
}
|
||||
this.arch = '<tree editable="bottom">' +
|
||||
'<field name="foo" attrs="{\'readonly\': [[\'bar\', \'=\', True]]}"/>' +
|
||||
'<field name="int_field"/>' +
|
||||
'<field name="bar"/>' +
|
||||
'<field name="qux"/>' +
|
||||
'</tree>';
|
||||
this.run(assert, done, function (list) {
|
||||
list.$buttons.find('.o_list_button_add').click();
|
||||
list.$buttons.find('.o_list_button_discard').click();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -660,8 +660,6 @@
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/mock_server.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_env.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/component_extension_tests.js"></script>
|
||||
</template>
|
||||
|
||||
<template id="web.qunit_suite">
|
||||
@@ -773,6 +771,7 @@
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_tests.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/owl_compatibility_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/component_extension_tests.js"></script>
|
||||
</template>
|
||||
|
||||
<template id="web.qunit_mobile_suite">
|
||||
@@ -807,9 +806,6 @@
|
||||
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
|
||||
<t t-set="title">Web Benchmarks</t>
|
||||
<t t-set="head">
|
||||
<link type="text/css" rel="stylesheet" href="/web/static/lib/qunit/qunit-2.9.1.css"/>
|
||||
<script type="text/javascript" src="/web/static/lib/qunit/qunit-2.9.1.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/qunit_config.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/benchmarkjs/lodash.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/benchmarkjs/benchmark.js"></script>
|
||||
|
||||
@@ -817,30 +813,11 @@
|
||||
<t t-call-assets="web.assets_backend" t-js="false"/>
|
||||
<t t-call-assets="web.assets_common" t-css="false"/>
|
||||
<t t-call-assets="web.assets_backend" t-css="false"/>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/qunit_asserts.js"></script>
|
||||
<t t-call-assets="web.tests_assets" t-js="false"/>
|
||||
<t t-call-assets="web.tests_assets" t-css="false"/>
|
||||
|
||||
<script type="text/javascript">
|
||||
QUnit.config.hidepassed = false;
|
||||
|
||||
odoo.define('web.WebClientWithoutServices', function (require) {
|
||||
var WebClient = require('web.WebClient');
|
||||
var WebClientWithoutServices = WebClient.extend({
|
||||
/**
|
||||
* Patch web client so that it is no longer a service provider.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_onCallService: function () {},
|
||||
});
|
||||
return WebClientWithoutServices;
|
||||
});
|
||||
// define the 'web.web_client' module because some other modules require it
|
||||
odoo.define('web.web_client', function (require) {
|
||||
var WebClient = require('web.WebClientWithoutServices');
|
||||
var web_client = new WebClient();
|
||||
return web_client;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -857,18 +834,6 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_create.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_dom.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_fields.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_form.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_graph.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_kanban.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_mock.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_modal.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils_pivot.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/test_utils.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/mock_server.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/views/list_benchmarks.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/kanban_benchmarks.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/form_benchmarks.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user