Call a template expression from another in XTend - code-generation

i have a question about calling template expression methods from another template expression.
The example below didn't work, ie. it doesn't expand and 'prints' the code on the spot it was called. How can I modify this code to print the result of ResourceGenerator().generate(resource) on the spot where it is called? Note that ResourceGenerator().generate(resource) is in itself a template expression.
class ServerGenerator extends RESTServiceGenerator {
def generate(Server it) '''
package nl.sytematic.projects.RESTServiceServlet;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("«it.baseURI»")
public class «it.name» {
«it.resources.forEach[ resource |new ResourceGenerator().generate(resource)]»
}
'''
}
Hope I am clear in my question. An example would be great! (Again: ResourceGenerator().generate returns a CharSequence).

forEach always returns null and is just about doing side-effects. What you want is a map and a join.
it.resources.map(resource |new ResourceGenerator().generate(resource)).join
But there's an even better way:
«FOR resource : resources»
«new ResourceGenerator().generate(resource)»
«ENDFOR»
I suggest to hold and reuse a single instance of ResourceGenerator as a field (do you use dependency injection?) or make ResourceGenerator::generate static.

Related

Open Web Components Testing / Lit - component not being rendered?

I'm trying to test my Lit components with #open-wc/testing. Lit has an example repo here, with this test:
https://github.com/lit/lit-element-starter-ts/blob/main/src/test/my-element_test.ts#L44
When I try to render my element like they do in their example, I get this error:
jtests/components/coding-editor.test.ts:
🚧 Browser logs:
HTMLElement: <coding-editor></coding-editor>
❌ renders
TypeError: Cannot read properties of null (reading 'querySelector')
at o.<anonymous> (jtests/components/coding-editor.test.ts:16:30)
My component works in the browser and uses the name "coding-editor". It's as if this test renderer has no idea that I'm using a custom component though. I don't know why shadowRoot is null in my case.
My code is roughly this:
import { CodingEditor } from '../../app/javascript/components/coding-editor';
import {expect, fixture} from '#open-wc/testing';
import {html} from 'lit/static-html.js';
it('renders', async () => {
const el = await fixture(html`
<coding-editor></coding-editor>
`) as CodingEditor;
console.log(el);
const text = el.shadowRoot!.querySelector('.table-constrainer');
// expect(text).to.not.be.null
});
How can I get my test to render this properly, with the shadowRoot populated?
This is likely due to TypeScript removing the CodingEditor import that's only used as a type so the side effect of defining the custom element is not happening.
You can either set the TS compiler option importsNotUsedAsValues to preserve (See https://www.typescriptlang.org/tsconfig/#importsNotUsedAsValues) or add another import line for the side-effect like
import '../../app/javascript/components/coding-editor';
Additional explanation here too: https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-imports-being-elided-in-my-emit
As a side-note, in the starter example you linked to, the imported class is used in assert.instanceOf as a value so it does not get elided by TypeScript.

Odoo Modify or extend import process

I want modify or extend the process on csv import in Odoo.
I have some fields autocalculated and other needed but is not in the csv file.
Having search the code and try using ir.action.todo, and ir.action.client but dont work.
Any idea, using hooks, or other work?
Thanks
Yoinier.
You just need to inherit the 'base_import.import' model
class Import(models.TransientModel):
_inherit = 'base_import.import'
#api.model
def _convert_import_data(self, fields, options):
# Override base method
# Called when actual import start
data, import_fields = super(Import, self)._convert_import_data(fields, options)
# Do something ...
return data, import_fields
def parse_preview(self, options, count=10):
# Override base method
# Called when data loaded
preview_data = super(Import, self).parse_preview(options, count=count)
# Do something ...
return preview_data
but, override the base import method is probably not a good idea, I'd suggest to use custom import wizard to do your custom import.

Is there a way to create a "Verify Element Text is Not" keyword?

I need to verify an element had been randomized from a fixed starting state. I already have a test step that verifies the fixed state is working that uses "Verify Element Text" is "inserttexthere".
So I need a way to verify that the text is not "inserttexthere" after I click the randomizing button.
Is there anyway to do this that wouldn't require too much programming knowledge? (I use katalon studio because I have limited tech knowledge)
or is there an if else statement I can use that would pass the step only if the text is different?
Background and other methods I do know of or tried:
I can create another verify text command and just accept it as an intended to fail step. However that's harder to be aware of, especially if the text doesnt change because the test step will pass and I have to remember thats bad.
The other commands that are available only cover if the element no longer has text or if the element is no longer visible/clickable. There is nothing that lets me verify an attribute as "!=" or "NOT"
This is how you need to create a custom keyword in Katalon: Click
Code:
class help_keyword_elemtnotPresent {
#Keyword
def isElemetNotPresent() {
WebUI.verifyElementNotPresent(findTestObject(‘someobject’, timeout, FailureHandling.OPTIONAL)
}
for : if/else
More example
Here's a short beginners' practical tutorial:
Create a keyword in Keywords (1) (right-click, new keyword).
Create a package (2) (right-click, new package) called examplePackage.
Create a new class called ExampleClass inside that package:
public class ExampleClass {
#Keyword
public static verifyElementTextIsNot(String text1, String text2){
assert text1 != text2
}
}
Example test case showing how you can call the above keyword (Keyword is Katalon's name for method):
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable
import examplePackage.ExampleClass
String someText = "It is a rainy day"
String someOtherText = "It is a sunny day"
ExampleClass.verifyElementTextIsNot(someText, someOtherText)

How to order imports with tslint's import-ordering rule

On my project tslint's "import-ordering" rule is used
import CopyLensModal from './CopyLensModal';
import FetchStatus from '../../../../../state/generic/models/FetchStatus';
import FlexRow from '../../../../generic/components/FlexRow';
import Geofilter from '../../../../../state/geofilter/models/Geofilter';
import Input from '../../../../generic/components/Input';
import * as React from 'react';
import * as salert from 'sweetalert';
import { func } from '../../../../../types/func';
import { Iterable } from 'immutable';
import { Button } from 'react-bootstrap';
tslint is not happy with this order and crashes with error
[2, 1]: Import sources within a group must be alphabetized.
[4, 1]: Import sources within a group must be alphabetized.
This page didn't help that much, I've tried to place imports in many different ways but without luck. Which order will be correct?
I agree that it's confusing. The problem is that the source string comparisons include the ../.. portions of the module names, so to appease the rule, you would need to sort them like this:
import FetchStatus from '../../../../../state/generic/models/FetchStatus';
import Geofilter from '../../../../../state/geofilter/models/Geofilter';
import FlexRow from '../../../../generic/components/FlexRow';
import Input from '../../../../generic/components/Input';
import CopyLensModal from './CopyLensModal';
The rule has two parts and can be configured to enforce orderings of the import names and sources separately. To enforce only the ordering of names only, you could use a configuration like this:
"ordered-imports": [true, {
"import-sources-order": "any",
"named-imports-order": "case-insensitive"
}]
That would raise an error for imports like this:
import { A, C, B } from 'some-module';
but wouldn't enforce ordering for the module paths, etc.
This error also happens if there is not empty new line added as separation between groups of imports.
import * as fs from 'fs';
import * as os from 'os';
import * as bar from './bar';
import * as foo from './foo';
Also notice if the error says like this:
***(5,1): Import sources within a group must be alphabetized.***
This means in the specified file go to line #5 and press enter to add a new empty line there as separator.
I did that and this resolved my problem. For more reference about this issue review this page
In file tslint.json add
"rules": {
"ordered-imports": [false],
"object-literal-sort-keys": [false]
}
For example, then file tslint.json will look like this
{
"extends": [
"tslint:recommended",
"tslint-react",
"tslint-config-prettier"
],
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts",
"coverage/lcov-report/*.js"
]
},
"rules": {
"ordered-imports": [false],
"object-literal-sort-keys": [false]
}
}

How can I export an interface that I have imported?

I am creating a library in typescript, which is spread across multiple files. I take all the classes and constants I have defines and import them into one module, which exports them all under one namespace. I have just defines an interface, and I wish to include it in the same namespace/module as all the other parts of my library. But apparently I can't.
Here's a simplified example:
/app.ts is the entry point of the application, all I do in it at the moment is include my library MyLib:
//app.ts
import myLib = require("lib/MyLib/MyLib"); // this works fine
/lib/MyLib/MyLib.ts is the file in which I import all of the things defined by MyLib, and export them together:
// lib/MyLib/MyLib.ts
import VehiclesImport = require("./transport/vehicles");
// error under VehiclesImport.IAutomobile, saying that VehiclesImport has no property IAutomobile
export var IAutomobile = VehiclesImport.IAutomobile;
export var Car = VehiclesImport.Car;
In /lib/MyLib/transport/vehicles.ts, I define several classes and interfaces of vehicles, here, I'll just show IAutomobile and Car:
// lib/MyLib/transport/vehicles.ts
export interface IAutomobile {
weight: number
}
export class Car implements IAutomobile {
weight = 3000
}
I have tried creating a class truck in MyLib.ts, which properly implements IAutomobile, and that works fine, without any error messages. The problem only seems to arise when I want to access IAutomobile outside of an 'implements' statement.
I apologize if this seems like a 'code dump', but in my opinion, this is a serious problem that I cannot access my interfaces except in a class declaration. I have searched Google for the past two hours and found nothing on the subject. Thanks for any help you can give me!
Edit: I understand that typescript interfaces are not part of the compiled javascript code, but that should not stop me from manipulating them within typescript.
Use the import keyword to bring in something into the type declaration space (as opposed to var which brings it into the variable declaration space).
This is demonstrated below. a.ts:
export interface A {
val: number;
}
To re-export this from another file b.ts:
import a = require('./a');
export import B = a.A; // Important use of import
Sample usage in some other file c.ts:
import b = require('./b');
var foo: b.B;
foo.val = 123;
interface C extends b.B {
val2:number;
}
var bar: C;
bar.val2 = 456;
The example rewritten following TS language specification:
a.ts:
export interface A {
val: number;
}
To re-export this from another file b.ts:
export {A} from './a'
Usage in some other file c.ts:
import {A} from './b'
var foo: A = {val: 2};
foo.val = 123;
interface C extends A {
val2:number;
}
var bar: C = {val: 1, val2: 3};
bar.val2 = 456;
Types can't be assigned to variables, they exist in different "declaration spaces". Classes can be assigned to variables, because they contribute their names to the type declaration space as well as defining the class objects. Interfaces only contribute to the types declaration space, so can't be referenced as values.
The language is a bit verbose, but this is spelt out in detail in section 2.3 of the language spec
foo.ts
export interface ITest {
...
}
bar.ts
import * as foo from "./foo";
export type ITest = foo.ITest;
This works to re-export types/interfaces
import type { MyInterface, MyType } from './randomModule';
export { MyInterface, MyType }
The key is the surrounding braces in the export statement. Works in TypeScript 4.7.4. Reference.
In TypeScript 3.9.6, this worked for me:
import { Foo as FooType } from './some-path';
export type Foo = FooType;