-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start testing component compilation #154
Changes from all commits
77eb8c3
1a38eb3
3ea81fa
ac4cb2a
e20f37a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Editors may run prettier per-workspace, which would ignore | ||
# the top-level workspaces' prettier config. | ||
fixtures/ |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,106 @@ | ||||||||||||||||||||||
import { execa } from 'execa'; | ||||||||||||||||||||||
import fs from 'node:fs/promises'; | ||||||||||||||||||||||
import path from 'node:path'; | ||||||||||||||||||||||
import { afterEach, beforeEach, describe, it } from 'vitest'; | ||||||||||||||||||||||
|
||||||||||||||||||||||
import { AddonFixtureHelper } from '../fixture-helper.js'; | ||||||||||||||||||||||
import { createAddon, createTmp, install } from '../utils.js'; | ||||||||||||||||||||||
|
||||||||||||||||||||||
let packageManager = 'pnpm'; | ||||||||||||||||||||||
|
||||||||||||||||||||||
describe('components (build)', () => { | ||||||||||||||||||||||
describe('co-located JS', () => { | ||||||||||||||||||||||
let cwd = ''; | ||||||||||||||||||||||
let tmpDir = ''; | ||||||||||||||||||||||
let addonOnlyJS: AddonFixtureHelper; | ||||||||||||||||||||||
|
||||||||||||||||||||||
beforeEach(async () => { | ||||||||||||||||||||||
tmpDir = await createTmp(); | ||||||||||||||||||||||
|
||||||||||||||||||||||
console.debug(`Debug test repo at ${tmpDir}`); | ||||||||||||||||||||||
|
||||||||||||||||||||||
let { name } = await createAddon({ | ||||||||||||||||||||||
args: [`--pnpm=true`, '--addon-only'], | ||||||||||||||||||||||
options: { cwd: tmpDir }, | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
cwd = path.join(tmpDir, name); | ||||||||||||||||||||||
Comment on lines
+22
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit, and unrelated to this PR really, but as I'm seeing this code here...
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
addonOnlyJS = new AddonFixtureHelper({ | ||||||||||||||||||||||
cwd, | ||||||||||||||||||||||
packageManager: 'pnpm', | ||||||||||||||||||||||
scenario: 'addon-only-js', | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
await install({ cwd, packageManager, skipPrepare: true }); | ||||||||||||||||||||||
|
||||||||||||||||||||||
// NOTE: This isn't needed to make the tests pass atm, but it would be | ||||||||||||||||||||||
// required when consumers try to use these compiled components | ||||||||||||||||||||||
await execa('pnpm', ['add', '--save-peer', '@glimmer/component'], { cwd }); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
afterEach(async () => { | ||||||||||||||||||||||
fs.rm(tmpDir, { recursive: true, force: true }); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
it('generates correct files with no template', async () => { | ||||||||||||||||||||||
await addonOnlyJS.use('src/components/no-template.js'); | ||||||||||||||||||||||
await addonOnlyJS.build(); | ||||||||||||||||||||||
await addonOnlyJS.matches('dist/components/no-template.js'); | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tbh I am not sure if I would want these kind of snapshot tests against dist-output. Wouldn't these test become super brittle? Like you could update something rollup or babel dependency, which makes the out put slightly different but still perfectly valid, but still you would have tests failing. Especially annoying if you have to fix renovate PRs by hand all the time... I do see value for fixture-based tests for all the blueprint-generated files, especially those whose content cannot be covered by smoke tests, like e.g. correct path, package manager calls etc. in the generated But for the dist-output we don't have to care what the content really is, we only need to care if it works as expected. And we could cover this by making our smoke tests more detailed, like having different forms of components (TO, colocated, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, these are good points -- my thinking with these tests is that they'd be faster than full smoke tests. But maybe it's still worth it? I will adjust to more e2e-style |
||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
it('generates correct files with a template', async () => { | ||||||||||||||||||||||
await addonOnlyJS.use('src/components/co-located.js'); | ||||||||||||||||||||||
await addonOnlyJS.use('src/components/co-located.hbs'); | ||||||||||||||||||||||
await addonOnlyJS.build(); | ||||||||||||||||||||||
await addonOnlyJS.matches('dist/components/co-located.js'); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
describe('co-located TS', () => { | ||||||||||||||||||||||
let cwd = ''; | ||||||||||||||||||||||
let tmpDir = ''; | ||||||||||||||||||||||
let addonOnlyTS: AddonFixtureHelper; | ||||||||||||||||||||||
|
||||||||||||||||||||||
beforeEach(async () => { | ||||||||||||||||||||||
tmpDir = await createTmp(); | ||||||||||||||||||||||
|
||||||||||||||||||||||
console.debug(`Debug test repo at ${tmpDir}`); | ||||||||||||||||||||||
|
||||||||||||||||||||||
let { name } = await createAddon({ | ||||||||||||||||||||||
args: [`--pnpm=true`, '--addon-only', '--typescript'], | ||||||||||||||||||||||
options: { cwd: tmpDir }, | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
cwd = path.join(tmpDir, name); | ||||||||||||||||||||||
|
||||||||||||||||||||||
addonOnlyTS = new AddonFixtureHelper({ | ||||||||||||||||||||||
cwd, | ||||||||||||||||||||||
packageManager: 'pnpm', | ||||||||||||||||||||||
scenario: 'addon-only-ts', | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
await install({ cwd, packageManager, skipPrepare: true }); | ||||||||||||||||||||||
await execa('pnpm', ['add', '--save-peer', '@glimmer/component'], { cwd }); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
afterEach(async () => { | ||||||||||||||||||||||
fs.rm(tmpDir, { recursive: true, force: true }); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
it('generates correct files with no template', async () => { | ||||||||||||||||||||||
await addonOnlyTS.use('src/components/no-template.ts'); | ||||||||||||||||||||||
await addonOnlyTS.build(); | ||||||||||||||||||||||
await addonOnlyTS.matches('dist/components/no-template.js'); | ||||||||||||||||||||||
await addonOnlyTS.matches('declarations/components/no-template.d.ts'); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
|
||||||||||||||||||||||
it('generates correct files with a template', async () => { | ||||||||||||||||||||||
await addonOnlyTS.use('src/components/co-located.ts'); | ||||||||||||||||||||||
await addonOnlyTS.use('src/components/co-located.hbs'); | ||||||||||||||||||||||
await addonOnlyTS.build(); | ||||||||||||||||||||||
await addonOnlyTS.matches('dist/components/co-located.js'); | ||||||||||||||||||||||
await addonOnlyTS.matches('declarations/components/co-located.d.ts'); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
}); | ||||||||||||||||||||||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { matchesFixture } from './assertions.js'; | ||
import { copyFixture, runScript } from './utils.js'; | ||
|
||
export class AddonFixtureHelper { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't want to overcomplicate things, but with #151 providing some testing infrastructure, should't this file and Another though here, and I am totally fine ignoring this for now, like doing later or not doing at all, but given we have a more elaborate testing class here (i.e. it own some state), does it make sense to integrate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes! I will move it over there -- I have a fear of making PRs too big -- especially when utils-prs really need usages to see how the utils will be used / what their purpose is.
I really like this idea 🎉 will do |
||
#cwd: string; | ||
#scenario: string; | ||
#packageManager: 'npm' | 'pnpm' | 'yarn'; | ||
|
||
constructor(options: { | ||
cwd: string; | ||
scenario?: string; | ||
packageManager: 'pnpm' | 'npm' | 'yarn'; | ||
}) { | ||
this.#cwd = options.cwd; | ||
this.#scenario = options.scenario || 'default'; | ||
this.#packageManager = options.packageManager; | ||
} | ||
|
||
async use(file: string) { | ||
await copyFixture(file, { scenario: this.#scenario, cwd: this.#cwd }); | ||
} | ||
|
||
async build() { | ||
await runScript({ cwd: this.#cwd, script: 'build', packageManager: this.#packageManager }); | ||
} | ||
|
||
async matches(outputFile: string) { | ||
await matchesFixture(outputFile, { scenario: this.#scenario, cwd: this.#cwd }); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{{this.someGetter}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Component from '@glimmer/component'; | ||
|
||
export class CoLocated extends Component { | ||
get someGetter() { | ||
return 'someGetter'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Component from '@glimmer/component'; | ||
|
||
export class NoTemplate extends Component { | ||
get someGetter() { | ||
return 'someGetter'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Component from '@glimmer/component'; | ||
interface Signature { | ||
Args: {}; | ||
Blocks: { | ||
default: []; | ||
}; | ||
} | ||
export default class CoLocated extends Component<Signature> { | ||
get someGetter(): string; | ||
} | ||
export {}; | ||
//# sourceMappingURL=co-located.d.ts.map |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Component from '@glimmer/component'; | ||
interface Signature { | ||
Args: {}; | ||
Blocks: {}; | ||
} | ||
export declare class NoTemplate extends Component<Signature> { | ||
get someGetter(): string; | ||
} | ||
export {}; | ||
//# sourceMappingURL=no-template.d.ts.map |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{{this.someGetter}} | ||
|
||
{{yield}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Component from '@glimmer/component'; | ||
|
||
interface Signature { | ||
Args: {}, | ||
Blocks: { default: [] } | ||
} | ||
|
||
export default class CoLocated extends Component<Signature> { | ||
get someGetter() { | ||
return 'someGetter'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Component from '@glimmer/component'; | ||
|
||
interface Signature { | ||
Args: {}, | ||
Blocks: {} | ||
} | ||
|
||
export class NoTemplate extends Component<Signature> { | ||
get someGetter() { | ||
return 'someGetter'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,5 +7,6 @@ | |
|
||
// Vite's internal types aren't relevant to us | ||
"skipLibCheck": true | ||
} | ||
}, | ||
"exclude": ["fixtures/"] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we doing this for
addon-only
here? When setting up new tests, shouldn't we just start with the default scenario first?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
related to here i was focusing on compiled output, rather than e2e "workingness", if that makes sense -- I'm going to shift to the default scenario tho, and make sure that each type of component can be rendered in the test-app