@freeappstore/quality 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fixture.test.d.ts +2 -0
- package/dist/fixture.test.d.ts.map +1 -0
- package/dist/fixture.test.js +320 -0
- package/dist/fixture.test.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +168 -3
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +155 -3
- package/dist/index.test.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.test.d.ts","sourceRoot":"","sources":["../src/fixture.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
/**
|
|
3
|
+
* Fixture-driven tests for snapshot() and the auditor's per-viewport
|
|
4
|
+
* verdict.
|
|
5
|
+
*
|
|
6
|
+
* The spec lives at /tmp/freegamestore/audit-fixture/index.html
|
|
7
|
+
* (deployed at https://auditor-fixture.freegamestore.online). Each
|
|
8
|
+
* `?scenario=<id>` there is a deliberately-broken layout that the
|
|
9
|
+
* platform auditor must catch. The fixture HTML *is* the spec; this
|
|
10
|
+
* file is the unit-level mirror.
|
|
11
|
+
*
|
|
12
|
+
* Two-tier coverage:
|
|
13
|
+
* - this file (jsdom): replicates each scenario's effective DOM
|
|
14
|
+
* shape and asserts snapshot() reports the right thing.
|
|
15
|
+
* - fixture.live.test.ts (TODO; cron in CI): drives the deployed
|
|
16
|
+
* page in a real browser, captures the postMessage stream, and
|
|
17
|
+
* asserts the same expectations against the live build.
|
|
18
|
+
*
|
|
19
|
+
* Adding a new fixture scenario? Add its id to CANONICAL_SCENARIOS,
|
|
20
|
+
* then either register a `scenario(id, ...)` block or add an entry
|
|
21
|
+
* to NOT_UNIT_TESTABLE with the reason. The "fixture coverage guard"
|
|
22
|
+
* test at the bottom fails loudly otherwise.
|
|
23
|
+
*/
|
|
24
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
25
|
+
import { snapshot } from './index.js';
|
|
26
|
+
/**
|
|
27
|
+
* Every scenario id the fixture page defines. Order matches the
|
|
28
|
+
* SCENARIOS object in the fixture HTML for easy diffing.
|
|
29
|
+
*/
|
|
30
|
+
const CANONICAL_SCENARIOS = [
|
|
31
|
+
'fits',
|
|
32
|
+
'scroll-x',
|
|
33
|
+
'scroll-y',
|
|
34
|
+
'clip-inner',
|
|
35
|
+
'clip-inner-y',
|
|
36
|
+
'vh-bug',
|
|
37
|
+
'gap-mid',
|
|
38
|
+
'landscape-only-bad',
|
|
39
|
+
'no-reporter',
|
|
40
|
+
'large-scrollwidth-fp',
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* Scenarios that intentionally have no jsdom-level mirror, with the
|
|
44
|
+
* reason. The coverage guard treats these as covered.
|
|
45
|
+
*/
|
|
46
|
+
const NOT_UNIT_TESTABLE = {
|
|
47
|
+
'vh-bug': 'iOS Safari URL-bar dynamic viewport — requires a real device viewport. Covered by fixture.live.test.ts.',
|
|
48
|
+
'no-reporter': 'Tests *absence* of postMessage, not snapshot() output. Belongs in the live integration test.',
|
|
49
|
+
};
|
|
50
|
+
/** Populated by scenario() at registration time; checked by the coverage guard. */
|
|
51
|
+
const REGISTERED_SCENARIOS = new Set();
|
|
52
|
+
/**
|
|
53
|
+
* Wrap describe() so every fixture-mirroring block registers its id
|
|
54
|
+
* against CANONICAL_SCENARIOS. The string typing means a typo'd id
|
|
55
|
+
* fails to compile rather than silently skipping coverage.
|
|
56
|
+
*/
|
|
57
|
+
function scenario(id, fn) {
|
|
58
|
+
if (REGISTERED_SCENARIOS.has(id)) {
|
|
59
|
+
throw new Error(`Duplicate scenario registration: ${id}`);
|
|
60
|
+
}
|
|
61
|
+
REGISTERED_SCENARIOS.add(id);
|
|
62
|
+
describe(`fixture: ${id}`, fn);
|
|
63
|
+
}
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
document.body.innerHTML = '';
|
|
66
|
+
// Reset hostname so appId extraction is deterministic.
|
|
67
|
+
Object.defineProperty(window, 'location', {
|
|
68
|
+
value: { hostname: 'auditor-fixture.freegamestore.online' },
|
|
69
|
+
configurable: true,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* Set documentElement scroll dimensions. jsdom doesn't actually do
|
|
74
|
+
* layout, so we have to mock these explicitly per test.
|
|
75
|
+
*/
|
|
76
|
+
function setDocSize(scrollW, scrollH, clientW, clientH) {
|
|
77
|
+
const root = document.documentElement;
|
|
78
|
+
Object.defineProperty(root, 'scrollWidth', { get: () => scrollW, configurable: true });
|
|
79
|
+
Object.defineProperty(root, 'scrollHeight', { get: () => scrollH, configurable: true });
|
|
80
|
+
Object.defineProperty(root, 'clientWidth', { get: () => clientW, configurable: true });
|
|
81
|
+
Object.defineProperty(root, 'clientHeight', { get: () => clientH, configurable: true });
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Stub getComputedStyle to return a specific overflow per element.
|
|
85
|
+
* Falls back to the original for elements not in the map.
|
|
86
|
+
*/
|
|
87
|
+
function withComputedStyles(map) {
|
|
88
|
+
const orig = window.getComputedStyle;
|
|
89
|
+
window.getComputedStyle = ((el) => {
|
|
90
|
+
const override = map.get(el);
|
|
91
|
+
if (override)
|
|
92
|
+
return { ...orig(el), ...override };
|
|
93
|
+
return orig(el);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Stub element layout dimensions. jsdom returns 0 for everything, so
|
|
98
|
+
* tests must set what they expect.
|
|
99
|
+
*/
|
|
100
|
+
function setElSize(el, scrollW, scrollH, clientW, clientH) {
|
|
101
|
+
Object.defineProperty(el, 'scrollWidth', { get: () => scrollW, configurable: true });
|
|
102
|
+
Object.defineProperty(el, 'scrollHeight', { get: () => scrollH, configurable: true });
|
|
103
|
+
Object.defineProperty(el, 'clientWidth', { get: () => clientW, configurable: true });
|
|
104
|
+
Object.defineProperty(el, 'clientHeight', { get: () => clientH, configurable: true });
|
|
105
|
+
}
|
|
106
|
+
scenario('fits', () => {
|
|
107
|
+
it('reports no scroll, no clipping, valid app id', () => {
|
|
108
|
+
setDocSize(393, 852, 393, 852);
|
|
109
|
+
document.body.innerHTML = '<div>Trivial layout</div>';
|
|
110
|
+
const s = snapshot();
|
|
111
|
+
expect(s.appId).toBe('auditor-fixture');
|
|
112
|
+
expect(s.document.scrollsX).toBe(false);
|
|
113
|
+
expect(s.document.scrollsY).toBe(false);
|
|
114
|
+
expect(s.clipping).toEqual([]);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
scenario('scroll-x', () => {
|
|
118
|
+
it('reports scrollsX=true (9999px-wide content)', () => {
|
|
119
|
+
setDocSize(9999, 852, 393, 852);
|
|
120
|
+
document.body.innerHTML = '<div style="width:9999px;height:100px"></div>';
|
|
121
|
+
const s = snapshot();
|
|
122
|
+
expect(s.document.scrollsX).toBe(true);
|
|
123
|
+
expect(s.document.scrollsY).toBe(false);
|
|
124
|
+
expect(s.document.scrollWidth).toBe(9999);
|
|
125
|
+
expect(s.document.clientWidth).toBe(393);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
scenario('scroll-y', () => {
|
|
129
|
+
it('reports scrollsY=true (9999px-tall content)', () => {
|
|
130
|
+
setDocSize(393, 9999, 393, 852);
|
|
131
|
+
const s = snapshot();
|
|
132
|
+
expect(s.document.scrollsX).toBe(false);
|
|
133
|
+
expect(s.document.scrollsY).toBe(true);
|
|
134
|
+
expect(s.document.scrollHeight).toBe(9999);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
scenario('clip-inner', () => {
|
|
138
|
+
it('document fits but inner element clips horizontally', () => {
|
|
139
|
+
setDocSize(393, 852, 393, 852);
|
|
140
|
+
document.body.innerHTML = '<div class="clipper"><div class="child"></div></div>';
|
|
141
|
+
const clipper = document.querySelector('.clipper');
|
|
142
|
+
const child = document.querySelector('.child');
|
|
143
|
+
setElSize(clipper, 9999, 100, 100, 100);
|
|
144
|
+
setElSize(child, 9999, 100, 9999, 100);
|
|
145
|
+
withComputedStyles(new Map([
|
|
146
|
+
[clipper, { overflowX: 'hidden', overflowY: 'visible' }],
|
|
147
|
+
]));
|
|
148
|
+
const s = snapshot();
|
|
149
|
+
// Document doesn't scroll — the clipper masks the overflow.
|
|
150
|
+
expect(s.document.scrollsX).toBe(false);
|
|
151
|
+
expect(s.document.scrollsY).toBe(false);
|
|
152
|
+
// But the clipper IS clipping content.
|
|
153
|
+
const hit = s.clipping.find((c) => c.selector.includes('clipper'));
|
|
154
|
+
expect(hit).toBeDefined();
|
|
155
|
+
expect(hit?.clipsX).toBe(true);
|
|
156
|
+
expect(hit?.clipsY).toBe(false);
|
|
157
|
+
expect(hit?.scrollWidth).toBe(9999);
|
|
158
|
+
expect(hit?.clientWidth).toBe(100);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
scenario('clip-inner-y', () => {
|
|
162
|
+
it('reports vertical clipping on a 50px-tall overflow:hidden parent', () => {
|
|
163
|
+
setDocSize(393, 852, 393, 852);
|
|
164
|
+
document.body.innerHTML = '<div class="clipper"></div>';
|
|
165
|
+
const clipper = document.querySelector('.clipper');
|
|
166
|
+
setElSize(clipper, 393, 999, 393, 50);
|
|
167
|
+
withComputedStyles(new Map([
|
|
168
|
+
[clipper, { overflowX: 'visible', overflowY: 'hidden' }],
|
|
169
|
+
]));
|
|
170
|
+
const s = snapshot();
|
|
171
|
+
const hit = s.clipping[0];
|
|
172
|
+
expect(hit?.clipsY).toBe(true);
|
|
173
|
+
expect(hit?.clipsX).toBe(false);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
scenario('gap-mid', () => {
|
|
177
|
+
/**
|
|
178
|
+
* Fixture CSS: a `.force` child with `min-width: 700px`, released
|
|
179
|
+
* to `min-width: 0` only by `@media (min-width: 769px)` and
|
|
180
|
+
* `@media (max-width: 599px)`. So at viewports 600–768 the child
|
|
181
|
+
* stays 700px wide and pushes the document into horizontal scroll.
|
|
182
|
+
*
|
|
183
|
+
* jsdom does not evaluate @media. We simulate the *effective*
|
|
184
|
+
* post-CSS document dimensions at three representative widths.
|
|
185
|
+
* The complementary scoring assertion (bucket-summed share for a
|
|
186
|
+
* mid-gap pass pattern) lives in index.test.ts under
|
|
187
|
+
* `computeQualityIndex > catches a gap in the middle`.
|
|
188
|
+
*
|
|
189
|
+
* Fixture nuance, recorded but not "fixed" here (different repo):
|
|
190
|
+
* the fixture's stated "fails at 600/768" is half-right. With the
|
|
191
|
+
* fixture's `box-sizing: border-box` reset, a 700px-min-width child
|
|
192
|
+
* fits inside a 768-32=736px content area. Only 600 actually
|
|
193
|
+
* overflows. We assert the mathematically-true behaviour.
|
|
194
|
+
*/
|
|
195
|
+
it('narrow viewport (393): @media max-width 599 releases min-width — fits', () => {
|
|
196
|
+
setDocSize(393, 852, 393, 852);
|
|
197
|
+
expect(snapshot().document.scrollsX).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
it('mid viewport (600): no @media releases — 700px child overflows the 600px viewport', () => {
|
|
200
|
+
setDocSize(700, 852, 600, 852);
|
|
201
|
+
expect(snapshot().document.scrollsX).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
it('wide viewport (1024): @media min-width 769 releases min-width — fits', () => {
|
|
204
|
+
setDocSize(1024, 1366, 1024, 1366);
|
|
205
|
+
expect(snapshot().document.scrollsX).toBe(false);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
scenario('landscape-only-bad', () => {
|
|
209
|
+
/**
|
|
210
|
+
* Fixture CSS: `.ok` has no width constraint by default; under
|
|
211
|
+
* `@media (orientation: landscape)` it gets `width: 1500px`. So
|
|
212
|
+
* portrait viewports fit cleanly and landscape viewports overflow
|
|
213
|
+
* horizontally on every device narrower than 1500px.
|
|
214
|
+
*
|
|
215
|
+
* The complementary scoring assertion (overall = min(portrait,
|
|
216
|
+
* landscape) for any-orientation apps) lives in index.test.ts
|
|
217
|
+
* under `computeQualityIndex > overall = min of orientation
|
|
218
|
+
* scores`.
|
|
219
|
+
*/
|
|
220
|
+
it('portrait viewport (393×852): no width override — fits', () => {
|
|
221
|
+
setDocSize(393, 852, 393, 852);
|
|
222
|
+
expect(snapshot().document.scrollsX).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
it('landscape viewport (852×393): @media orientation:landscape forces 1500px — overflows', () => {
|
|
225
|
+
setDocSize(1500, 393, 852, 393);
|
|
226
|
+
const s = snapshot();
|
|
227
|
+
expect(s.document.scrollsX).toBe(true);
|
|
228
|
+
expect(s.document.scrollWidth).toBe(1500);
|
|
229
|
+
expect(s.document.clientWidth).toBe(852);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
scenario('large-scrollwidth-fp', () => {
|
|
233
|
+
it('does NOT flag clipping when scrollWidth exceeds clientWidth by ≤1px (rounding)', () => {
|
|
234
|
+
setDocSize(393, 852, 393, 852);
|
|
235
|
+
document.body.innerHTML = '<div class="grid"></div>';
|
|
236
|
+
const grid = document.querySelector('.grid');
|
|
237
|
+
// Sub-pixel rounding: scrollWidth = 394 in a 393-wide container.
|
|
238
|
+
setElSize(grid, 394, 100, 393, 100);
|
|
239
|
+
withComputedStyles(new Map([
|
|
240
|
+
[grid, { overflowX: 'hidden', overflowY: 'visible' }],
|
|
241
|
+
]));
|
|
242
|
+
const s = snapshot();
|
|
243
|
+
expect(s.clipping).toEqual([]);
|
|
244
|
+
});
|
|
245
|
+
it('DOES flag clipping when overflow exceeds 1px', () => {
|
|
246
|
+
setDocSize(393, 852, 393, 852);
|
|
247
|
+
document.body.innerHTML = '<div class="grid"></div>';
|
|
248
|
+
const grid = document.querySelector('.grid');
|
|
249
|
+
setElSize(grid, 395, 100, 393, 100); // 2px overflow
|
|
250
|
+
withComputedStyles(new Map([
|
|
251
|
+
[grid, { overflowX: 'hidden', overflowY: 'visible' }],
|
|
252
|
+
]));
|
|
253
|
+
const s = snapshot();
|
|
254
|
+
expect(s.clipping.length).toBe(1);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
/**
|
|
258
|
+
* Extras — cover snapshot() behaviour that isn't a fixture scenario
|
|
259
|
+
* but is referenced by the same auditor contract. Kept here to live
|
|
260
|
+
* next to the scenarios they shore up; not registered against
|
|
261
|
+
* CANONICAL_SCENARIOS.
|
|
262
|
+
*/
|
|
263
|
+
describe('extra: overflow:clip parity with overflow:hidden', () => {
|
|
264
|
+
it('treats overflow:clip the same as overflow:hidden', () => {
|
|
265
|
+
setDocSize(393, 852, 393, 852);
|
|
266
|
+
document.body.innerHTML = '<div class="clipper"></div>';
|
|
267
|
+
const clipper = document.querySelector('.clipper');
|
|
268
|
+
setElSize(clipper, 500, 100, 100, 100);
|
|
269
|
+
withComputedStyles(new Map([
|
|
270
|
+
[clipper, { overflowX: 'clip', overflowY: 'visible' }],
|
|
271
|
+
]));
|
|
272
|
+
const s = snapshot();
|
|
273
|
+
expect(s.clipping.length).toBe(1);
|
|
274
|
+
expect(s.clipping[0]?.clipsX).toBe(true);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
describe('extra: scroll containers (overflow:auto/scroll) are NOT clipping', () => {
|
|
278
|
+
it('overflow:auto with overflowing content does not register as clipping', () => {
|
|
279
|
+
// Justification: overflow:auto means the user CAN scroll inside.
|
|
280
|
+
// It's a UX warning, not a hidden-content bug. The reporter's
|
|
281
|
+
// clipping field is reserved for the hidden case.
|
|
282
|
+
setDocSize(393, 852, 393, 852);
|
|
283
|
+
document.body.innerHTML = '<div class="scroller"></div>';
|
|
284
|
+
const sc = document.querySelector('.scroller');
|
|
285
|
+
setElSize(sc, 9999, 100, 393, 100);
|
|
286
|
+
withComputedStyles(new Map([[sc, { overflowX: 'auto', overflowY: 'visible' }]]));
|
|
287
|
+
const s = snapshot();
|
|
288
|
+
expect(s.clipping).toEqual([]);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
/**
|
|
292
|
+
* Coverage guard. Every id in CANONICAL_SCENARIOS must be either
|
|
293
|
+
* registered via scenario() above OR explicitly listed in
|
|
294
|
+
* NOT_UNIT_TESTABLE with a reason. Adding a fixture scenario without
|
|
295
|
+
* touching this file fails CI here, with a message naming the gap.
|
|
296
|
+
*/
|
|
297
|
+
describe('fixture coverage guard', () => {
|
|
298
|
+
it('every canonical scenario is either unit-tested or marked not-unit-testable', () => {
|
|
299
|
+
const skipped = new Set(Object.keys(NOT_UNIT_TESTABLE));
|
|
300
|
+
const covered = new Set([...REGISTERED_SCENARIOS, ...skipped]);
|
|
301
|
+
const missing = CANONICAL_SCENARIOS.filter((id) => !covered.has(id));
|
|
302
|
+
expect(missing, `Fixture scenarios with no unit mirror and no NOT_UNIT_TESTABLE entry: ${missing.join(', ')}`).toEqual([]);
|
|
303
|
+
});
|
|
304
|
+
it('no scenario is double-counted (registered AND marked not-unit-testable)', () => {
|
|
305
|
+
const skipped = new Set(Object.keys(NOT_UNIT_TESTABLE));
|
|
306
|
+
const overlap = [...REGISTERED_SCENARIOS].filter((id) => skipped.has(id));
|
|
307
|
+
expect(overlap, `Scenarios both tested and skipped: ${overlap.join(', ')}`).toEqual([]);
|
|
308
|
+
});
|
|
309
|
+
it('NOT_UNIT_TESTABLE keys are all canonical', () => {
|
|
310
|
+
// Defends against typos in NOT_UNIT_TESTABLE keys silently passing
|
|
311
|
+
// the guard. (CANONICAL_SCENARIOS is `as const` typed, so the
|
|
312
|
+
// ScenarioId Partial<Record<...>> already enforces this at compile
|
|
313
|
+
// time — this is a runtime belt for future refactors that widen
|
|
314
|
+
// the key type.)
|
|
315
|
+
const canon = new Set(CANONICAL_SCENARIOS);
|
|
316
|
+
const stray = Object.keys(NOT_UNIT_TESTABLE).filter((id) => !canon.has(id));
|
|
317
|
+
expect(stray, `NOT_UNIT_TESTABLE has non-canonical keys: ${stray.join(', ')}`).toEqual([]);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
//# sourceMappingURL=fixture.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.test.js","sourceRoot":"","sources":["../src/fixture.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,59 @@ interface ReporterHandle {
|
|
|
71
71
|
/** Force a snapshot + post immediately (e.g. after a layout change). */
|
|
72
72
|
reportNow(): void;
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* The reference device matrix. Each entry pairs a viewport size with the
|
|
76
|
+
* cumulative device share at that width (percent of devices whose viewport
|
|
77
|
+
* is ≥ this wide). Used for both the CLI screencheck and the dashboard so
|
|
78
|
+
* scores are computed identically. Numbers blend StatCounter + caniuse.
|
|
79
|
+
*/
|
|
80
|
+
export declare const REFERENCE_VIEWPORTS: ReadonlyArray<{
|
|
81
|
+
width: number;
|
|
82
|
+
height: number;
|
|
83
|
+
label: string;
|
|
84
|
+
orientation: 'portrait' | 'landscape';
|
|
85
|
+
/** Cumulative share: % of devices with viewport width ≥ this size. */
|
|
86
|
+
share: number;
|
|
87
|
+
kind: 'phone' | 'tablet';
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Compute Quality Index from a per-viewport pass/fail map.
|
|
91
|
+
*
|
|
92
|
+
* Cumulative share is the percentage of devices with viewport WIDTH ≥
|
|
93
|
+
* this size. So consecutive widths form non-overlapping buckets:
|
|
94
|
+
*
|
|
95
|
+
* bucket[i] share = share[i] − share[i+1] for i < N-1
|
|
96
|
+
* bucket[N-1] = share[N-1] (everything ≥ widest)
|
|
97
|
+
*
|
|
98
|
+
* The Index sums the bucket-shares of every PASSING viewport. This
|
|
99
|
+
* correctly handles the "gap in the middle" case our naive max-share
|
|
100
|
+
* formula got wrong: e.g. layout that passes at 568 but fails at 667/736
|
|
101
|
+
* and passes again at 1024+ should NOT score 99% — it scores roughly
|
|
102
|
+
* (99-96) + (60-35) + (35-20) + 20 = 63%.
|
|
103
|
+
*
|
|
104
|
+
* For multi-orientation apps the score is the LOWER of the two
|
|
105
|
+
* orientations (worst-case across orientations), since real users
|
|
106
|
+
* encounter both.
|
|
107
|
+
*
|
|
108
|
+
* @param matrix viewports the audit considered (typically REFERENCE_VIEWPORTS, but callers can scope to a subset)
|
|
109
|
+
* @param passingKeys set of `${orientation}:${width}x${height}` keys that passed
|
|
110
|
+
*/
|
|
111
|
+
export declare function computeQualityIndex(matrix: ReadonlyArray<{
|
|
112
|
+
width: number;
|
|
113
|
+
height: number;
|
|
114
|
+
orientation: 'portrait' | 'landscape';
|
|
115
|
+
share: number;
|
|
116
|
+
}>, passingKeys: ReadonlySet<string>): {
|
|
117
|
+
portrait: number;
|
|
118
|
+
landscape: number;
|
|
119
|
+
overall: number;
|
|
120
|
+
};
|
|
121
|
+
/** Build the canonical key used by computeQualityIndex's passingKeys set. */
|
|
122
|
+
export declare function viewportKey(v: {
|
|
123
|
+
width: number;
|
|
124
|
+
height: number;
|
|
125
|
+
orientation: 'portrait' | 'landscape';
|
|
126
|
+
}): string;
|
|
74
127
|
/**
|
|
75
128
|
* Start the reporter. Idempotent — calling twice returns the existing
|
|
76
129
|
* handle. Designed for one-line use: `initQualityReporter()` from your
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC;IACV,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,iGAAiG;IACjG,QAAQ,EAAE;QACR,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,6FAA6F;IAC7F,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,gFAAgF;IAChF,WAAW,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1C,6CAA6C;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB;oDACgD;IAChD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC;IACV,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,iGAAiG;IACjG,QAAQ,EAAE;QACR,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,6FAA6F;IAC7F,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,gFAAgF;IAChF,WAAW,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1C,6CAA6C;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB;oDACgD;IAChD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAsBD;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,cAAc,CAgGzC;AAED,UAAU,cAAc;IACtB,+CAA+C;IAC/C,IAAI,IAAI,IAAI,CAAC;IACb,wEAAwE;IACxE,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,UAAU,GAAG,WAAW,CAAC;IACtC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC1B,CAoFA,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,WAAW,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,EACF,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,GAC/B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAsC1D;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,CAAC,EAAE;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,WAAW,CAAC;CACvC,GAAG,MAAM,CAET;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CA0DpD"}
|
package/dist/index.js
CHANGED
|
@@ -102,7 +102,9 @@ export function snapshot() {
|
|
|
102
102
|
? 'dark'
|
|
103
103
|
: 'light'
|
|
104
104
|
: 'unknown';
|
|
105
|
-
const reducedMotion = typeof matchMedia === 'function'
|
|
105
|
+
const reducedMotion = typeof matchMedia === 'function'
|
|
106
|
+
? matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
107
|
+
: false;
|
|
106
108
|
// App ID is the leftmost subdomain on a *.freeappstore.online or
|
|
107
109
|
// *.freegamestore.online host; bare domains (local dev, custom domains)
|
|
108
110
|
// get the empty string and the dashboard falls back to the iframe URL.
|
|
@@ -129,6 +131,167 @@ export function snapshot() {
|
|
|
129
131
|
reporterVersion: REPORTER_VERSION,
|
|
130
132
|
};
|
|
131
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* The reference device matrix. Each entry pairs a viewport size with the
|
|
136
|
+
* cumulative device share at that width (percent of devices whose viewport
|
|
137
|
+
* is ≥ this wide). Used for both the CLI screencheck and the dashboard so
|
|
138
|
+
* scores are computed identically. Numbers blend StatCounter + caniuse.
|
|
139
|
+
*/
|
|
140
|
+
export const REFERENCE_VIEWPORTS = [
|
|
141
|
+
{
|
|
142
|
+
width: 320,
|
|
143
|
+
height: 568,
|
|
144
|
+
label: 'iPhone SE',
|
|
145
|
+
orientation: 'portrait',
|
|
146
|
+
share: 99,
|
|
147
|
+
kind: 'phone',
|
|
148
|
+
},
|
|
149
|
+
{ width: 360, height: 800, label: 'Android', orientation: 'portrait', share: 96, kind: 'phone' },
|
|
150
|
+
{
|
|
151
|
+
width: 393,
|
|
152
|
+
height: 852,
|
|
153
|
+
label: 'iPhone 15',
|
|
154
|
+
orientation: 'portrait',
|
|
155
|
+
share: 92,
|
|
156
|
+
kind: 'phone',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
width: 414,
|
|
160
|
+
height: 896,
|
|
161
|
+
label: 'iPhone 11 PM',
|
|
162
|
+
orientation: 'portrait',
|
|
163
|
+
share: 88,
|
|
164
|
+
kind: 'phone',
|
|
165
|
+
},
|
|
166
|
+
{ width: 600, height: 800, label: 'Tablet', orientation: 'portrait', share: 60, kind: 'tablet' },
|
|
167
|
+
{ width: 768, height: 1024, label: 'iPad', orientation: 'portrait', share: 35, kind: 'tablet' },
|
|
168
|
+
{
|
|
169
|
+
width: 1024,
|
|
170
|
+
height: 1366,
|
|
171
|
+
label: 'iPad Pro',
|
|
172
|
+
orientation: 'portrait',
|
|
173
|
+
share: 20,
|
|
174
|
+
kind: 'tablet',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
width: 568,
|
|
178
|
+
height: 320,
|
|
179
|
+
label: 'iPhone SE land.',
|
|
180
|
+
orientation: 'landscape',
|
|
181
|
+
share: 99,
|
|
182
|
+
kind: 'phone',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
width: 667,
|
|
186
|
+
height: 375,
|
|
187
|
+
label: 'iPhone 8 land.',
|
|
188
|
+
orientation: 'landscape',
|
|
189
|
+
share: 96,
|
|
190
|
+
kind: 'phone',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
width: 736,
|
|
194
|
+
height: 414,
|
|
195
|
+
label: 'iPhone+ land.',
|
|
196
|
+
orientation: 'landscape',
|
|
197
|
+
share: 88,
|
|
198
|
+
kind: 'phone',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
width: 800,
|
|
202
|
+
height: 600,
|
|
203
|
+
label: 'Tablet land.',
|
|
204
|
+
orientation: 'landscape',
|
|
205
|
+
share: 60,
|
|
206
|
+
kind: 'tablet',
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
width: 1024,
|
|
210
|
+
height: 768,
|
|
211
|
+
label: 'iPad land.',
|
|
212
|
+
orientation: 'landscape',
|
|
213
|
+
share: 35,
|
|
214
|
+
kind: 'tablet',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
width: 1366,
|
|
218
|
+
height: 1024,
|
|
219
|
+
label: 'iPad Pro land.',
|
|
220
|
+
orientation: 'landscape',
|
|
221
|
+
share: 20,
|
|
222
|
+
kind: 'tablet',
|
|
223
|
+
},
|
|
224
|
+
];
|
|
225
|
+
/**
|
|
226
|
+
* Compute Quality Index from a per-viewport pass/fail map.
|
|
227
|
+
*
|
|
228
|
+
* Cumulative share is the percentage of devices with viewport WIDTH ≥
|
|
229
|
+
* this size. So consecutive widths form non-overlapping buckets:
|
|
230
|
+
*
|
|
231
|
+
* bucket[i] share = share[i] − share[i+1] for i < N-1
|
|
232
|
+
* bucket[N-1] = share[N-1] (everything ≥ widest)
|
|
233
|
+
*
|
|
234
|
+
* The Index sums the bucket-shares of every PASSING viewport. This
|
|
235
|
+
* correctly handles the "gap in the middle" case our naive max-share
|
|
236
|
+
* formula got wrong: e.g. layout that passes at 568 but fails at 667/736
|
|
237
|
+
* and passes again at 1024+ should NOT score 99% — it scores roughly
|
|
238
|
+
* (99-96) + (60-35) + (35-20) + 20 = 63%.
|
|
239
|
+
*
|
|
240
|
+
* For multi-orientation apps the score is the LOWER of the two
|
|
241
|
+
* orientations (worst-case across orientations), since real users
|
|
242
|
+
* encounter both.
|
|
243
|
+
*
|
|
244
|
+
* @param matrix viewports the audit considered (typically REFERENCE_VIEWPORTS, but callers can scope to a subset)
|
|
245
|
+
* @param passingKeys set of `${orientation}:${width}x${height}` keys that passed
|
|
246
|
+
*/
|
|
247
|
+
export function computeQualityIndex(matrix, passingKeys) {
|
|
248
|
+
const score = (orientation) => {
|
|
249
|
+
// Sort by width ASCENDING (shares descending). Buckets are then:
|
|
250
|
+
// [W0, W1): share[W0] − share[W1] (devices in the narrowest range)
|
|
251
|
+
// [W1, W2): share[W1] − share[W2]
|
|
252
|
+
// ...
|
|
253
|
+
// [Wn, ∞): share[Wn] (everything ≥ widest test point)
|
|
254
|
+
const inOrientation = matrix
|
|
255
|
+
.filter((v) => v.orientation === orientation)
|
|
256
|
+
.slice()
|
|
257
|
+
.sort((a, b) => a.width - b.width);
|
|
258
|
+
if (inOrientation.length === 0)
|
|
259
|
+
return -1;
|
|
260
|
+
let total = 0;
|
|
261
|
+
for (let i = 0; i < inOrientation.length; i++) {
|
|
262
|
+
const v = inOrientation[i];
|
|
263
|
+
const next = inOrientation[i + 1];
|
|
264
|
+
// Next viewport has SMALLER share (it's wider). Bucket =
|
|
265
|
+
// current.share − next.share, except for the last (widest)
|
|
266
|
+
// which is just current.share.
|
|
267
|
+
const bucketShare = next ? v.share - next.share : v.share;
|
|
268
|
+
const key = `${orientation}:${v.width}x${v.height}`;
|
|
269
|
+
if (passingKeys.has(key))
|
|
270
|
+
total += bucketShare;
|
|
271
|
+
}
|
|
272
|
+
return Math.round(total);
|
|
273
|
+
};
|
|
274
|
+
const portrait = score('portrait');
|
|
275
|
+
const landscape = score('landscape');
|
|
276
|
+
const haveP = portrait >= 0;
|
|
277
|
+
const haveL = landscape >= 0;
|
|
278
|
+
let overall;
|
|
279
|
+
if (haveP && haveL)
|
|
280
|
+
overall = Math.min(portrait, landscape);
|
|
281
|
+
else if (haveP)
|
|
282
|
+
overall = portrait;
|
|
283
|
+
else
|
|
284
|
+
overall = Math.max(0, landscape);
|
|
285
|
+
return {
|
|
286
|
+
portrait: haveP ? portrait : 0,
|
|
287
|
+
landscape: haveL ? landscape : 0,
|
|
288
|
+
overall,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/** Build the canonical key used by computeQualityIndex's passingKeys set. */
|
|
292
|
+
export function viewportKey(v) {
|
|
293
|
+
return `${v.orientation}:${v.width}x${v.height}`;
|
|
294
|
+
}
|
|
132
295
|
/**
|
|
133
296
|
* Start the reporter. Idempotent — calling twice returns the existing
|
|
134
297
|
* handle. Designed for one-line use: `initQualityReporter()` from your
|
|
@@ -146,7 +309,8 @@ export function initQualityReporter() {
|
|
|
146
309
|
const w = typeof window !== 'undefined' ? window : null;
|
|
147
310
|
if (!w)
|
|
148
311
|
return { stop: () => undefined, reportNow: () => undefined };
|
|
149
|
-
const existing = w
|
|
312
|
+
const existing = w
|
|
313
|
+
.__FAS_QUALITY_REPORTER__;
|
|
150
314
|
if (existing)
|
|
151
315
|
return existing;
|
|
152
316
|
if (!shouldReport()) {
|
|
@@ -189,7 +353,8 @@ export function initQualityReporter() {
|
|
|
189
353
|
stop: () => {
|
|
190
354
|
w.removeEventListener('resize', onResize);
|
|
191
355
|
w.removeEventListener('message', onMessage);
|
|
192
|
-
delete w
|
|
356
|
+
delete w
|
|
357
|
+
.__FAS_QUALITY_REPORTER__;
|
|
193
358
|
},
|
|
194
359
|
reportNow: post,
|
|
195
360
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0CH,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACjC,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;;;GAOG;AACH,SAAS,YAAY;IACnB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAK,MAAyD,CAAC,qBAAqB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { computeQualityIndex, initQualityReporter, REFERENCE_VIEWPORTS, snapshot, viewportKey, } from './index.js';
|
|
4
4
|
describe('snapshot', () => {
|
|
5
5
|
it('returns the schema-1 shape with required keys', () => {
|
|
6
6
|
const s = snapshot();
|
|
@@ -74,7 +74,8 @@ describe('initQualityReporter', () => {
|
|
|
74
74
|
delete window.__FAS_QUALITY_DISABLE;
|
|
75
75
|
});
|
|
76
76
|
afterEach(() => {
|
|
77
|
-
const h = window
|
|
77
|
+
const h = window
|
|
78
|
+
.__FAS_QUALITY_REPORTER__;
|
|
78
79
|
if (h?.stop)
|
|
79
80
|
h.stop();
|
|
80
81
|
});
|
|
@@ -113,4 +114,155 @@ describe('initQualityReporter', () => {
|
|
|
113
114
|
Object.defineProperty(window, 'parent', { value: window, configurable: true });
|
|
114
115
|
});
|
|
115
116
|
});
|
|
117
|
+
describe('REFERENCE_VIEWPORTS', () => {
|
|
118
|
+
it('has 6 portrait + 7 viewports total in landscape orientation columns', () => {
|
|
119
|
+
const portrait = REFERENCE_VIEWPORTS.filter((v) => v.orientation === 'portrait');
|
|
120
|
+
const landscape = REFERENCE_VIEWPORTS.filter((v) => v.orientation === 'landscape');
|
|
121
|
+
expect(portrait.length).toBe(7);
|
|
122
|
+
expect(landscape.length).toBe(6);
|
|
123
|
+
});
|
|
124
|
+
it('shares are strictly decreasing as widths increase (per orientation)', () => {
|
|
125
|
+
for (const orientation of ['portrait', 'landscape']) {
|
|
126
|
+
const inOrient = REFERENCE_VIEWPORTS.filter((v) => v.orientation === orientation);
|
|
127
|
+
const sorted = inOrient.slice().sort((a, b) => a.width - b.width);
|
|
128
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
129
|
+
expect(sorted[i].share, `share at width ${sorted[i].width} (${sorted[i].share}) must be < width ${sorted[i - 1].width} (${sorted[i - 1].share})`).toBeLessThanOrEqual(sorted[i - 1].share);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
it('all entries have width > 0, height > 0, share between 0 and 100', () => {
|
|
134
|
+
for (const v of REFERENCE_VIEWPORTS) {
|
|
135
|
+
expect(v.width).toBeGreaterThan(0);
|
|
136
|
+
expect(v.height).toBeGreaterThan(0);
|
|
137
|
+
expect(v.share).toBeGreaterThanOrEqual(0);
|
|
138
|
+
expect(v.share).toBeLessThanOrEqual(100);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('viewportKey', () => {
|
|
143
|
+
it('produces a stable canonical string per viewport', () => {
|
|
144
|
+
expect(viewportKey({ width: 393, height: 852, orientation: 'portrait' })).toBe('portrait:393x852');
|
|
145
|
+
expect(viewportKey({ width: 568, height: 320, orientation: 'landscape' })).toBe('landscape:568x320');
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('computeQualityIndex', () => {
|
|
149
|
+
/** All-pass against every viewport in the reference matrix. */
|
|
150
|
+
function allPassKeys() {
|
|
151
|
+
return new Set(REFERENCE_VIEWPORTS.map(viewportKey));
|
|
152
|
+
}
|
|
153
|
+
it('returns 99/99/99 when every viewport passes', () => {
|
|
154
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, allPassKeys());
|
|
155
|
+
// Sum of all bucket shares = the widest viewport's share + all bucket
|
|
156
|
+
// diffs back to the narrowest = the narrowest's share, which is 99.
|
|
157
|
+
expect(r.portrait).toBe(99);
|
|
158
|
+
expect(r.landscape).toBe(99);
|
|
159
|
+
expect(r.overall).toBe(99);
|
|
160
|
+
});
|
|
161
|
+
it('returns 0/0/0 when no viewport passes', () => {
|
|
162
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, new Set());
|
|
163
|
+
expect(r.portrait).toBe(0);
|
|
164
|
+
expect(r.landscape).toBe(0);
|
|
165
|
+
expect(r.overall).toBe(0);
|
|
166
|
+
});
|
|
167
|
+
it('catches a gap in the middle: pass-fail-fail-pass-pass-pass', () => {
|
|
168
|
+
// The exact bug the dashboard surfaced on tetris landscape:
|
|
169
|
+
// 568 passes, 667 + 736 fail, 800/1024/1366 pass.
|
|
170
|
+
// Naive "max passing share" returns 99. The correct bucket-summed
|
|
171
|
+
// share is (99-96) + (60-35) + (35-20) + 20 = 3 + 25 + 15 + 20 = 63.
|
|
172
|
+
const passKeys = new Set([
|
|
173
|
+
viewportKey({ width: 568, height: 320, orientation: 'landscape' }),
|
|
174
|
+
viewportKey({ width: 800, height: 600, orientation: 'landscape' }),
|
|
175
|
+
viewportKey({ width: 1024, height: 768, orientation: 'landscape' }),
|
|
176
|
+
viewportKey({ width: 1366, height: 1024, orientation: 'landscape' }),
|
|
177
|
+
]);
|
|
178
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, passKeys);
|
|
179
|
+
expect(r.landscape).toBe(63);
|
|
180
|
+
});
|
|
181
|
+
it('overall = min of orientation scores for any-orientation apps', () => {
|
|
182
|
+
// Portrait all pass (99), landscape only iPad+ pass (35).
|
|
183
|
+
// Overall should be min(99, 35) = 35.
|
|
184
|
+
const passKeys = new Set([
|
|
185
|
+
...REFERENCE_VIEWPORTS.filter((v) => v.orientation === 'portrait').map(viewportKey),
|
|
186
|
+
viewportKey({ width: 1024, height: 768, orientation: 'landscape' }),
|
|
187
|
+
viewportKey({ width: 1366, height: 1024, orientation: 'landscape' }),
|
|
188
|
+
]);
|
|
189
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, passKeys);
|
|
190
|
+
expect(r.portrait).toBe(99);
|
|
191
|
+
expect(r.landscape).toBe(35); // 35-20 + 20 = 35
|
|
192
|
+
expect(r.overall).toBe(35);
|
|
193
|
+
});
|
|
194
|
+
it('handles single-orientation matrices (portrait-only manifest)', () => {
|
|
195
|
+
const portraitOnly = REFERENCE_VIEWPORTS.filter((v) => v.orientation === 'portrait');
|
|
196
|
+
const r = computeQualityIndex(portraitOnly, new Set(portraitOnly.map(viewportKey)));
|
|
197
|
+
expect(r.portrait).toBe(99);
|
|
198
|
+
expect(r.landscape).toBe(0);
|
|
199
|
+
expect(r.overall).toBe(99); // single-orientation app — overall = portrait
|
|
200
|
+
});
|
|
201
|
+
it('only the widest viewport passes → score = widest viewport share', () => {
|
|
202
|
+
// If only iPad Pro portrait (1024×1366, share=20) passes, score = 20.
|
|
203
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, new Set([viewportKey({ width: 1024, height: 1366, orientation: 'portrait' })]));
|
|
204
|
+
expect(r.portrait).toBe(20); // share at the widest = its full share
|
|
205
|
+
});
|
|
206
|
+
it('only the narrowest viewport passes → score = bucket between narrowest and second-narrowest', () => {
|
|
207
|
+
// 320 passes (share=99), 360 onwards fail.
|
|
208
|
+
// Bucket for 320 = 99 - 96 = 3. So score = 3.
|
|
209
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, new Set([viewportKey({ width: 320, height: 568, orientation: 'portrait' })]));
|
|
210
|
+
expect(r.portrait).toBe(3);
|
|
211
|
+
});
|
|
212
|
+
it('passing keys for non-matrix viewports are ignored', () => {
|
|
213
|
+
// Bogus key like "portrait:999x999" not in REFERENCE_VIEWPORTS.
|
|
214
|
+
const r = computeQualityIndex(REFERENCE_VIEWPORTS, new Set(['portrait:999x999']));
|
|
215
|
+
expect(r.portrait).toBe(0);
|
|
216
|
+
expect(r.overall).toBe(0);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
describe('snapshot edge cases', () => {
|
|
220
|
+
it('caps clipping hits to a reasonable count', () => {
|
|
221
|
+
// Manufacture 30 overflow-hidden divs that each clip — reporter
|
|
222
|
+
// should cap at MAX_CLIPPING_HITS (20) so a deeply-broken page
|
|
223
|
+
// doesn't post a giant message back to the parent.
|
|
224
|
+
document.body.innerHTML = '';
|
|
225
|
+
for (let i = 0; i < 30; i++) {
|
|
226
|
+
document.body.innerHTML += `<div data-c="${i}"></div>`;
|
|
227
|
+
}
|
|
228
|
+
const origGet = window.getComputedStyle;
|
|
229
|
+
window.getComputedStyle = ((el) => el instanceof HTMLDivElement && el.dataset.c !== undefined
|
|
230
|
+
? { overflowX: 'hidden', overflowY: 'visible' }
|
|
231
|
+
: origGet(el));
|
|
232
|
+
document.querySelectorAll('[data-c]').forEach((el) => {
|
|
233
|
+
Object.defineProperty(el, 'scrollWidth', { get: () => 100, configurable: true });
|
|
234
|
+
Object.defineProperty(el, 'clientWidth', { get: () => 50, configurable: true });
|
|
235
|
+
Object.defineProperty(el, 'scrollHeight', { get: () => 50, configurable: true });
|
|
236
|
+
Object.defineProperty(el, 'clientHeight', { get: () => 50, configurable: true });
|
|
237
|
+
});
|
|
238
|
+
const s = snapshot();
|
|
239
|
+
expect(s.clipping.length).toBeLessThanOrEqual(20);
|
|
240
|
+
window.getComputedStyle = origGet;
|
|
241
|
+
});
|
|
242
|
+
it('selector falls back to plain tag name when no id or class', () => {
|
|
243
|
+
document.body.innerHTML = '<div></div>';
|
|
244
|
+
const div = document.querySelector('div');
|
|
245
|
+
const origGet = window.getComputedStyle;
|
|
246
|
+
window.getComputedStyle = ((el) => el === div
|
|
247
|
+
? { overflowX: 'hidden', overflowY: 'visible' }
|
|
248
|
+
: origGet(el));
|
|
249
|
+
Object.defineProperty(div, 'scrollWidth', { get: () => 100 });
|
|
250
|
+
Object.defineProperty(div, 'clientWidth', { get: () => 50 });
|
|
251
|
+
Object.defineProperty(div, 'scrollHeight', { get: () => 50 });
|
|
252
|
+
Object.defineProperty(div, 'clientHeight', { get: () => 50 });
|
|
253
|
+
const s = snapshot();
|
|
254
|
+
// No id, no class → selector is just the tag name (no trailing punctuation).
|
|
255
|
+
expect(s.clipping[0]?.selector).toBe('div');
|
|
256
|
+
window.getComputedStyle = origGet;
|
|
257
|
+
});
|
|
258
|
+
it('schema field is exactly 1 (locks the wire format)', () => {
|
|
259
|
+
// If we ever bump the schema, every dashboard listening on schema 1
|
|
260
|
+
// breaks until updated. Lock it down so tests catch a silent change.
|
|
261
|
+
expect(snapshot().schema).toBe(1);
|
|
262
|
+
expect(snapshot().type).toBe('fas:quality');
|
|
263
|
+
});
|
|
264
|
+
it('reporterVersion is a valid semver-ish string', () => {
|
|
265
|
+
expect(snapshot().reporterVersion).toMatch(/^\d+\.\d+\.\d+$/);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
116
268
|
//# sourceMappingURL=index.test.js.map
|
package/dist/index.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@freeappstore/quality",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Quality reporter — apps post viewport metrics to a parent dashboard via postMessage so /quality can audit fit / scroll / clipping at every reference viewport without driving a headless browser per app.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"homepage": "https://github.com/freeappstore-online/
|
|
15
|
+
"homepage": "https://github.com/freeappstore-online/platform#readme",
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/freeappstore-online/
|
|
18
|
+
"url": "git+https://github.com/freeappstore-online/platform.git",
|
|
19
19
|
"directory": "packages/quality"
|
|
20
20
|
},
|
|
21
21
|
"bugs": {
|
|
22
|
-
"url": "https://github.com/freeappstore-online/
|
|
22
|
+
"url": "https://github.com/freeappstore-online/platform/issues"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
25
25
|
"freeappstore",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"jsdom": "^25.0.0",
|
|
40
40
|
"typescript": "^5.7.0",
|
|
41
|
-
"vitest": "^2.
|
|
41
|
+
"vitest": "^3.2.4"
|
|
42
42
|
},
|
|
43
43
|
"sideEffects": false,
|
|
44
44
|
"scripts": {
|