421 Commits
Author SHA1 Message Date
Martin Trigaux (mat) aa84ccfa61 [ADD] test_translation_import: export source terms
Add a test for exporting the source terms of modules.
This will allow automated scripts to fetch latest terms

Backport save_test_file with a parameter on date_format to have
predictable filenames

closes odoo/odoo#159373

X-original-commit: e7246ea48828746471a2e3a485bee30687eeee80
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2024-03-29 07:53:00 +00:00
Xavier-Do 63214e55e8 [IMP] tests: add test for screencast
Screencast are not always enable and a recent change broke the ffmpeg
call. This call was already broken in some ffmpeg versions.

This test will help to ensure this feature continues to work, and will
also test it in different ffmpeg versions during distro builds.

closes odoo/odoo#156738

X-original-commit: a3d6ef64e218683f7455f60d20860b62780be3b9
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2024-03-07 08:25:55 +00:00
Xavier-Do d1a53e15e4 [IMP] tests: manage screencast frames after clear.
Reduce the log size in case of failure of a screencast frames
Avoid a race condition while removing tree.

closes odoo/odoo#156341

X-original-commit: 97dc741929eb9497f9b44c110607254f0a873698
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2024-03-05 10:03:19 +00:00
Jairo Llopis 6fda467597 [FIX] tests: make sure screencasts dir exists before writing to it
Without this patch, running this command on an environment where the tour will fail, will create massive and useless logs:

    odoo --stop-after-init -i auth_totp --test-enable --test-tags /auth_totp

This is because this method is a callback that can come in a different thread, creating a race condition.

There's no problem on checking wether the directory exists before creating the file, and then safeguarding from the problem.

@moduon MT-1075

closes odoo/odoo#151579

X-original-commit: 7aca8ae8728c66700c3afdca350e99ea78a63d88
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2024-01-30 12:19:57 +00:00
Raphael Collet 59eec8711c [FIX] core: avoid hiding access error in onchange() with Form
When the server-side form view reads its record, the call to web_read()
leaves data in cache, which may prevent some access error to be
triggered in the first call to onchange().  In order to avoid that,
simply clean up the environment like after the other method calls.

Part-of: odoo/odoo#148997
2024-01-11 17:00:50 +00:00
Rémy Voet (ryv) 914ac6d0b9 [FIX] tests: fix assert message of required field check
closes odoo/odoo#147400

X-original-commit: 0b9257009154eb92a723f72ad64a31cf9b577748
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-12-23 17:01:38 +00:00
Pierre Paridans 8266af8339 [FIX] tests: error when Chrome websocket returns empty message
Since Chrome 120 (specifically Chromium build 1208985), an empty message
is received from the CDT at the end of a test run, which obviously
cannot be parsed as JSON.

This is due to a fix made in Chromium [1] where ChromeDriver didn't send
the CLOSE frame in response to the CLOSE frame sent by the client. The
websocket-client library we use to talk with the CDT interprets this
frame as a empty string when receiving message (cf. in `_core.py` [2]).

As we don't need to interpret more complex low-level messages, this
commit simply skips the empty message (which was already implicitly done
in 15.0 [3]).

[1]: https://bugs.chromium.org/p/chromedriver/issues/detail?id=4499
[2]: https://github.com/websocket-client/websocket-client/blob/69e470fee083cd4d5f42bccaff3a6168bfeee863/websocket/_core.py#L379-L399
[3]: https://github.com/odoo/odoo/blob/b5b069564c0a0246f3f263804088d40c3990633a/odoo/tests/common.py#L1169

closes odoo/odoo#146913

X-original-commit: 28d5a2603fb0284629079af2b8b431b45d58cd18
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Signed-off-by: Pierre Paridans (app) <app@odoo.com>
2023-12-19 22:45:59 +00:00
Yannick Tivisse a913272136 [FIX] base: Make tests demo data independent
Part-of: odoo/odoo#146649
2023-12-18 23:32:05 +00:00
william-andre 7c1256a302 [FIX] tests: do not assertQueries before warmup
Just like for `assertQueryCount`, we should not take into account
queries that are not run after a warmup, for consistency.
This allows to easily interchange both context managers for debugging
purpose for instance.

closes odoo/odoo#142450

X-original-commit: aaa1d287085c8b2fe20b6591ca9f1b5bbe65d3db
Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: William André (wan) <wan@odoo.com>
2023-11-20 03:46:43 +00:00
Raphael Collet f1b1a2b44d [FIX] tests: make server-side Form use web_save() like the web client
closes odoo/odoo#142275

Signed-off-by: Rémy Voet (ryv) <ryv@odoo.com>
2023-11-16 11:44:57 +00:00
Xavier Morel bc81230311 [FIX] core: skip marking completed tours as failed, restore had_failure
Succeeds #140464

Misunderstood `had_failure` and should not have reused it, its goal is
to avoid eagerly aborting some JS tests -- specifically the unit test
suites -- while still logging errors normally (useful when watching
interactively, or for the runbot's own reporting).

So the *checks* added on `had_failure` should in fact be checks on
`_result.exception()`, and as it turns out on `_result.done()`: if a
tour is already marked as successful we can't fail it either.

So we should not, we should log an error (to notify the caller /
runbot) and then bail. While #140464 did improve some things, we could
still lose legit errors and get pages of unhelpful `InvalidStateError`
if a tour would succeed *then* failures would occur, as the guard only
checked that the tour had already failed.

closes odoo/odoo#141815

X-original-commit: 87fcf66203dcbd281470285d648365d33d0e2fca
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-11-13 14:38:40 +00:00
Xavier Morel 2143ae7a9f [IMP] core: skip on marking tour as failed if it's already failed
If the web client gets into a bad state and piles on errors (or
exceptions) this leads to a mess with hundreds of kilobytes of
warnings being logged as we try to set an already failed tour to
failed (and also take screenshots), as in
http://runbot142.odoo.com/runbot/static/build/53098209-master/logs/test_only.txt

Also update `has_failure` to directly depend on an exception being
set, as that should be a more reliable indicator. And much like the
case of an error log skip trying to set the tour to failed in
`_set_exception` if it's already failed. Although in that case do log
the traceback as an `error`.

closes odoo/odoo#140879

X-original-commit: 96c501036a6dcb216e82e0dfa42b59a9b917d742
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-11-04 05:35:42 +00:00
Xavier-Do 4820be3cb7 [IMP] base: add test for wkhtmltopdf generation
The current used version of wkhtmltopdf manages is frozen to 0.12.5
because some features used by odoo are only available in this version
using a patched qt.

Anyway, it become difficult to keep this version up to date, especially
with Ubuntu Jammy and updates of the dependencies used by wkhtmltopdf.
More than that because of qt related issues, wkhtmltopdf maintenance
will end soon.

Adding a test to check some caracteristics of pdf reports may be usefull
to check that current version is still working, and eventually to find
an alternative solution.

This test checks that pdf reports contains the expected headers and
footers elements with the correct page number (2 record of 2 pages)
This also check that the pdf is in the expected A4 format.

Future test may check other formats, margins, layout,
page size/pagebreak combination, (table of content?), ...

This test may also check performances and existing limitations.

closes odoo/odoo#136626

Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
2023-10-19 13:20:28 +00:00
Xavier-Do b67f50a57a [IMP] tests: improve logging of active patcher
Part-of: odoo/odoo#137215
2023-10-03 07:19:00 +00:00
Raphael Collet 020ddc3a6b [IMP] core: introduce SQL wrapper
We introduce a new class of objects to wrap SQL code together with its
parameters.  It is designed to be easily composable and to discourage
SQL injections.  Its API is similar to the methods of module 'logging':
the code is a format string, and the positional parameters are meant to
be merged into it using the string formatting operator.

    # default and increment are parameters of the SQL code in first argument
    term = SQL("COALESCE(value, %s) + %s", default, increment)

    # term can safely be injected into another SQL, besides regular parameters
    query = SQL("SELECT %s FROM mytable WHERE id = %s", term, id_)

The SQL wrapper can return the final SQL code string as query.code, and
the corresponding parameters as query.params (list).  The cursor method
execute() can now take an SQL object, and execute it just like

    cr.execute(query.code, query.params)

It is quite easy to make SQL objects safe against SQL injections: if the
code is a string literal, then the SQL object is guaranteed safe,
provided the SQL objects within its parameters are themselves safe.

Part-of: odoo/odoo#134677
2023-09-27 03:01:44 +00:00
erl-odoo 8c62f4a563 [IMP] core: ease testing upgrade scripts in custom modules
Upgrade (aka migration) scripts are a core part of Odoo, allowing
database manipulations for modules during version changes.

Any module, including custom ones can run upgrade scripts, even if the
`--upgrade-path` flag (and with it, the `odoo.upgrade` sub-module) is
not present. Currently only the "standard" modules benefit of easy
upgrade script testing. Any custom modules that want to run tests of
their upgrades have to import the tests in the usual `tests` folder,
which is not ideal.

Therefore, to allow TDD and programmatic testing of upgrade scripts in
custom modules, the test discovery is here modified to also parse the
module's `migrations` and `upgrades` sub-modules for tests.

closes odoo/odoo#136505

X-original-commit: c924434d35f80c223491371a87da7eab18956004
Signed-off-by: Christophe Simonis (chs) <chs@odoo.com>
2023-09-25 17:11:32 +00:00
Xavier Morel 6177b04ce5 [FIX] core: remove unnecessary ast.unparse
Only available in Python 3.9, and for now at least Odoo remains
committed to supporting Python 3.8.

And it's not actually necessary: `literal_eval` supports ast node
input, because internally it just `ast.parse`s the input then
evaluates it, giving it an AST node just skips the parse step.

closes odoo/odoo#135302

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-09-13 13:49:38 +00:00
Xavier Morel 2da41ec07b [IMP] core: don't log cache being nuked during test teardown
Improves on #119813 (595aa24843): the
commit splits the ORM cache into several, and adds a log entry when
invalidating caches (both individual and all).

To keep tests isolated and coherent (and also make performance tests
usable), the test framework has to clear all caches between tests to
ensure they don't affect one another. This adds a line of log
to *every* test, pointing into the guts of the test framework.

Since the clearing is willful, unconditional, and not bypassable, the
log line has essentially no value, it just adds tremendous amounts of
noise to the logs.

Fix by muting the registry logger specifically when clearing the cache
in the test suite (there is currently no dedicated cache logger, if
there ever is mute that instead).

closes odoo/odoo#133811

X-original-commit: 52371bac7d4fadbeab139e4cd044cdc6b1005299
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-09-01 05:53:42 +00:00
Raphael Collet 132e9f72ed [REF] *: rename onchange2 to onchange
closes odoo/odoo#133049

Related: odoo/enterprise#46240
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-08-31 05:11:44 +00:00
flvr-odooandAlex Roscav 54b8a41bb6 [FIX] adding a standalone test for markup
This commits make a new standalone test for Markup()

The idea is to only flag the usage of Markup inside of runbot if
it is called on the non-constant string.

Markup('<span> %s </span>') % text #should not raise a flag,

Markup('<span> %s </span>' % 'text') #should raise a flag

closes odoo/odoo#131206

Signed-off-by: Vranckx Florian (flvr) <flvr@odoo.com>
Co-authored-by: Alex Roscav  <roal@odoo.com>
2023-08-30 11:49:00 +00:00
Xavier Morel 5dbdf7ca69 [IMP] core: reintroduce warning on watch
Was removed during the watch refactoring of #111422, present to avoid
people merging `watch=True`.

closes odoo/odoo#132727

X-original-commit: d2b33743e1b6faef82b24eb1e30b142e6b072290
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-08-23 07:40:34 +02:00
Raphael Collet 26cfa95f11 [IMP] tests: improve fields_spec for web_read() and onchange2() used in Form
This includes the context in fields.

Part-of: odoo/odoo#124614
2023-08-18 19:16:48 +02:00
Raphael Collet 7a86ad8957 [IMP] tests: make Form use onchange2() instead of onchange()
Part-of: odoo/odoo#124614
2023-08-18 19:16:46 +02:00
Raphael Collet aa87c0a6ba [IMP] tests: make Form use web_read() instead of read()
Part-of: odoo/odoo#124614
2023-08-18 19:16:45 +02:00
Gorash cdaa761ced [REF] base: Update modifier syntax (invisible, required, readonly)
Goal:
* Simplified modifiers to only have one way to define modifiers;
* Remove states attributes on python field;
* Use python expression in view `required`, `readonly`, `invisible`;
* More accurate validation of xml views.

This commit change the syntax to python expression. The next commit
will update/convert all xml views.

Before this commit:
* the `required`, `readonly` and `invisible` attributes can only have
values of `True`, `False`, 1, 0 or a python expression to use the
context;
* the `attrs` attribute define a dict. The key of this dict was
`required`, `readonly` and `invisible` and the values are the domain or
a string representing a domain to be evaluate as python expression.
This python expressions was evaluate by the javascript with view fields
and other contextual values as: context, uid, parent, active_id,
active_ids, active_model, allowed_company_ids, current_company_id.
* the `states` attribute in the view was a comma separated list of the
state. This list was combined with the `invisible` attribute;
* the `invisible` attribute on python field is used as default value;
* the `states` attribute on python field was dictionnary with state as
key and list of tuple. This structure was combined with `readonly` view
attribute.
* After combining, the resulting domains of the different attributes
`required`, `readonly` and `invisible` are evaluated with the values of
the fields. The `invisible` attributes is splitted into two use:
`invisible` and `column_invisible`.

After this commit:
* The attributes `required`, `readonly`, `invisible` and
`column_invisible` define python expression. This python expressions
are evaluate by the javascript with view fields and other contextual
values as: context, uid, parent, active_id, active_ids, active_model,
allowed_company_ids, current_company_id.

The domains can contains contextual value and will be evaluate by the
javascript.

```xml
    <field name="field_a" readonly="not context.get('show_a')" attrs="{'readonly': [('field_b', '!=', False), ('field_c', '=', parent.c)]}"/>
    <field name="field_b" states="draft"/>
```
will be replaced by
```xml
    <field name="field_a" readonly="not context.get('show_a') or field_b and field_c == parent.c"/>
    <field name="field_b" invisible="state != 'draft'"/>
```

Some inherited views will be modified differently in order to maintain
the previous behavior:

```xml
    <field name="field_a" readonly="not context.get('show_a')" attrs="{'invisible': [('field_b', '!=', False)]}">
```
```xml
    <field name="field_a" position="attributes">
        <attribute name="attrs">{'readonly': [('field_c', '=', False)], 'invisible': [('field_d', '!=', '3')]}<attribute>
    </field>
```
will be replaced by
```xml
    <field name="field_a" readonly="not context.get('show_a')" invisible="field_b">
```
```xml
    <field name="field_a" position="attributes">
        <attribute name="readonly" add="(not field_c)" separator=" or "/>
        <attribute name="invisible">field_d != 3<attribute>
    </field>
```

Validation:
A stricter control is made on the level of the attributes (modifiers)
and the fields necessary for these. The use of the previous attributes
'attr' and 'states' triggers an error (these no longer exist after the
application of the migration script)

task-2495504

Part-of: odoo/odoo#104741
2023-08-18 09:49:08 +02:00
tsm-odoo b5896c9d03 [IMP] *: add generic make_jsonrpc method in tests
*: bus, crm_livechat, crm_mail_plugin, im_livechat, payment, payment_demo,
pos_online_payment, test_discuss_full, test_mail_full, tests, website_livechat,
website_sale.

Several python tests have their own way to make jsonrpc requests. This PR adds a
generic `make_jsonrpc_request` method to the `HttpCase` in order to provide a
generic way to do so.

At the same time, calls to `_open_livechat_channel` are removed in favor of
jsonrpc request to `get_session`. This makes the tests more realistics (some
incoherences were present like passing `country_id` to the open channel method
while the user country id is not set...)

Finally, this will ease the diff in the PR introducing livechat visitors as mail
guests.

part of task-3332628

closes odoo/odoo#130036

Related: odoo/enterprise#44840
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
2023-07-31 23:21:10 +02:00
Xavier-Do fd8ec5001d [FIX] tests: reset sequence at the end of test
Some test may perform a request without being in test_mode

In this case, a check signaling could be called and since the sequence
was incremented the registry may be reloaded.

This is a simple fix to avoid this issue waiting for a stronger check.

closes odoo/odoo#129814

X-original-commit: 41bb17b3046e8f1605d6f893ca1807d77ed21173
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2023-07-27 03:50:53 +02:00
Xavier Morel f96988cbe5 [IMP] core: improve test request blocker
Better tag selection
====================

The block was originally hooked onto the `external` tag under the
assumption that this was the tag used to allow external requests.

It's not, it's the tag for the "external" test suite, which is only
one of the test suites allowed to perform external calls. Hook again
onto `standard`, this might have some false positives (allow requests
which we'd rather block), but it should have a lot less false
negatives (block requests we want to allow).

Make Overrides Easier
=====================

Currently `_request_handler` raises a regular `ConnectionError`, this
is an issue because it passes some requests through, which could
themselves trigger genuine `ConnectionError`.

When overriding `_request_handler` to implement fallbacks for bespoke
URL mocks, these two cases need to be distinguishable as overrides
likely want to handle blocked requests, not actual failures.

Therefore `_request_handler` should a dedicated exception. This
exception should be a subclass of `ConnectionError`, so that blocked
requests are treated as regular connection failures by normal Odoo
code.

Class-scope
===========

Originally `_request_handler` was scoped on the instance with the idea
that it'd be a `mock` object, which individual tests could
`configure_mock`. This turned out not to work correctly, because
`Mock.side_effect` does not receive a `self`, hence the `Session` was
inaccessible and it was not possible to passthrough local requests.

While I moved to a regular `lambda` (because a direct method didn't
work either), I forgot to remove the `request_mock` attribute, and
didn't think that the block could now be lifted up to the class
scope. Doing this, requests performed during a "standard" test case's
`setUpClass` are now also blocked, which they very much should be.

closes odoo/odoo#128977

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-07-19 13:13:32 +02:00
Xavier-Do 595aa24843 [IMP] registry: multiple ormcache
One of the main issue with ormcache is that the invalidation clears
everything, meaning that some value, slow to compute but with a long
lifetime, can be removed from the cache because an easy to invalidate
value is cleared, like after writting or creating a product has an
example.

Most example in the code will try to invalidate the cache of the models
doing something like `env['ir.qweb'].clear_caches()` but it is
finally equivalent to `env.registry.clear_cache()`, and cross worker.

The idea is to have multiple cache, maybe with specific sizes for a
specific purpose.

Having one per model is maybe a bad idea because it will be difficult
to size the LRU correcly, and it is too dynamic. Checking invalidation
may be expensive.

The proposed solution is closed allow a limited number of named caches,
using onse sequence per cache. This is actually close to the
cache_longterm.

We want to discourage using a specific cache for one use case in
the buisness code. Adding a cache shouldn't be something easy, doable
in stable.

Note that we could also change the invalisation mecanism using an
insert only table. We an check the sequence of this table, but also
fetch all invalidation messages.
Another possible improvement, especially if we have more than x cache is
to have a global sequence, checking signaling would mean to check the
main sequence, and only the other ones if the main one changed.

Note that this poc is inspired from the long term cache but not all
use case where applie yet.

Part-of: odoo/odoo#119813
2023-07-18 11:42:26 +02:00
Xavier Morel 4111f02fb3 [ADD] core: block requests calls during tests
Non-external tests should not be performing requests to external
websites or services.

Add a mock to handle such requests:

- if the test is not tagged external
- and the request is not to localhost
- and the request is not to `file:` (it's possible to install a
  FileAdapter in a session to resolve file URLs)
- raise a connection error (and log, both with some details of the
  blocked request for debugging)

The mock is layered on the lowest possible level (`Session.send`), so
tests can either:

- reconfigure the mock to handle cases differently (the mock is
  re-created on every test)
- layer their own mock at a higher level of the library

Eventually we might also built-in a routing / dispatch mechanism so
it's easier to declare external services you want to mock, somewhat
similar to what's available client-side.

Whitelist `file:` because e.g. zeep performs `file:` request, using a
bespoke adapter installed in its session.

Part-of: odoo/odoo#128497
2023-07-15 12:00:11 +02:00
Raphael Collet b33452cd57 [IMP] tests: simplify implementation of Form
- simplify initialization of form._values (don't fill in with False)
- use UpdateDict for form._values (more consistent with x2many values)
- better/simpler API for getting save/onchange/all values
- don't reparse subview in O2MForm (already done by toplevel Form)
- guarantee that one2many fields always have an edition view
- add assignment on many2many fields
- add __getitem__/__setitem__ to access/assign fields with dynamic name

Part-of: odoo/odoo#127400
2023-07-05 18:46:49 +02:00
Xavier-Do 6d5d234f15 [IMP] base: better ormcache management
1. move cache to _get_asset_paths

The `_get_asset_content` cache has many cache key that are related to a
posprocessing of the `_get_asset_paths` result, the heavy part of this
method. Moving the cache to _get_asset_content will have the benefit
to create less duplicates entries in the ormcache as well as less cache
miss.

To simplify even further, the css and js parameters are removed since
they only filter the output of get_paths, the heavy part of globing the
file will be done before that. Anyway, they are both true when called
from _get_asset_content, and the only other call, in
`_get_related_bundle` don't really need to filter them since it is not
a critical part regarding performance, and the funtional result will
stay the same.

The initial orm cache key was using `_get_template_cache_keys`, a little
overkill and possibly creating duplicates entries again. The only
context key needed is website_id for `_get_related_assets`.

Note that it is not really enough, the orm cache key should actually
contain `request.session.get('force_website_id')` as well has
`request.httprequest.host`. This will be addressed latter since a nicer
solution would be to have website_id as a unique parameter computed
earlier.

2. better _get_asset_paths cache key

The orm cache key was simplified in previous point but there is still
one concern, the website_id depends on more parameters than that:
- request.session.get('force_website_id')
- request.httprequest.host
- existing websites

The idea here is to call `get_current_website` instead of using all
parameters that could define the webiste.

In the same spirit of `_get_template_cache_keys` `_assets_path_params`
can be overriden to give extra params that are usefull to list assets
path. Those params are computed before entering the method
`_get_asset_paths`. This may latter put at a higher level latter, in
get_asset_node, to simplify the _generate_asset_nodes_cache key.

3. better assets_node caches key

The main purpose of this part is to improve ormcache containing assets
nodes. The ormcache key contains
- to much context key
- missing session/host/env info
- unwanted boolean options.
- keys leading to the same cache value

The main goal being to reduce the size of the cache keys, decrease the
number of cache entries and improve the cache hit.
This will also make the behaviour more coherent and hopefully less bug
prone because of mismatch in parameters.

The main reason of the orm cache is the slowness of the validation of
the assets. This includes:
- listing files (dedicated orm cache)
- computing version

The cache key was depending on
- `debug`
The only relevant value for debug is "contains assets"
We dont need to differ between debug='', debug='1', debug='test',
and 'debug=assets', 'debug=tests,assets', ...
- `defer_load`, `lazy_load`, `media`
Those values are only useful to generate html node, a leightweight
operations that does not really needs to be in cache. `media` was also
used in the generation but it looks useless if we have the media on the
node. THIS NEEDS TO BE VALIDATED but in any case, since media is not
used to generate the url, it doesn't make sence to use it in the
generation.
The main idea to remove them from the ormcache key is simply to generate
the nodes outide the ormcached values.
-`async_load`
This one is similar to `defer_load` and `lazy_load` but it looks like
it wasn't used anymore. This was simply removed
- context.get('lang')
The only information needed is the direction, rtl or ltr. This means
en and fr languages, despite sharing the same css assets, will duplicate
the ormcache entries.
-`_get_template_cache_keys`
Only the lang and webiste where really relevant in this flow. Other
keys are actually useless in this flow.

Some information used in the generation where not in the orm cache key
- `self.env.user.lang` if there is no lang in the context
- `request.session.get('force_website_id')`
- `request.httprequest.host`
- ...

The proposed solution is to:
- extract any informùation needed from thecontext, request, environment
before entering the ormcache, reduce it to the minimal possible set of
values needed
```
    rtl = self.env['res.lang']._lang_get_direction(self.env.context.get('lang') or self.env.user.lang) == 'rtl'
    assets_params = self.env['ir.asset']._get_assets_params()  # website_id
    debug_assets = debug and 'assets' in debug
```

and remove a leightweight part of the logic

```
    def _get_asset_nodes(self, bundle, css=True, js=True, debug=False, defer_load=False, lazy_load=False, media=None):
        links = self._get_asset_links(bundle, css=css, js=js, debug=debug)
        return self._links_to_nodes(links, defer_load=defer_load, lazy_load=lazy_load, media=media)
```

Where _get_asset_links is the cached part, and _links_to_nodes is the
lightweight part generating the nodes based on the `defer_load`, ....

Additionnal notes:
- data-asset-version and data-asset-bundle are removed from the node
since they don't seem to be used anymore since 65d70acdbf
- async_load is removed since there is no occurence of this in the code.
- a small hack is still needed to pass javascript content instead of
links, this is only to manage css compile error and will hopefully be
removed in the future.
- a context key is still in use to generate the bundle, the
`commit_assetsbundle` but it has no impact on content and will hopefully
be removed in the future.

4. Add test for ormcache hit/miss

In this context, hit/miss is about having the same cache key for the
same result. This test demonstrates the current state, were entries are
create in the ormcache only if the key is really different and will lead
to a different result.

5. remove cache invalidation

This cache invalidation is quite agressive since everytime an
assetbundle is updated, all workers will clear their cache.

The concerned cache by this clear_cache is `_generate_asset_nodes_cache`
throug `_get_asset_nodes`.

The cache is ignored, both in dev=xml and debug=assets.

This clear cache was made conditionnal in 553ea82f81 but this does
not solve an issue we can have in production.

Lets imagine a clean solution
- all sources are updated
- all workers are restarted.

The orm caches are all empty, but since the sources
changed, all bundles will be recomputed. This means that every bundle
updated in database with save_attachement will invalidate the cache of
all workers. Rendering a pdf report of any kind using a specific bundle
will invalidate all cache. Starting a debug=assets for the first time
will invalidate all cache, even if the cache is not used in this case.

But for a regenerated bundle we would expect the ormcache to be:
- empty (did not generate the same bundle yet)
- have the same value (concurrent generation of the same bundle)

Having a different value would mean that the bundle was generated with
another version of the sources. In this case it is maybe even better not
to invalidate the cache since it could lead to an invalidation war
between two workers.

The only case where invalidating this cache is useful is when a bundle
changes, Usually if an ir_asset is created, modified, ...

There is still another rare but possible possibility to have a 404 if
the transaction is rollbacked after populating the assets node cache.
In this case, we only need to clear the cache locally in case of
rollback.

Part-of: odoo/odoo#121376
2023-06-10 11:14:11 +02:00
Christophe Monniez 428b78e9bd [FIX] tests: move enter test_mode in setUpClass
Before this commit, the registry was entering test_mode in setUp,
leading to a hole during the setUpClass with a registry not in test mode
at this moment.

closes odoo/odoo#122585

X-original-commit: 993e4d2f98b9982eb64123d6cd0de8cc3b2056f4
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
2023-05-26 10:29:22 +02:00
Xavier Morel 2b30be424f [FIX] core: content tab discovery in headful mode
It's not clear when and how this happened but apparently "headful"
chrome has a built-in background_page for hangouts which appears
before the `about:blank` page in the list of targets, and possibly
appears before the `about:blank` page has opened at all.

odoo/odoo#111422 was tested with chromium which apparently doesn't
have this feature either (or does it?), which probably contributes to
having no idea when it appears.

This feature also doesn't respond to `--disable-extensions`, despite
its url marking it as one:

    chrome-extension://nkeimhogjdpnpccoofpliimaahmaaome/background.html

The result was that the tour runner would hook onto the hangouts
target and try to load pages, which it would reject with
`net::ERR_ABORTED`, hence the tours just getting stuck.

Fix by improving the heuristic to find a content page: look for a
target of type `page`, and with the url `about:blank`, rather than
just take whichever tab target is listed first. Requires modifying
`stop` as it can now be called after we've started the browser, but
before we've created the websocket connection.

Also move `--no-first-run` from the headless to the default switches
to avoid Chrome's migration & default browser popup, apparently it
doesn't cause Chromium grief anymore (???). If this turns out to be a
concern, add a condition on the `executable` or something.

closes odoo/odoo#122117

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-05-23 18:02:21 +02:00
Xavier Morel ce77b9f673 [IMP] core: avoid searching chrome binary once per browse_js
Delegate the property's resolution to a top-level function,
cached (with a single slot). This is slightly less efficient than
using some sort of global set once, but it's much easier.

Unlikely to be a huge issue in the face of *starting an entire
browser*, but may as well skip it.

closes odoo/odoo#111422

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2023-05-19 10:18:48 +02:00
Xavier Morel e6fd0ad5ee [IMP] core: cleanup browser API
It doesn't need to store so much crap as attributes, and the data flow
of the init can be made more explicit.

- have setup functions return stuff, which can be set on `self` by the
  `__init__`, making the dataflow more explicit
- maintain a high-level `Popen` object instead of moving a `pid` around
- pass items like browser size as parameters instead of attributes
- remove redundant attributes like `screencasts_frame_dir` (/ convert
  to properties)

Part-of: odoo/odoo#111422
2023-05-19 10:18:48 +02:00
Xavier Morel 2b0d9fa6a9 [ADD] core: ability to run tours in a regular (headful) browser
Chrome's screencast / remote view (in the remote devtools) is
apparently *designed* for touch emulation /
simulation (https://crbug.com/1410433), which is not convenient when
trying to debug mouse-bound issues in a tour (e.g. drag&drop
problems).

However we can "simply" run the thing in a normal browser, on a watch
basis, and shut down the entire thing after each tour-call. This also
obviates the need for complicated cleanup steps to try and isolate
tours (as we can just delete the profile the browser created),
although it is somewhat less efficient as we keep starting and
stopping the browser.

It does simplify the result of merging `clear` and `stop` (into stop).

The switches setup does have a few foibles:

- `--no-first-run` causes tours to not run at all on my machine, in a
  non-headless browser, so it's left just for headless
- also moved a bunch of other flags which seem to be mostly for
  automated annoyances to headless only
- left extensions for now, not entirely sure which is the right one,
  since we're running with fresh profiles I would assume there's no
  extensions anyway

Part-of: odoo/odoo#111422
2023-05-19 10:18:47 +02:00
Xavier-Do 031ea4d351 [FIX] tests, registry: reset_changes in httpcase
When inside an HttpCase, the end of a successful request will
`signal_changes` meaning that the registry_invalidated flag is removed.
A second issue is that this flag is thread local meaning that if a
request set the flag, it won't be visible from the test thread.

For those reasons, this commit ensures the registry sequences are
incremented as in production mode, and adds a check that the sequence
didn't change during the tests, calling `setup_models` the registry
manually if needed.

closes odoo/odoo#121268

Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
2023-05-16 13:37:10 +02:00
Christophe SimonisandAlvaro Fuentes f1161be0d0 [FIX] core: load tests from all entries in --upgrade-path
Allow extending tests for any modules, regardless of existing ones
in another entry of the `upgrade-path`.

Bonus point: tests no longer need to be imported in the `__init__.py`
file.

closes odoo/odoo#121453

X-original-commit: ed1b27dbdfc0a5084051c59da9c4578262b3bf8c
Signed-off-by: Christophe Simonis <chs@odoo.com>
Co-authored-by: Alvaro Fuentes <afu@odoo.com>
2023-05-15 19:48:39 +02:00
Julien Mougenot 805197daf9 [IMP] web: Optional start date in daterange fields
Before this commit, the date/datetime/daterange fields only allowed for
an optional end date field. This meant that the primary date was always
the start date.

This commit allows the field to do the opposite: with the primary date
being the end date, and having a `start_date_field` option for an
optional start date.

closes odoo/odoo#120695

Signed-off-by: Michaël Mattiello <mcm@odoo.com>
2023-05-11 09:36:24 +02:00
Xavier Morel 9f2cfb2cdf [IMP] test_module_operations: make uninstall step more graceful
- process modules to uninstall individually in order to better handle
  their state at that point
- uninstall (and reinstall) modules in provided order, rather than
  whatever postgres feels like (or a sort which might not match what
  we want), mostly useful when uninstalling modules in bulk
- warn if a module is either missing or already uninstalled, rather
  than silently do nothing

closes odoo/odoo#120261

X-original-commit: 034b317a908d1aea6dc6d992c489b30ffff8f1ce
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2023-05-05 18:08:00 +02:00
Xavier Morel 44f7ccc100 [IMP] test_module_operations: logging configuration
- switch to `dictConfig` for easier bulk-manipulation of loggers
- set `unlink` and `ir_model` loggers to warning, to limit the
  humongous spam that is a normal uninstall session

X-original-commit: bee7898a5af68128b599d30ac7d4c0193e765afd
Part-of: odoo/odoo#120261
2023-05-05 18:07:59 +02:00
Xavier Morel d5a3e3e794 [IMP] module_operation_tester: use subcommands
Add subcommands to make running the script clearer (as exclusive
switches is a bit weird nowadays).

Keep the old `--uninstall` and `--standalone` switches, but make them
mutually exclusive (and optional) to retain current behaviour.

X-original-commit: 933841eda86292f180170b32da621f55fe6f0b84
Part-of: odoo/odoo#120261
2023-05-05 18:07:59 +02:00
Xavier Morel f2de38b84a [IMP] test_module_operations: make debugging easier
- ensure `test_module_operations` exits with a non-zero status on
  failure, as the current makes it a lot less convenient to notice
  uninstall / reinstall errors (especially with lots of warnings
  crowding the logs)
- allow uninstalling without reinstalling, so it's easier to inspect
  db state after uninstall

X-original-commit: 712977faf9bf98d9087368ab4fe95f089a072601
Part-of: odoo/odoo#120261
2023-05-05 18:07:59 +02:00
Julien Mougenot 6cdbce8490 [IMP] form: Support daterange field dependencies
This commit allows the server-side form arch parser used in tests to
also include the "end_date_field" defined in the `options` attribute of
daterange widgets in the dictionnary of fields found in the arch.

The daterange widget is currently the only case where the client adds
another editable field dynamically in the list of known fields. This is
not ideal since the server does not know that when computing the initial
arch sent to the client. The workaround is to also include the
"end_date_field" in the arch with `invisible="1"`, and to add a special
case for the server-side form arch parser used in tests.

Ideally we would want a proper way to define field dependencies in the
arch, but since this widget here is the only use case for that feature
it is better for now to handle it in this simple, more naive way.

Part of task 3121497

closes odoo/odoo#112171

Related: odoo/enterprise#38569
Signed-off-by: Michaël Mattiello <mcm@odoo.com>
2023-05-05 13:52:22 +02:00
John Wilson bb1d9e7b26 [FIX] tests/common: Fix tests on Windows and with Debian release
closes odoo/odoo#120297

X-original-commit: 26c6997d8de5679307485cd8efb6b2ce5662f34c
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2023-05-03 12:39:53 +02:00
Xavier-Do 608c1ea100 [FIX] tests: check test tags *_install
Making a test post_install using @tagged should always remove the
at_install tag.

The main reason for that is that runbot split config select if an
at_install or post_install tests should be executed is using negation:
`--test-tags -post_install`. The reason for that is that giving a positive tag will
replace the "standard" tag and non standard tag could be executed if
giving `--test-tags at_install` (without negation)

Since runbot tests in parallel builds, one of them using
`--test-tags -post_install` and the other `--test-tags -at_install`,
a test that is both post install and at install wont be executed at all.

Also, a tests with both tags will be executed twice
in a normal flow, usually not intended.

The correct way to make a test post_install is to use

@tagged('post_install', '-at_install')

closes odoo/odoo#118969

X-original-commit: d1db306b212d4abb5b2faab9e56c8e83b85c53b9
Related: odoo/enterprise#39966
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2023-04-19 11:01:13 +02:00
Renaud Thiry dddb2f5355 [IMP] base: Clear precommits on test cleanup
Precommit hooks would stock data until a call to ``cr.flush`` was made.
Notably, this happens when the ``assertRaises`` method is called.
Functions were applied on records already cleared from the cache.

This change adds a cleanup call for `TransactionCase` as it keeps
the same cursor for all tests. Cursor precommits can now
be safely executed inside tests.

Task-2834304

Forward port of #117555

closes odoo/odoo#118290

X-original-commit: ff5d0c75fcea5842c5236b1b3f7480ef5a3dc415
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Signed-off-by: Thiry Renaud (reth) <reth@odoo.com>
2023-04-13 04:08:25 +02:00
Raphael Collet 63ee425b46 [IMP] tests: make server-side Form use get_views()
This aligns the behavior of Form with the web client form view.

Part-of: odoo/odoo#116779
2023-03-31 17:02:43 +02:00
Raphael Collet c93a212213 [IMP] tests: make Form call onchange with the context of the modified field
This aligns the behavior of Form with the web client form view.  Also
simplify the API of method _perform_onchange()

Part-of: odoo/odoo#116779
2023-03-31 17:02:43 +02:00