Simple html/css test tool

feature/develop-atys
Nimetu 4 years ago
parent 3b91146d23
commit 52e0e71c4a

@ -37,3 +37,8 @@ ENDIF()
IF(WITH_NEL_TESTS)
ADD_SUBDIRECTORY(nel_unit_test)
ENDIF()
IF(WITH_HTMLCSS_TEST)
ADD_SUBDIRECTORY(htmlcss_test)
ENDIF()

@ -0,0 +1,15 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
CMAKE_POLICY(SET CMP0015 NEW)
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${CMAKE_LIBRARY_DIR})
ADD_DEFINITIONS(${LIBXML2_DEFINITIONS})
FILE(GLOB SRC htmlcss_test.cpp)
ADD_EXECUTABLE(htmlcss_test ${SRC})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${LUA_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} )
TARGET_LINK_LIBRARIES(htmlcss_test nelmisc nelgui ${LUA_LIBRARIES} ${LIBXML2_LIBRARIES})
NL_DEFAULT_PROPS(htmlcss_test "Ryzom, Tests: html/css parser tests")
NL_ADD_RUNTIME_FLAGS(htmlcss_test)
INSTALL(TARGETS htmlcss_test RUNTIME DESTINATION bin COMPONENT tools)
# TODO: test fixtures

@ -0,0 +1,183 @@
/*
* File: main.cpp
* Author: Karu <nimetu@gmail.com>
*
* Created on 2015-04-11
*/
typedef struct _xmlNode xmlNode;
#include <string>
#include <fstream>
#include "nel/misc/types_nl.h"
#include "nel/misc/file.h"
#include "nel/misc/path.h"
#include "nel/gui/html_parser.h"
#include "nel/gui/css_parser.h"
#include "nel/gui/html_element.h"
#include "nel/gui/css_style.h"
#include "nel/gui/libwww.h"
using namespace std;
using namespace NLMISC;
using namespace NLGUI;
sint indent { 0 };
// ***************************************************************************
void checkRuleset(CHtmlElement &elm, CCssStyle &style, TStyleVec testset, bool exists)
{
bool verbose = false;
std::string existsMessage = exists ? "exist" : "unset";
for (auto it : testset)
{
bool failed = (exists != style.hasStyle(it.first));
if (failed)
{
bool failed2 = true;
if (it.first == "font-size")
{
printf("[%s]: font-size: %d; expected '%s'\n", existsMessage.c_str(), style.Current.FontSize, it.second.c_str());
printf(" (%s)\n", elm.toString().c_str());
failed2 = false;
}
else if (it.first == "background-color")
{
printf("[%s]: background-color: '%s'; expected '%s'\n", existsMessage.c_str(), style.Current.BackgroundColor.toString().c_str(), it.second.c_str());
printf(" (%s)\n", elm.toString().c_str());
failed2 = false;
}
if (failed2)
{
printf("[%s] FAIL: '%s': '%s'\n", existsMessage.c_str(), it.first.c_str(), it.second.c_str());
printf(" (%s)\n", elm.toString().c_str());
for (auto it2 : style.Current.StyleRules)
printf("'%s': '%s'\n", it2.first.c_str(), it2.second.c_str());
}
}
else if (exists && !style.checkStyle(it.first, it.second))
{
printf("[%s] FAIL: expecting '%s': '%s', got '%s'\n", existsMessage.c_str(), it.first.c_str(), it.second.c_str(), style.getStyle(it.first).c_str());
printf(" (%s)\n", elm.toString().c_str());
}
else if (!failed)
{
if (verbose)
printf("[%s] PASS: '%s': '%s'\n", existsMessage.c_str(), it.first.c_str(), it.second.c_str());
}
}
}
// ***************************************************************************
void recursiveHtmlRender(CHtmlElement &elm, CCssStyle &style)
{
bool verbose = false;
if (elm.Type == CHtmlElement::TEXT_NODE)
{
std::string val = trim(elm.Value);
if (verbose)
if (!val.empty())
printf("[%d] '%s'\n", indent, val.c_str());
}
else if (elm.Type == CHtmlElement::ELEMENT_NODE)
{
style.pushStyle();
if (verbose)
printf("========= '%s'\n", elm.toString().c_str());
style.getStyleFor(elm);
style.applyStyle(elm.Style);
if (elm.hasAttribute("data-ruleset"))
{
TStyleVec testset = CCssParser::parseDecls(elm.getAttribute("data-ruleset"));
checkRuleset(elm, style, testset, true);
}
if (elm.hasAttribute("data-ruleunset"))
{
TStyleVec testset = CCssParser::parseDecls(elm.getAttribute("data-ruleunset"));
checkRuleset(elm, style, testset, false);
}
if (elm.hasAttribute("data-ruleset-before"))
{
TStyleVec testset = CCssParser::parseDecls(elm.getAttribute("data-ruleset-before"));
}
for (auto it = elm.Children.begin(); it != elm.Children.end(); ++it)
{
recursiveHtmlRender(*it, style);
}
style.popStyle();
}
}
// ***************************************************************************
void runTestOnFile(const std::string &filename)
{
CHtmlElement dom;
CHtmlParser htmlParser;
std::vector<CHtmlParser::StyleLink> links;
std::vector<std::string> styles;
//, elm, styles, links
ifstream f(filename);
if (!f.is_open())
{
printf("!! failed to open file '%s'\n", filename.c_str());
return;
}
printf(": %s\n", filename.c_str());
std::string htmlString;
std::string line;
while (getline(f, line))
htmlString += line;
htmlParser.getDOM(htmlString, dom, styles, links);
CCssStyle style;
for (std::string s : styles)
{
if (!s.empty())
style.parseStylesheet(s);
}
for (auto it = dom.Children.begin(); it != dom.Children.end(); ++it)
recursiveHtmlRender(*it, style);
}
// ***************************************************************************
int main(int argc, const char *argv[])
{
CApplicationContext *appContext = new CApplicationContext;
// htmlcss_test file.html
if (argc == 2)
{
runTestOnFile(argv[1]);
}
else
{
std::vector<std::string> result;
CPath::getPathContent("tests/", true /*recursive*/, false /*wantDir*/, true /*wantFile*/, result, NULL /*callback*/, true /*showEverything*/);
printf(":: got %ld files\n", result.size());
for (const auto &fname : result)
{
if (endsWith(fname, ".html") && fname != "tests/XX-template.html")
runTestOnFile(fname);
}
}
printf(">>> all done\n");
return EXIT_SUCCESS;
}

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<body>
<style>
:lang(en) { --text: '(en)'; }
:lang(de-DE) { --text: '(de-DE)'; }
a { test: " (" var(--lang) ")"}
div {
/* '--a' and '--b' are both 'initial' */
--should-not-exist: var(--a, var(--b, ( "p() " ) ), { "b" [ "r" ] });
/* 'before -var- after' */
--concate-test: 'before' var(--exists) 'after';
--exists: '-var-';
/* fallback should be at least one char */
--invalid-fallback: var(--exists,);
/* using fallback */
--fallback: var(--a, 'ok');
}
</style>
<div data-ruleset="--concate-test: 'before' '-var-' 'after'; --exists: '-var-'; --fallback: 'ok';"
data-ruleunset="--should-not-exists: 1; --invalid-fallback: 1;" />
<a lang="en" data-ruleset="--text: '(en)';">link</a>
<a lang="de" data-ruleunset="--text: 1;">link</a>
</body>
</html>

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<body>
<style>
p {
--mq-sm: initial;
}
.small {
--mq-sm: ;
}
p {
--padding-when-small: var(--mq-sm) 2rem;
--padding-when-large: 4rem;
padding: var(--padding-when-small, var(--padding-when-large));
}
</style>
<p data-ruleset="padding-left: 4rem;" comment="--mq-sm==initial, should use fallback value" />
<div>
<p class="small" data-ruleset="padding-left: 2rem;" comment="--mq-sm==;, should use defined value"/>
</div>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<body>
<style>
:root {
--main-color: #06c;
--accent-color: #006;
}
/* The rest of the CSS file */
#foo h1 {
color: var(--main-color);
}
</style>
<div id="foo">
<h1 data-ruleset="color: #06c;">Header</h1>
</div>
</body>
</html>

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<body>
<style>
:root {
--main-color: #06c;
--accent-color: #006;
--MAIN-COLOR: #f00;
}
/* The rest of the CSS file */
#foo h1 {
color: var(--main-color);
}
h2 {
color: var(--MAIN-COLOR);
}
</style>
<div id="foo">
<h1 data-ruleset="color: #06c;">Header1</h1>
<h2 data-ruleset="color: #f00;">Header2</h1>
</div>
</body>
</html>

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<style>
:root {
--foo: if(x > 5) this.width = 10;
}
/* The rest of the CSS file */
#foo h1 {
test: var(--foo)
}
</style>
<div id="foo">
<h1 data-ruleset="test: if(x > 5) this.width = 10;">Header</h1>
</div>
</body>
</html>

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<style>
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
</style>
<p data-ruleset="color: blue;">I inherited blue from the root element!</p>
<div data-ruleset="color: green;">I got green set directly on me!</div>
<div id='alert' data-ruleset="color: red;">
While I got red set directly on me!
<p data-ruleset="color: red;">Im red too, because of inheritance!</p>
</div>
</body>
</html>

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<body>
<style>
a:lang(en) {--lang: 'en';}
a:lang(de) {--lang: 'de';}
a { test: var(--lang); }
</style>
<a lang="en" data-ruleset="test: 'en';">link</a>
<a lang="de" data-ruleset="test: 'de';">link</a>
</body>
</html>

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<body>
<style>
:root {
--main-color: #c06;
--accent-background: var(--main-color);
}
div {
test: var(--accent-background);
}
</style>
<div data-ruleset="test: #c06;"/>
</body>
</html>

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<body>
<style>
div {
--one: calc(var(--two) + 20px);
--two: calc(var(--one) - 20px);
--ok: 'ok';
}
</style>
<div data-ruleset="--ok: 'ok';"
data-ruleunset="--one: 1; --two: 1;" />
</body>
</html>

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<body>
<style>
one { --foo: 10px; }
two { --bar: calc(var(--foo) + 10px); }
three { --foo: calc(var(--bar) + 10px); }
</style>
<one data-ruleset="--foo: 10px;">
<two data-ruleset="--bar: calc( 10px + 10px);">
<three data-ruleset="--foo: calc( calc( 10px + 10px) + 10px);"/>
</two>
</one>
</body>
</html>

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<body>
<style>
/* In the components style: */
.component .header {
color: var(--header-color, blue);
}
.component .text {
color: var(--text-color, black);
}
/* In the larger applications style: */
.component {
--text-color: #080;
/* header-color isnt set, and so remains blue, the fallback value */
}
</style>
<div class="component">
<h1 class="header" data-ruleset="color: blue;">header</h1>
<p class="text" data-ruleset="color: #080;">text</p>
</div>
</body>
</html>

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<style>
div {
--side: margin-top;
var(--side): 20px;
}
</style>
<div data-ruleset="--side: margin-top;" data-ruleunset="var(--side): 1;" />
</body>
</html>

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<body>
<style>
div {
--gap: 20;
margin-top: var(--gap)px;
}
</style>
<!-- should have whitespace, ie '20 px' -->
<div data-ruleset="margin-top: 20 px;" />
</body>
</html>

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<body>
<style>
:root { --not-a-color: 20px; }
p { background-color: red; }
p { background-color: var(--not-a-color); }
</style>
<!-- this should have 'red' because var() has invalid value for color -->
<!-- TODO: not really supported by NEL currently -->
<div data-ruleset="background-color: red;" />
</body>
</html>
Loading…
Cancel
Save