File indexing completed on 2024-04-28 04:34:24

0001 /*
0002    This file is part of KDevelop
0003    Copyright 2009 Niko Sams <niko.sams@gmail.com>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License version 2 as published by the Free Software Foundation.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "parsertest.h"
0021 
0022 #include <QDebug>
0023 #include <QTest>
0024 
0025 #include "../parsesession.h"
0026 #include "cssdebugvisitor.h"
0027 #include "../editorintegrator.h"
0028 #include "../htmlparser.h"
0029 
0030 
0031 QTEST_MAIN(Css::TestParser)
0032 
0033 namespace Css
0034 {
0035 
0036 void TestParser::parser_data()
0037 {
0038     QTest::addColumn<QString>("contents");
0039 
0040     QTest::newRow("one declaration without semicolon")     << "body{color:red}";
0041     QTest::newRow("one declaration with semicolon") << "body{color:red;}";
0042     QTest::newRow("selector element") << "body{}";
0043     QTest::newRow("selector class") << ".foo{}";
0044     QTest::newRow("selector element.class") << "body.foo{}";
0045     QTest::newRow("selector star") << "*{}";
0046     QTest::newRow("selector star.class") << "*.foo{}";
0047     QTest::newRow("selector element attribute1") << "body[foo]{}";
0048     QTest::newRow("selector element attribute2") << "body[foo~=bar]{}";
0049     QTest::newRow("selector element attribute3") << "body[foo|=bar]{}";
0050     QTest::newRow("selector element pseudoclass") << "body:hover{}";
0051     QTest::newRow("selector element pseudoclass function") << "body:lang(no){}";
0052     QTest::newRow("selector element pseudoclass nth-child1") << "body:nth-child(even){}";
0053     QTest::newRow("selector element pseudoclass nth-child2") << "body:nth-child(4){}";
0054     QTest::newRow("selector element pseudoclass nth-child3") << "body:nth-child(5n+2){}";
0055     QTest::newRow("selector element pseudoclass selection") << "body::selection{}";
0056     QTest::newRow("declaration with px term") << "body{width:100px;}";
0057     QTest::newRow("declaration with em term") << "body{width:5em;}";
0058     QTest::newRow("declaration with none term") << "body{border:none;}";
0059     QTest::newRow("declaration with negative px term") << "body{width:-100px;}";
0060     QTest::newRow("declaration with positive px term") << "body{width:+100px;}";
0061     QTest::newRow("declaration with url term1") << "body{background-image:url(http://example.com/foo.png);}";
0062     QTest::newRow("declaration with url term2") << "body{background-image:url(/foo.png);}";
0063     QTest::newRow("declaration hex color term1") << "body{color:#ff0000;}";
0064     QTest::newRow("declaration hex color term2") << "body{color:#f00;}";
0065     QTest::newRow("declaration with multipe px terms") << "body{border-width:1px 2px 3px 4px;}";
0066     QTest::newRow("charset") << "@charset \"utf-8\"; body{}";
0067     QTest::newRow("import url") << "@import url(\"foo.css\"); body{}";
0068     QTest::newRow("import string") << "@import \"foo.css\"; body{}";
0069     QTest::newRow("two rules") << "h1{}h2{}";
0070     QTest::newRow("two rules whitespace") << "h1{} h2{}";
0071     QTest::newRow("missing value") << "body{width:;}"; //todo check for reported error
0072     QTest::newRow("missing value brace") << "body{width:1px;"; //todo check for reported error
0073     QTest::newRow("two selectors with spaces") << " a , b {}";
0074     QTest::newRow("selector with comma") << " a,{}"; //todo check for reported error
0075     QTest::newRow("selector without declarations") << "a"; //todo check for reported error
0076     QTest::newRow("selector without declarations2") << " a , "; //todo check for reported error
0077     QTest::newRow("selector without declarations3") << " a b "; //todo check for reported error
0078     QTest::newRow("space in declaration") << "body{ color:red;}";
0079     QTest::newRow("space in declaration") << "body{ color:red}";
0080     QTest::newRow("id selector") << "#foo{}";
0081     QTest::newRow("id element selector") << "body#foo{}";
0082     QTest::newRow("id element selector2") << "#foo a{}";
0083     QTest::newRow("selector with space") << "a a{}";
0084     QTest::newRow("empty declaration with space") << "a{ }";
0085     QTest::newRow("first property no value") << "a{color:;width:0;}";
0086     QTest::newRow("first property no value2") << "a{color: ; width:0;}";
0087     QTest::newRow("first property no value no semicolon") << "a{color:width :0;}";
0088     QTest::newRow("first property no value no semicolon2") << "a{color:width:0;}";
0089     QTest::newRow("first property no value no semicolon3") << "a{color: width:0;}";
0090     QTest::newRow("first property no value no semicolon4") << "a { color : width : 0 ; }";
0091     QTest::newRow("rgb value") << "a { color: rgb(1,2,3); }";
0092     QTest::newRow("rgb value2") << "a { color: rgb(1%,2%,3%); }";
0093     QTest::newRow("rgb value3") << "a { color: rgb(255,0,0); }";
0094     QTest::newRow("rgba value") << "a { color: rgba(255,0,0,127); }";
0095     QTest::newRow("missing closing brace") << "body{font-w";
0096     QTest::newRow("invalid character in class name") << ".$cssClass .submitWrapper {\n    float: right;\n    margin-top: -47px;\n}";
0097     QTest::newRow("custom function in value") << " p { filter: alpha(opacity=0); }";
0098 }
0099 
0100 void TestParser::parser()
0101 {
0102     QFETCH(QString, contents);
0103 
0104     ParseSession session;
0105     session.setContents(contents);
0106     StartAst* ast = nullptr;
0107     QVERIFY(session.parse(&ast));
0108     DebugVisitor debugVisitor(session.tokenStream(), session.contents());
0109     debugVisitor.visitStart(ast);
0110 }
0111 
0112 void TestParser::multiline()
0113 {
0114     ParseSession session;
0115     session.setContents("body{color:red}\nbody{color:blue}");
0116     //                   012345678901234  01234567890123456
0117     //                   0         1      0         1
0118     StartAst* ast = nullptr;
0119     QVERIFY(session.parse(&ast));
0120     DebugVisitor debugVisitor(session.tokenStream(), session.contents());
0121     RuleAst* el = ast->rules->rulesSequence->at(1)->element;
0122     debugVisitor.visitNode(el);
0123 
0124     EditorIntegrator editor;
0125     editor.setParseSession(&session);
0126     qDebug() << editor.findPosition(el->startToken, EditorIntegrator::FrontEdge);
0127     qDebug() << editor.findPosition(el->endToken, EditorIntegrator::BackEdge);
0128     QCOMPARE(editor.findPosition(el->endToken, EditorIntegrator::BackEdge),
0129                 KDevelop::CursorInRevision(1, 16));
0130 }
0131 
0132 void TestParser::htmlStyleElement()
0133 {
0134     HtmlParser p;
0135                  //0         1          2          3         4
0136                  //012345678901234567 890123456 78901234567890123456789
0137     p.setContents("<html><style type=\"text/css\">a{color:red}</style></html>");
0138     QList<HtmlParser::Part> res = p.parse();
0139     QCOMPARE(res.count(), 1);
0140     QCOMPARE(res[0].contents, QString("a{color:red}"));
0141     QCOMPARE(res[0].range, KTextEditor::Range(0, 29, 0, 41));
0142 }
0143 
0144 void TestParser::htmlInlineStyle()
0145 {
0146     HtmlParser p;
0147                  //0         1          2          3         4
0148                  //012345678901234 5678901234 5678901234567890123456789
0149     p.setContents("<html><p style=\"color:red\"></p></html>");
0150     QList<HtmlParser::Part> res = p.parse();
0151     QCOMPARE(res.count(), 1);
0152     QCOMPARE(res[0].contents, QString("color:red"));
0153     QCOMPARE(res[0].range, KTextEditor::Range(0, 16, 0, 25));
0154     QCOMPARE(res[0].tag, QString("p"));
0155 }
0156 
0157 void TestParser::htmlInlineStyle2()
0158 {
0159     HtmlParser p;
0160                  //0         1           2          3          4
0161                  //0123456789012345 6789 01234567 8901234567 890123456789
0162     p.setContents("<html>  <div id=\"foo\" style=\"color:red\"></html>");
0163     QList<HtmlParser::Part> res = p.parse();
0164     QCOMPARE(res.count(), 1);
0165     QCOMPARE(res[0].contents, QString("color:red"));
0166     QCOMPARE(res[0].range, KTextEditor::Range(0, 29, 0, 38));
0167 }
0168 
0169 void TestParser::htmlInlineStyle3()
0170 {
0171     HtmlParser p;
0172                  //0                         1                   2      3
0173                  //0         1           2   0          1        0      0
0174                  //0123456789012345 6789 01 2012345 67890123456 7012 3 40123456
0175     p.setContents("<html>  <div id=\"foo\" \nstyle=\"color:red;\nabc\"\n></html>");
0176     QList<HtmlParser::Part> res = p.parse();
0177     QCOMPARE(res.count(), 1);
0178     QCOMPARE(res[0].contents, QString("color:red;\nabc"));
0179     QCOMPARE(res[0].range, KTextEditor::Range(1, 7, 2, 3));
0180 }
0181 
0182 }
0183