Skip to content

Commit

Permalink
Merge pull request #108 from aurelia/vite
Browse files Browse the repository at this point in the history
vite+vitest setup
  • Loading branch information
3cp authored Aug 9, 2024
2 parents e2ec3f2 + 566497d commit f21e543
Show file tree
Hide file tree
Showing 27 changed files with 279 additions and 149 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/e2e-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
- latest,parcel,typescript
- latest,dumber,babel
- latest,dumber,typescript
- latest,vite,babel
- latest,vite,typescript
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node_version }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/e2e-macOS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
- latest,parcel,typescript
- latest,dumber,babel
- latest,dumber,typescript
- latest,vite,babel
- latest,vite,typescript
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node_version }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/e2e-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
- latest,parcel,typescript
- latest,dumber,babel
- latest,dumber,typescript
- latest,vite,babel
- latest,vite,typescript
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node_version }}
Expand Down
4 changes: 2 additions & 2 deletions __test__/before-task.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test('"before" task can select default-esnext preset', async t => {
const result = await before({unattended: false, prompts});
t.deepEqual(result, {
silentQuestions: true,
preselectedFeatures: ['app', 'webpack', 'babel', 'jest']
preselectedFeatures: ['app', 'vite', 'babel', 'vitest']
});
});

Expand All @@ -40,7 +40,7 @@ test('"before" task can select default-typescript preset', async t => {
const result = await before({unattended: false, prompts});
t.deepEqual(result, {
silentQuestions: true,
preselectedFeatures: ['app', 'webpack', 'typescript', 'jest']
preselectedFeatures: ['app', 'vite', 'typescript', 'vitest']
});
});

Expand Down
64 changes: 64 additions & 0 deletions __test__/transforms.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,67 @@ test.cb('ext-transform translates .ext file to .ts file when typescript is selec
contents: Buffer.from('<p></p>')
}));
});

test.cb('ext-transform translates css files to .module.css files when css-module is selected', t => {
const jsExt = extTransform({}, ['css-module']);
const files = [];

jsExt.pipe(new Writable({
objectMode: true,
write(file, enc, cb) {
files.push(file);
cb();
}
}));

jsExt.on('end', () => {
t.is(files.length, 2);
t.is(files[0].path.replace(/\\/g, '/'), 'test/a.module.css');
t.is(files[0].contents.toString(), '.p { color: green; }');
t.is(files[1].path.replace(/\\/g, '/'), 'test/b.module.scss');
t.is(files[1].contents.toString(), '.p { color: red; }');
t.end();
})

jsExt.write(new Vinyl({
path: 'test/a.css',
contents: Buffer.from('.p { color: green; }')
}));

jsExt.end(new Vinyl({
path: 'test/b.scss',
contents: Buffer.from('.p { color: red; }')
}));
});

test.cb('ext-transform leaves css files untouched files when css-module is not selected', t => {
const jsExt = extTransform({}, ['']);
const files = [];

jsExt.pipe(new Writable({
objectMode: true,
write(file, enc, cb) {
files.push(file);
cb();
}
}));

jsExt.on('end', () => {
t.is(files.length, 2);
t.is(files[0].path.replace(/\\/g, '/'), 'test/a.css');
t.is(files[0].contents.toString(), '.p { color: green; }');
t.is(files[1].path.replace(/\\/g, '/'), 'test/b.scss');
t.is(files[1].contents.toString(), '.p { color: red; }');
t.end();
})

jsExt.write(new Vinyl({
path: 'test/a.css',
contents: Buffer.from('.p { color: green; }')
}));

jsExt.end(new Vinyl({
path: 'test/b.scss',
contents: Buffer.from('.p { color: red; }')
}));
});
5 changes: 0 additions & 5 deletions app-min/e2e__if_playwright/app.spec.ext__if_not_plugin
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
// @if typescript
import { test, expect } from '@playwright/test';
// @endif
// @if babel
const { test, expect } = require('@playwright/test');
// @endif

test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:9000');
Expand Down
5 changes: 4 additions & 1 deletion app-min/test__if_not_no-unit-tests/my-app.spec.ext
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// @if mocha
import { expect } from 'chai';
// @endif
// @if vitest
import { describe, it, expect } from 'vitest';
// @endif
// @if shadow-dom
import { CustomElement } from 'aurelia';
// @endif
Expand All @@ -25,7 +28,7 @@ describe('my-app', () => {
// @if !shadow-dom
const text = node.textContent;
// @endif
// @if jasmine || jest
// @if jasmine || jest || vitest
expect(text.trim()).toBe('Hello World!');
// @endif
// @if mocha
Expand Down
11 changes: 8 additions & 3 deletions before.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// Use "before" task to ask user to select a preset (to skip questionnaire).

const PRESETS = {
'default-esnext': ['app', 'webpack', 'babel', 'jest'],
'default-typescript': ['app', 'webpack', 'typescript', 'jest'],
'default-esnext': ['app', 'vite', 'babel', 'vitest'],
'default-typescript': ['app', 'vite', 'typescript', 'vitest'],
// TODO: move plugin to vite+vitest
// FIXME: vite compiles plugin with separate css dist file, and removed
// import('./style.css') from js code, need to:
// 1. hook up a css loader in runtime for normal css and css-module.
// 2. hook up a text loader in runtime for shadow-dom css.
'default-esnext-plugin': ['plugin', 'webpack', 'babel', 'shadow-dom', 'jest'],
'default-typescript-plugin': ['plugin', 'webpack', 'typescript', 'shadow-dom', 'jest'],
};

const REQUIRE_NODEJS_VESION = [14, 15, 0];
const REQUIRE_NODEJS_VESION = [18, 0, 0];

function isNodejsOutdated() {
const version = process.version.slice(1).split('.');
Expand Down
2 changes: 2 additions & 0 deletions common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// @endif
// @if plugin
"description": "An Aurelia 2 plugin.",
// TODO: turn on after moved plugin to vite steup
// "type": "module",
"main": "dist/index.js",
"files": [
"dist"
Expand Down
6 changes: 3 additions & 3 deletions common/src/resource.d.ts__if_typescript
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ declare module '*.html' {
}

// @if css-module
declare module '*.css' {
declare module '*.module.css' {
const value: Record<string, string>;
export default value;
}
// @if less
declare module '*.less' {
declare module '*.module.less' {
const value: Record<string, string>;
export default value;
}
// @endif
// @if sass
declare module '*.scss' {
declare module '*.module.scss' {
const value: Record<string, string>;
export default value;
}
Expand Down
8 changes: 3 additions & 5 deletions dumber/gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,7 @@ function buildHtml(src) {
// standard DOM APIs in "closed" mode.
.pipe(au2({ defaultShadowOptions: { mode: 'open' }, hmr: false }));
// @endif
// @if css-module
.pipe(au2({ useCSSModule: true, hmr: false }));
// @endif
// @if !shadow-dom && !css-module
// @if !shadow-dom
.pipe(au2({ hmr: false }));
// @endif
}
Expand Down Expand Up @@ -177,7 +174,8 @@ function buildCss(src) {
// improve compatibility on svg.
postcssUrl({ url: 'inline', encodeType: 'base64' })
]))/* @if css-module */
.pipe(cssModule())/* @endif */;
// Use .module.css naming convention
.pipe(gulpif(f => f.basename.endsWith('.module.css'), cssModule()))/* @endif */;
}

function build() {
Expand Down
47 changes: 12 additions & 35 deletions e2e-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
// Have to run "npm run test:e2e" manually before a release.

const spawn = require('cross-spawn');
const os = require('os');
const fs = require('fs');
const path = require('path');
const test = require('ava');
const puppeteer = require('puppeteer');
const kill = require('tree-kill');
const {possibleFeatureSelections} = require('makes');
const questions = require('./questions');
Expand All @@ -24,7 +22,7 @@ const allSkeletons = possibleFeatureSelections(questions);

const isWin32 = process.platform === 'win32';

const folder = path.join(os.tmpdir(), 'test-skeletons');
const folder = path.join(__dirname, 'test-skeletons');
console.log('-- cleanup ' + folder);
fs.rmSync(folder, {recursive: true, force: true});
fs.mkdirSync(folder);
Expand All @@ -40,7 +38,7 @@ function killProc(proc) {
kill(proc.pid);
}

function run(command, dataCB, errorCB) {
function run(command, cwd, dataCB, errorCB) {
const [cmd, ...args] = command.split(' ');
return new Promise((resolve, reject) => {
const env = Object.create(process.env);
Expand All @@ -49,7 +47,7 @@ function run(command, dataCB, errorCB) {
// need to reset NODE_ENV back to development because this whole
// test is running in NODE_ENV=test which will affect gulp build
env.NODE_ENV = 'development';
const proc = spawn(cmd, args, {env});
const proc = spawn(cmd, args, {env, cwd});
proc.on('exit', async (code, signal) => {
await delay(1);
if (code && signal !== 'SIGTERM' && !win32Killed.has(proc.pid)) {
Expand Down Expand Up @@ -85,15 +83,6 @@ function run(command, dataCB, errorCB) {
});
}

async function takeScreenshot(url, filePath) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
await new Promise(r => setTimeout(r, 6000));
await page.screenshot({path: filePath});
await browser.close();
}

const targetFeatures = (process.env.TARGET_FEATURES || '').toLowerCase().split(',').filter(p => p);
if (!targetFeatures.includes('playwright')) {
targetFeatures.push('playwright');
Expand All @@ -111,6 +100,7 @@ if (targetFeatures.length) {
function getServerRegex(features) {
if (features.includes('webpack')) return /Loopback: (\S+)/;
if (features.includes('parcel')) return /Server running at (\S+)/;
if (features.includes('vite')) return /(http:\/\/\S+\/)/;
return /Dev server is started at: (\S+)/;
}

Expand All @@ -126,26 +116,24 @@ skeletons.forEach((features, i) => {

test.serial(title, async t => {
console.log(title);
process.chdir(folder);

const makeCmd = `npx makes ${__dirname} ${appName} -s ${features.join(',')}`;
console.log('-- ' + makeCmd);
await run(makeCmd);
await run(makeCmd, folder);
t.pass('made skeleton');
process.chdir(appFolder);

console.log('-- npm i');
await run('npm i');
await run('npm i', appFolder);
t.pass('installed deps');

if (!features.includes('no-unit-tests')) {
console.log('-- npm test');
await run('npm test');
await run('npm test', appFolder);
t.pass('finished unit tests');
}

console.log('-- npm run build');
await run('npm run build', null,
await run('npm run build', appFolder, null,
(data, kill) => {
// Skip parcel warnings.
if (features.includes('parcel')) return;
Expand All @@ -164,32 +152,21 @@ skeletons.forEach((features, i) => {
if (!m) return;
const url = m[1];
t.pass(m[0]);

try {
if (!process.env.GITHUB_ACTIONS) {
console.log('-- take screenshot');
await takeScreenshot(url, path.join(folder, appName + '.png'));
}
kill();
} catch (e) {
t.fail(e.message);
kill();
}
kill();
};

// Webpack5 now prints Loopback: http://localhost:5000 in stderr!
await run('npm start', runE2e, runE2e);
await run('npm start', appFolder, runE2e, runE2e);

if (features.includes('playwright')) {
console.log('-- npx playwright test --project chromium');
await run('npx playwright install --with-deps');
await run('npx playwright test --project chromium');
await run('npx playwright install --with-deps', appFolder);
await run('npx playwright test --project chromium', appFolder);
}

await delay(1);

console.log('-- remove folder ' + appName);
process.chdir(folder);
await fs.promises.rm(appFolder, {recursive: true});
});
});
10 changes: 2 additions & 8 deletions jest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,15 @@
// @if shadow-dom
"\\.(js|html)$": [ "@aurelia/babel-jest", { defaultShadowOptions: { mode: 'open' } } ]
// @endif
// @if css-module
"\\.(js|html)$": [ "@aurelia/babel-jest", { useCSSModule: true } ]
// @endif
// @if !shadow-dom && !css-module
// @if !shadow-dom
"\\.(js|html)$": "@aurelia/babel-jest",
// @endif
// @endif
// @if typescript
// @if shadow-dom
"\\.(ts|html)$": [ "@aurelia/ts-jest", { defaultShadowOptions: { mode: 'open' } } ]
// @endif
// @if css-module
"\\.(ts|html)$": [ "@aurelia/ts-jest", { useCSSModule: true } ]
// @endif
// @if !shadow-dom && !css-module
// @if !shadow-dom
"\\.(ts|html)$": "@aurelia/ts-jest",
// @endif
// @endif
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"glob": "^10.3.1",
"makes": "^3.2.0",
"npm-check-updates": "^16.10.13",
"puppeteer": "^20.7.3",
"semver": "^7.5.3",
"standard-changelog": "^3.0.0",
"tree-kill": "^1.2.2",
Expand Down
2 changes: 1 addition & 1 deletion parcel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ By Parcel2 conventions, the `index.html` is in `src/` folder.

## Aurelia 2 config

To control the behaviour of ShadownDOM and CSS-Module setup in Aurelia 2, create a section `"aurelia"` in the `package.json` file.
To control the behaviour of ShadownDOM in Aurelia 2, create a section `"aurelia"` in the `package.json` file.
https://www.npmjs.com/package/@aurelia/parcel-transformer
Loading

0 comments on commit f21e543

Please sign in to comment.