Skip to content

Commit

Permalink
feat: add vitest for plugin test
Browse files Browse the repository at this point in the history
  • Loading branch information
sanyuan0704 committed Sep 10, 2022
1 parent 92fbacf commit b189299
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 24 deletions.
6 changes: 4 additions & 2 deletions package.json
Expand Up @@ -11,7 +11,8 @@
"start:node": "cd src/node && tsc -w",
"dev:playground": "node ./bin/island playground",
"build:playground": "node ./bin/island build playground",
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx --quiet ./"
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx --quiet ./",
"test": "vitest run"
},
"keywords": [],
"author": "",
Expand Down Expand Up @@ -81,6 +82,7 @@
"typescript": "^4.7.4",
"unified": "^10.1.2",
"unist-util-visit": "^4.1.1",
"vite-plugin-inspect": "^0.6.1"
"vite-plugin-inspect": "^0.6.1",
"vitest": "^0.23.1"
}
}
125 changes: 125 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/client/app/client-entry.tsx
@@ -1,6 +1,6 @@
import { hydrateRoot, createRoot } from 'react-dom/client';
import React, { createElement } from 'react';
import { BrowserRouter, useLocation } from 'react-router-dom';
import React, { ComponentType, createElement } from 'react';
import { BrowserRouter } from 'react-router-dom';
import './sideEffects';
import { DataContext } from './hooks';

Expand Down
48 changes: 48 additions & 0 deletions src/node/__tests__/babel-plugin-island.test.ts
@@ -0,0 +1,48 @@
import { expect, describe, test } from 'vitest';
import { transformAsync, TransformOptions } from '@babel/core';
import babelPluginIsland from '../babel-plugin-island';
import { MASK_SPLITTER } from '../constants';

describe('test babel-plugin-island', () => {
const ISLAND_PATH = '../Comp/index';
const IMPORTER_PATH = '/User/code/project/test.tsx';
const babelOptions: TransformOptions = {
filename: IMPORTER_PATH,
presets: ['@babel/preset-react'],
plugins: [babelPluginIsland]
};
test('Should compile jsx identifier', async () => {
const code = `import A from '${ISLAND_PATH}'; export default function App() { return <A __island>hello</A>; }`;
const result = await transformAsync(code, babelOptions);
expect(result?.code).toContain(
`__island: "${ISLAND_PATH}${MASK_SPLITTER}${IMPORTER_PATH}"`
);
});

test('Should compile jsx member expression', async () => {
const code = `import A from '${ISLAND_PATH}'; export default function App() { return <A.B __island>hello</A.B>; }`;
const result = await transformAsync(code, babelOptions);
expect(result?.code).toContain(
`__island: "${ISLAND_PATH}${MASK_SPLITTER}${IMPORTER_PATH}"`
);
});

test('Should compile jsx namespace expression', async () => {
const code = `import * as A from '${ISLAND_PATH}'; export default function App() { return <A __island>hello</A>; }`;
const result = await transformAsync(code, babelOptions);
expect(result?.code).toContain(
`__island: "${ISLAND_PATH}${MASK_SPLITTER}${IMPORTER_PATH}"`
);
});

test('Should do nothing', async () => {
const code = `import * as A from '${ISLAND_PATH}'; export default function App() { return <A>hello</A>; }`;
const result = await transformAsync(code, babelOptions);
expect(result?.code).toMatchInlineSnapshot(`
"import * as A from '../Comp/index';
export default function App() {
return /*#__PURE__*/React.createElement(A, null, \\"hello\\");
}"
`);
});
});
41 changes: 27 additions & 14 deletions src/node/babel-plugin-island.ts
Expand Up @@ -15,27 +15,40 @@ import type { Visitor } from '@babel/traverse';
import {} from 'vite';
import { MASK_SPLITTER } from './constants';

const TRACE_ID = '__island';
const ID = '__island';

export default declare((api) => {
api.assertVersion(7);

const visitor: Visitor<PluginPass> = {
JSXOpeningElement(path, state) {
const name = path.node.name;
if (name.type === 'JSXIdentifier') {
const binding = path.scope.getBinding(name.name);
if (binding?.path.parent.type === 'ImportDeclaration') {
const source = (binding?.path.parent as t.ImportDeclaration).source;
const attributes = (path.container as t.JSXElement).openingElement
.attributes;
for (let i = 0; i < attributes.length; i++) {
const name = (attributes[i] as t.JSXAttribute).name;
if (name?.name === TRACE_ID) {
(attributes[i] as t.JSXAttribute).value = t.stringLiteral(
`${source.value}${MASK_SPLITTER}${state.filename}`
);
}
let bindingName: string;
if (t.isJSXIdentifier(name)) {
bindingName = name.name;
} else if (t.isJSXMemberExpression(name)) {
let object = name.object;
while (t.isJSXMemberExpression(object)) {
object = object.object;
}
bindingName = object.name;
} else if (t.isJSXNamespacedName(name)) {
bindingName = name.namespace.name;
} else {
return;
}

const binding = path.scope.getBinding(bindingName);
if (binding?.path.parent.type === 'ImportDeclaration') {
const source = (binding?.path.parent as t.ImportDeclaration).source;
const attributes = (path.container as t.JSXElement).openingElement
.attributes;
for (let i = 0; i < attributes.length; i++) {
const name = (attributes[i] as t.JSXAttribute).name;
if (name?.name === ID) {
(attributes[i] as t.JSXAttribute).value = t.stringLiteral(
`${source.value}${MASK_SPLITTER}${state.filename}`
);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/node/build/bundle.ts
@@ -1,4 +1,4 @@
import { OutputBundle, RollupOutput } from 'rollup';
import { RollupOutput } from 'rollup';
import { build, InlineConfig } from 'vite';
import { CLIENT_ENTRY_PATH, SERVER_ENTRY_PATH, TEMP_PATH } from '../constants';
import { createIslandPlugins } from '../plugin';
Expand Down
4 changes: 2 additions & 2 deletions src/node/build/render.ts
@@ -1,5 +1,5 @@
import { join } from 'path';
import fs from 'fs-extra';
import fs, { remove } from 'fs-extra';
import type { RollupOutput } from 'rollup';
import { dynamicImport } from '../utils';
import { okMark, Builder } from './bundle';
Expand Down Expand Up @@ -125,5 +125,5 @@ export async function renderPages(
symbol: okMark
});
// Render ended, remove temp files
// await remove(join(root, TEMP_PATH));
await remove(join(root, TEMP_PATH));
}
3 changes: 1 addition & 2 deletions src/node/plugin-island/index.ts
Expand Up @@ -38,8 +38,7 @@ export function pluginIsland(
alias: {
'island:theme': `/@fs/${DEFAULT_THEME_PATH}`,
'island:client': `/@fs/${CLIENT_PATH}`,
'island:routes': join(c.root!, ROUTE_PATH),
'island:islands': join(`/@fs/${THEME_ISLANDS_PATH}`)
'island:routes': join(c.root!, ROUTE_PATH)
}
},
css: {
Expand Down

0 comments on commit b189299

Please sign in to comment.