Refine subscription panel layout and feedback
Build and Deploy Gateway / build-and-push (push) Successful in 19s
Build and Deploy Gateway / deploy (push) Successful in 7s

This commit is contained in:
2026-08-11 07:47:28 +03:00
parent 5cad3e9061
commit 9a8191dc91
7 changed files with 56 additions and 134 deletions
+1 -1
View File
@@ -133,7 +133,7 @@ test('server picker starts simple and reveals advanced controls on demand', () =
assert.match(picker, /\.slice\(0, SIMPLE_SERVER_LIMIT\)/);
assert.match(picker, /\{selected && <ServerRow/);
assert.match(styles, /\.client-profile-body \.client-server-row \{[\s\S]*?grid-template-columns: minmax\(0, 1fr\) 64px;/);
assert.match(styles, /\.client-profile-body \.client-server-row\.is-selected \{[\s\S]*?background: color-mix\(in oklch, var\(--client-accent\) 5%, transparent\);/);
assert.match(styles, /\.client-profile-body \.client-server-row\.is-selected \{[\s\S]*?background: color-mix\(in oklch, var\(--client-accent\) 2%, transparent\);/);
assert.match(styles, /\.client-profile-body \.client-server-check-label \{[\s\S]*?display: inline;/);
assert.doesNotMatch(styles, /\.client-profile-body \.client-server-check::after/);
});
+16 -16
View File
@@ -36,26 +36,26 @@ const expectedImports = [
const sha256 = (value) => crypto.createHash('sha256').update(value).digest('hex');
const acceptedLedger = {
counts: {
cascadeEdges: 792,
cascadeEdges: 790,
customProperties: 31,
declarations: 2977,
declarations: 2941,
important: 0,
keyframes: 51,
keyframes: 49,
media: 13,
rules: 910,
variableReferences: 338,
rules: 906,
variableReferences: 328,
},
hashes: {
cascadeEdges: 'f83d896540885ddaf09e55551a2f1ba5b587dcebfc285cc305efe80136154d93',
cascadeEdges: '1f4fd4cc495ac8d430f0d3891a7d63db34ee44313b4f865b58de7c587378b261',
customProperties: 'c7dd331e4bad898c450568999d8c9c6837e275a79c365c7680e143026fde4545',
declarations: '14728723e4a95d6031b60eb39c0864da0ccc061e24798091cd093b6354a5d906',
declarations: 'c17ab95f3bccd3fca26b2707f07e5298deda0f6343e80d77dbc5df8e97ef0ecb',
duplicateKeyframes: '4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945',
duplicateSelectors: 'c0ec5c96e48cd2ceed32aa5050383bcf29c3c0b8f1b440ed6883435e3e9b964d',
keyframes: '9e87e997d0b776462ac3e495c7ced584871a5d9512226e5008eb84b4d311530a',
ruleDeclarationSequences: 'eac60ada2de39eff87713f71f5ca533cd831ee7d400d27eaa09562c29dfbfadd',
selectors: 'e79f61996bcd2a806828406c0a626e87d60112f1b24264d60b8670f9b8f831af',
variableReferences: '5c56197ab72968fc007f333c0cc58f90b6ec90465d6273bc757b7c77503dd26e',
witnesses: '7066589e7b69a5b3c728ff70430a8d6d3c6c6d562cea91377244c0754e18b8da',
keyframes: 'bde9c628dc86cb8a4299d5397eb7a81c5fbc9481136a073130991d3182d0799d',
ruleDeclarationSequences: 'a0e34d9639e87e77a2a095503196f4472a95ac875e398908f184b64b5bf5feba',
selectors: '7051c489e7dac8bd04f3cdeb44bda8c069793cff4232ea730d40a19545ea0475',
variableReferences: '37d0cec8ffda35b4b3823322c0e21802ad0d3252258deade0e2124bdc6eb6ca0',
witnesses: '1b0e3d6fb35dde7acd7b3597f290c2e8b2f25ca569e74b047457121967affc6f',
},
};
@@ -110,7 +110,7 @@ test('tokens, shared primitives, and feature styles have one explicit owner', ()
test('accepted stylesheet has pinned declaration, selector, keyframe, variable, and cascade ledgers', () => {
const witnesses = readStyleWitnesses(root);
assert.equal(witnesses.length, 735);
assert.equal(witnesses.length, 734);
assert.equal(witnesses.filter((witness) => witness.unknown || witness.ancestorUnknown).length, 0);
const ledger = createStyleLedger(readStyleSource(root), { witnesses });
assert.deepEqual(ledger.counts, acceptedLedger.counts);
@@ -306,8 +306,8 @@ test('main owns one public stylesheet and the regrouped production CSS is determ
assert.equal((main.match(/import ['"][^'"]+\.css['"]/g) || []).length, 1);
const assets = fs.readdirSync(path.join(root, 'dist/assets')).filter((file) => file.endsWith('.css'));
assert.deepEqual(assets, ['index-pEpt1ReD.css']);
assert.deepEqual(assets, ['index-hHmAphe7.css']);
const built = fs.readFileSync(path.join(root, 'dist/assets', assets[0]));
assert.equal(built.byteLength, 111837);
assert.equal(sha256(built), 'f797af224ecae5e0435c7fb165cc158a237d11654c48a8cb287b32b2230e6b0c');
assert.equal(built.byteLength, 110356);
assert.equal(sha256(built), '67a5df63d5ee0624c0e58f7fc9751c279a0c009c37abc8ef77567892c93da931');
});
@@ -87,7 +87,8 @@ test('validation rejection parser preserves structured errors and normalizes non
test('feature keeps exact slots, truthy closes and subscription DOM order', () => {
assert.match(feature, /const host = new URL\(normalizedUrl\)\.hostname;[\s\S]*if \(!await onAdd\(label, normalizedUrl\)\) return;[\s\S]*resetAdd\(\)/);
assert.match(feature, /if \(!await onForget\(deleteProfile\.id, deleteStopsVpn \? 'stop-and-delete' : 'delete'\)\) return;[\s\S]*setDeleteId\(''\)/);
assert.match(feature, /client-profiles-operation[\s\S]*\{statusSlot\}[\s\S]*client-profile-list[\s\S]*feature\.adding[\s\S]*AddProfileForm[\s\S]*client-profile-add-trigger/);
assert.match(feature, /\{statusSlot\}[\s\S]*client-profile-list[\s\S]*feature\.adding[\s\S]*AddProfileForm[\s\S]*client-profile-add-trigger/);
assert.doesNotMatch(feature, /client-profiles-operation|activeOperation|operationText/);
assert.doesNotMatch(feature, /client-profiles-current|aria-label="Добавить подписку"/);
assert.match(feature, /const drawerOpen = feature\.open && feature\.profiles\.length > 0/);
assert.match(feature, /feature\.profiles\.length === 0 && <div className="client-form client-subscription-first-run"/);