parsing tests

commit_hash:72c5665e8ea78584437a239df3ae94bdb87e2c09
This commit is contained in:
4eb0da
2026-05-05 11:01:11 +03:00
parent 3519ac3194
commit 6d3da8b773
7 changed files with 101 additions and 0 deletions
+1
View File
@@ -26845,6 +26845,7 @@
"client/web/divkit/tests/hermione/screens/regression/Visible_in_div-base/Click_on_visible/chromeMobile/visible.png":"divkit/public/client/web/divkit/tests/hermione/screens/regression/Visible_in_div-base/Click_on_visible/chromeMobile/visible.png",
"client/web/divkit/tests/hermione/screens/regression/Visible_in_div-base/Click_on_visible/firefoxMobile/visible.png":"divkit/public/client/web/divkit/tests/hermione/screens/regression/Visible_in_div-base/Click_on_visible/firefoxMobile/visible.png",
"client/web/divkit/tests/hermione/static/index.html":"divkit/public/client/web/divkit/tests/hermione/static/index.html",
"client/web/divkit/tests/parsing/parsing.test.ts":"divkit/public/client/web/divkit/tests/parsing/parsing.test.ts",
"client/web/divkit/tests/templates/__snapshots__/array.test.ts.snap":"divkit/public/client/web/divkit/tests/templates/__snapshots__/array.test.ts.snap",
"client/web/divkit/tests/templates/__snapshots__/array_of_nested_items.test.ts.snap":"divkit/public/client/web/divkit/tests/templates/__snapshots__/array_of_nested_items.test.ts.snap",
"client/web/divkit/tests/templates/__snapshots__/array_with_transform.test.ts.snap":"divkit/public/client/web/divkit/tests/templates/__snapshots__/array_with_transform.test.ts.snap",
@@ -0,0 +1,80 @@
/* eslint-disable max-depth */
import * as path from 'node:path';
import * as fs from 'node:fs';
import {
describe,
expect,
test
} from 'vitest';
import { applyTemplate } from '../../src/utils/applyTemplate';
import type { TemplateContext } from '../../typings/common';
const dir = path.resolve(__filename, '../../../../../../test_data/parsing_test_data/templates');
function applyTemplates(json: any, templates: Record<string, unknown>, context: TemplateContext) {
if (!(json.type && json.type in templates)) {
return json;
}
const result = applyTemplate(json, context, templates || {}, error => {
throw error;
});
const walk = (obj: any, context: TemplateContext) => {
if (obj && typeof obj === 'object') {
if (obj.type && obj.type in templates) {
const res = applyTemplate(obj, context, templates, error => {
throw error;
});
return walk(res.json, res.templateContext);
}
const copy: any = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (key === 'items' || Array.isArray(obj)) {
copy[key] = walk(obj[key], context);
} else {
copy[key] = obj[key];
}
}
return copy;
}
return obj;
};
return walk(result.json, result.templateContext);
}
function runCase(name: string, itemPath: string): void {
const json = JSON.parse(fs.readFileSync(itemPath, 'utf8'));
if (!json.platforms || json.platforms.includes('web')) {
test(name.replace('.json', ''), () => {
const cardJson = json.card.states[0].div;
const result = applyTemplates(cardJson, json.templates || {}, {});
expect(result).toMatchObject(json.expected.card.states[0].div);
});
}
}
function proc(dir: string): void {
const items = fs.readdirSync(dir);
for (const item of items) {
const itemPath = path.join(dir, item);
if (fs.statSync(itemPath).isDirectory()) {
describe(item, () => {
proc(itemPath);
});
} else {
runCase(item, itemPath);
}
}
}
describe('parsing', () => {
proc(dir);
});
@@ -1,5 +1,9 @@
{
"description": "A template definition declares both a literal value and a reference definition for the same field. Verifies the literal wins — the reference substitution is skipped when the field is already populated — even when the usage supplies a reference value.",
"platforms": [
"android",
"ios"
],
"templates": {
"conflicted": {
"type": "text",
@@ -1,5 +1,9 @@
{
"description": "A reference declared on the leaf template resolves against a reference value declared at two levels: a default on the usage site inside an intermediate template's body, and a card-level override on the outer instance. Verifies the card-level value cascades down through template-body content and overrides the intermediate body's default.",
"platforms": [
"android",
"ios"
],
"card": {
"log_id": "test",
"states": [
@@ -1,5 +1,9 @@
{
"description": "A two-hop reference chain via nested usage: a template usage inside another template's body declares its own reference definition that points to a card field, while the used template has its own reference definition for a different field (with a literal default). Verifies the two-hop chain does not propagate and the affected item is dropped with an error.",
"platforms": [
"android",
"ios"
],
"templates": {
"base_text": {
"type": "text",
@@ -1,5 +1,9 @@
{
"description": "A template usage inside another template's body declares its own reference definition that points to a field on the outer instance, and the used template has its own reference definition for the same slot. Verifies that a two-hop reference chain (instance field → usage reference → definition reference) does not propagate: only the single-hop sibling resolves, the chained item is dropped with an error.",
"platforms": [
"android",
"ios"
],
"templates": {
"header": {
"type": "text",
@@ -1,5 +1,9 @@
{
"description": "Not a template test — verifies that an invalid field value (div-text.font_size = -1) is replaced by the field's default and reported as an error.",
"platforms": [
"android",
"ios"
],
"card": {
"log_id": "test",
"states": [