ifnex/03_WordPress/wp-includes/js/customize-preview-widgets.min.js
Kazem Alghasi f1d5667fe8 feat(deploy): preflight + smoke-test + UAT checklist (phases 3.9.1–3.11)
Prepare the project for production deployment and final client
acceptance testing. Adds preflight fail-fast command, hardened FX rate
importer, currency seeder, deploy scripts, E2E smoke test, and the
43-item UAT checklist document with sign-off form.

Key changes:

- Phase 3.9.1 — hotfix (AddressBookEntry):
  - Add $attributes defaults (use_count=0, is_default=false) so
    instance values are populated right after create() without
    refresh(). Resolves the red test
    `it_increments_use_count_and_sets_last_used_at`.

- Phase 3.10 — deploy infrastructure (Laravel):
  - Add `ifnex:preflight` command: fail-fast audit of production
    environment (APP_ENV, APP_DEBUG, APP_KEY, IFNEX_API_KEY,
    IFNEX_BRIDGE_API_KEY, ZARINPAL_SANDBOX, DB_CONNECTION, CORS,
    currencies seeded, PHP extensions, storage writable). Exits 1
    if any check fails; supports --skip-db for pre-migrate runs.
  - Add `ifnex:import-fx-rates` command: replacement for
    `ifnex:update-rates`. Fetches USD/AED from Exir.io + EUR/CNY
    from FreeCurrencyAPI. Supports --auto-approve (cron use) and
    --threshold (max change % for auto-approve). Logs critical on
    HTTP failure. URL configurable via EXIR_API_URL env.
  - Add `CurrencySeeder`: creates 5 base currencies (USD/AED/EUR/
    CNY/IRR) with rate=0 (IRR=1). Idempotent — does not overwrite
    real rates already set by admin or cron.
  - Update `DatabaseSeeder`: skip super_admin with password
    'password' in production (still created in local/testing).
  - Fix `bootstrap/app.php`: remove dead `use ApiKeyAuth` import
    (actual class is ApiKeyMiddleware). Latent fatal if api_key
    alias was used.
  - Add `config/ifnex.php` exir block + preflight config.
  - Harden `.env.example`: MySQL default, EXIR_API_URL,
    SANCTUM_STATEFUL_DOMAINS, APP_TIMEZONE, LOG_DAILY_DAYS, fix
    duplicate CURRENCY_API_KEY.

- Phase 3.10 — deploy scripts (Linux):
  - Add `scripts/deploy.sh`: idempotent 13-step deploy (composer
    install → key:generate → preflight → migrate → seed → FX import
    → cache → chown). Fail-fast with set -e.
  - Add `scripts/cron-exir-rates.sh`: daily cron wrapper for
    `ifnex:import-fx-rates --source=all --auto-approve`.

- Phase 3.10.1 — preflight hotfix:
  - Make expected DB connection configurable
    (ifnex.preflight.expected_db_connection) instead of hardcoded
    'mysql'. Prevents cascade test failure when tests would have to
    mutate database.default to mysql in a sqlite test environment
    (Unknown database ':memory:' → broken connection pool → 22
    previously-green tests fail with "There is already an active
    transaction").
  - Rewrite IfnexPreflightTest to use config() rather than mutating
    database.default.

- Phase 3.11 — UAT:
  - Add `ifnex:smoke-test` command: E2E post-deploy automated test
    (25+ checks: DB connection, core tables, currencies with
    non-zero rates, countries count, roles, admin user, system
    settings, storage writable, config/route cache, 4 API
    endpoints: /up, /countries, /track/{invalid}, /customer/profile
    without token).
  - Add 9 feature tests for smoke-test (PASS + 6 FAIL + custom URL
    + 422/500 handling + auth bypass detection).
  - Add `UAT-3.11.md`: 43-item Persian checklist for client
    acceptance testing across 15 feature areas. Includes sign-off
    form for both parties (client + VernaSoft).
  - Update `CLIENT_DELIVERY.md` to record phases 3.10 and 3.11.

Tests:
- Total: 51 → 82 tests, 150 → 220+ assertions, all green.
- New: IfnexPreflightTest (9), IfnexImportFxRatesTest (9),
  CurrencySeederTest (4), IfnexSmokeTestTest (9) = 31 new tests.

Documentation:
- DEPLOYMENT_HANDOFF.md §2.4: add CurrencySeeder + import-fx-rates.
- DEPLOYMENT_HANDOFF.md §2.8: update cron to use cron-exir-rates.sh.
- UAT-3.11.md: new 43-item client acceptance checklist + sign-off.
- CLIENT_DELIVERY.md: record phases 3.10 and 3.11 completion.
2026-10-31 22:18:15 +03:30

2 lines
7.7 KiB
JavaScript

/*! This file is auto-generated */
wp.customize.widgetsPreview=wp.customize.WidgetCustomizerPreview=function(s,o,c){var l={renderedSidebars:{},renderedWidgets:{},registeredSidebars:[],registeredWidgets:{},widgetSelectors:[],preview:null,l10n:{widgetTooltip:""},selectiveRefreshableWidgets:{},init:function(){var i=this;i.preview=c.preview,o.isEmpty(i.selectiveRefreshableWidgets)||i.addPartials(),i.buildWidgetSelectors(),i.highlightControls(),i.preview.bind("highlight-widget",i.highlightWidget),c.preview.bind("active",function(){i.highlightControls()}),c.preview.bind("refresh-widget-partial",function(e){var t="widget["+e+"]";c.selectiveRefresh.partial.has(t)?c.selectiveRefresh.partial(t).refresh():i.renderedWidgets[e]&&c.preview.send("refresh")})}};return l.WidgetPartial=c.selectiveRefresh.Partial.extend({initialize:function(e,t){var i=this,r=e.match(/^widget\[(.+)]$/);if(!r)throw new Error("Illegal id for widget partial.");i.widgetId=r[1],i.widgetIdParts=l.parseWidgetId(i.widgetId),(t=t||{}).params=o.extend({settings:[l.getWidgetSettingId(i.widgetId)],containerInclusive:!0},t.params||{}),c.selectiveRefresh.Partial.prototype.initialize.call(i,e,t)},refresh:function(){var e,t=this;return l.selectiveRefreshableWidgets[t.widgetIdParts.idBase]?c.selectiveRefresh.Partial.prototype.refresh.call(t):((e=s.Deferred()).reject(),t.fallback(),e.promise())},renderContent:function(e){var t=this;c.selectiveRefresh.Partial.prototype.renderContent.call(t,e)&&(c.preview.send("widget-updated",t.widgetId),c.selectiveRefresh.trigger("widget-updated",t))}}),l.SidebarPartial=c.selectiveRefresh.Partial.extend({initialize:function(e,t){var i=this,r=e.match(/^sidebar\[(.+)]$/);if(!r)throw new Error("Illegal id for sidebar partial.");if(i.sidebarId=r[1],(t=t||{}).params=o.extend({settings:["sidebars_widgets["+i.sidebarId+"]"]},t.params||{}),c.selectiveRefresh.Partial.prototype.initialize.call(i,e,t),!i.params.sidebarArgs)throw new Error("The sidebarArgs param was not provided.");if(1<i.params.settings.length)throw new Error("Expected SidebarPartial to only have one associated setting")},ready:function(){var i=this;o.each(i.settings(),function(e){c(e).bind(o.bind(i.handleSettingChange,i))}),c.selectiveRefresh.bind("partial-content-rendered",function(e){e.partial.extended(l.WidgetPartial)&&-1!==o.indexOf(i.getWidgetIds(),e.partial.widgetId)&&c.selectiveRefresh.trigger("sidebar-updated",i)}),c.bind("change",function(e){var t,e=l.parseWidgetSettingId(e.id);e&&(t=e.idBase,e.number&&(t+="-"+String(e.number)),-1!==o.indexOf(i.getWidgetIds(),t))&&i.ensureWidgetPlacementContainers(t)})},findDynamicSidebarBoundaryNodes:function(){var i=this,r={},n=/^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/,a=function(e){o.each(e,function(e){var t;8===e.nodeType?(t=e.nodeValue.match(n))&&t[2]===i.sidebarId&&(o.isUndefined(r[t[3]])&&(r[t[3]]={before:null,after:null,instanceNumber:parseInt(t[3],10)}),"dynamic_sidebar_before"===t[1]?r[t[3]].before=e:r[t[3]].after=e):1===e.nodeType&&a(e.childNodes)})};return a(document.body.childNodes),o.values(r)},placements:function(){var t=this;return o.map(t.findDynamicSidebarBoundaryNodes(),function(e){return new c.selectiveRefresh.Placement({partial:t,container:null,startNode:e.before,endNode:e.after,context:{instanceNumber:e.instanceNumber}})})},getWidgetIds:function(){var e=this.settings()[0];if(!e)throw new Error("Missing associated setting.");if(!c.has(e))throw new Error("Setting does not exist.");if(e=c(e).get(),o.isArray(e))return e.slice(0);throw new Error("Expected setting to be array of widget IDs")},reflowWidgets:function(){var e=this,t=[],i=e.getWidgetIds(),r=e.placements(),s={};return o.each(i,function(e){var t=c.selectiveRefresh.partial("widget["+e+"]");t&&(s[e]=t)}),o.each(r,function(i){var r,n=[],a=!1,d=-1;o.each(s,function(t){o.each(t.placements(),function(e){i.context.instanceNumber===e.context.sidebar_instance_number&&(r=e.container.index(),n.push({partial:t,placement:e,position:r}),r<d&&(a=!0),d=r)})}),a&&(o.each(n,function(e){i.endNode.parentNode.insertBefore(e.placement.container[0],i.endNode),c.selectiveRefresh.trigger("partial-content-moved",e.placement)}),t.push(i))}),0<t.length&&c.selectiveRefresh.trigger("sidebar-updated",e),t},ensureWidgetPlacementContainers:function(i){var r,n=this,a=!1,e="widget["+i+"]",d=c.selectiveRefresh.partial(e);return d=d||new l.WidgetPartial(e,{params:{}}),r=o.findWhere(l.registeredSidebars,{id:n.sidebarId}),o.each(n.placements(),function(t){var e;r&&!o.find(d.placements(),function(e){return e.context.sidebar_instance_number===t.context.instanceNumber})&&(e=s(r.before_widget.replace(/%1\$s/g,i).replace(/%2\$s/g,"widget")+r.after_widget))[0]&&(e.attr("data-customize-partial-id",d.id),e.attr("data-customize-partial-type","widget"),e.attr("data-customize-widget-id",i),e.data("customize-partial-placement-context",{sidebar_id:n.sidebarId,sidebar_instance_number:t.context.instanceNumber}),t.endNode.parentNode.insertBefore(e[0],t.endNode),a=!0)}),c.selectiveRefresh.partial.add(d),a&&n.reflowWidgets(),d},handleSettingChange:function(e,t){var i,r=this,n=[];0<t.length&&0===e.length||0<e.length&&0===t.length?r.fallback():(i=o.difference(t,e),o.each(i,function(e){var t=c.selectiveRefresh.partial("widget["+e+"]");t&&o.each(t.placements(),function(e){(e.context.sidebar_id===r.sidebarId||e.context.sidebar_args&&e.context.sidebar_args.id===r.sidebarId)&&e.container.remove()}),delete l.renderedWidgets[e]}),i=o.difference(e,t),o.each(i,function(e){var t=r.ensureWidgetPlacementContainers(e);n.push(t),l.renderedWidgets[e]=!0}),o.each(n,function(e){e.refresh()}),c.selectiveRefresh.trigger("sidebar-updated",r))},refresh:function(){var e=this,t=s.Deferred();return t.fail(function(){e.fallback()}),0===e.placements().length?t.reject():(o.each(e.reflowWidgets(),function(e){c.selectiveRefresh.trigger("partial-content-rendered",e)}),t.resolve()),t.promise()}}),c.selectiveRefresh.partialConstructor.sidebar=l.SidebarPartial,c.selectiveRefresh.partialConstructor.widget=l.WidgetPartial,l.addPartials=function(){o.each(l.registeredSidebars,function(e){var t="sidebar["+e.id+"]",i=c.selectiveRefresh.partial(t);i||(i=new l.SidebarPartial(t,{params:{sidebarArgs:e}}),c.selectiveRefresh.partial.add(i))})},l.buildWidgetSelectors=function(){var r=this;s.each(r.registeredSidebars,function(e,t){var t=[t.before_widget,t.before_title,t.after_title,t.after_widget].join(""),t=s(t),i=t.prop("tagName")||"",t=t.prop("className")||"";t&&((t=(t=t.replace(/\S*%[12]\$s\S*/g,"")).replace(/^\s+|\s+$/g,""))&&(i+="."+t.split(/\s+/).join(".")),r.widgetSelectors.push(i))})},l.highlightWidget=function(e){var t=s(document.body),i=s("#"+e);t.find(".widget-customizer-highlighted-widget").removeClass("widget-customizer-highlighted-widget"),i.addClass("widget-customizer-highlighted-widget"),setTimeout(function(){i.removeClass("widget-customizer-highlighted-widget")},500)},l.highlightControls=function(){var t=this,e=this.widgetSelectors.join(",");c.settings.channel&&(s(e).attr("title",this.l10n.widgetTooltip),s(document).on("mouseenter",e,function(){t.preview.send("highlight-widget-control",s(this).prop("id"))}),s(document).on("click",e,function(e){e.shiftKey&&(e.preventDefault(),t.preview.send("focus-widget-control",s(this).prop("id")))}))},l.parseWidgetId=function(e){var t={idBase:"",number:null},i=e.match(/^(.+)-(\d+)$/);return i?(t.idBase=i[1],t.number=parseInt(i[2],10)):t.idBase=e,t},l.parseWidgetSettingId=function(e){var t={idBase:"",number:null},e=e.match(/^widget_([^\[]+?)(?:\[(\d+)])?$/);return e?(t.idBase=e[1],e[2]&&(t.number=parseInt(e[2],10)),t):null},l.getWidgetSettingId=function(e){var e=this.parseWidgetId(e),t="widget_"+e.idBase;return e.number&&(t+="["+String(e.number)+"]"),t},c.bind("preview-ready",function(){s.extend(l,_wpWidgetCustomizerPreviewSettings),l.init()}),l}(jQuery,_,wp.customize);