# -*- coding: utf-8 -*- import pytest from autojsdoc.parser import jsdoc from support import params, parse def test_classvar(): [mod] = parse(""" odoo.define('a.A', function(require) { var Class = require('Class'); /** * This is my class-kai */ var A = Class.extend({}); return A; }); """) cls = mod.exports assert type(cls) == jsdoc.ClassDoc assert type(cls.superclass) == jsdoc.ClassDoc assert cls.superclass.name == 'Class' assert cls.name == 'A' assert cls.constructor is None assert cls.properties == [] assert cls['doc'] == 'This is my class-kai' def test_classret(): [mod] = parse(""" odoo.define('a.A', function(require) { var Class = require('Class'); /** * This is my class-kai */ return Class.extend({}); }); """) cls = mod.exports assert type(cls) == jsdoc.ClassDoc assert cls.name == '' assert cls.constructor is None assert cls.properties == [] assert cls['doc'] == 'This is my class-kai' def test_methods(): [mod] = parse(""" odoo.define('a.A', function(require) { var Class = require('Class'); return Class.extend({ /** * @param {Widget} parent */ init: function (parent) {}, /** * @returns {Widget} */ itself: function () { return this; }, /** * @param {MouseEvent} e */ _onValidate: function (e) {}, }); }); """) cls = mod.exports assert len(cls.properties) == 3 assert cls.constructor # assume methods are in source order [_, init] = cls.properties[0] assert init == cls.constructor assert init.name == 'init' assert not init.is_private assert init.is_constructor [param] = init.params assert params(param) == ('parent', 'Widget', '') [_, itself] = cls.properties[1] assert itself.name == 'itself' assert not itself.is_private assert not itself.is_constructor assert not itself.params assert params(itself.return_val) == ('', 'Widget', '') [_, _on] = cls.properties[2] assert _on.name == '_onValidate' assert _on.is_private assert not _on.is_constructor [param] = _on.params assert params(param) == ('e', 'MouseEvent', '') def test_mixin_explicit(): [mod] = parse(""" odoo.define('a.A', function (require) { var Class = require('Class'); var mixins = require('mixins'); /** * This is my class-kai * @mixes mixins.Bob */ return Class.extend({}); }); """) cls = mod.exports # FIXME: ClassDoc may want to m2r(mixin, scope)? assert cls.mixins == ['mixins.Bob'] def test_mixin_implicit(): [mod] = parse(""" odoo.define('a.A', function(require) { var Class = require('Class'); var Mixin = require('Mixin'); /** * This is my class-kai */ return Class.extend(Mixin, { foo: function() {} }); }); """) cls = mod.exports [mixin] = cls.mixins assert type(mixin) == jsdoc.MixinDoc assert params(mixin.properties[0][1]) == ('a', 'Function', '') assert params(mixin.get_property('a')) == ('a', 'Function', '') assert params(cls.get_property('foo')) == ('foo', 'Function', '') def test_instanciation(): [A, a] = parse(""" odoo.define('A', function (r) { var Class = r('Class'); /** * @class A */ return Class.extend({ foo: function () {} }); }); odoo.define('a', function (r) { var A = r('A'); var a = new A; return a; }); """) assert type(a.exports) == jsdoc.InstanceDoc assert a.exports.cls.name == A.exports.name def test_non_function_properties(): [A] = parse(""" odoo.define('A', function (r) { var Class = r('Class'); return Class.extend({ template: 'thing', a_prop: [1, 2, 3], 'other': {a: 7} }); }); """) t = A.exports.get_property('template') assert type(t) == jsdoc.PropertyDoc assert params(t) == ('template', 'String', '') assert not t.is_private def test_non_extend_classes(): [mod] = parse(""" odoo.define('A', function () { /** * @class */ var Class = function () {} return Class; }); """) assert type(mod.exports) == jsdoc.ClassDoc def test_extend(): [a, _] = parse(""" odoo.define('A', function (require) { var Class = require('Class'); return Class.extend({}); }); odoo.define('B', function (require) { var A = require('A'); A.include({ /** A property */ a: 3, /** A method */ b: function () {} }); }); """) cls = a.exports assert type(cls) == jsdoc.ClassDoc a = cls.get_property('a') assert type(a) == jsdoc.PropertyDoc assert params(a) == ('a', 'Number', 'A property') b = cls.get_property('b') assert type(b) == jsdoc.FunctionDoc assert params(b) == ('b', 'Function', 'A method') # TODO: also support virtual members? # TODO: computed properties? @pytest.mark.skip(reason="Need to implement member/var-parsing?") def test_members(): [mod] = parse(""" odoo.define('A', function (r) { var Class = r('Class'); return Class.extend({ init: function () { /** * This is bob * @var {Foo} */ this.foo = 3; this.bar = 42; /** * @member {Baz} */ this.baz = null; } }); }); """) cls = mod.exports assert params(cls.members[0]) == ('foo', 'Foo', 'This is bob') assert params(cls.members[1]) == ('bar', '', '') assert params(cls.members[2]) == ('baz', 'Baz', '')