Extent Reports V4 overwriting test results - extentreports

I was using Extent Reports V3 with selenium / C# and I just upgraded to V4. Previously each run would give me a unique report based on the Date stamp / Class Name / Time stamp. However, after moving to V4, it always puts everything under the same file named "index" and a separate file named "dashboard" which is a file to sit above the other for navigation purposes.
Here is my code for starting the report:
htmlReporter = new ExtentHtmlReporter($"C:\\Test-Results\\" + dateStamp + "\\" + TestClassName + " " + timeStamp + ".html");
extent = new ExtentReports();
extent.AttachReporter(htmlReporter);
extent.AddSystemInfo("Host Name", "Extent Framework");
extent.AddSystemInfo("Environment", "Local Machine");
extent.AddSystemInfo("User Name", "MyName");
htmlReporter.LoadConfig(CurrentDirectory + "\\extent-config.xml");
Now, each time I run a test, it overwrites the existing Index file with the new test results rather than appending my current results OR giving me a unique index file. I can provide any additional information needed about how i'm starting the reports / creating the tests if needed but for now here is what lives in my test file:
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
report.startReport("Report Name");
}
[ClassCleanup()]
public static void MyClassCleanup()
{
report.Flush();
}
[TestInitialize()]
public void MyTestInitialize()
{
string name = TestContext.TestName;
report.CreateTest(name);
}

It is enhanced feature of v4. To overcome it, We have to use ExtentV3HtmlReporter class in version 4. By using this class, We will be have Reports as we had. It will not override with index file. Also, There are many bugs get solved in V4. So things used same as version 4 report. You can compare both reports and you will be have your solution.

I started working on Extent Reports v4 recently and to solve files getting replaced issue you have to use v4 with v3 format as per #Ishita Shah answer, please see this Extent Reports generating two HTML Reports
Also, I have done a little tweak to generate new html files for every run without replacing the already generated files.
string fileName = "ExtentReport_" + DateTime.Now.ToString("MMM-dd-yyyy hh-mm-ss");
//Rename index.html with a new file name
renameFile("C:\\Reports\\index.html", fileName + "_Index.html");
//Replace "index.html" string inside the "index.html" file with the new filename
replaceTextHTMLFile("C:\\Reports\\" + fileName + "_Index.html", "index.html", fileName + "_Index.html");
same logic can be used for Dashboard.html and tags.html
renameFile:
public static void renameFile(string filePath, string oldFileName, string newFileName)
{
System.IO.File.Move(filePath + oldFileName, filePath + newFileName);
}
replaceTextHTMLFile:
public static void replaceTextHTMLFile(string filePath, string findText, string replaceText)
{
try
{
StreamReader objReader = new StreamReader(filePath);
string content = objReader.ReadToEnd();
objReader.Close();
content = Regex.Replace(content, findText, replaceText);
StreamWriter writerObj = new StreamWriter(filePath);
writerObj.Write(content);
writerObj.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception occurred. Messgae: " + e.Message);
}
}

Related

Tridion 2009 SP1: Is it possible to publish a .htaccess file?

I am using ISAPI rewrite on a project and would like to know if it is possible to publish a .htaccess file from Tridion?
I have tried creating a Page Template with the .htaccess extension but can't create a page with no name.
Any ideas?
Could I use a C# TBB to change the page name?
I would also choose to use a binary to achieve this, but if you want to manage the htaccess file using text, rather than as a multimedia component, you can push a binary into your package using the following technique:
1) Push the text of the Htaccess file into the package with an accessible name (i.e. Binary_Text)
2) Use code similar to the following to create a text file from the text in the variable and add it to the package
class publishStringItemAsBinary : ITemplate
{
public void Transform(Engine engine, Package package)
{
TemplatingLogger log = TemplatingLogger.GetLogger(typeof(publishStringItemAsBinary));
TemplateUtilities utils = new TemplateUtilities();
System.IO.Stream inputStream = null;
try
{
string strInputName = package.GetValue("InputItem");
string strFileName = package.GetValue("strFileName");
string sg_Destination = package.GetValue("sg_Destination");
string itemComponent = package.GetValue("mm_Component");
inputStream = new MemoryStream(Encoding.UTF8.GetBytes(package.GetValue(strInputName)));
log.Debug("InputObject:" + strInputName);
log.Debug("Filename for binary:" + strFileName);
log.Debug("Destination StructureGroup:" + sg_Destination);
Publication contextPub = utils.getPublicationFromContext(package, engine);
TcmUri uriLocalSG = TemplateUtilities.getLocalUri(new TcmUri(contextPub.Id), new TcmUri(sg_Destination));
TcmUri uriLocalMMComp = TemplateUtilities.getLocalUri(new TcmUri(contextPub.Id), new TcmUri(itemComponent));
StructureGroup sg = (StructureGroup)engine.GetObject(uriLocalSG);
Component comp = (Component)engine.GetObject(uriLocalMMComp);
String sBinaryPath = engine.PublishingContext.RenderedItem.AddBinary(inputStream, strFileName, sg, "nav", comp, "text/xml").Url;
//Put a copy of the path in the package in case you need it
package.PushItem("BinaryPath", package.CreateStringItem(ContentType.Html, sBinaryPath));
}
catch (Exception e)
{
log.Error(e.Message);
}
finally
{
if (inputStream != null)
{
inputStream.Close();
}
}
}
}
I think the code is pretty self explanatory. This publishes a binary of type text/xml, but there should be no issue converting it to do a plain text file.
I think you can use multimedia component to store your .htaccess. Even if you will not be able to upload file without name (Windows limitation), you will be able to change filename later, by modifying BinaryContent.Filename property of multimedia component. You can then publish this component seperately, or use AddBinary method in one of your templates.
There's also a user schema where you can change some other rules: "\Tridion\bin\cm_xml_usr.xsd", but you will not be able to allow empty filenames

Calling a Remote Java Servlet

I have a jsp page which holds a form, it is supposed to send off the form data to a remote servlet, which calculates it, and then returns it as XML. It works, but at the moment I'm creating an instance and dispatcher which only works with local servlets whereas I want it to work with a remote servlet.
I was previously told that HTTPClient would do this, but this thing has become such a headache and it seems like a complete overkill for what I want to do. There must be some simple method as opposed to faffing around with all these jar components and dependencies?
Please give sample code if possible, I'm really a complete novice to Java, much more of a PHP guy :P
Figured it out with the help of some online resources. Had to first collect the submitted values (request.getParamater("bla")), build the data string (URLEnconder), start up a URLConnection and tell it to open a connection with the designated URL, startup an OutputStreamWriter and then tell it to add the string of data (URLEncoder), then finally read the data and print it...
Below is the gist of the code:
String postedVariable1 = request.getParameter("postedVariable1");
String postedVariable2 = request.getParameter("postedVariable2");
//Construct data here... build the string like you would with a GET URL
String data = URLEncoder.encode("postedVariable1", "UTF-8") + "=" + URLEncoder.encode(postedVariable1, "UTF-8");
data += "&" + URLEncoder.encode("postedVariable2", "UTF-8") + "=" + URLEncoder.encode(submitMethod, "UTF-8");
try {
URL calculator = new URL("http://remoteserver/Servlet");
URLConnection calcConnection = calculator.openConnection();
calcConnection.setDoOutput(true);
OutputStreamWriter outputLine = new OutputStreamWriter(calcConnection.getOutputStream());
outputLine.write(data);
outputLine.flush();
// Get the response
BufferedReader streamReader = new BufferedReader(new InputStreamReader(calcConnection.getInputStream()));
String line;
//streamReader = holding the data... can put it through a DOM loader?
while ((line = streamReader.readLine()) != null) {
PrintWriter writer = response.getWriter();
writer.print(line);
}
outputLine.close();
streamReader.close();
} catch (MalformedURLException me) {
System.out.println("MalformedURLException: " + me);
} catch (IOException ioe) {
System.out.println("IOException: " + ioe);
}

How to rename a file in C#

Consider:
strPath= c:\images\gallery\add.gif
I need to rename this file from add.gif to thumb1.gid, and I should write one command method, whatever the file name. We need to
replace that name with this like below.
string strfilename = **"thumb"**
****Result thum.gif**
strPath= c:\images\gallery\thum.gif **
You have several problems, looking up the value in the XML file, and renaming the file.
To look up the number corresponding to Gallery2 or whatever, I would recommend having a look at Stack Overflow question How to implement a simple XPath lookup which explains how to look up nodes/values in an XML file.
To rename a file in .NET, use something like this:
using System.IO;
FileInfo fi = new FileInfo("c:\\images\\gallery\\add.gif");
if (fi.Exists)
{
fi.MoveTo("c:\\images\\gallery\\thumb3.gif");
}
Of course, you would use string variables instead of string literals for the paths.
That should give you enough information to piece it together and solve your particular lookup-rename problem.
I created a utility method to help encapsulate how to rename a file.
public class FileUtilities
{
public static void RenameFile(string oldFilenameWithPathWithExtension, string newFilenameWithoutPathWithExtension)
{
try
{
string directoryPath = Path.GetDirectoryName(oldFilenameWithPathWithExtension);
if (directoryPath == null)
{
throw new Exception($"Directory not found in given path value:{oldFilenameWithPathWithExtension}");
}
var newFilenameWithPath = Path.Combine(directoryPath, newFilenameWithoutPathWithExtension);
FileInfo fileInfo = new FileInfo(oldFilenameWithPathWithExtension);
fileInfo.MoveTo(newFilenameWithPath);
}
catch (Exception e)
{
//Boiler plate exception handling
Console.WriteLine(e);
throw;
}
}
}
I omitted several other file system checks that could optionally be done, but as #JoelCoehoorn pointed out in a comment on this page, the File System is Volatile, so wrapping it in a try-catch may be all that is necessary.
With that class in your library, now you can simply call:
var fullFilename = #"C:\images\gallery\add.gif";
var newFilename = "Thumb.gif";
FileHelper.RenameFile(fullFilename,newFilename);

Uploading an XML file, referencing an XSD, in ASP.Net

I have an XML file which is being uploaded to an ASP.Net page via the normal file upload control. When it gets up, I am attempting to validate and deserialize the XML. However, the code below is really very handy for validating an XML file which references it's XSD like this:
xsi:schemaLocation="someurl ..\localSchemaPath.xsd"
However, if I upload this XML file, only the XML file gets uploaded, so ..\localSchemaPath.xsd doesn't exist, so it can't validate.
Even if I stored the XSD locally, it still wouldn't be quite right as the XML file could be written with a schema location like:
xsi:schemaLocation="someurl ..\localSchemaPath.xsd"
or
xsi:schemaLocation="someurl localSchemaPath.xsd"
or
xsi:schemaLocation="someurl ..................\localSchemaPath.xsd"
if it so wished.
Dilemma!
(For the purposes of this question, I have pinched the code below from: Validating an XML against referenced XSD in C#)
using System.Xml;
using System.Xml.Schema;
using System.IO;
public class ValidXSD
{
public static void Main()
{
// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
// Create the XmlReader object.
XmlReader reader = XmlReader.Create("inlineSchema.xml", settings);
// Parse the file.
while (reader.Read()) ;
}
// Display any warnings or errors.
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);
}
}
Here is a chunk of code I use to validate xml with a local schema:
string errors = string.Empty;
try
{
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(string.Empty, Page.MapPath("~/xml/Schema.xsd"));
XmlDocument doc = new XmlDocument();
doc.Schemas = schemas;
doc.Load(Page.MapPath("~/xml/sampleXML.xml"));
//use this line instead of the one above for a string in memory.
//doc.InnerXml = xmlToValidate;
ValidationEventHandler validator = delegate(object send, ValidationEventArgs ve)
{
errors += "\n" + ve.Severity + ": " + ve.Message;
};
doc.Validate(validator);
}
catch (XmlException xe)
{
errors += "\n" + xe.Message;
}
catch (XmlSchemaValidationException xe)
{
errors += "\n" + xe.Message;
}
I can't quite make out whether you are attempting a generic validate-against-any-referenced-schema, or if you have a specific schema that you validate against every time, and are just not sure how to handle the references.
If it's the latter, then make the schema public on the internet, and tell people to reference it by URI.
If it's the former, then I would suggest the following:
First the user uploads an XML file.
Parse the XML file for a schema reference. Tell them "References to yourSchema.xsd were found; please upload this file below" with a new upload box.
Then, validate the file against the uploaded schema. To do this, modify the Schemas property of your settings object, instead of modifying the ValidationFlags property.

Convert a single file aspx to code behind

I'm working on a web site (not a web application) in VS 2008 .Net 3.5 and it uses the single file .aspx model where the server code is included in the head portion of the html instead of using a .aspx.cs code behind page.
I'd like to quickly convert the files to use the code-behind model, but so far the only way I can do this is by removing the file, creating a new, code-behind aspx page of the same name, then manually copying in the aspx related code to the .aspx page and the server code to the .aspx.cs page.
Is there a faster way to do this?
I have seen two article that seem to answer this question, but unfortunately don't:
Working with Single-File Web Forms Pages in Visual Studio .NET and
How do you convert an aspx or master page file to page and code behind?
Both offer a simple solution whereby VS does the leg work, you just point it to a file and shoot. For whatever reason, they aren't working. The first article seems to refer to VS 2002 and the second seems to refer to a web application.
Is there any hope for a web site?
Also, maybe I'm seeing this the wrong way, is there an advantage to the single page model? I do plan on converting the whole web site to a web application soon, does the single page model work well in web applications?
If manual conversion is too time-intensive, and the automatic conversion isn't working, I think your only other option would be to build your own converter. You could write a simple console app which takes a directory path on the command line and processes every file in that directory. This isn't too hard - here, I'll get you started:
using System;
using System.IO;
class Program
{
const string ScriptStartTag = "<script language=\"CS\" runat=\"server\">";
const string ScriptEndTag = "</script>";
static void Main(string[] args)
{
DirectoryInfo inPath = new DirectoryInfo(args[0]);
DirectoryInfo outPath = new DirectoryInfo(args[0] + "\\codebehind");
if (!outPath.Exists) inPath.CreateSubdirectory("codebehind");
foreach (FileInfo f in inPath.GetFiles())
{
if (f.FullName.EndsWith(".aspx"))
{
// READ SOURCE FILE
string fileContents;
using (TextReader tr = new StreamReader(f.FullName))
{
fileContents = tr.ReadToEnd();
}
int scriptStart = fileContents.IndexOf(ScriptStartTag);
int scriptEnd = fileContents.IndexOf(ScriptEndTag, scriptStart);
string className = f.FullName.Remove(f.FullName.Length-5).Replace("\\", "_").Replace(":", "_");
// GENERATE NEW SCRIPT FILE
string scriptContents = fileContents.Substring(
scriptStart + ScriptStartTag.Length,
scriptEnd-(scriptStart + ScriptStartTag.Length)-1);
scriptContents =
"using System;\n\n" +
"public partial class " + className + " : System.Web.UI.Page\n" +
"{\n" +
" " + scriptContents.Trim() +
"\n}";
using (TextWriter tw = new StreamWriter(outPath.FullName + "\\" + f.Name + ".cs"))
{
tw.Write(scriptContents);
tw.Flush();
}
// GENERATE NEW MARKUP FILE
fileContents = fileContents.Remove(
scriptStart,
scriptEnd - scriptStart + ScriptEndTag.Length);
int pageTagEnd = fileContents.IndexOf("%>");
fileContents = fileContents.Insert(PageTagEnd,
"AutoEventWireup=\"true\" CodeBehind=\"" + f.Name + ".cs\" Inherits=\"" + className + "\" ");
using (TextWriter tw = new StreamWriter(outPath.FullName + "\\" + f.Name))
{
tw.Write(fileContents);
tw.Flush();
}
}
}
}
}
30 minutes coding, 30 minutes debugging. There are some obvious bugs - like, if your code contains a closing script tag anywhere inside, then it won't get exported correctly. The results won't be pretty, but this should take care of 90% of your code, and you should be able to clean up any problem results manually. There, does that help?
Basically you need to create a class file. Inherit the class from System.Web.UI.Page and then change the page directive of the page to point to the code behind.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="_Default" %>
Where Inherits is the name of your class file, and the CodeBehind is the code file you just created. You might need to reload the project to get the solution explorer to display the file nested, but even if you don't it should work.
You can also check out the accepted answer to for an alternative. How does IIS know if it's serving a Web Site or a Web Application project?
I don't know of a shortcut way to be honest.
Your probably best bet is to create a new page and copy paste across until everything works, then delete your source, rename your new file to the old name and rebuild.
Not ideal, but probably the quickest/cleanest/safest way to port over.
Thanks alot! Here is a slighlty modified version if your code is written i VB.Net. Just compile and run the converter in every folder that contains aspx sites.
using System.IO;
namespace Converter
{
class Program
{
const string ScriptStartTag = "<script runat=\"server\">";
const string ScriptEndTag = "</script>";
static void Main(string[] args)
{
string currentDirectory = System.Environment.CurrentDirectory;
var inPath = new DirectoryInfo(currentDirectory);
var outPath = new DirectoryInfo(currentDirectory);
if (!outPath.Exists) inPath.CreateSubdirectory("codebehind");
foreach (FileInfo f in inPath.GetFiles())
{
if (f.FullName.EndsWith(".aspx"))
{
// READ SOURCE FILE
string fileContents;
using (TextReader tr = new StreamReader(f.FullName))
{
fileContents = tr.ReadToEnd();
}
int scriptStart = fileContents.IndexOf(ScriptStartTag);
int scriptEnd = fileContents.IndexOf(ScriptEndTag, scriptStart);
string className = f.FullName.Remove(f.FullName.Length - 5).Replace("\\", "_").Replace(":", "_");
// GENERATE NEW SCRIPT FILE
string scriptContents = fileContents.Substring(
scriptStart + ScriptStartTag.Length,
scriptEnd - (scriptStart + ScriptStartTag.Length) - 1);
scriptContents =
"Imports System\n\n" +
"Partial Public Class " + className + " \n Inherits System.Web.UI.Page\n" +
"\n" +
" " + scriptContents.Trim() +
"\nEnd Class\n";
using (TextWriter tw = new StreamWriter(outPath.FullName + "\\" + f.Name + ".vb"))
{
tw.Write(scriptContents);
tw.Flush();
}
// GENERATE NEW MARKUP FILE
fileContents = fileContents.Remove(
scriptStart,
scriptEnd - scriptStart + ScriptEndTag.Length);
int pageTagEnd = fileContents.IndexOf("%>");
fileContents = fileContents.Insert(pageTagEnd,
"AutoEventWireup=\"false\" CodeBehind=\"" + f.Name + ".vb\" Inherits=\"" + className + "\" ");
using (TextWriter tw = new StreamWriter(outPath.FullName + "\\" + f.Name))
{
tw.Write(fileContents);
tw.Flush();
}
}
}
}
}
}
if your aspx file has 2 sections and your are able to split it in a mechanical way why you don't write just a small parser to automate the work? Shouldn't be hard, it's just plain text manipulation and a recursive file find.

Resources