That's fine with me.

This week I'm starting to look at automated web browser tests (possibly
using Geb [1] as a layer over Selenium).  Plan is for Estatio to act as a
regression suite for Isis as a whole.  So no immediate rush my end.

Cheers
Dan


[1] http://www.gebish.org/


On 8 September 2013 08:35, GESCONSULTOR <[email protected]> wrote:

> For sure!
>
> Unless you or Jeremy plan to use it immediately let me check and improve
> it this week through some BDD features we must implement.
>
> Thanks,
>
> Oscar
>
>
> El 08/09/2013, a las 09:20, Dan Haywood <[email protected]>
> escribió:
>
> > Looks very good, Oscar, exactly the sort of thing that should be in the
> > framework, I think.
> >
> > Could you raise a ticket and provide a commit?  If you have the time,
> > perhaps you could also refactor the ToDo app to show its use?
> >
> > Many thanks
> >
> > Cheers
> > Dan
> >
> >
> >
> > On 7 September 2013 19:05, GESCONSULTOR - Óscar Bou
> > <[email protected]>wrote:
> >
> >>
> >> I've just been thinking about a way to avoid to define a Spec
> Transformer
> >> for every Entity class in the Domain.
> >>
> >> As it's just "infrastructure software", I thought that was "just
> enough".
> >>
> >> The attached code allows to use just one Spec Transformer when the Glue
> is
> >> written like this:
> >> -  the employee with name "PETER"
> >> - the employee named "PETER"
> >> - the property with reference "REF-001"
> >> - the property referenced "REF-001"
> >> - the product with id "PR-001"
> >>
> >> From there, we know that:
> >> - The Entity singular name is "employee" (so it can be obtained from the
> >> Isis Object Specifications, reinforcing the Ubiquitous Language use on
> BDD
> >> specifications).
> >> - We must search by name
> >> - The name must be PETER
> >>
> >>
> >>
> >> For using it, I must define a Glue like this one:
> >>
> >> Define a Glue like this one:
> >> @When("The company (employee with name \"[^\"]*\") has a role assigned")
> >> public void
> >>
> the_company_employee_with_name(@Transform(GenericIsisJdoTransformer.class)
> >> final  Employee employee) {
> >>   ...
> >> }
> >>
> >>
> >>
> >> First "proof-of-concept" code version follows this text.
> >>
> >> It can be improved in many ways, for allowing customization through
> >> inheritance, avoiding JDO through the use of the Apache Isis query
> methods,
> >> etc.
> >>
> >>
> >> But I would let you know, right to know if you think it can be useful.
> >>
> >> On this way, the only implemented classes  are the ones supporting the
> >> Glues (and only the Spec Transformers for more specific use cases).
> >>
> >>
> >> HTH,
> >>
> >> Oscar
> >>
> >>
> >>
> >>
> >>
> >> ---------------------
> >>
> >>
> >>
> >>
> >> package com.xms.framework.testing.integration.spectransformers;
> >>
> >> import java.util.HashMap;
> >> import java.util.Map;
> >> import java.util.regex.Matcher;
> >> import java.util.regex.Pattern;
> >>
> >> import javax.jdo.Query;
> >>
> >> import org.opensaml.artifact.InvalidArgumentException;
> >>
> >> import org.apache.isis.applib.DomainObjectContainer;
> >> import org.apache.isis.core.metamodel.spec.ObjectSpecification;
> >> import org.apache.isis.core.runtime.system.context.IsisContext;
> >> import org.apache.isis.core.specsupport.scenarios.ScenarioExecution;
> >> import
> >>
> org.apache.isis.objectstore.jdo.datanucleus.service.support.IsisJdoSupportImpl;
> >>
> >> /**
> >> * Requires the Gherkin's capture in the format '([entitySingularName]
> >> [(.+?)
> >> * name(d)|(.+?) reference|(.+?) id] \"[entityId]\")'.
> >> * <p>
> >> * For example:
> >> * <ul>
> >> * <li>the employee with name "PETER"</li>
> >> * <li>the employee named "PETER"</li>
> >> * <li>the property with reference "REF-001"</li>
> >> * <li>the property referenced "REF-001"</li>
> >> * <li>the product with id "PR-001"</li>
> >> * </ul>
> >> * <p>
> >> * For matching the first one we will need the following Gherkin regular
> >> * expression:
> >> * <ul>
> >> * <li>
> >> * \\@When("The company's (employee with name \"[^\"]*\") has a role
> >> assigned")</li>
> >> * </ul>
> >> * <p>
> >> * From there, we know that:
> >> * <ul>
> >> * <li>The Entity singular name is "employee".</li>
> >> * <li>We must search by name</li>
> >> * <li>The name must be PETER</li>
> >> * </ul>
> >> *
> >> */
> >> public class GenericIsisJdoTransformer extends
> >> NullRecognizingTransformer<Object> {
> >>
> >>    private static Map<String, ObjectSpecification>
> >> specificationsBySingularName;
> >>
> >>    /**
> >>     * Tries to obtain the Entity class name, id and search field from
> the
> >>     * Cucumber capture, and find it on the JDO Object Store.
> >>     *
> >>     * @see com.xms.framework.testing.integration.spectransformers.
> >>     *      NullRecognizingTransformer#transformNonNull(java.lang.String)
> >>     */
> >>    @Override
> >>    protected Object transformNonNull(final String capture) {
> >>
> >>        return this.findFromCapture(capture);
> >>
> >>    }
> >>
> >>    /**
> >>     * @param entityName
> >>     *            Name of the Entity specified on the Gherkin's capture.
> >>     * @return
> >>     */
> >>    private ObjectSpecification specificationOf(final String entityName)
> {
> >>
> >>        if (IsisJdoTransformer.specificationsBySingularName == null) {
> >>            IsisJdoTransformer.specificationsBySingularName = new
> >> HashMap<String, ObjectSpecification>();
> >>
> >>            for (final ObjectSpecification current :
> >> IsisContext.getSpecificationLoader().allSpecifications()) {
> >>
> >>
> >>
> IsisJdoTransformer.specificationsBySingularName.put(current.getSingularName().toLowerCase(),
> >> current);
> >>            }
> >>
> >>        }
> >>        return
> >>
> IsisJdoTransformer.specificationsBySingularName.get(entityName.toLowerCase());
> >>
> >>    }
> >>
> >>    private final Class<?> entityClassFrom(final String capture) {
> >>
> >>        // The Entity Id will be between "".
> >>        String entityName = "";
> >>
> >>        final String[] recognizedPatterns = { "( with name )", "( named
> >> )", "( with reference )", "( referenced )", "( with id )" };
> >>
> >>        for (final String currentPattern : recognizedPatterns) {
> >>            final Pattern p = Pattern.compile(currentPattern);
> >>            final Matcher m = p.matcher(capture);
> >>            if (m.find()) {
> >>                entityName = capture.substring(0, m.start());
> >>                break;
> >>            }
> >>        }
> >>
> >>        if (entityName == "") {
> >>            throw new InvalidArgumentException(String.format("Cannot find
> >> the entity's name on the capture %s. The format must be
> >> '([entitySingularName] [with name|with reference|named|referenced]
> >> \"[entityId]\")'", capture));
> >>        }
> >>
> >>        final ObjectSpecification specification =
> >> this.specificationOf(entityName);
> >>        if (specification == null) {
> >>            throw new InvalidArgumentException(String.format("There is no
> >> Entity registered in Isis with '%s' as it's singular name",
> entityName));
> >>        }
> >>        return specification.getCorrespondingClass();
> >>
> >>    }
> >>
> >>    /**
> >>     * @param capture
> >>     *            The Gherkin's capture
> >>     * @return
> >>     */
> >>    private final String filterFrom(final String capture) {
> >>        // Find by "name".
> >>        if (capture.matches("(.+?)name(.+?)")) {
> >>            return String.format("name==\"%s\"",
> >> this.entityIdFrom(capture));
> >>        }
> >>
> >>        // Find by "reference".
> >>        if (capture.matches("(.+?)reference(.+?)")) {
> >>            return String.format("reference==\"%s\"",
> >> this.entityIdFrom(capture));
> >>        }
> >>
> >>        // Find by "id".
> >>        if (capture.matches("(.+?)id(.+?)")) {
> >>            return String.format("id==\"%s\"",
> this.entityIdFrom(capture));
> >>        }
> >>
> >>        throw new InvalidArgumentException(String.format("The entity id
> >> has not been found on the capture '%s'. It must be between two \"
> >> characters.", capture));
> >>    }
> >>
> >>    private final Object entityIdFrom(final String capture) {
> >>        // The Entity Id will be between "".
> >>        final Pattern p = Pattern.compile("\"(.+?)\"");
> >>        final Matcher m = p.matcher(capture);
> >>        if (m.find()) {
> >>            return m.group().replace("\"", "");
> >>        } else {
> >>            throw new InvalidArgumentException(String.format("The entity
> >> id has not been found on the capture '%s'. It must be between two \"
> >> characters.", capture));
> >>        }
> >>    }
> >>
> >>    private final Object findFromCapture(final String capture) {
> >>
> >>        // Need to flush().
> >>        // The Entity can be created on the same transaction.
> >>        // If we don't flush() the changes, perhaps the entity have not
> >> been
> >>        // saved to the object store yet, and will not be found.
> >>
> >>
> ScenarioExecution.current().service(DomainObjectContainer.class).flush();
> >>
> >>        final Query query =
> >>
> ScenarioExecution.current().service(IsisJdoSupportImpl.class).getJdoPersistenceManager().newQuery();
> >>        query.setClass(this.entityClassFrom(capture));
> >>        query.setFilter(this.filterFrom(capture));
> >>        query.setUnique(true);
> >>
> >>        final Object result = query.execute();
> >>
> >>        return result;
> >>
> >>    }
> >> }
> >>
> >>
> >>
> >>
> >> ---------------------
> >>
> >>
> >>
> >>
> >>
> >> El 27/08/2013, a las 20:24, Kevin Meyer - KMZ <[email protected]>
> escribió:
> >>
> >>> Hi Jeremy,
> >>>
> >>> If I remember correctly, Dan has examples for overriding the "Finder"
> >>> methods in the ToDo demo / artefact that use JDO search classes to
> >>> build queries.
> >>>
> >>> In fact:
> >>>
> >>> In the  "ToDoItemsJdo" class (which extends an
> >>> AbstractFactoryAndRepository):
> >>>   // {{ notYetComplete (action)
> >>>   @Override
> >>>   protected List<ToDoItem> doNotYetComplete() {
> >>>       return allMatches(
> >>>               new QueryDefault<ToDoItem>(ToDoItem.class,
> >>>                       "todo_notYetComplete",
> >>>                       "ownedBy", currentUserName()));
> >>>   }
> >>>   // }}
> >>>
> >>> This appears in an old copy of the repo I have in the wicket JDO
> >>> quickstart project.
> >>>
> >>> So while you can't use "FindByPattern", JDO has implemented a
> >>> useful alternative.
> >>>
> >>> Regards,
> >>> Kevin
> >>>
> >>>
> >>> On 27 Aug 2013 at 14:37, Jeremy Gurr wrote:
> >>>
> >>>> I'm playing around with the cucumber support tools in isis (a testing
> >> framework for behavior driven development, for those who don't know),
> and
> >> have created a test that basically looks like this:
> >>>>
> >>>> <snip>
> >>>>
> >>>> It's very convenient that cucumber instantiates my ServiceClass model
> >> object and automatically plugs in fields according to the feature spec
> >> column header. This enables me to add new fields simply by adding a
> column
> >> in the spec, and adding the corresponding column in my model object. It
> >> skips the extra hassle of having to update the glue code as well as
> service
> >> methods to construct the object.
> >>>>
> >>>> The "exists" method contains this code:
> >>>>
> >>>> public boolean exists(ServiceClass serviceClass) {
> >>>> final QueryFindByPattern<ServiceClass> query = new
> >> QueryFindByPattern<ServiceClass>(ServiceClass.class, serviceClass);
> >>>> final ServiceClass firstMatch = firstMatch(query);
> >>>>
> >>>> return firstMatch != null;
> >>>> }
> >>>>
> >>>> I'm just trying to verify that an object exists with fields matching
> >> the incoming object, some fields of which may be null, meaning that they
> >> can be any value. The QueryFindByPattern class seemed to be a perfect
> fit
> >> since I'm passing around ServiceClass instances anyway. However,
> running it
> >> executes code that is not yet implemented:
> >>>>
> >>>> <snip>
> >>
> >>
>

Reply via email to