$(function () { module("api", { setup: function(){ fx = $('#async-fixture'); $.support.transition = false; } }); test("validate, getValue, option", function () { var e = $( '<a href="#" data-type="text" id="username">user</a>' + '<a href="#" data-type="textarea" id="comment">12345</a>' + '<a href="#" data-type="select" id="sex" data-value="1" data-source=\'{"1":"q", "2":"w"}\'>q</a>' + '<a href="#" data-type="date" id="dob" data-format="dd.mm.yyyy">15.05.1984</a>' ).appendTo('#qunit-fixture').editable(), e1 = $('#username').editable('option', 'validate', function(value) { if($.trim(value) !== 'user1') return 'username is required'; }), e2 = $('#sex').editable('option', 'validate', function(value) { if($.trim(value) != 2) return 'error'; }); //check get value var values = e.editable('getValue'); equal(values.username, 'user', 'username ok') ; equal(values.comment, '12345', 'comment ok') ; equal(values.sex, 1, 'sex ok') ; equal(values.dob, '15.05.1984', 'dob ok') ; //validate var errors = e.editable('validate'); ok(errors.username && errors.sex && !errors.comment, 'validation failed ok'); //enter correct values e1.click(); var p = tip(e1); p.find('input').val('user1'); p.find('button[type="submit"]').click(); ok(!p.is(':visible'), 'username changed'); e2.click(); p = tip(e2); p.find('select').val(2); p.find('button[type="submit"]').click(); ok(!p.is(':visible'), 'sex changed'); //validate again var errors = e.editable('validate'); ok($.isEmptyObject(errors), 'validation ok'); }); test("getValue with originally empty elements", function () { var e = $( '<a href="#" data-type="text" id="username"></a>' + '<a href="#" data-type="textarea" id="comment"></a>' + '<a href="#" data-type="select" id="sex" data-source=\'{"1":"q", "2":"w"}\'></a>' + '<a href="#" data-type="date" id="dob"></a>' ).appendTo('#qunit-fixture').editable(); //check get value var values = e.editable('getValue'); equal(values.username, '', 'text empyt value') ; equal(values.comment, '', 'textarea empty value') ; ok(!('sex' in values), 'select value not present') ; ok(!('dob' in values), 'date value not present') ; }); test("'init' event", function () { expect(1); var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo('#qunit-fixture'); e.on('init', function(e, editable) { equal(editable.value, 'abc', 'init triggered, value correct'); }); e.editable(); }); asyncTest("events: shown / hidden (reason: cancel, onblur, nochange, manual)", function () { expect(15); var val = '1', test_reason, e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx); e.on('shown', function(event) { var editable = $(this).data('editable'); equal(editable.value, val, 'shown triggered, value correct'); }); e.on('hidden', function(event, reason) { ok((reason === test_reason) || (test_reason === 'manual' && reason === undefined), 'hidden triggered, reason ok'); }); e.editable({ source: 'groups.php' }); e.click(); setTimeout(function() { var p = tip(e); test_reason = 'cancel' p.find('.editable-cancel').click(); //cancel ok(!p.is(':visible'), 'popover closed'); test_reason = 'onblur' e.click(); p = tip(e); ok(p.is(':visible'), 'popover shown'); e.parent().click(); ok(!p.is(':visible'), 'popover closed'); test_reason = 'nochange' e.click(); p = tip(e); ok(p.is(':visible'), 'popover shown'); p.find('form').submit(); //submit value without changes ok(!p.is(':visible'), 'popover closed'); test_reason = 'manual' e.click(); p = tip(e); ok(p.is(':visible'), 'popover shown'); e.editable('hide'); ok(!p.is(':visible'), 'popover closed'); e.remove(); start(); }, timeout); }); asyncTest("event: save / hidden (reason: save)", function () { expect(2); var val = '1', e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx); e.on('save', function(event, params) { equal(params.newValue, 2, 'save triggered, value correct'); }); e.on('hidden', function(event, reason) { equal(reason, 'save', 'hidden triggered, reason ok'); }); e.editable({ source: groups }); e.click(); var p = tip(e); p.find('select').val(2); p.find('form').submit(); setTimeout(function() { e.remove(); start(); }, timeout); }); test("show/hide/toggle methods", function () { var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo('#qunit-fixture').editable(); e.editable('show'); var p = tip(e); ok(p.is(':visible'), 'popover shown'); e.editable('hide'); p = tip(e); ok(!p.is(':visible'), 'popover closed'); e.editable('toggle'); p = tip(e); ok(p.is(':visible'), 'popover shown'); }); test("enable/disable/toggleDisabled methods", function () { var e = $('<a href="#" data-type="text" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo('#qunit-fixture').editable({ disabled: true }); ok(e.hasClass('editable-disabled'), 'has disabled class'); ok(e.hasClass('editable-click'), 'has click class'); e.click(); ok(!e.data('editableContainer'), 'nothing on click'); e.editable('enable'); ok(!e.hasClass('editable-disabled'), 'does not have disabled class'); e.click(); var p = tip(e); ok(p.is(':visible'), 'popover shown on click'); e.editable('disable'); p = tip(e); ok(e.hasClass('editable-disabled'), 'has disabled class'); ok(!p.is(':visible'), 'popover closed'); e.editable('toggleDisabled'); ok(!e.hasClass('editable-disabled'), 'does not have disabled class (toggle)'); }); test("option method (string and object)", function () { var e = $('<a href="#" data-url="post.php" data-name="text">abc</a>').appendTo('#qunit-fixture').editable(), e1 = $('<a href="#" data-pk="1" data-name="text1">abc</a>').appendTo('#qunit-fixture').editable(), url = 'abc'; $('#qunit-fixture a').editable('option', 'pk', 2); equal(e.data('editable').options.pk, 2, 'pk set correctly'); equal(e1.data('editable').options.pk, 2, 'pk2 set correctly'); $('#qunit-fixture a').editable('option', {pk: 3, value: 'abcd'}); equal(e.data('editable').options.pk, 3, 'pk set correctly (by object)'); equal(e.data('editable').value, 'abcd', 'value set correctly (by object)'); equal(e.text(), 'abcd', 'text set correctly (by object)'); }); asyncTest("'submit' method: client and server validation errors", function () { var ev1 = 'ev1', ev2 = 'ev2', e1v = 'e1v', e = $('<a href="#" class="new-val" data-type="text" data-url="post.php" data-name="text">'+ev1+'</a>').appendTo(fx).editable({ validate: function(value) { if(value == ev1) return 'invalid'; } }), e1 = $('<a href="#" class="new-val" data-type="text" data-name="text1">'+e1v+'</a>').appendTo(fx).editable(); $.mockjax({ url: 'new-error.php', response: function(settings) { equal(settings.data.text, ev2, 'first value ok'); equal(settings.data.text1, e1v, 'second value ok'); equal(settings.data.a, 123, 'custom data ok'); equal(settings.type, 'PUT', 'ajaxOptions ok'); this.responseText = {errors: { text1: 'server-invalid' } }; } }); $.mockjax({ url: 'new.php', response: function(settings) { ok(false, 'should not submit to new.php'); } }); $(fx).find('.new-val').editable('submit', { url: 'new.php', error: function(errors) { equal(errors.text, 'invalid', 'client validation error ok'); } }); //change value to pass client side validation e.click(); var p = tip(e); p.find('input[type=text]').val(ev2); p.find('button[type=submit]').click(); $(fx).find('.new-val').editable('submit', { url: 'new-error.php', data: {a: 123}, success: function(data, config) { ok(data.errors, 'errors received from server'); ok(typeof config.error === 'function', 'config passed correctly'); if(data && data.id) { //success } else if(data && data.errors){ config.error.call(this, data.errors); //call error from success } }, error: function(errors) { equal(errors.text1, 'server-invalid', 'server validation error ok'); }, ajaxOptions: { type: 'PUT', dataType: 'json' } }); setTimeout(function() { e.remove(); e1.remove(); start(); }, timeout); }); asyncTest("'submit' method: server error", function () { var ev1 = 'ev1', e1v = 'e1v', e = $('<a href="#" class="new-err" data-type="text" data-url="post.php" data-name="text">'+ev1+'</a>').appendTo(fx).editable(), e1 = $('<a href="#" class="new-err" data-type="text" data-name="text1">'+e1v+'</a>').appendTo(fx).editable(); $(fx).find('.new-err').editable('submit', { url: 'error.php', error: function(data) { equal(this[0], $(fx).find('.new-err')[0], 'success context ok'); equal(this[1], $(fx).find('.new-err')[1], 'success context2 ok'); equal(data.status, 500, 'status 500 ok'); equal(data.responseText, 'customtext', 'server error ok'); e.remove(); e1.remove(); start(); } }); }); asyncTest("'submit' method: success", function () { var ev1 = 'ev1', e1v = 'e1v', pk = 123, e = $('<a href="#" class="new" data-type="text" data-url="post.php" data-name="text">'+ev1+'</a>').appendTo(fx).editable(), e1 = $('<a href="#" class="new" data-type="text" data-name="text1">'+e1v+'</a>').appendTo(fx).editable(); $.mockjax({ url: 'new-success.php', response: function(settings) { equal(settings.data.text, ev1, 'first value ok'); equal(settings.data.text1, e1v, 'second value ok'); this.responseText = 'response-body'; } }); $(fx).find('.new').editable('submit', { url: 'new-success.php', success: function(data) { equal(this[0], $(fx).find('.new')[0], 'success context ok'); equal(this[1], $(fx).find('.new')[1], 'success context2 ok'); equal(data, 'response-body', 'response body ok'); e.remove(); e1.remove(); start(); }, error: function(errors) { ok(false, 'error should not be called'); } }); }); test("setValue method", function () { var e = $('<a href="#" data-name="name" data-type="select" data-url="post.php"></a>').appendTo('#qunit-fixture').editable({ value: 1, source: groups }); equal(e.data('editable').value, 1, 'value correct'); equal(e.text(), groups[1], 'text shown correctly'); e.editable('setValue', 2); equal(e.data('editable').value, 2, 'new value correct'); equal(e.text(), groups[2], 'new text shown correctly'); }); test("`destroy` method", function () { var e = $('<a href="#" data-name="name" data-type="text" data-url="post.php"></a>').appendTo('#qunit-fixture').editable({ }); e.click(); var p = tip(e); ok(p.is(':visible'), 'container visible'); e.editable('destroy'); ok(!p.is(':visible'), 'container closed'); ok(!e.data('editable'), 'editable instance removed'); ok(!e.data('editableContainer'), 'editableContainer instance removed'); ok(!e.hasClass('editable'), 'editable class removed'); ok(!e.hasClass('editable-click'), 'editable-click class removed'); e.click(); }); });