Skip to content
This repository has been archived by the owner on Oct 9, 2024. It is now read-only.

Commit

Permalink
Merge pull request #13 from flarelabs-net/improve-module-resolution-f…
Browse files Browse the repository at this point in the history
…ixture-tests

improve the `cloudflare-dev-module-resolution` testing structure
  • Loading branch information
dario-piotrowicz authored Sep 23, 2024
2 parents 37ad0e3 + 9629578 commit 8dafb36
Show file tree
Hide file tree
Showing 26 changed files with 213 additions and 70 deletions.
11 changes: 7 additions & 4 deletions fixtures/cloudflare-dev-module-resolution/entry-workerd.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
const allowedPaths = new Set([
'/react',
'/remix',
'/discord-api-types',
'/slash-create',
'/require-ext',
'/require-no-ext',
'/require-json',
'/third-party/react',
'/third-party/remix',
'/third-party/discord-api-types',
'/third-party/slash-create',
]);

export default {
Expand Down
77 changes: 21 additions & 56 deletions fixtures/cloudflare-dev-module-resolution/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,33 @@
import { createServer } from 'vite';
import { describe, expect, test } from 'vitest';

import config from './vite.config';
import { fetchOutputFromViteDevServer } from './utils';

describe('Cloudflare dev module resolution', () => {
test('can successfully import from "react"', async () => {
const output = await fetchOutputFromViteDevServer('/react');
describe('basic module resolution', () => {
test('`require` js/cjs files with specifying their file extension', async () => {
const output = await fetchOutputFromViteDevServer('/require-ext');

expect(output?.['(react) typeof React']).toEqual('object');
expect(output?.['(react) typeof React.cloneElement']).toEqual('function');
expect(output?.['(react) reactVersionsMatch']).toEqual(true);
expect(output).toEqual({
'(requires/ext) helloWorld': 'hello (.js) world (.cjs)',
'(requires/ext) hello.cjs (wrong-extension)': null,
'(requires/ext) world.js (wrong-extension)': null,
});
});

test('can successfully import utilities from "@remix-run/cloudflare"', async () => {
const output = await fetchOutputFromViteDevServer('/remix');
test('`require` js/cjs files without specifying their file extension', async () => {
const output = await fetchOutputFromViteDevServer('/require-no-ext');

expect(output?.['(remix) typeof cloudflare json({})']).toEqual('object');
expect(output?.['(remix) remixRunCloudflareCookieName']).toEqual(
'my-remix-run-cloudflare-cookie',
);
expect(output).toEqual({
'(requires/no-ext) helloWorld': 'hello (.js) world (.cjs)',
});
});

test('can successfully import from "discord-api-types/v10"', async () => {
const output = await fetchOutputFromViteDevServer('/discord-api-types');
test('`require` json files', async () => {
const output = await fetchOutputFromViteDevServer('/require-json');

expect(output?.['(discord-api-types/v10) Utils.isLinkButton({})']).toEqual(
false,
);
expect(
output?.['(discord-api-types/v10) RPCErrorCodes.InvalidUser'],
).toEqual(4010);
});

test('can successfully import from "slash-create" (which `require`s its package.json)', async () => {
const output = await fetchOutputFromViteDevServer('/slash-create');

expect(output?.['(slash-create/web) VERSION']).toMatch(/^6\./);
expect(
output?.[
'(slash-create/web) slashCreatorInstance is instance of SlashCreator'
],
).toEqual(true);
expect(output?.['(slash-create/web) myCollection.random()']).toEqual(54321);
expect(output).toEqual({
'(requires/json) package name':
'@cloudflare-dev-module-resolution/requires',
'(requires/json) package version': '1.0.0',
});
});
});

async function fetchOutputFromViteDevServer(path: string): Promise<unknown> {
const viteServer = await createServer({
...config,
});

await viteServer.listen();

const addressInfo = viteServer.httpServer?.address();

if (!addressInfo) {
throw new Error('addressInfo not found');
}

const address =
typeof addressInfo === 'string'
? addressInfo
: `http://localhost:${addressInfo.port}${path}`;
const resp = await fetch(address);
await viteServer.close();
return await resp.json();
}
3 changes: 2 additions & 1 deletion fixtures/cloudflare-dev-module-resolution/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"undici": "^6.19.8",
"vite": "^5.4.4",
"vitest": "^2.1.0",
"wrangler": "^3.57.2"
"wrangler": "^3.57.2",
"@cloudflare-dev-module-resolution/requires": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const helloWorldExt: string;

export const helloCjs: null;
export const worldJs: null;
13 changes: 13 additions & 0 deletions fixtures/cloudflare-dev-module-resolution/packages/requires/ext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
exports.helloWorldExt = `${require('./hello.js').default} ${require('./world.cjs').default}`;

let helloCjs = null;
try {
helloCjs = require('./hello.cjs');
} catch { }
exports.helloCjs = helloCjs;

let worldJs = null;
try {
helloCjs = require('./world.js');
} catch { }
exports.worldJs = worldJs;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.default = 'hello (.js)';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const helloWorldNoExt: string;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.helloWorldNoExt = `${require('./hello').default} ${require('./world').default}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const packageName: string;

export const packageVersion: string;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exports.packageName = `${require('./package.json').name}`;

exports.packageVersion = `${require('./package.json').version}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const helloWorldNoExt: string;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.helloWorldNoExt = `${require('./hello').default} ${require('./world').default}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@cloudflare-dev-module-resolution/requires",
"description": "a packages which has require calls of different types each used in its own entrypoint",
"version": "1.0.0",
"exports": {
"./ext": {
"default": "./ext.js",
"types": "./ext.d.ts"
},
"./no-ext": {
"default": "./no-ext.js",
"types": "./no-ext.d.ts"
},
"./json": {
"default": "./json.js",
"types": "./json.d.ts"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.default = 'world (.cjs)';
11 changes: 11 additions & 0 deletions fixtures/cloudflare-dev-module-resolution/src/require-ext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {
helloWorldExt,
helloCjs,
worldJs,
} from '@cloudflare-dev-module-resolution/requires/ext';

export default {
'(requires/ext) helloWorld': helloWorldExt,
'(requires/ext) hello.cjs (wrong-extension)': helloCjs,
'(requires/ext) world.js (wrong-extension)': worldJs,
};
9 changes: 9 additions & 0 deletions fixtures/cloudflare-dev-module-resolution/src/require-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {
packageName,
packageVersion,
} from '@cloudflare-dev-module-resolution/requires/json';

export default {
'(requires/json) package name': packageName,
'(requires/json) package version': packageVersion,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { helloWorldNoExt } from '@cloudflare-dev-module-resolution/requires/no-ext';

export default {
'(requires/no-ext) helloWorld': helloWorldNoExt,
};
55 changes: 55 additions & 0 deletions fixtures/cloudflare-dev-module-resolution/third-party.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, expect, test } from 'vitest';

import { fetchOutputFromViteDevServer } from './utils';

/**
* These tests check that module resolution works as intended for various third party npm packages (these tests are more
* realistic but less helpful than the other ones (these can be considered integration tests whilst the other unit tests)).
*
* These are packages that involve non-trivial module resolutions (and that in the past we had issues with), they have no
* special meaning to us.
*/
describe('third party packages resolutions', () => {
test('react', async () => {
const output = await fetchOutputFromViteDevServer('/third-party/react');

expect(output).toEqual({
'(react) reactVersionsMatch': true,
'(react) typeof React': 'object',
'(react) typeof React.cloneElement': 'function',
});
});

test('@remix-run/cloudflare', async () => {
const output = await fetchOutputFromViteDevServer('/third-party/remix');

expect(output).toEqual({
'(remix) remixRunCloudflareCookieName': 'my-remix-run-cloudflare-cookie',
'(remix) typeof cloudflare json({})': 'object',
});
});

test('discord-api-types/v10', async () => {
const output = await fetchOutputFromViteDevServer(
'/third-party/discord-api-types',
);

expect(output).toEqual({
'(discord-api-types/v10) RPCErrorCodes.InvalidUser': 4010,
'(discord-api-types/v10) Utils.isLinkButton({})': false,
});
});

test('slash-create', async () => {
const output = await fetchOutputFromViteDevServer(
'/third-party/slash-create',
);

expect(output).toEqual({
'(slash-create/web) VERSION': '6.2.1',
'(slash-create/web) myCollection.random()': 54321,
'(slash-create/web) slashCreatorInstance is instance of SlashCreator':
true,
});
});
});
32 changes: 32 additions & 0 deletions fixtures/cloudflare-dev-module-resolution/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createServer } from 'vite';

import config from './vite.config';

export async function fetchOutputFromViteDevServer(
path: string,
): Promise<unknown> {
const viteServer = await createServer({
...config,
});

await viteServer.listen();

const addressInfo = viteServer.httpServer?.address();

if (!addressInfo) {
throw new Error('addressInfo not found');
}

const address =
typeof addressInfo === 'string'
? addressInfo
: `http://localhost:${addressInfo.port}${path}`;
const resp = await fetch(address);
await viteServer.close();
try {
return await resp.json();
} catch (e) {
console.error(e);
return undefined;
}
}
26 changes: 17 additions & 9 deletions fixtures/cloudflare-dev-module-resolution/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,23 @@ export default defineConfig({
optimizeDeps: {
include: [],
},
environments: {
[ssrEnvName]: {
resolve: {
// We're testing module resolution for external modules, so let's treat everything as external
// (if we were not to do this all the packages in cloudflare-dev-module-resolution/packages
// wouldn't be treated as such)
external: true,
},
},
},
plugins: [
...cloudflareEnvironment(ssrEnvName),
{
name: 'cloudflare-dev-module-resolution-fixture',
async configureServer(server) {
const devEnv = server.environments[ssrEnvName] as DevEnvironment;

if (!devEnv) {
throw new Error('Dev environment not found');
}
Expand All @@ -30,14 +40,12 @@ export default defineConfig({
});

return async () => {
server.middlewares.use(
async (req, res) => {
const url = `http://localhost${req.url ?? '/'}`;
const nativeReq = new Request(url);
const resp = await handler(nativeReq);
res.end(await resp.text());
},
);
server.middlewares.use(async (req, res) => {
const url = `http://localhost${req.url ?? '/'}`;
const nativeReq = new Request(url);
const resp = await handler(nativeReq);
res.end(await resp.text());
});
};
},
},
Expand Down
5 changes: 5 additions & 0 deletions pnpm-lock.yaml

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

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ packages:
- 'packages/*'
- 'examples/*'
- 'fixtures/*'
- 'fixtures/cloudflare-dev-module-resolution/packages/*'

0 comments on commit 8dafb36

Please sign in to comment.