Skip to content

Commit

Permalink
Introduce a test package using stable/preview types
Browse files Browse the repository at this point in the history
This package intentionally does *not* have any of the runtime config or
dependencies; it only needs `ember-source` and the Glint packages to be
able to verify that type checking works correctly using the types
published as part of the `ember-source` package. An annoying exception:
we include the ESLint deps since we run ESLint from the root. We might
be able to fix that in the future, but for now this unblocks things.

This package also includes a check to make sure that this test package
is *not* accidentally (read: via incorrect dependency hoisting) getting
the DT types.
  • Loading branch information
chadhietala authored and chriskrycho committed Nov 23, 2022
1 parent dfcac1f commit 86975ef
Show file tree
Hide file tree
Showing 49 changed files with 696 additions and 6 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Compiled output
/packages/*/lib
/test-packages/*/lib
/packages/scripts/bin
dist/

Expand Down
9 changes: 9 additions & 0 deletions test-packages/ts-ember-app/app/components/ember-component.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
{{@required}}
{{@optional}}
{{@hasDefault}}

{{!--
This pair of checks needs to work in this app, which uses DT types, and the
preview/stable types app which does *not*.
--}}
{{get this "required"}}

{{! @glint-expect-error: non-existent property }}
{{get this "unrelated"}}
</div>

{{#if this.showFunctionHelpers}}
Expand Down
4 changes: 4 additions & 0 deletions test-packages/ts-ember-app/wat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { expectTypeOf } from 'expect-type';

import type { ComputedPropertyMarker } from '@ember/object/-private/types';
expectTypeOf<ComputedPropertyMarker<unknown>>().not.toBeUnknown();
25 changes: 25 additions & 0 deletions test-packages/ts-ember-preview-types/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# unconventional js
/blueprints/*/files/
/vendor/

# compiled output
/dist/
/tmp/

# dependencies
/bower_components/
/node_modules/

# misc
/coverage/
!.*
.*/
.eslintcache

# ember-try
/.node_modules.ember-try/
/bower.json.ember-try
/npm-shrinkwrap.json.ember-try
/package.json.ember-try
/package-lock.json.ember-try
/yarn.lock.ember-try
56 changes: 56 additions & 0 deletions test-packages/ts-ember-preview-types/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
legacyDecorators: true,
},
},
plugins: ['ember', '@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
env: {
browser: true,
},
rules: {
'@typescript-eslint/no-empty-interface': 'off',
},
overrides: [
// node files
{
files: [
'.eslintrc.js',
'.template-lintrc.js',
'ember-cli-build.js',
'testem.js',
'blueprints/*/index.js',
'config/**/*.js',
'lib/*/index.js',
'server/**/*.js',
],
parserOptions: {
sourceType: 'script',
},
env: {
browser: false,
node: true,
},
plugins: ['node'],
extends: ['plugin:node/recommended'],
rules: {
// this can be removed once the following is fixed
// https://github.com/mysticatea/eslint-plugin-node/issues/77
'node/no-unpublished-require': 'off',
'@typescript-eslint/no-var-requires': 'off',
},
},
],
};
3 changes: 3 additions & 0 deletions test-packages/ts-ember-preview-types/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ts-ember-preview-types

This application demonstrates the usage of glint in an Ember project with the Ember preview types.
12 changes: 12 additions & 0 deletions test-packages/ts-ember-preview-types/app/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Application from '@ember/application';
import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import config from 'ts-ember-app/config/environment';

export default class App extends Application {
modulePrefix = config.modulePrefix;
podModulePrefix = config.podModulePrefix;
Resolver = Resolver;
}

loadInitializers(App, config.modulePrefix);
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{this.name}}-{{@grault}}

{{! @glint-expect-error: invalid arg }}
{{@waldo}}
19 changes: 19 additions & 0 deletions test-packages/ts-ember-preview-types/app/components/bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// eslint-disable-next-line ember/no-classic-components
import Component from '@ember/component';

export interface BarSignature {
Args: {
grault: number;
};
}

// eslint-disable-next-line ember/require-tagless-components
export default class Bar extends Component<BarSignature> {
name = 'BAR';
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
Bar: typeof Bar;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<div ...attributes id={{unique-id}}>
{{this.required}}
{{this.optional}}
{{this.hasDefault}}

{{@required}}
{{@optional}}
{{@hasDefault}}

{{!--
This pair of checks needs to work in this app, which uses the preview/stable
types, and the ts-ember-app types app which uses legacy DT types.
--}}
{{get this "required"}}

{{! @glint-expect-error: non-existent property }}
{{get this "unrelated"}}
</div>

{{#if this.showFunctionHelpers}}
{{! @glint-expect-error: missing arg }}
{{this.isLongString}}

{{! @glint-expect-error: wrong arg type }}
{{this.isLongString 123}}

{{this.isLongString 'hi'}}
{{/if}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
import Component from '@ember/component';

export interface EmberComponentArgs {
required: string;
hasDefault?: string;
optional?: number;
}

export interface EmberComponentSignature {
Element: HTMLDivElement;
Args: EmberComponentArgs;
}

export default interface EmberComponent extends EmberComponentArgs {}
export default class EmberComponent extends Component<EmberComponentSignature> {
public hasDefault = 'defaultValue';
public showFunctionHelpers = false;

public isLongString(value: string): boolean {
return value.length > 5;
}

public checkTypes(): unknown {
const required: string = this.required;
const hasDefault: string = this.hasDefault;
const optional: number | undefined = this.optional;

return { required, hasDefault, optional };
}
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
EmberComponent: typeof EmberComponent;
'ember-component': typeof EmberComponent;
}
}
99 changes: 99 additions & 0 deletions test-packages/ts-ember-preview-types/app/components/foo.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{{this.name}}

{{! @glint-expect-error: invalid property }}
{{this.corge}}

<Bar @grault={{0}} />

<Bar
{{! @glint-expect-error: wrong type }}
@grault={{this.obj.a}}
/>

<Bar
{{! @glint-expect-error: bad arg }}
@fred={{2}}
/>

{{! @glint-expect-error: missing required arg }}
<Bar />

<Baz />

<Qux />

<this.MaybeComponent @arg="hi" />

{{! @glint-expect-error: missing required arg }}
<this.MaybeComponent />

{{! @glint-expect-error: missing required arg }}
<EmberComponent />

<EmberComponent @required="req" />

<EmberComponent
{{! @glint-expect-error: bad type for `required` }}
@required={{1}}
/>

<EmberComponent @required="req" @optional={{1}} />

<EmberComponent
@required="req"

{{! @glint-expect-error: bad type for `optional` }}
@optional="opt"
/>

<EmberComponent @required="req" @hasDefault="override" />

<EmberComponent
@required="req"

{{! @glint-expect-error: bad type for `hasDefault` }}
@hasDefault={{false}}
/>

<EmberComponent @required="hi">
{{! @glint-expect-error: bad named block }}
<:foo>hello</:foo>
</EmberComponent>

<WrapperComponent @value="req" as |WC|>
<WC.InnerComponent @optional={{1}} class="custom" />

{{! should work, even though MaybeComponent might not be present }}
<WC.MaybeComponent @key="hi" />

{{! @glint-expect-error: strings aren't invokable }}
<WC.stringValue />
</WrapperComponent>

{{repeat "foo" 3}}

{{! @glint-expect-error: missing second arg }}
{{repeat "foo"}}

{{! @glint-expect-error: incorrect type for second arg }}
{{repeat "foo" "bar"}}

{{affix "fuel" prefix="re" suffix="ing"}}

{{affix "fuel" prefix="re"}}

{{affix "fuel" suffix="ing"}}

{{affix "fuel"}}

{{! @glint-expect-error: missing positional arg }}
{{affix prefix="re" suffix="ing"}}

{{! @glint-expect-error: extra positional arg }}
{{affix "fuel" "up" prefix="re" suffix="ing"}}

{{! @glint-expect-error: incorrect type for named arg }}
{{affix "fuel" prefix=1 suffix="ing"}}

{{! @glint-expect-error: incorrect named arg given }}
{{affix "fuel" prefix="re" suff="ing"}}
17 changes: 17 additions & 0 deletions test-packages/ts-ember-preview-types/app/components/foo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
import Component from '@ember/component';
import { ComponentLike } from '@glint/template';

export default class Foo extends Component {
name = 'FOO';

obj = { a: 'A', b: 'B', c: 1, 𝚪: '' };

MaybeComponent?: ComponentLike<{ Args: { arg: string } }>;
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
Foo: typeof Foo;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{this.message}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Component from '@glimmer/component';

export default class MyComponent extends Component {
message = 'hi';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{! @glint-nocheck }}

{{this.nothing}}

<Bar />

{{repeat "foo"}}
12 changes: 12 additions & 0 deletions test-packages/ts-ember-preview-types/app/components/qux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-disable ember/no-classic-components, ember/require-tagless-components */
import Component from '@ember/component';

export default class Qux extends Component {
name = 'QUX';
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
Qux: typeof Qux;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{@message}}, world
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import templateOnlyComponent from '@ember/component/template-only';

interface TemplateOnlyModuleSignature {
Args: { message: string };
Blocks: { default: [] };
}

const TemplateOnlyModule = templateOnlyComponent<TemplateOnlyModuleSignature>();

export default TemplateOnlyModule;

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
TemplateOnlyModule: typeof TemplateOnlyModule;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Foo />

{{this}}

{{! @glint-expect-error }}
{{@foo}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello!
Loading

0 comments on commit 86975ef

Please sign in to comment.