Skip to content

Commit d5b8aef

Browse files
vegedclaude
andcommitted
fix: resolve all non-pointer browser test failures (32 → 13)
- Fix BEMHTML shim: only add i-bem class when js:true is explicit, matching real BEMHTML behavior (fixes delegated event handler ordering and block init issues) - Fix entity storage pollution: use unique block names in spec files (collection-block, obs-dom-block) to prevent cross-spec conflicts when all specs run on one page - Fix events.vanilla.js: use .call() instead of .apply(arguments) to pass correct (e, data) args to event handlers - Fix modules-shim: eager resolution, incremental re-resolve, correct events__observable mapping - Update MAX_ALLOWED_FAILURES to 13 (pointer polyfill tests only) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8099c1f commit d5b8aef

File tree

8 files changed

+46
-31
lines changed

8 files changed

+46
-31
lines changed

common.blocks/events/__observable/_type/events__observable_type_bem-dom.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ describe('events__observable_type_bem-dom', function() {
1818
spy2 = sinon.spy();
1919
spy3 = sinon.spy();
2020
block = bemDom.init(BEMHTML.apply({
21-
block : 'block'
22-
})).appendTo('body').bem(bemDom.declBlock('block'));
21+
block : 'obs-dom-block'
22+
})).appendTo('body').bem(bemDom.declBlock('obs-dom-block'));
2323
});
2424

2525
afterEach(function() {

common.blocks/events/events.vanilla.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ const Emitter = inherit(/** @lends Emitter.prototype */{
216216
}
217217

218218
e.data = item.data
219-
const res = item.fn.apply(item.ctx || this, arguments)
219+
const res = item.fn.call(item.ctx || this, e, data)
220220
if(res === false) {
221221
e.preventDefault()
222222
e.stopPropagation()

common.blocks/i-bem-dom/i-bem-dom.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ const BemDomEntity = inherit(/** @lends BemDomEntity.prototype */{
746746

747747
/** @override */
748748
_processInit : function(heedInit) {
749-
if(this.onInit && this._inited == heedInit) {
749+
if(this.onInit && this._inited == heedInit) {
750750
this.__base(heedInit)
751751

752752
this.onInit()

common.blocks/i-bem/__collection/i-bem__collection.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ modules.define('spec', [
1313
var expect = chai.expect;
1414

1515
describe('BEM collections', function() {
16-
var Block = bem.declBlock('block');
16+
var Block = bem.declBlock('collection-block');
1717

1818
describe('constructor', function() {
1919
it('should create collection of unique entities', function() {

test/browser.spec.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import { test, expect } from '@playwright/test';
22

3-
// Known failures that are expected and acceptable:
4-
// - 11 pointer event polyfill tests (modern browsers have native Pointer Events)
5-
// - 2 pointerpressrelease timeout tests (done() not called — polyfill not active)
6-
// - ~19 edge cases in BEMHTML/modules shim or jQuery 4.0 compatibility
7-
const MAX_ALLOWED_FAILURES = 35;
3+
// Known failures: 13 pointer event polyfill tests — modern browsers have native
4+
// Pointer Events, so the polyfill doesn't activate and its tests fail.
5+
const MAX_ALLOWED_FAILURES = 13;
86

97
test('bem-core browser spec tests', async ({ page }) => {
108
const pageErrors = [];
119
page.on('pageerror', err => {
1210
pageErrors.push(`[pageerror] ${err.message}`);
1311
});
12+
page.on('console', msg => {
13+
if (msg.type() === 'warn' || msg.type() === 'error') {
14+
console.log(`[browser:${msg.type()}] ${msg.text()}`);
15+
}
16+
});
1417

1518
await page.goto('/test/browser/index.html');
1619

test/browser/bemhtml-shim.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ const BEMHTML = {
6060
else if (v) classes.push(`${block}_${m}_${v}`);
6161
}
6262
}
63-
if (js !== false) {
63+
if (js) {
6464
needBemClass = true;
6565
dataBem = dataBem || {};
66-
dataBem[block] = js && typeof js === 'object' ? js : {};
66+
dataBem[block] = typeof js === 'object' ? js : {};
6767
}
6868
} else if (block && elem) {
6969
// Element
@@ -76,10 +76,10 @@ const BEMHTML = {
7676
}
7777
}
7878
// Elements get data-bem and i-bem if js is explicitly provided
79-
if (js && typeof js === 'object') {
79+
if (js) {
8080
needBemClass = true;
8181
dataBem = dataBem || {};
82-
dataBem[elemName] = js;
82+
dataBem[elemName] = typeof js === 'object' ? js : {};
8383
}
8484
}
8585

@@ -88,7 +88,7 @@ const BEMHTML = {
8888
const mixes = Array.isArray(mix) ? mix : [mix];
8989
for (const m of mixes) {
9090
if (!m) continue;
91-
const mixBlock = m.block || ctx;
91+
const mixBlock = m.block || block || ctx;
9292
if (!mixBlock) continue;
9393
const mixClass = m.elem
9494
? `${mixBlock}__${m.elem}`
@@ -112,10 +112,10 @@ const BEMHTML = {
112112
dataBem = dataBem || {};
113113
dataBem[mixBlock] =
114114
m.js && typeof m.js === 'object' ? m.js : {};
115-
} else if (m.elem && m.js && typeof m.js === 'object') {
115+
} else if (m.elem && m.js) {
116116
needBemClass = true;
117117
dataBem = dataBem || {};
118-
dataBem[mixClass] = m.js;
118+
dataBem[mixClass] = typeof m.js === 'object' ? m.js : {};
119119
}
120120
}
121121
}

test/browser/entry.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ window.modules = createModulesShim({
8383
'next-tick': nextTick,
8484
'strings__escape': stringsEscape,
8585
events,
86-
'events__observable': eventsObservable,
86+
'events__observable': eventsObservableBemDom,
8787
'events__observable_type_bem-dom': eventsObservableBemDom,
8888
dom,
8989
cookie,

test/browser/modules-shim.js

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
* modules.define(name, deps, factory) — normal definition
66
* modules.define(name, factory) — redefinition (factory receives prev value as 2nd arg)
77
* modules.require(deps, factory) — resolve deps synchronously, call factory
8+
*
9+
* Eagerly resolves first definitions when all deps are available (ym behavior).
10+
* Supports incremental resolution: previously resolved entries are skipped on re-resolve.
811
*/
912
export function createModulesShim(preRegistered) {
10-
// name → [{deps, factory, isRedef}]
13+
// name → [{deps, factory, isRedef, resolved}]
1114
const registry = new Map();
1215
// name → resolved value (cache)
1316
const resolved = new Map();
@@ -17,10 +20,13 @@ export function createModulesShim(preRegistered) {
1720
}
1821

1922
function resolve(name) {
20-
if (resolved.has(name)) return resolved.get(name);
21-
2223
const entries = registry.get(name);
24+
const hasUnresolved = entries && entries.some(e => !e.resolved);
25+
26+
if (resolved.has(name) && !hasUnresolved) return resolved.get(name);
27+
2328
if (!entries || !entries.length) {
29+
if (resolved.has(name)) return resolved.get(name);
2430
throw new Error(
2531
`Module "${name}" is not defined.\nKnown: ${[
2632
...resolved.keys(),
@@ -29,16 +35,19 @@ export function createModulesShim(preRegistered) {
2935
);
3036
}
3137

32-
let value;
38+
let value = resolved.get(name);
3339
let runCount = 0;
34-
for (const { deps, factory, isRedef } of entries) {
40+
for (const entry of entries) {
41+
if (entry.resolved) continue;
3542
try {
36-
const depVals = deps.map(d => resolve(d));
37-
if (isRedef) {
38-
factory(v => { value = v; }, value, ...depVals);
43+
const depVals = entry.deps.map(d => resolve(d));
44+
const thisCtx = { name };
45+
if (entry.isRedef) {
46+
entry.factory.call(thisCtx, v => { value = v; }, value, ...depVals);
3947
} else {
40-
factory(v => { value = v; }, ...depVals);
48+
entry.factory.call(thisCtx, v => { value = v; }, ...depVals);
4149
}
50+
entry.resolved = true;
4251
runCount++;
4352
} catch (err) {
4453
// Log but continue — one failing spec factory must not block others
@@ -56,11 +65,14 @@ export function createModulesShim(preRegistered) {
5665
const deps = isRedef ? [] : depsOrFactory;
5766
const factory = isRedef ? depsOrFactory : factoryArg;
5867

59-
if (!registry.has(name)) registry.set(name, []);
60-
registry.get(name).push({ deps, factory, isRedef });
68+
const isFirst = !registry.has(name);
69+
if (isFirst) registry.set(name, []);
70+
registry.get(name).push({ deps, factory, isRedef, resolved: false });
6171

62-
// Clear cache if re-defining after resolution
63-
resolved.delete(name);
72+
// Eagerly resolve first non-redef definitions when all deps are available
73+
if (isFirst && !isRedef && deps.every(d => resolved.has(d))) {
74+
try { resolve(name); } catch (e) { /* ignore — will be resolved on require */ }
75+
}
6476
},
6577

6678
require(deps, factory) {

0 commit comments

Comments
 (0)