I'm currently trying to 'clean up' custom properties from a SOAP UI test case, using groovy script.
From this other post, I tried to do so but I'm facing a problem : I can't access the removeProperty method.
I get my data :
data = context.testCase.testSuite.getTestCaseByName("Test multi TT");
and from it I can only use a removePropertyChangeListener method.
I tried to use data.getPropertyAt() function to get a suitable object but it does not return the correct data class.
How can I get a PropertyChangeListener parameter from my custom property that I could use to remove it programmatically ?
All the posts I've been through provide answers with removeProperty and I can't find any that mentions removePropertyChangeListener
any help appreciated
EDIT: Based on the discussion over chat with OP, OP wants to remove the existing properties and add properties from external file to test case level custom properties.
Below is the Setup Script for the soapui test case. And this does the following (after discussion with OP on the chat):
Remove existing properties
Add the properties from file to test case level custom properties.
Setup Script:
//Change external properties file path as needed
def filename = 'C:/Users/apps/Documents/test.properties'
def properties = new Properties()
def propertiesFile = new File(flename)
assert propertiesFile.exists(), "$filename does not exists"
propertiesFile.withInputStream { properties.load(it) }
//Remove properties
testCase.propertyNames.collect { testCase.removeProperty(it) }
//load the properties of external file
properties.collect { k, v -> testCase.setPropertyValue(k, v) }
Here is a solution with no external file. The aim is to remove only the new properties I created for testCase purpose, in the teardown script:
import java.util.regex.Pattern
data = context.testCase.testSuite.getTestCaseByName("myTestCase");
log.info " ********************** old props ***********************"
String[] customProps = new String[data.getPropertyCount()];
customProps = data.getPropertyNames();
Pattern myRegex = ~/maProp_/ // I name my new properties with the same pattern and an index
for (propertyName in customProps){
log.info "info = " + propertyName
myMatcher = propertyName =~ /$myRegex/
if (myMatcher.count != 0){
match = myMatcher[0] == 'maProp_'
//log.info "match ? " + match // to check only my maProp_xx properties are matching
context.getTestCase().removeProperty(propertyName)
}
}
// verification
newProps = data.getPropertyNames();
log.info " ********************** new props ***********************"
for (i in newProps){
log.info "info = " +i
}
Related
I am using Cucumber-Extent reporting to generate reports for the test execution. In that I am dynamically passing name to the report file. I am able to pass a timestamp as extent report file name in #before of runner class. But I need to pass the scenario name or feature name along with the timestamp. Give me an idea to get the scenario name in runner class and append it to extent report name.
#CucumberOptions( features = "classpath:features",
tags = {"#InsuredInfoScreenAddressValidation"},
glue="classpath:stepDefinition",
plugin = "com.cucumber.listener.ExtentCucumberFormatter:",
"pretty",
"html:target/cucumber-html-report"},
monochrome=true //tags = "#Sample" //tags = "#Testing" )
You can get the name of the Scenario mentioned in the feature file from Scenario object in the #Before hook:
#Before()
public void beforeScenario(Scenario scenario)
{
extent = new ExtentReports (userDir + \\test-output\\" + scenario.getName()+ ".html", true);
}
I would like to use the Autodesk Design Automation API to extract all Text and Header information from a .dwg file into a json object. Is this possible with the Design Automation API?
Any example would help.
Thankyou
#Kaliph, yes, without a plugin in .NET/C++/Lisp code, it is impossible to extract block attributes by script only. I'd recommend .NET. It would be easier for you to get started with if you are not familiar with C++.
Firstly, I'd suggest you take a look at the training labs of AutoCAD .NET API:
https://www.autodesk.com/developer-network/platform-technologies/autocad
pick the latest version if you installed a latest version of AutoCAD. The main workflow of API is same across different versions, though. you can also pick C++ (ObjectARX) if you like.
In the tutorials above, it demos how to work with block. And the blog below talks about how to get attributes:
http://through-the-interface.typepad.com/through_the_interface/2006/09/getting_autocad.html
I copied here for convenience:
using Autodesk.AutoCAD;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
namespace MyApplication
{
public class DumpAttributes
{
[CommandMethod("LISTATT")]
public void ListAttributes()
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
Database db =
HostApplicationServices.WorkingDatabase;
Transaction tr =
db.TransactionManager.StartTransaction();
// Start the transaction
try
{
// Build a filter list so that only
// block references are selected
TypedValue[] filList = new TypedValue[1] {
new TypedValue((int)DxfCode.Start, "INSERT")
};
SelectionFilter filter =
new SelectionFilter(filList);
PromptSelectionOptions opts =
new PromptSelectionOptions();
opts.MessageForAdding = "Select block references: ";
PromptSelectionResult res =
ed.GetSelection(opts, filter);
// Do nothing if selection is unsuccessful
if (res.Status != PromptStatus.OK)
return;
SelectionSet selSet = res.Value;
ObjectId[] idArray = selSet.GetObjectIds();
foreach (ObjectId blkId in idArray)
{
BlockReference blkRef =
(BlockReference)tr.GetObject(blkId,
OpenMode.ForRead);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
blkRef.BlockTableRecord,
OpenMode.ForRead
);
ed.WriteMessage(
"\nBlock: " + btr.Name
);
btr.Dispose();
AttributeCollection attCol =
blkRef.AttributeCollection;
foreach (ObjectId attId in attCol)
{
AttributeReference attRef =
(AttributeReference)tr.GetObject(attId,
OpenMode.ForRead);
string str =
("\n Attribute Tag: "
+ attRef.Tag
+ "\n Attribute String: "
+ attRef.TextString
);
ed.WriteMessage(str);
}
}
tr.Commit();
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage(("Exception: " + ex.Message));
}
finally
{
tr.Dispose();
}
}
}
}
I have a sample on making signs on a drawing. It covers getting attributes and modifying attributes:
https://forge.autodesk.com/cloud_and_mobile/2016/02/sign-title-block-of-dwg-file-with-autocad-io-view-data-api.html
And I also have a sample on getting Table cells of a drawing:
https://forge.autodesk.com/blog/get-cell-data-autocad-table-design-automation-api
Hope these could help you to make the plugin for your requirements.
What do you mean by "Header" information? Can you give an example?
Finding an extracting all text objects is relatively easy if you are familiar with the AutoCAD .NET API (or C++ or Lisp).
Here's an example that extracts blocks and layer names:
https://github.com/Autodesk-Forge/design.automation-.net-custom.activity.sample
My module creates a custom content item through the controller:
private ContentItem createContentItem()
{
// Add the field
_contentDefinitionManager.AlterPartDefinition(
"TestType",
cfg => cfg
.WithField(
"NewField",
f => f
.OfType(typeof(BooleanField).Name)
.WithDisplayName("New Field"))
);
// Not sure if this is needed
_contentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.WithPart("TestType")
);
// Create new TestType item
var newItem = _contentManager.New("TestType");
_contentManager.Create(TestItem, VersionOptions.Published);
// Set the added boolean field to true
BooleanField newField = ((dynamic)newItem).TestType.NewField as BooleanField;
newField.Value = true;
// Set title (as date created, for convenience)
var time = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt", CultureInfo.InvariantCulture).Replace(':', '.');
newItem.As<TitlePart>().Title = time;
return newItem;
}
The end result of this is a new TestType item with a field that's set to true. Viewing the content item in the dashboard as well as examining ContentItemVersionRecord in the database confirms that the value was set correctly.
However, queries don't seem to work properly on fields that are set in this manner. I found the record IntegerFieldIndexRecord, which is what I assume projections use to fill query result pages. On this, the value of TestField remains at 0 (false), instead of 1 (true).
Going to the content item edit page and simply clicking 'save' updates IntegerFieldIndexRecord correctly, meaning that the value is now picked up by the query. How can the record be updated for field values set programmatically?
Relevant section of migration:
SchemaBuilder.CreateTable(typeof(TestTypePartRecord).Name, table => table
.ContentPartRecord()
);
ContentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.DisplayedAs("Test Type")
.WithPart(typeof(TitlePart).Name)
.WithPart(typeof(ContainablePart).Name)
.WithPart(typeof(CommonPart).Name)
.WithPart(typeof(IdentityPart).Name)
);
Edit: The fix for this is to manually change the projection index record whenever changing a field value, using this call:
_fieldIndexService.Set(testResultItem.As<FieldIndexPart>(),
"TestType", // Resolves as TestTypePart, which holds the field
"newField",
"", // Not sure why value name should be empty, but whatever
true, // The value to be set goes here
typeof(bool));
In some cases a simple contentManager.Publish() won't do.
I've had a similar problem some time ago and actually implemented a simple helper service to tackle this problem; here's an excerpt:
public T GetStringFieldValues<T>(ContentPart contentPart, string fieldName)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
return this.fieldIndexService.Get<T>(fieldIndexPart, partName, fieldName, string.Empty);
}
private void SetStringFieldValue(ContentPart contentPart, string fieldName, IEnumerable<int> ids)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
var encodedValues = "{" + string.Join("},{", ids) + "}";
this.fieldIndexService.Set(fieldIndexPart, partName, fieldName, string.Empty, encodedValues, typeof(string));
}
I've actually built this for use with MediaLibrary- and ContentPicker fields (they encode their value as string internally), so it might not be suitable for the boolean field in your example.
But it can't be that hard to implement, just look at the existing drivers and handlers for those fields.
There are 2 ways to fix this:
1) Ensure the newly created item is getting published by calling ContentManager.Publish() as Orchard.Projections.Handlers.FieldIndexPartHandler listens to the publish event to update the FieldIndexPartRecord
2) use IFieldIndexService to update FieldIndexPartRecord manually, see implementation of Orchard.Projections.Handlers.FieldIndexPartHandler to get in idea how to do this
Hope this helps.
:edit
Due to calling Create(...Published) the ContentManager.Published() won't do anything as the item is already considered published.
You can do the following to force the publish logic to run:
bool itemPublished = newItem.VersionRecord.Published;
// unpublish item first when it is already published as ContentManager.Publish() internally first checks for published flag and when set it aborts silently
// -> this behaviour prevents calling publish listeners
if (itemPublished)
_contentManager.Unpublish(newItem);
// the following call will result in calls to IContentHandler.Publishing() / IContentHandler.Published()
_contentManager.Publish(newItem);
or just create the item as a draft and publish it when everything is setup correctly.
I am not able to create a list content type using the below snippet. It throws a ServerException with additional information - "The site content type has already been added to this list."
var list = clientContext.Web.Lists.GetByTitle("sometitle");
var documentCT = clientContext.Web.ContentTypes.GetById("0x0101");
clientContext.Load(list,l=> l.ContentTypes);
clientContext.Load(documentCT);
clientContext.ExecuteQuery();
var test = new ContentTypeCreationInformation(){
Name = "TestCT", ParentContentType =documentCT };
list.ContentTypes.Add(test);
list.Update();
clientContext.ExecuteQuery();
Basically, I want to create a list content type whose parent is the "Document" CT.
I encountered this same problem.
What is happening here is that you have added the content type to the list successfully but you haven't turned on "allow management of content types" in Library settings > Advanced Settings > First setting. You will not see the content type via the UI.
Once you turn on this setting you will see your content type was in fact added.
Here's how I create a library
public static List CreateLibrary(ClientContext context, string title, bool allowContentTypes)
{
ListCreationInformation lci = new ListCreationInformation
{
Description = "Library used to hold Dynamics CRM documents",
Title = title,
TemplateType = 101,
};
List lib = context.Web.Lists.Add(lci);
lib.ContentTypesEnabled = allowContentTypes ? true : false;
lib.Update();
context.Load(lib);
context.ExecuteQuery();
return lib;
}
For your case just add in the line:
list.ContentTypesEnabled = true;
Don't forget the list.Update(), I see you have it in your code but for anyone else, this part is essential before you use ExecuteQuery()
I am importing data and documents from third party application into Acumatica.
After importing, I am creating Vendor dynamically using below code along with attachments.
VendorMaint graph = PXGraph.CreateInstance<VendorMaint>();
VendorR row1 = null;
row1 = new VendorR();
row1.AcctName = VendorName;
row1.NoteID = noteid; // Existing - GUID created while importing
graph.BAccount.Update(row1);
If attachment already exists then it should update instead of duplicating.
In this case if Vendor already exists with files attached, then my code overrides these attachments and remove all previous files attached to that existing vendor.
I want to add the attachment instead of override the existing attachment. Any suggestion?
Try to use insert method of view:
VendorMaint graph = PXGraph.CreateInstance<VendorMaint>();
var row1 = new VendorR();
row1 = graph.BAccount.Insert(row1);
if (row1 == null) // already inserted or wasn't able to insert
{
//some logic with newly created vendor
}
else
{
//some logic with existed
}
row1.AcctName = "vendor name";
row1.NoteID = noteid; // Existing - GUID created while importing
graph.BAccount.Update(row1);
I have found the solution for the issue. Below code helps to create a new attachment and does not override any existing attachments for an existing Vendor.
// Getting the FileID of the attached file from DACClass
UploadFile uf = PXSelectJoin<UploadFile,
InnerJoin<NoteDoc, On<NoteDoc.fileID, Equal<UploadFile.fileID>>,
InnerJoin<DACClass, On<DACClass.noteID, Equal<NoteDoc.noteID>>>>,
Where<DACClass.noteID, Equal<Required<DACClass.noteID>>>>.Select(this, noteid);
if (uf != null)
{
PXNoteAttribute.SetFileNotes(graph.BAccount.Cache, graph.BAccount.Current, uf.FileID.Value);
NoteDoc doc = new NoteDoc();
doc.NoteID = uf.FileID.Value;
doc.FileID = new Guid();
graph.BAccount.Cache.Insert(doc);
}