I am having a problem in setting my symbols and retrieving them using Fitnesse symbols. I am creating a new class called Carrier which is a simple Java bean which takes a WebDriver object.
My Java implementation for setting symbols looks like this:
public class ColumnFixtureTest extends ColumnFixture{
private WebDriver driver;
public Carrier together(){
driver = new FirefoxDriver();
Carrier c = new Carrier();
c.setMyDriver(driver);
return c;
}
}
My Java implementation for retrieving them looks like this:
public class SymbolsTest extends ColumnFixture{
private Carrier symbolValue;
public boolean check(){
if(symbolValue.getMyDriver()!=null){
return true;
}
return false;
}
}
My carrier object looks like this:
public class Carrier {
WebDriver myDriver;
public WebDriver getMyDriver() {
return myDriver;
}
public void setMyDriver(WebDriver myDriver) {
this.myDriver = myDriver;
}
}
My Fit table looks like this :
!|ColumnFixtureTest|
|=together()|
|comb|
!|SymbolsTest|
|symbolValue=|check?|
|comb|true|
But after running it, I am getting the following error:
comb
Could not parse: com.symbolTest.Carrier#5ed75ed7, expected type: com.symbolTest.Carrier.
My value is getting set properly though as :
comb = com.ebay.srp.symbolTest.Carrier#5ed75ed7
Any help would be appreciated. Stuck with this for a while now :(
I haven't used the Fit tables in a long time now. I suspect that the problem is that the ColumnFixture class cannot move instances of objects back and forth. It may either only work with stock types that can be expressed as strings. But I could be way off on that.
Is there a reason you are using Fit style tables? I would either recommend that you look at Slim, or go to FitLibrary. For WebDriver testing, FitLibrary has SpiderFixture and there are projects already using WebDriver for Slim (Xebium being an option).
I do know this. Passing around object references in a symbol is supported in Slim.
Related
Can anybody help me with explaining this error message please:
system.componentmodel.composition.changerejectedexception
The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error.
The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint:
ContractName Itok.BusinessLogic.Interfaces.IFolderService
RequiredTypeIdentity Itok.BusinessLogic.Interfaces.IFolderService
Resulting in: Cannot set import 'Itok.Web.Photos.Presenters.DefaultPresenter._folderService (ContractName="Itok.BusinessLogic.Interfaces.IFolderService")' on part 'Itok.Web.Photos.Presenters.DefaultPresenter'.
Element: Itok.Web.Photos.Presenters.DefaultPresenter._folderService (ContractName="Itok.BusinessLogic.Interfaces.IFolderService") --> Itok.Web.Photos.Presenters.DefaultPresenter
Here is the IFolderService.cs:
using System;
using System.Collections.Generic;
using Itok.Entities;
namespace Itok.BusinessLogic.Interfaces
{
public interface IFolderService
{
List<Folder> GetFriendsFolders(Int32 AccountID);
void DeleteFolder(Folder folder);
List<Folder> GetFoldersByAccountID(Int32 AccountID);
Folder GetFolderByID(Int64 FolderID);
Int64 SaveFolder(Folder folder);
}
}
And this is the exporting class definition, FolderService.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Itok.BusinessLogic.Interfaces;
using System.ComponentModel.Composition;
using Itok.DataAccess.Interfaces;
using Itok.Common;
using Itok.DataAccess;
using Itok.Interfaces;
using Itok.Entities;
namespace Itok.BusinessLogic
{
[Export(typeof(IFolderService))]
[Export(typeof(ICache))]
public class FolderService : IFolderService
{
[Import]
private IFriendRepository _friendRepository;
[Import]
private IFolderRepository _folderRepository;
[Import]
private ICache _cacheService;
public FolderService()
{
MEFManager.Compose(this);
}
public List<Folder> GetFriendsFolders(Int32 AccountID)
{
List<Friend> friends = _friendRepository.GetFriendsByAccountID(AccountID);
List<Folder> folders = _folderRepository.GetFriendsFolders(friends);
folders.OrderBy(f => f.CreateDate).Reverse();
return folders;
}
public void DeleteFolder(Folder folder)
{
if (_cacheService.Exists(folder.AccountID.ToString()))
{
_cacheService.Delete(folder.AccountID.ToString());
}
_folderRepository.DeleteFolder(folder);
}
public List<Folder> GetFoldersByAccountID(int AccountID)
{
List<Folder> cachedFolders = _cacheService.Get(AccountID.ToString()) as List<Folder>;
if (cachedFolders != null)
{
return cachedFolders;
}
else
{
cachedFolders = _folderRepository.GetFoldersByAccountID(AccountID);
_cacheService.Set(AccountID.ToString(), cachedFolders);
return cachedFolders;
}
}
public Folder GetFolderByID(Int64 FolderID)
{
return _folderRepository.GetFolderByID(FolderID);
}
public Int64 SaveFolder(Folder folder)
{
return _folderRepository.SaveFolder(folder);
}
}
}
I thank you prior to any help for saving my time.
The error message means that MEF is looking for a class that is exported with the interface IFolderService but there isn't one in the container.
To investigate this, firstly check that there is a class that exports that interface and if there is, then look into whether that class being picked up by the container or not and thirdly, if neither of those resolve the issue, look into whether the class that is exported with the interface IFolderService has some other imports that can't be satisfied.
Finally, I found the Solution for the problem. It has got has nothing to do directly with IFolderService that MEF was pointing to. The App has dependencies on a component (FolderService) in the business logic, which in turn is dependent upon an interface ICache, and an implementation wrapper, Cache.cs. ICache, specified by a contract name Itok.Interfaces.ICache, had been exported FOUR times (on just one Import). This was left unnoticed while I was trying to scale the solution. MEF couldn't tell which Export to use. The real problem is that MEF was pointing to a class two levels upper the chain!
Thanks TomDoesCode for looking at the problem, and I hope this will help others who'll get a similar problem.
A long term solution for this problem would be if you have many Exports that will satisfy an Import, you'll probably have two options:
I) Change the [Import] with [ImportMany]. Then during runtime, decide which import to use for the contract. Ask yourself if just picking up the first available, or using one at a time in random.
II) Use [ImportMany] in conjunction with Metadata in order to decide which Import to use.
I refer to this site link text
Using the wrong event name in the
[Bindable] tag can cause your
application to not bind your property,
and you will not even know why. When
you use the [Bindable] tag with a
custom name, the example below looks
like a good idea:
public static const EVENT_CHANGED_CONST:String = "eventChangedConst";
private var _number:Number = 0;
[Bindable(event=EVENT_CHANGED_CONST)]
public function get number():Number
{
return _number;
}
public function set number(value:Number) : void
{
_number = value;
dispatchEvent(new Event(EVENT_CHANGED_CONST));
}
The code above assigns a static
property to the event name, and then
uses the same assignment to dispatch
the event. However, when the value
changes, the binding does not appear
to work. The reason is that the event
name will be EVENT_CHANGED_CONST and
not the value of the variable.
The code should have been written as
follows:
public static const EVENT_CHANGED_CONST:String = "eventChangedConst";
private var _number:Number = 0;
[Bindable(event="eventChangedConst")]
public function get number():Number
{
return _number;
}
public function set number(value:Number) : void
{
_number = value;
dispatchEvent(new Event(EVENT_CHANGED_CONST));
}
I agree, the wrong example does look like a good idea and I would do it that way because I think it's the right way and avoids the possibility of a typing error. Why is the name of the constant used instead of it's value? Surely this can't be right?
I appreciate your insights
Because the standard Flex compiler isn't that clever at times... and I feel your pain! I've complained about this exact problem more than a few times.
If I remember correctly, it's because the compiler does multiple passes. One of the early passes changes the Metadata into AS code. At this point in the compiler it hasn't parsed the rest of the AS code, so its not capable of parsing Constants or references to static variables in other files.
The only thing I can suggest is sign up to the Adobe JIRA, vote for the bug, and hope that the compiler fixes in 4.5 bring some relief.
Based on this article, I've written a custom class which implements the Watin.Core.interfaces.IFindByDefaultFactory, but I don't think I'm correctly assigning it to the watin settings, because it is never used.
Basically, Where/when should I assign to the Settings.FindByDefaultFactory? I've tried in my test Setup, and the text fixture's constructor, but neither seem to cause my custom class to be used. The tests still run and work, but I have to use the full asp.net ID's.
I'm using Watin 2.0.15.928 in VS2008 from nUnit 2.5.2.9222. I am running visual studio as administrator, and tests run sucessfully as long as I don't rely on my custom find logic.
Here's what the start of my text fixture looks like, where I set the FindByDefaultFactory
namespace Fundsmith.Web.Main.BrowserTests
{
[TestFixture]
class WatinHomepageTests
{
private IE _ie;
[SetUp]
public void Setup()
{
Settings.FindByDefaultFactory = new FindByAspIdFactory();
_ie = new IE("http://localhost/somepage.aspx");
}
//etc etc...
And this is what my custom Find By Default factory looks like (simplified), unfortunately, it's never called.
using System.Text.RegularExpressions;
using WatiN.Core;
using WatiN.Core.Constraints;
using WatiN.Core.Interfaces;
namespace Fundsmith.Web.Main.BrowserTests
{
public class FindByAspIdFactory : IFindByDefaultFactory
{
public Constraint ByDefault(string value)
{
// This code is never called :(
// My custom find by id code to cope with asp.net webforms ids...
return Find.ById(value);
}
public Constraint ByDefault(Regex value)
{
return Find.ById(value);
}
}
}
Edit: Extra information after the fact.
Based on me fuguring this out, (see answer below), It turns out that the way I was consuming Watin to find the elements was wrong. I was explicitly calling Find.ById, rather than letting the default action occur. So I'd reassigned the default but was then failing to use it!
[Test]
public void StepOneFromHomepageShouldRedirectToStepTwo()
{
_ie.TextField(Find.ById("textBoxId")).TypeText("100");
//Other test stuff...
}
Right, I've figured this one out, and it was me being an idiot and explicitly calling the Find.ById method, rather than letting the default action occur. It seems the test setup is a fine place to set the FindByDefaultFactory.
ie, I was doing this (wrong):
[Test]
public void StepOneFromHomepageShouldRedirectToStepTwo()
{
_ie.TextField(Find.ById("textBoxId")).TypeText("100");
//Other test stuff...
}
When I should have been simply doing this. (Without the explicit "Find.ById")
[Test]
public void StepOneFromHomepageShouldRedirectToStepTwo()
{
_ie.TextField("textBoxId").TypeText("100");
//Other test stuff...
}
Not only was this me being stupid, but I didn't include this in my original question, so it would have been impossible for anyone else to figure it out for certain. Double slaps for me.
I'm using Python+PyAMF to talk back and forth with Flex clients, but I've run into a problem with the psudo-Enum-Singletons I'm using:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
}
When I'm using locally created instances, everything is peachy:
if (someInstance.type == Type.EMPTY) { /* do things */ }
But, if 'someInstance' has come from the Python code, it's instance of 'type' obviously won't be either Type.EMPTY or Type.FULL.
So, what's the best way to make my code work?
Is there some way I can control AMF's deserialization, so when it loads a remote Type, the correct transformation will be called? Or should I just bite the bullet and compare Types using something other than ==? Or could I somehow trick the == type cohesion into doing what I want?
Edit: Alternately, does Flex's remoting suite provide any hooks which run after an instance has been deserialized, so I could perform a conversion then?
Random thought: Maybe you could create a member function on Type that will return the canonical version that matches it?
Something like:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
// I'm assuming this is where that string passed
// in to the constructor goes, and that it's unique.
private var _typeName:String;
public function get canonical():Type {
switch(this._typeName) {
case "empty": return EMPTY;
case "full": return FULL;
/*...*/
}
}
}
As long as you know which values come from python you would just convert them initially:
var fromPython:Type = /*...*/
var t:Type = fromPython.canonical;
then use t after that.
If you can't tell when things come from python and when they're from AS3 then it would get pretty messy, but if you have an isolation layer between the AS and python code you could just make sure you do the conversion there.
It's not as clean as if you could control the deserialization, but as long as you've got a good isolation layer it should work.
What I'd like to do is something like the following:
FooClass.prototype.method = function():String
{
return "Something";
}
var foo:FooClass = new FooClass();
foo.method();
Which is to say, I'd like to extend a generated class with a single method, not via inheritance but via the prototype.
The class is generated from a WSDL, it's not a dynamic class, and I don't want to touch the generated code because it will be overwritten anyway.
Long story short, I'd like to have the moral equivalent of C# 3:s Extension Methods for AS3.
Edit: I accepted aib's answer, because it fits what I was asking best -- although upon further reflection it doesn't really solve my problem, but that's my fault for asking the wrong question. :) Also, upmods for the good suggestions.
Yes, such a thing is possible.
In fact, your example is very close to the solution.
Try
foo["method"]();
instead of
foo.method();
#Theo: How would you explain the following working in 3.0.0.477 with the default flex-config.xml (<strict>true</strict>) and even a -compiler.strict parameter passed to mxmlc?
Foo.as:
package
{
public class Foo
{
public var foo:String;
public function Foo()
{
foo = "foo!";
}
}
}
footest.as:
package
{
import flash.display.Sprite;
public class footest extends Sprite
{
public function footest()
{
Foo.prototype.method = function():String
{
return "Something";
}
var foo:Foo = new Foo();
trace(foo["method"]());
}
}
}
Note that the OP said inheritance was unacceptable, as was modifying the generated code. (If that weren't the case, adding "dynamic" to the class definition would probably be the easiest solution.)
Depending on how many methods your class has, this may work:
Actual Class:
public class SampleClass
{
public function SampleClass()
{
}
public function method1():void {
Alert.show("Hi");
}
Quick Wrapper:
var actualClass:SampleClass = new SampleClass();
var QuickWrapper:Object = {
ref: actualClass,
method1: function():void {
this.ref.method1();
},
method2: function():void {
Alert.show("Hello!");
}
};
QuickWrapper.method1();
QuickWrapper.method2();
#aib is unfortunately incorrect. Assuming strict mode (the default compiler mode) it is not possible to modify the prototype of non-dynamic class types in ActionScript 3. I'm not even sure that it's possible in non-strict mode.
Is wrapping an option? Basically you create a class that takes one of the objects you get from the web service and just forwards all method calls to that, but also has methods of its own:
public class FooWrapper extends Foo {
private var wrappedFoo : Foo;
public function FooWrapper( foo : Foo ) {
wrappedFoo = foo;
}
override public function methodFromFoo( ) : void {
wrappedFoo.methodFromFoo();
}
override public function anotherMethodFromFoo( ) : void {
wrappedFoo.anotherMethodFromFoo();
}
public function newMethodNotOnFoo( ) : String {
return "Hello world!"
}
}
When you want to work with a Foo, but also have the extra method you need you wrap the Foo instance in a FooWrapper and work with that object instead.
It's not the most convenient solution, there's a lot of typing and if the generated code changes you have to change the FooWrapper class by hand, but unless you can modify the generated code either to include the method you want or to make the class dynamic I don't see how it can be done.
Another solution is to add a step to your build process that modifies the source of the generated classes. I assume that you already have a step that generates the code from a WSDL, so what you could do is to add a step after that that inserts the methods you need.
Monkey patching is an (inelegant) option.
For example, suppose you don't like the fact that Flex 3 SpriteAsset.as returns a default border metrics of [7,7,7,7] (unlike flex 2). To fix this, you can:
Create a copy of SpriteAsset.as and add it to your project at /mx/core/SpriteAsset.as
Edit your local copy to fix any problems you find
Run your ap
Google "flex monkey patch" for more examples and instructions.