-
Notifications
You must be signed in to change notification settings - Fork 192
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
Prevent #1688 (and other accidental prettier breakages) #1689
base: main
Are you sure you want to change the base?
Changes from 11 commits
bcf1cd3
07347e6
67841dc
0e3dde1
dcebdb4
42ee4d0
4554a5a
85685a9
b22bc20
41c9a7b
e484f96
ba76cdb
ddd5f2b
2d05f5a
5de9010
05069ee
c31c56d
ebf3909
8074cd1
b161bc5
09d3fc0
3207df8
e6c337d
1003ff5
75061ca
5455815
4a89ee9
8206d97
3e14e23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "@glimmer-workspace/integration-node-tests", | ||
"version": "0.92.0", | ||
"type": "module", | ||
"private": true, | ||
"repo-meta": { | ||
"strictness": "loose", | ||
"lint": [ | ||
"test/**/*" | ||
] | ||
}, | ||
"scripts": { | ||
"test:lint": "eslint . --quiet", | ||
"test:node": "vitest --run" | ||
}, | ||
"dependencies": { | ||
"@glimmer/syntax": "workspace:*", | ||
"execa": "^9.5.2", | ||
"prettier": "^3.4.2" | ||
}, | ||
"devDependencies": { | ||
"vitest": "^3.0.4" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
import { mkdtemp, readFile, writeFile } from 'node:fs/promises'; | ||
import { createRequire } from 'node:module'; | ||
import os from 'node:os'; | ||
import { join } from 'node:path'; | ||
|
||
import { $ } from 'execa'; | ||
import * as prettier from 'prettier'; | ||
import { describe, expect, it } from 'vitest'; | ||
|
||
const monorepoRoot = join(import.meta.dirname, '../../../../'); | ||
const require = createRequire(import.meta.url); | ||
|
||
/** | ||
* See: https://github.com/glimmerjs/glimmer-vm/issues/1688 | ||
* | ||
* Requires the root package.json#pnpm#overrides point at our internal | ||
* copy of @glimmer/syntax, or else prettier brings its own already published | ||
* copy of @glimmer/syntax | ||
*/ | ||
describe('Prettier', () => { | ||
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. Love having formal prettier tests. |
||
it(`SANITY: we've symlinked to the in-repo copy of @glimmer/syntax`, () => { | ||
NullVoxPopuli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let workspacePath = require.resolve('@glimmer/syntax'); | ||
let prettierPath = require.resolve('prettier'); | ||
let prettierGlimmer = require.resolve('@glimmer/syntax', { paths: [prettierPath] }); | ||
|
||
expect(prettierGlimmer).toBe(workspacePath); | ||
}); | ||
|
||
it('Underlynig preprocess API works', async () => { | ||
let result = (await import('@glimmer/syntax')).preprocess('<h1></h1>'); | ||
|
||
expect(result, `It can be await import()'d, and doesn't error`).toBeTruthy(); | ||
}); | ||
|
||
it('Prettier can call preprocess', async () => { | ||
let result = await prettier.format(` <div>\n</div>`, { parser: 'glimmer' }); | ||
|
||
expect(result).toMatchInlineSnapshot(` | ||
"<div> | ||
</div>" | ||
`); | ||
}); | ||
|
||
/** | ||
* This is important because we don't test the code we ship to npm | ||
* (the code we ship to npm goes through a build process, and we opted | ||
* to not do that for in-repo dev ergonomics) | ||
* | ||
* Process: | ||
* 1. build @glimmer/syntax (and dependencies) | ||
* 2. creat a tmp folder | ||
* 3. create a project in that tmp folder | ||
* 4. pack and add the tarballs to the project | ||
* 5. See if a basic import and call to pre-process works | ||
*/ | ||
it('Uses the real build, and not our monorepo infra', { timeout: 20_000 }, async () => { | ||
/** | ||
* pnpm packs tgz's with the name format ${hyphenated-package-name}-${version}.tgz | ||
*/ | ||
async function versionOf(name) { | ||
let manifestPath = join(monorepoRoot, 'packages', name, 'package.json'); | ||
let manifestString = await readFile(manifestPath); | ||
return JSON.parse(manifestString.toString()).version; | ||
} | ||
|
||
let tarballs = { | ||
NullVoxPopuli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
syntax: `glimmer-syntax-${await versionOf('@glimmer/syntax')}`, | ||
util: `glimmer-util-${await versionOf('@glimmer/util')}`, | ||
wireFormat: `glimmer-wire-format-${await versionOf('@glimmer/wire-format')}`, | ||
}; | ||
|
||
let file = `console.log((await import('@glimmer/syntax')).preprocess('<h1></h1>'));`; | ||
let manifest = JSON.stringify({ | ||
name: 'real-test', | ||
type: 'module', | ||
private: true, | ||
devDependencies: { | ||
'@glimmer/syntax': `file://./${tarballs.syntax}`, | ||
NullVoxPopuli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'@glimmer/util': `file://./${tarballs.util}`, | ||
'@glimmer/wire-format': `file://./${tarballs.wireFormat}`, | ||
}, | ||
pnpm: { | ||
overrides: { | ||
'@glimmer/syntax': `file://./${tarballs.syntax}.tgz`, | ||
'@glimmer/util': `file://./${tarballs.util}.tgz`, | ||
'@glimmer/wire-format': `file://./${tarballs.wireFormat}.tgz`, | ||
}, | ||
}, | ||
}); | ||
|
||
async function newTmpDir() { | ||
const tmpDir = await mkdtemp( | ||
join(os.tmpdir(), `glimmer-node-integration-testing-${Date.now()}-`) | ||
); | ||
|
||
return tmpDir; | ||
} | ||
|
||
function inDir(dir: string, cmd: string, options = {}) { | ||
return $({ cwd: dir, preferLocal: true, shell: true, ...options })(cmd); | ||
} | ||
function inRoot(cmd: string) { | ||
return inDir(monorepoRoot, cmd); | ||
} | ||
|
||
function inTmp(cmd: string, options = {}) { | ||
return inDir(tmp, cmd, options); | ||
} | ||
|
||
////////// | ||
// 1 build | ||
// When turbo is set up with "dependsOn": "["^prepack"], we see these packages | ||
// - @glimmer/syntax | ||
// - @glimmer/util | ||
// - @glimmer/wire-format | ||
// | ||
// So these 3 packages need to be packed and installed | ||
await inRoot(`pnpm turbo --filter "@glimmer/syntax" prepack`); | ||
|
||
////////// | ||
// 2 create a space that doesn't mess up the repo | ||
let tmp = await newTmpDir(); | ||
|
||
// eslint-disable-next-line no-console | ||
console.debug(`Project can be inspected at ${tmp}`); | ||
|
||
////////// | ||
// 3 create a project that represents real consumer usage | ||
await writeFile(join(tmp, 'package.json'), manifest); | ||
await writeFile(join(tmp, 'index.js'), file); | ||
|
||
////////// | ||
// 4 install the tarballs using stable names so we don't have to | ||
// dynamically build the package.json | ||
let packToTemp = `pnpm pack --pack-destination ${tmp}`; | ||
NullVoxPopuli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
await inDir(join(monorepoRoot, 'packages/@glimmer/syntax'), packToTemp); | ||
await inDir(join(monorepoRoot, 'packages/@glimmer/util'), packToTemp); | ||
await inDir(join(monorepoRoot, 'packages/@glimmer/wire-format'), packToTemp); | ||
await inTmp(`pnpm install`); | ||
|
||
////////// | ||
// 5 does it work? | ||
// | ||
// NOTE: dev isn't allowed because it requires that @glimmer/env be compiled away | ||
// let dev = await inTmp(`node --conditions="development" index.js`); | ||
// | ||
let prod = await inTmp(`node --conditions="production" index.js`); | ||
// should also be prod, as dev won't work without a build system | ||
let defaultConditions = await inTmp(`node index.js`); | ||
|
||
expect(prod.stdout).toMatchInlineSnapshot(` | ||
"{ | ||
type: 'Template', | ||
body: [ | ||
{ | ||
type: 'ElementNode', | ||
path: [Object], | ||
attributes: [], | ||
modifiers: [], | ||
params: [], | ||
comments: [], | ||
children: [], | ||
openTag: [j], | ||
closeTag: [j], | ||
loc: [j], | ||
tag: [Getter/Setter], | ||
blockParams: [Getter/Setter], | ||
selfClosing: [Getter/Setter] | ||
} | ||
], | ||
blockParams: [], | ||
loc: j { | ||
data: J { source: [tt], hbsPositions: [Object], kind: 'HbsPosition' }, | ||
isInvisible: false | ||
} | ||
}" | ||
`); | ||
// expect(dev.stdout).toMatchInlineSnapshot(); | ||
expect(defaultConditions.stdout).toMatchInlineSnapshot(` | ||
"{ | ||
type: 'Template', | ||
body: [ | ||
{ | ||
type: 'ElementNode', | ||
path: [Object], | ||
attributes: [], | ||
modifiers: [], | ||
params: [], | ||
comments: [], | ||
children: [], | ||
openTag: [j], | ||
closeTag: [j], | ||
loc: [j], | ||
tag: [Getter/Setter], | ||
blockParams: [Getter/Setter], | ||
selfClosing: [Getter/Setter] | ||
} | ||
], | ||
blockParams: [], | ||
loc: j { | ||
data: J { source: [tt], hbsPositions: [Object], kind: 'HbsPosition' }, | ||
isInvisible: false | ||
} | ||
}" | ||
`); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,8 +14,8 @@ export function assertPresent<T>(value: T, message?: string): asserts value is P | |
} | ||
} | ||
|
||
export function isPresentArray<T>(list: readonly T[]): list is PresentArray<T> { | ||
return list.length > 0; | ||
export function isPresentArray<T>(list?: readonly T[]): list is PresentArray<T> { | ||
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. Hm... what uses 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. nothing -- it's a minification bug! input: private matchFor(
left: OffsetKind,
right: OffsetKind
): (left: PositionData, right: PositionData) => Out {
const nesteds = this._whens.match(left);
localAssert(
isPresentArray(nesteds),
`no match defined for (${left}, ${right}) and no AnyMatch defined either`
);
const callback = new WhenList(nesteds).first(right);
localAssert(
callback !== null,
`no match defined for (${left}, ${right}) and no AnyMatch defined either`
);
return callback;
} output: matchFor(t, e) {
const s = this._whens.match(t);
return P(), new I(s).first(e);
} |
||
return list ? list.length > 0 : false; | ||
} | ||
|
||
export function ifPresent<T, U, V>( | ||
|
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.
nothing was calling
test:node
prior to this PR, and run-node-tests called globalember
, which isn't used in CI