Angular: Provide convenient Gradle setup for contributors
[idea/contrib.git] / AngularJS / test-ex / org / angular2 / lang / html / parser / Angular2HtmlParsingTest.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package org.angular2.lang.html.parser;
3
4 import com.intellij.html.HtmlParsingTest;
5 import com.intellij.javascript.JSHtmlEmbeddedContentSupport;
6 import com.intellij.lang.LanguageASTFactory;
7 import com.intellij.lang.css.CSSLanguage;
8 import com.intellij.lang.css.CSSParserDefinition;
9 import com.intellij.lang.javascript.JavascriptParserDefinition;
10 import com.intellij.lang.javascript.dialects.ECMA6ParserDefinition;
11 import com.intellij.lang.javascript.dialects.JSLanguageLevel;
12 import com.intellij.lexer.EmbeddedTokenTypesProvider;
13 import com.intellij.lexer.HtmlEmbeddedContentSupport;
14 import com.intellij.openapi.progress.EmptyProgressIndicator;
15 import com.intellij.openapi.util.TextRange;
16 import com.intellij.pom.tree.events.TreeChangeEvent;
17 import com.intellij.psi.PsiFile;
18 import com.intellij.psi.css.CssElementDescriptorProvider;
19 import com.intellij.psi.css.CssEmbeddedTokenTypesProvider;
20 import com.intellij.psi.css.CssHtmlEmbeddedContentSupport;
21 import com.intellij.psi.css.impl.CssTreeElementFactory;
22 import com.intellij.psi.css.impl.util.scheme.CssElementDescriptorFactory2;
23 import com.intellij.psi.css.impl.util.scheme.CssElementDescriptorProviderImpl;
24 import com.intellij.psi.impl.BlockSupportImpl;
25 import com.intellij.psi.impl.DebugUtil;
26 import com.intellij.psi.impl.DiffLog;
27 import org.angular2.lang.expr.parser.Angular2ParserDefinition;
28 import org.angularjs.AngularTestUtil;
29 import org.jetbrains.annotations.NotNull;
30
31 import java.io.IOException;
32 import java.util.Collections;
33
34 public class Angular2HtmlParsingTest extends HtmlParsingTest {
35
36   public Angular2HtmlParsingTest() {
37     super("", "html",
38           new Angular2HtmlParserDefinition(),
39           new Angular2ParserDefinition(),
40           new JavascriptParserDefinition(),
41           new CSSParserDefinition());
42   }
43
44   @Override
45   protected void setUp() throws Exception {
46     super.setUp();
47     registerExtensions(EmbeddedTokenTypesProvider.EXTENSION_POINT_NAME, EmbeddedTokenTypesProvider.class,
48                        Collections.singletonList(new CssEmbeddedTokenTypesProvider()));
49     registerExtension(HtmlEmbeddedContentSupport.EP_NAME, new CssHtmlEmbeddedContentSupport());
50     registerExtension(HtmlEmbeddedContentSupport.EP_NAME, new JSHtmlEmbeddedContentSupport());
51
52     addExplicitExtension(LanguageASTFactory.INSTANCE, CSSLanguage.INSTANCE, new CssTreeElementFactory());
53     registerExtensionPoint(CssElementDescriptorProvider.EP_NAME, CssElementDescriptorProvider.class);
54     registerExtension(CssElementDescriptorProvider.EP_NAME, new CssElementDescriptorProviderImpl());
55     getApplication().registerService(CssElementDescriptorFactory2.class,
56                                      new CssElementDescriptorFactory2("css-parsing-tests.xml"));
57
58     // Update parser definition if version is changed
59     assert JSLanguageLevel.DEFAULT == JSLanguageLevel.ES6;
60     registerParserDefinition(new ECMA6ParserDefinition());
61   }
62
63   @Override
64   protected void registerEmbeddedContentProviders() {
65     super.registerEmbeddedContentProviders();
66   }
67
68   @Override
69   protected void checkResult(@NotNull String targetDataName, @NotNull PsiFile file) throws IOException {
70     super.checkResult(targetDataName, file);
71     ensureReparsingConsistent(file);
72   }
73
74   private static void ensureReparsingConsistent(@NotNull PsiFile file) {
75     DebugUtil.performPsiModification("ensureReparsingConsistent", () -> {
76       final String fileText = file.getText();
77       final DiffLog diffLog = new BlockSupportImpl().reparseRange(
78         file, file.getNode(), TextRange.allOf(fileText), fileText, new EmptyProgressIndicator(), fileText);
79       TreeChangeEvent event = diffLog.performActualPsiChange(file);
80       assertEmpty(event.getChangedElements());
81     });
82   }
83
84   @Override
85   protected String getTestDataPath() {
86     return AngularTestUtil.getBaseTestDataPath(Angular2HtmlParsingTest.class);
87   }
88
89   public void testNgParseElementsInsideNgTemplate() throws Exception {
90     doTestHtml("<ng-template><span></span></ng-template>");
91   }
92
93   public void testNgSupportVoidElements() throws Exception {
94     doTestHtml("<link rel=\"author license\" href=\"/about\">");
95   }
96
97   public void _testNgNotErrorOnVoidHtml5Elements() throws Exception {
98     doTestHtml("<map><area></map><div><br></div><colgroup><col></colgroup>" +
99                "<div><embed></div><div><hr></div><div><img></div><div><input></div>" +
100                "<object><param>/<object><audio><source></audio><audio><track></audio>" +
101                "<p><wbr></p>");
102   }
103
104   public void _testNgReportClosingTagForVoidElement() throws Exception {
105     doTestHtml("<input></input>");
106   }
107
108   public void _testNgReportSelfClosingHtmlElement() throws Exception {
109     doTestHtml("<p />");
110   }
111
112   public void testNgCloseVoidElementsOnTextNodes() throws Exception {
113     doTestHtml("<p>before<br>after</p>");
114   }
115
116   public void testNgSupportOptionalEndTags() throws Exception {
117     doTestHtml("<div><p>1<p>2</div>");
118   }
119
120   public void testNgSupportNestedElements() throws Exception {
121     doTestHtml("<ul><li><ul><li></li></ul></li></ul>");
122   }
123
124   public void testNgSupportSelfClosingVoidElements() throws Exception {
125     doTestHtml("<input />");
126   }
127
128   public void testNgParseExpansionForms1() throws Exception {
129     doTestHtml("<div>before{messages.length, plural, =0 {You have <b>no</b> messages} =1 {One {{message}}}}after</div>");
130   }
131
132   public void testNgParseExpansionForms2() throws Exception {
133     doTestHtml("<div><span>{a, plural, =0 {b}}</span></div>");
134   }
135
136   public void testNgParseExpansionForms3() throws Exception {
137     doTestHtml("{messages.length, plural, =0 { {p.gender, select, male {m}} }}");
138   }
139
140   public void testNgErrorOnUnterminatedExpansionForm() throws Exception {
141     doTestHtml("{messages.length, plural, =0 {one}");
142   }
143
144   public void testNgICUWithNumbers() throws Exception {
145     doTestHtml("{sex, select, male {m} female {f} 0 {other}}");
146   }
147
148   public void testNgErrorOnUnterminatedExpansionCase() throws Exception {
149     doTestHtml("{messages.length, plural, =0 {one");
150   }
151
152   public void testNgErrorOnInvalidHTMLInExpansionCase() throws Exception {
153     doTestHtml("{messages.length, plural, =0 {<div>}}");
154   }
155
156   public void testNgWhitespacesInExpansionCase() throws Exception {
157     doTestHtml("{ messages . length,  plural ,  =0   {  <div> } }");
158   }
159
160   public void testExpansionFormComplex() throws Exception {
161     doTestHtml("<div>Text{ form, open, =23 {{{{foo: 12} }} is {inner, open, =34{{{\"test\"}} cool } =12{<tag test='12'></tag>}}}}}} {}");
162   }
163
164   public void testNgReportUnexpectedClosingTag() throws Exception {
165     doTestHtml("<div></p></div>");
166   }
167
168   public void testNgReportSubsequentOpenTagWithoutCloseTag() throws Exception {
169     doTestHtml("<div</div>");
170   }
171
172   public void testNgParseBoundProperties() throws Exception {
173     doTestHtml("<div [someProp]='v'></div>" +
174                "<div [some-prop]='v'></div>" +
175                "<div [dot.name]='v'></div>" +
176                "<div [attr.someAttr]='v'></div>" +
177                "<div [class.some-class]='v'></div>" +
178                "<div [style.someStyle]='v'></div>" +
179                "<div data-[style.someStyle]='v'></div>" +
180                "<div bind-prop='v'></div>" +
181                "<div prop='{{v}}'></div>" +
182                "<div bind-animate-someAnimation='val'></div>" +
183                "<div [@someAnimation]='v'></div>" +
184                "<div @someAnimation='v'></div>");
185   }
186
187   public void testNgParseEvents() throws Exception {
188     doTestHtml("<div (window:event)='v'></div>" +
189                "<div (event)='v'></div>" +
190                "<div data-(event)='v'></div>" +
191                "<div (some-event)='v'></div>" +
192                "<div (someEvent)='v'></div>" +
193                "<div on-event='v'></div>");
194   }
195
196   public void testNgParseAnimationEvents() throws Exception {
197     doTestHtml("<a (@click)='doStuff()'></a>" +
198                "<b on-animate-click='doStuff()'></b>" +
199                "<a (@click.done)='doStuff()'></a>" +
200                "<b on-animate-click.start='doStuff()'></b>");
201   }
202
203   public void testNgParseReferences() throws Exception {
204     doTestHtml("<div #a></div>" +
205                "<div ref-a></div>" +
206                "<div a #a='dirA'></div>" +
207                "<div #a-b></div>" +
208                "<div #></div>" +
209                "<div ref- ></div>");
210   }
211
212   public void testNgParseVariables() throws Exception {
213     doTestHtml("<div let-a></div>" +
214                "<ng-template let-a='b'></ng-template>");
215   }
216
217   public void testNgParseInlineTemplates() throws Exception {
218     doTestHtml("<div *ngIf></div>" +
219                "<div *ngIf='condition'></div>" +
220                "<div *ngIf='#a=b'>Report error on vars with #</div>" +
221                "<div *ngIf='let a=b'></div>" +
222                "<div data-*ngIf='let a=b'></div>" +
223                "<div *ngIf='expr as local'></div>");
224   }
225
226   public void testNgReportErrorsInExpressions() throws Exception {
227     doTestHtml("<div [prop]='a b'></div>");
228   }
229
230   public void testNgBindingAttributeComplex() throws Exception {
231     doTestHtml("<div (lang)=\"{'current':i == (wordIndex | async)}\"></div>");
232   }
233
234   public void testNgCss() throws Exception {
235     doTestHtml("<div *ngFor=\"let something of items\" class=\"inDaClass foo\" style=\"color: #fff\"></div>");
236   }
237
238   public void testNgBindingElvis() throws Exception {
239     doTestHtml("<div lang=\"{{interpolation?.here}}\"></div>");
240   }
241
242   public void testNgEntity() throws Exception {
243     doTestHtml("<div>{{foo ? ' &mdash;' + bar : \"\"}}</div>");
244   }
245
246   public void testNgStringWithEntity() throws Exception {
247     doTestHtml("{{ &quot;fo&#123;o\" }}");
248   }
249
250   public void testNgStringWithEntity2() throws Exception {
251     doTestHtml("<div [input]='&apos;foo&quot;&dash;&apos;'");
252   }
253
254   public void testNgStringWithEntity3() throws Exception {
255     doTestHtml("<div [input]='&apos;foo&quot;&dash;&apos;\"second\"'");
256   }
257
258   public void testNgWeb20713() throws Exception {
259     doTestHtml("<h5>Last Updated: {{(viewModel.lastUpdated$ | async) | date:'mediumTime'}}</h5>");
260   }
261
262   public void testNgWeb24804() throws Exception {
263     doTestHtml("<div *myStructuralDirective style=\"z-index: 10;\"></div>");
264   }
265
266   public void testNgTextInterpolation() throws Exception {
267     doTestHtml("<div>my {{interpolated}} text</div>\n" +
268                "<div>my{{interpolated}}text</div>\n" +
269                "<div>my{{double}}{{interpolated}}text</div>\n" +
270                "<div>my{{double}}double{{interpolated}}text</div>");
271   }
272
273   public void testNgTextInterpolationWithLineBreaks() throws Exception {
274     doTestHtml("{{todo\n" +
275                "            | started : status\n" +
276                "            | search : term\n" +
277                "            }}");
278   }
279
280   public void testNgIgnoredInterpolation() throws Exception {
281     doTestHtml("this {{ is {{ <ignored/> interpolation }}");
282   }
283
284   public void testNgIgnoredInterpolationInTag() throws Exception {
285     doTestHtml("<div>this{{is{{<ignored/> interpolation}}</div>another{{ignored{{<interpolation/>");
286   }
287
288   public void testNgInterpolationEmpty() throws Exception {
289     doTestHtml("empty {{}} interpolation");
290   }
291
292
293   public void testNgScriptWithEventAndAngularAttr() throws Exception {
294     doTestHtml("<script src=\"//example.com\" onerror=\"console.log(1)\" (error)='console.log(1)'" +
295                "onload=\"console.log(1)\" (load)='console.log(1)'>\n" +
296                "  console.log(2)\n" +
297                "</script>\n" +
298                "<div></div>");
299   }
300
301   public void testNgStyleTag() throws Exception {
302     doTestHtml("<style>\n" +
303                "  div {\n" +
304                "  }\n" +
305                "</style>\n" +
306                "<div></div>");
307   }
308
309   public void testNgStyleAngularAttr() throws Exception {
310     doTestHtml("<style (load)='disabled=true'>\n" +
311                "  div {\n" +
312                "  }\n" +
313                "</style>\n" +
314                "<div></div>");
315   }
316
317   public void testNgStyleWithEventAndAngularAttr() throws Exception {
318     doTestHtml("<style (load)='disabled=true' onload=\"this.disabled=true\" (load)='disabled=true'>\n" +
319                "  div {\n" +
320                "  }\n" +
321                "</style>\n" +
322                "<div></div>");
323   }
324
325   public void testNgContentSelect() throws Exception {
326     doTestHtml("<div><ng-content select='foo,bar'></ng-content></div>");
327   }
328
329   public void testNgNonBindable() throws Exception {
330     doTestHtml("<div><span ngNonBindable>f{{bar}}a</span>f{{foo}}a</div>");
331   }
332
333   public void testNgNonBindable2() throws Exception {
334     doTestHtml("<div><span ngNonBindable ngNonBindable>s{{bar}}e</span>s{{foo}}e</div>");
335   }
336
337   public void testNgNonBindable3() throws Exception {
338     doTestHtml("<div><span ngNonBindable ngNonBindable>{{bar}}<b ngNonBindable>{{boo}}</b></span>{{foo}}</div>");
339   }
340
341   public void testNgNonBindable4() throws Exception {
342     doTestHtml("<p ngNonBindable>{{foo}}<p>{{bar}}");
343   }
344
345   public void testNgNonQuotedAttrs() throws Exception {
346     doTestHtml("<div (click)=doIt()></div>\n" +
347                "<div [id]=foo></div>\n" +
348                "<div #foo=bar></div>\n" +
349                "<ng-content select=[header-content]></ng-content>\n");
350   }
351
352   public void testEmptyLetAndRef() throws Exception {
353     doTestHtml("<ng-template let-/><div let-/><div #/><div ref-/>");
354   }
355
356 }