/** * Gets a DefDescriptor instance based on a name with additional checks for sources that supports * a default namespace * * @param name The simple String representation of the instance requested ("foo:bar" or * "java://foo.Bar") * @param clazz The Interface's Class for the DefDescriptor being requested. * @return An instance of a AuraDescriptor for the provided tag with updated ns for sources with * default namespace support */ protected <E extends Definition> DefDescriptor<E> getDefDescriptor(String name, Class<E> clazz) { DefDescriptor<E> defDesc = DefDescriptorImpl.getInstance(name, clazz); if (("apex".equals(defDesc.getPrefix()) || "markup" .equals(defDesc.getPrefix())) // only needed for apex && markup def descriptors && isDefaultNamespaceUsed(defDesc.getNamespace())) { // and default ns is used String qualifiedName = DefDescriptorImpl.buildQualifiedName( defDesc.getPrefix(), source.getDescriptor().getNamespace(), defDesc.getName()); defDesc = DefDescriptorImpl.getInstance(qualifiedName, clazz); } return defDesc; }
public ComponentDefRefHandler( RootTagHandler<P> parentHandler, XMLStreamReader xmlReader, Source<?> source) { super(parentHandler, xmlReader, source); builder.setDescriptor(DefDescriptorImpl.getInstance(getTagName(), ComponentDef.class)); builder.setLocation(getLocation()); body = new ArrayList<>(); }
/** * Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. This test case includes * these scenarios: * * <ul> * <li>A null source * <li>A null Descriptor * <li>Trying to create a Source for a Def type while no corresponding js file is present for * the component * </ul> */ public void testNullCases() throws Exception { DefDescriptor<TestSuiteDef> descriptor = DefDescriptorImpl.getInstance("js://test.testNoJSControllers", TestSuiteDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); boolean failed = false; // Test case 1: Try to create a Source for a component which does not // have any javascript associated with it // getSource() call is looking for testNoJSControllersTest.js in the // component folder try { parser.parse(descriptor, source); failed = true; } catch (Exception e) { // Expect a file not found Exception assertEquals( "Exception must be " + AuraRuntimeException.class.getSimpleName(), AuraRuntimeException.class, e.getClass()); e.getMessage().contains("testNoJSControllersTest.js"); } assertFalse("Parser should have thrown and exception", failed); // Test case 2: Null source try { parser.parse(descriptor, null); fail("should not load null source"); } catch (Exception e) { checkExceptionFull(e, NullPointerException.class, null); } // Test Case 3: Null component descriptor try { parser.parse(null, source); fail("should not load null component descriptor"); } catch (Exception e) { checkExceptionFull(e, NullPointerException.class, null); } }
@Override public DefDescriptor<ComponentDef> provide() { BaseComponent<?, ?> component = Aura.getContextService().getCurrentContext().getCurrentComponent(); String num = (String) component.getAttributes().getExpression("implNumber"); // Warning: test:test_Provider_providerImpl no longer exist return DefDescriptorImpl.getInstance( "test:test_Provider_providerImpl" + num, ComponentDef.class); }
/** confirm that we get an error if the override theme is specified but non existent */ public void testAppThemeDefDoesntExist() throws QuickFixException { addNsTheme(theme().var("color", "red")); DefDescriptor<ThemeDef> override = DefDescriptorImpl.getInstance("idont:exist", ThemeDef.class); try { setupOverride(override).getValue("color", null); fail("expected an exception"); } catch (Exception e) { checkExceptionContains(e, DefinitionNotFoundException.class, "No THEME"); } }
/** Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. */ public void testParse() throws Exception { DefDescriptor<TestSuiteDef> descriptor = DefDescriptorImpl.getInstance("js://test.testJSTestSuite", TestSuiteDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); // Step 1: Parse the source which refers to a simple component with a // reference to Javascript test suite Definition testSuite = parser.parse(descriptor, source); assertTrue(testSuite instanceof JavascriptTestSuiteDef); // Step 2: Gold file the Json output of the test suite object serializeAndGoldFile(testSuite, "_JSTestSuite"); }
/** * Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. The DefDescriptor is * referring to a Controller but the Javascript should have had only functions. In this scenario * there is a variable declaration which is not expected in a controller file. The JSparser will * flag an exception for this. * * @throws Exception */ public void testInvalidJSController() throws Exception { DefDescriptor<ControllerDef> descriptor = DefDescriptorImpl.getInstance("js://test.testInvalidJSController", ControllerDef.class); Source<ControllerDef> source = getJavascriptSourceLoader().getSource(descriptor); ControllerDef cd = (ControllerDef) parser.parse(descriptor, source); try { cd.validateDefinition(); fail("Javascript controller must only contain functions"); } catch (Exception e) { this.checkExceptionContains(e, InvalidDefinitionException.class, "Expected ':'"); } }
// TODO: W-689596 is a broad bug that would cover this case. // Uncommnet the test once validation is added in // JavascriptRendererDefHandler. public void _testInvalidJSRenderer() throws Exception { DefDescriptor<RendererDef> descriptor = DefDescriptorImpl.getInstance("js://test.testInvalidJSRenderer", RendererDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); try { // Parse and create the RedererDef object for the component parser.parse(descriptor, source); fail("Javascript renderer should have only two actions : render & rerender"); } catch (AuraRuntimeException expected) { // this test is disabled, update error msg when we enable the test checkExceptionStart(expected, AuraRuntimeException.class, null); } }
@Override protected ComponentDefRef createDefinition() { if (!body.isEmpty()) { setBody(body); } // hacky. if there is an interface, grab that descriptor too DefDescriptor<InterfaceDef> id = DefDescriptorImpl.getInstance( builder.getDescriptor().getQualifiedName(), InterfaceDef.class); if (id.exists()) { builder.setIntfDescriptor(id); } return builder.build(); }
@Override @SuppressWarnings("unchecked") public IncludeDefImpl getElement() throws XMLStreamException, QuickFixException { if (parentHandler.getDefDescriptor().getDefType() != DefType.LIBRARY) { error("aura:include may only be set in a library."); } DefDescriptor<LibraryDef> parentDescriptor = (DefDescriptor<LibraryDef>) parentHandler.getDefDescriptor(); builder.setLocation(getLocation()); String name = getAttributeValue(ATTRIBUTE_NAME); if (!AuraTextUtil.isNullEmptyOrWhitespace(name)) { builder.setName(name); } else { error("aura:include must specify a valid library name."); } if (name.toLowerCase().endsWith(".js")) { name = name.substring(0, name.length() - 3); } builder.setDescriptor( DefDescriptorImpl.getInstance( String.format("js://%s.%s", parentDescriptor.getNamespace(), name), IncludeDef.class, parentDescriptor)); String imports = getAttributeValue(ATTRIBUTE_IMPORTS); if (!AuraTextUtil.isNullEmptyOrWhitespace(imports)) { builder.setImports(Arrays.asList(imports.split("\\s*\\,\\s*"))); } String exports = getAttributeValue(ATTRIBUTE_EXPORTS); if (!AuraTextUtil.isNullEmptyOrWhitespace(exports)) { builder.setExports(exports); } builder.setParentDescriptor(parentDescriptor); int next = xmlReader.next(); if (next != XMLStreamConstants.END_ELEMENT || !TAG.equalsIgnoreCase(getTagName())) { error("expected end of %s tag", TAG); } builder.setOwnHash(source.getHash()); return builder.build(); }
/** * Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. The DefDescriptor in * this case is referring to a simple Component with a Javascript test suite {@link * DefType#TESTSUITE}. One of the test cases has no function assigned to them, this should cause * an Exception */ public void testJSTestSuiteWithoutAttributes() throws Exception { DefDescriptor<TestSuiteDef> descriptor = DefDescriptorImpl.getInstance( "js://test.testJSTestSuiteWithoutAttributes", TestSuiteDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); // Step 1: Parse the source which refers to a simple component with a // reference to Javascript test suite Definition testSuite = parser.parse(descriptor, source); assertTrue(testSuite instanceof JavascriptTestSuiteDef); // Step 2: Verify the properties of the JavascriptTestSuiteDef object // OBject that is to be verified, Qualified name, assertEquals( "unexpected qualifiedName of testSuite", "js://test.testJSTestSuiteWithoutAttributes", ((JavascriptTestSuiteDef) testSuite).getDescriptor().getQualifiedName()); // Step 3: Verify each testCaseDef objects in the test suite object List<TestCaseDef> testCases = ((JavascriptTestSuiteDef) testSuite).getTestCaseDefs(); assertEquals(2, testCases.size()); for (Object o : testCases.toArray()) { assertTrue(o instanceof JavascriptTestCaseDef); JavascriptTestCaseDef testCaseDef = (JavascriptTestCaseDef) o; Map<String, Object> attributes = testCaseDef.getAttributeValues(); if (testCaseDef.getName().equals("testHelloWorld")) { assertTrue(attributes.size() == 1); assertTrue(attributes.containsKey("num")); assertEquals("2", attributes.get("num")); // OBject that is to be verified, Qualified name assertEquals( "unexpected qualifiedName of testHelloWorld", "js://test.testJSTestSuiteWithoutAttributes/TESTCASE$testHelloWorld", ((DefinitionImpl<?>) o).getDescriptor().getQualifiedName()); } else if (testCaseDef.getName().equals("testHelloWorld3")) { assertNull(attributes); // OBject that is to be verified, Qualified name assertEquals( "unexpected qualifiedName of testHelloWorld3", "js://test.testJSTestSuiteWithoutAttributes/TESTCASE$testHelloWorld3", ((DefinitionImpl<?>) o).getDescriptor().getQualifiedName()); } else { fail("There should be no other test cases created"); } } }
/** * Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. The DefDescriptor in * this case is referring to a simple Component with a Javascript Rederer {@link * DefType#RENDERER}. * * @newTestCase Verify the serialized format of Javascript RendererDef. * @hierarchy Aura.Unit Tests.Components.Renderer * @priority medium * @userStorySyncIdOrName a07B0000000Ekdr */ public void testJSRenderer() throws Exception { DefDescriptor<RendererDef> descriptor = DefDescriptorImpl.getInstance("js://test.testJSRenderer", RendererDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); // STEP 1: // Parse and create the RedererDef object for the component Definition renderer = parser.parse(descriptor, source); // STEP 2:Verify the RENDERERDEF object assertTrue(renderer instanceof JavascriptRendererDef); // Convert from a generic DEFINITION to a Javascript Renderer Definition JavascriptRendererDef obj = (JavascriptRendererDef) renderer; // Step 3: Gold file the JAvascriptRenderDef serializeAndGoldFile(renderer, "_JSRendererDef"); // Step 4: Verify properties of JavascriptRenderDef Object // OBject that is to be verified, Qualified name, assertEquals( "unexpected qualifiedName of renderer", "js://test.testJSRenderer", obj.getDescriptor().getQualifiedName()); }
/** * Having duplicate controller methods What if there are two actions in the javascript controller * with the same name. */ public void testDuplicateJSController() throws Exception { DefDescriptor<ControllerDef> descriptor = DefDescriptorImpl.getInstance("js://test.testDuplicateJSController", ControllerDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); Definition controller = parser.parse(descriptor, source); assertTrue(controller instanceof JavascriptControllerDef); JavascriptControllerDef obj = (JavascriptControllerDef) controller; Map<String, JavascriptActionDef> controllerActions = obj.getActionDefs(); assertTrue(controllerActions.containsKey("functionName")); // If we have more than one controller function with same name, the // later one will replace the previous one assertTrue(controllerActions.size() == 1); // Verify the only JavascriptAction Def we have JavascriptActionDef jsActionDef = null; jsActionDef = controllerActions.get("functionName"); assertEquals(ActionType.CLIENT, jsActionDef.getActionType()); String[] jsonres = (JsonEncoder.serialize(jsActionDef)).split("\""); // Verify the second function did replace the first one assertEquals( "second function didn't survive", ":function(component) {var v = 2;},", jsonres[10]); }
/** * Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. The DefDescriptor in * this case is referring to a Nested Component with a Javascript Controller {@link * DefType#CONTROLLER}. */ public void testNestedComponent() throws Exception { DefDescriptor<ControllerDef> descriptor = DefDescriptorImpl.getInstance("js://test.testJSControllerParent", ControllerDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); // STEP 1: // Parse and create the ControllerDef object for the component Definition controller = parser.parse(descriptor, source); // STEP 2: // 2.1:Verify the CONTROLLERDEF object assertTrue(controller instanceof JavascriptControllerDef); // Convert from a generic controller to a Javascript type controller JavascriptControllerDef obj = (JavascriptControllerDef) controller; // Get all the actions defined in the Javascript Map<String, JavascriptActionDef> controllerActions = obj.getActionDefs(); // STEP 3: // 3.1: Verify the number of ACTIONDEF objects assertTrue(controllerActions.size() == 1); // 3.2: Verify the name of ActionDefs assertTrue(controllerActions.containsKey("functionName1")); // 3.4: Verify each JavascriptAction Def JavascriptActionDef jsActionDef = null; // 3.4.1 Action Def 1 jsActionDef = controllerActions.get("functionName1"); assertEquals(ActionType.CLIENT, jsActionDef.getActionType()); assertNull(jsActionDef.getReturnType()); // 3.4.2: Verify the Serialized form of the objects serializeAndGoldFile(jsActionDef, "_actionDef_functionName1"); // OBject that is to be verified, Qualified name assertEquals( "unexpected qualifiedName of functionName1", "js://test.testJSControllerParent/ACTION$functionName1", jsActionDef.getDescriptor().getQualifiedName()); }
protected Map<DefDescriptor<AttributeDef>, AttributeDefRef> getAttributes() throws QuickFixException { // TODOJT: add varargs "validAttributeNames" to this and validate that // any attributes we find are in that list. // TODOJT: possibly those arguments are like *Param objects with // built-in value validation? Map<DefDescriptor<AttributeDef>, AttributeDefRef> attributes = new LinkedHashMap<>(); for (int i = 0; i < xmlReader.getAttributeCount(); i++) { String attName = xmlReader.getAttributeLocalName(i); String prefix = xmlReader.getAttributePrefix(i); if (!XMLHandler.isSystemPrefixed(attName, prefix)) { // W-2316503: remove compatibility code for both SJSXP and Woodstox if (!AuraTextUtil.isNullEmptyOrWhitespace(prefix) && !attName.contains(":")) { attName = prefix + ":" + attName; } DefDescriptor<AttributeDef> att = DefDescriptorImpl.getInstance(attName, AttributeDef.class); String attValue = xmlReader.getAttributeValue(i); if (attributes.containsKey(att)) { error("Duplicate values for attribute %s on tag %s", att, getTagName()); } TextTokenizer tt = TextTokenizer.tokenize(attValue, getLocation()); Object value = tt.asValue(getParentHandler()); AttributeDefRefImpl.Builder atBuilder = new AttributeDefRefImpl.Builder(); atBuilder.setDescriptor(att); atBuilder.setLocation(getLocation()); atBuilder.setValue(value); attributes.put(att, atBuilder.build()); } } return attributes; }
/** * Test method for {@link JavascriptParser#parse(DefDescriptor, Source)}. The DefDescriptor in * this case is referring to a simple Component with a Javascript Controller {@link * DefType#CONTROLLER}. */ public void testJSController() throws Exception { DefDescriptor<ControllerDef> descriptor = DefDescriptorImpl.getInstance("js://test.testJSController", ControllerDef.class); Source<?> source = getJavascriptSourceLoader().getSource(descriptor); // STEP 1: // Parse and create the ControllerDef object for the component Definition controller = parser.parse(descriptor, source); // STEP 2: // 2.1:Verify the CONTROLLERDEF object assertTrue(controller instanceof JavascriptControllerDef); // Convert from a generic controller to a Javascript type controller JavascriptControllerDef obj = (JavascriptControllerDef) controller; // Step 4: Verify properties of JavascriptRenderDef Object // OBject that is to be verified: Qualified name, assertEquals( "unexpected qualifiedName of controller", "js://test.testJSController", obj.getDescriptor().getQualifiedName()); serializeAndGoldFile(controller, "_JSControllerDef"); // 2.2: Should be able to create an instance of the client action on // the server side, but it's a pseudo action try { obj.createAction("newAction", new HashMap<String, Object>()); fail("Should not be able to create an instance of the client action on the server side"); } catch (Exception e) { // Expect a definition not found Exception checkExceptionFull( e, DefinitionNotFoundException.class, "No ACTION named js://test.testJSController/ACTION$newAction found"); } JavascriptPseudoAction action = (JavascriptPseudoAction) obj.createAction("functionName1", null); assertEquals(State.ERROR, action.getState()); // 2.3 Extract the action defs and verify each of them in Step 3 // Get all the actions defined in the Javascript Map<String, JavascriptActionDef> controllerActions = obj.getActionDefs(); // STEP 3: // 3.1: Verify the number of ACTIONDEF objects is 2 assertTrue(controllerActions.size() == 2); // 3.2: Verify the name of actiodefs assertTrue(controllerActions.containsKey("functionName1")); assertTrue(controllerActions.containsKey("functionName2")); // 3.3: Verify each JavascriptAction Def JavascriptActionDef jsActionDef = null; // 3.3.1 Action Def 1 jsActionDef = controllerActions.get("functionName1"); // Javascript Controllers are to be called on the Client side assertEquals(ActionType.CLIENT, jsActionDef.getActionType()); // Javascript actions have no return type assertNull(jsActionDef.getReturnType()); // Verify the Serialized form of the objects serializeAndGoldFile(controllerActions.get("functionName1"), "_actionDef_functionName1"); // OBject that is to be verified, Qualified name assertEquals( "unexpected qualifiedName for functionName1", "js://test.testJSController/ACTION$functionName1", jsActionDef.getDescriptor().getQualifiedName()); // 3.3.2 Action Def 2 jsActionDef = controllerActions.get("functionName2"); // Javascript Controllers are to be called on the Client side assertEquals(ActionType.CLIENT, jsActionDef.getActionType()); // Javascript actions have no return type assertNull(jsActionDef.getReturnType()); // Verify the Serialized form of the objects serializeAndGoldFile(controllerActions.get("functionName2"), "_actionDef_functionName2"); // OBject that is to be verified, Qualified name assertEquals( "unexpected qualifiedName for functionName2", "js://test.testJSController/ACTION$functionName2", jsActionDef.getDescriptor().getQualifiedName()); }
@Override @SuppressWarnings("unchecked") public IncludeDefRefImpl getElement() throws XMLStreamException, QuickFixException { DefDescriptor<LibraryDef> parentDescriptor = (DefDescriptor<LibraryDef>) parentHandler.getDefDescriptor(); if (parentDescriptor.getDefType() != DefType.LIBRARY) { throw new InvalidDefinitionException( "aura:include may only be set in a library.", getLocation()); } validateAttributes(); builder.setLocation(getLocation()); String name = getAttributeValue(ATTRIBUTE_NAME); if (AuraTextUtil.isNullEmptyOrWhitespace(name)) { throw new InvalidDefinitionException( ("aura:include must specify a valid library name."), getLocation()); } builder.setDescriptor( SubDefDescriptorImpl.getInstance(name, parentDescriptor, IncludeDefRef.class)); builder.setIncludeDescriptor( DefDescriptorImpl.getInstance( String.format("%s.%s", parentDescriptor.getNamespace(), name), IncludeDef.class, parentDescriptor)); String importNames = getAttributeValue(ATTRIBUTE_IMPORTS); if (!AuraTextUtil.isNullEmptyOrWhitespace(importNames)) { List<DefDescriptor<IncludeDef>> imports = Lists.newLinkedList(); for (String importName : Arrays.asList(importNames.trim().split("\\s*\\,\\s*"))) { String[] parts = importName.split(":"); if (parts.length == 1) { // local import imports.add( DefDescriptorImpl.getInstance( String.format("%s.%s", parentDescriptor.getNamespace(), importName), IncludeDef.class, parentDescriptor)); } else if (parts.length == 3) { // external import DefDescriptor<LibraryDef> externalLibrary = DefDescriptorImpl.getInstance( String.format("%s:%s", parts[0], parts[1]), LibraryDef.class); imports.add( DefDescriptorImpl.getInstance( String.format("%s.%s", parts[0], parts[2]), IncludeDef.class, externalLibrary)); } else { // invalid import name throw new InvalidDefinitionException( String.format("Invalid name in aura:include imports property: %s", importName), getLocation()); } } builder.setImports(imports); } String export = getAttributeValue(ATTRIBUTE_EXPORT); if (!AuraTextUtil.isNullEmptyOrWhitespace(export)) { builder.setExport(export); } builder.setDescription(getAttributeValue(RootTagHandler.ATTRIBUTE_DESCRIPTION)); int next = xmlReader.next(); if (next != XMLStreamConstants.END_ELEMENT || !TAG.equalsIgnoreCase(getTagName())) { error("expected end of %s tag", TAG); } builder.setOwnHash(source.getHash()); return builder.build(); }
@Override public DefDescriptor<TokensDef> provide() throws QuickFixException { return DefDescriptorImpl.getInstance("tokenProviderTest:tokenComboTest", TokensDef.class); }
@Override public DefDescriptor<ThemeDef> provide() throws QuickFixException { return DefDescriptorImpl.getInstance("themeProviderTest:tvp", ThemeDef.class); }