2

I'm looking for a way to create unique and deterministic test id's to be used for end-to-end testing. This would mean that running any iteration would produce the exact same id for the exact same component so that tests would have a reliable way to reference an item.

Starting with an example of applying a directive on every button:

@Directive({
    selector: 'button',
})
export class FormControlPropertiesDirective {

    constructor(
        private element: ElementRef,
    ) {
    }
}

Is there any way I could apply an algorithm or use some distinct property of the element to create something deterministic?

tareqx3
  • 561
  • 5
  • 24
  • Your question is way too broad. Please limit it to a single issue. Consider providing examples of what you're trying to achieve and what you have tried so far. –  Jun 28 '19 at 13:16
  • I don't feel the question is too broad, what i'm looking for is an automated way to mark elements with a unique test id attribute. So far I haven't found anything that remains constant through multiple passes of the angular application. – tareqx3 Jun 28 '19 at 13:39
  • So something like [HTML ID attribute](https://www.w3schools.com/tags/att_global_id.asp) ... –  Jun 28 '19 at 13:42
  • sure, an id attribute or an arbitrary attribute like [data-test-id], that will be used to target a specific element for end-to-end testing – tareqx3 Jun 28 '19 at 17:29

1 Answers1

0

If you manage to link your components to a certain model you could use an hash function over that model... an hash function like this (Taken from an answer from this question Simple (non-secure) hash function for JavaScript? and transformed it as a simple function):

 hashObject(o: any) {
    var l = 2;
    var i, c, r = [];
    for (i = 0; i < l; i++)
        r.push(i * 268803292);
    function stringify(o) {
        var i, r;
        if (o === null) return "n";
        if (o === true) return "t";
        if (o === false) return "f";
        if (o instanceof Date) return "d:" + o.toString();
        i = typeof o;
        if (i === "string") return "s:" + o.replace(/([\\\\;])/g, "\\$1");
        if (i === "number") return "n:" + o;
        if (o instanceof Function) return "m:" + o.toString().replace(/([\\\\;])/g, "\\$1");
        if (o instanceof Array) {
            r = [];
            for (i = 0; i < o.length; i++)
                r.push(stringify(o[i]));
            return "a:" + r.join(";");
        }
        r = [];
        for (i in o) {
            r.push(i + ":" + stringify(o[i]));
        }
        return "o:" + r.join(";");
    }
    o = stringify(o);
    for (i = 0; i < o.length; i++) {
        for (c = 0; c < r.length; c++) {
            r[c] = (r[c] << 13) - (r[c] >> 19);
            r[c] += o.charCodeAt(i) << (r[c] % 24);
            r[c] = r[c] & r[c];
        }
    }
    for (i = 0; i < r.length; i++) {
        r[i] = this.toHex(r[i]);
    }
    return r.join("");
}

  toHex(number: number): string {
        var ret = ((number < 0 ? 0x8 : 0) + ((number >> 28) & 0x7)).toString(16) + (number & 0xfffffff).toString(16);
        while (ret.length < 8) ret = "0" + ret;
        return ret;
    }

Or, if you really just need to generate test ids you could use faker.js (https://github.com/marak/Faker.js/). By providing a seed to its data generator you can obtain deterministic results

  • I like the faker implementation for seeding a result, the only unknown that remains for me is what to use as a seed. It should be something extractable from the targeted html element that does not ever change over multiple compiles/runs of the application. – tareqx3 Jun 28 '19 at 17:32