puppeteer/test-d/NodeFor.test-d.ts
Joe Gomain Hoyes bef1061c06
feat(puppeteer-core): Infer element type from complex selector (#9253)
**What kind of change does this PR introduce?**

Better type inference.

**Did you add tests for your changes?**

~Not yet.~ Yes.

**If relevant, did you update the documentation?**

Not yet.

**Summary**

<!-- Explain the **motivation** for making this change. What existing
problem does the pull request solve? -->
<!-- Try to link to an open issue for more information. -->
Currently methods that return an element handle, i.e. `.$`,
`.waitForSelector` attempt to infer the node element type from the
selector string. However, this only works when the selector is an exact
match of the element tag, i.e. a selector `"a"` would be inferred as
`HTMLAnchorElement` . And not when the selector is complex, i.e.
selectors `"a#some-id"`, `div > a`, `a:nth-child(2)` would all fallback
on `Element`.

This is due to simply looking up the the selector in
`HTMLElementTagNameMap` and `SVGElementTagNameMap` without any attempt
to parse the selector string.

This PR is an attempt to do so.

**Does this PR introduce a breaking change?**

<!-- If this PR introduces a breaking change, please describe the impact
and a migration path for existing applications. -->
This could break existing incorrect assertions using the `as` keyword.

**Other information**

~This PR introduces a dependency on the `type-fest` package.~

This PR is far from complete (no tests, no docs). Put out early for
feedback and discussion.

Co-authored-by: Alex Rudenko <OrKoN@users.noreply.github.com>
2022-11-23 10:59:23 +01:00

145 lines
3.6 KiB
TypeScript

import type {NodeFor} from 'puppeteer';
import {expectType, expectNotType} from 'tsd';
declare const nodeFor: <Selector extends string>(
selector: Selector
) => NodeFor<Selector>;
{
{
expectType<HTMLAnchorElement>(nodeFor('a'));
expectNotType<Element>(nodeFor('a'));
}
{
expectType<HTMLAnchorElement>(nodeFor('a#ignored'));
expectNotType<Element>(nodeFor('a#ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('a.ignored'));
expectNotType<Element>(nodeFor('a.ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('a[ignored'));
expectNotType<Element>(nodeFor('a[ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('a:ignored'));
expectNotType<Element>(nodeFor('a:ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored a'));
expectNotType<Element>(nodeFor('ignored a'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored a#ignored'));
expectNotType<Element>(nodeFor('ignored a#ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored a.ignored'));
expectNotType<Element>(nodeFor('ignored a.ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored a[ignored'));
expectNotType<Element>(nodeFor('ignored a[ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored a:ignored'));
expectNotType<Element>(nodeFor('ignored a:ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored > a'));
expectNotType<Element>(nodeFor('ignored > a'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored > a#ignored'));
expectNotType<Element>(nodeFor('ignored > a#ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored > a.ignored'));
expectNotType<Element>(nodeFor('ignored > a.ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored > a[ignored'));
expectNotType<Element>(nodeFor('ignored > a[ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored > a:ignored'));
expectNotType<Element>(nodeFor('ignored > a:ignored'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored + a'));
expectNotType<Element>(nodeFor('ignored + a'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored ~ a'));
expectNotType<Element>(nodeFor('ignored ~ a'));
}
{
expectType<HTMLAnchorElement>(nodeFor('ignored | a'));
expectNotType<Element>(nodeFor('ignored | a'));
}
{
expectType<HTMLAnchorElement>(
nodeFor('ignored ignored > ignored + ignored | a#ignore')
);
expectNotType<Element>(
nodeFor('ignored ignored > ignored + ignored | a#ignore')
);
}
}
{
{
expectType<Element>(nodeFor(''));
}
{
expectType<Element>(nodeFor('#ignored'));
}
{
expectType<Element>(nodeFor('.ignored'));
}
{
expectType<Element>(nodeFor('[ignored'));
}
{
expectType<Element>(nodeFor(':ignored'));
}
{
expectType<Element>(nodeFor('ignored #ignored'));
}
{
expectType<Element>(nodeFor('ignored .ignored'));
}
{
expectType<Element>(nodeFor('ignored [ignored'));
}
{
expectType<Element>(nodeFor('ignored :ignored'));
}
{
expectType<Element>(nodeFor('ignored > #ignored'));
}
{
expectType<Element>(nodeFor('ignored > .ignored'));
}
{
expectType<Element>(nodeFor('ignored > [ignored'));
}
{
expectType<Element>(nodeFor('ignored > :ignored'));
}
{
expectType<Element>(nodeFor('ignored + #ignored'));
}
{
expectType<Element>(nodeFor('ignored ~ #ignored'));
}
{
expectType<Element>(nodeFor('ignored | #ignored'));
}
{
expectType<Element>(
nodeFor('ignored ignored > ignored ~ ignored + ignored | #ignored')
);
}
}