Files
Veyra/apps/mobile/tests/native-text.test.ts
T

33 lines
1.8 KiB
TypeScript

import test from "node:test"
import assert from "node:assert/strict"
import {readdirSync,readFileSync} from "node:fs"
import {join} from "node:path"
import {fileURLToPath} from "node:url"
import ts from "typescript"
// Native containers cannot render literal text, including a same-line JSX space.
const textComponents=new Set(["Text","Body","Title"])
function rawText(source:string,file="fixture.tsx"):string[]{
const ast=ts.createSourceFile(file,source,ts.ScriptTarget.Latest,true,ts.ScriptKind.TSX),errors:string[]=[]
function visit(node:ts.Node){
if(ts.isJsxText(node)&&node.text&&(!/^\s*$/.test(node.text)||!/[\r\n]/.test(node.text))){
const parent=node.parent,name=ts.isJsxElement(parent)?parent.openingElement.tagName.getText(ast):"fragment"
if(!textComponents.has(name)){const {line}=ast.getLineAndCharacterOfPosition(node.pos);errors.push(`${file}:${line+1} ${name}: ${JSON.stringify(node.text)}`)}
}
ts.forEachChild(node,visit)
}
visit(ast);return errors
}
function files(dir:string):string[]{return readdirSync(dir,{withFileTypes:true}).flatMap(e=>e.isDirectory()?files(join(dir,e.name)):e.name.endsWith(".tsx")?[join(dir,e.name)]:[])}
test("native text check distinguishes literal spaces from formatting and Text content",()=>{
assert.equal(rawText('<View><Text>hello world</Text> <Text>next</Text></View>').length,1)
assert.equal(rawText('<View>bare text</View>').length,1)
assert.equal(rawText('<><Text>hello</Text> </>').length,1)
assert.deepEqual(rawText('<View>\n <Text>hello world</Text>\n <Body>body</Body>\n</View>'),[])
})
test("App screens and components contain no text outside text components",()=>{
const root=fileURLToPath(new URL("../",import.meta.url))
const errors=[...files(join(root,"app")),...files(join(root,"src"))].flatMap(file=>rawText(readFileSync(file,"utf8"),file))
assert.deepEqual(errors,[],errors.join("\n"))
})