mirror of
https://github.com/meteor/meteor.git
synced 2026-01-10 08:08:24 -05:00
200 lines
6.7 KiB
JavaScript
200 lines
6.7 KiB
JavaScript
import {
|
|
killProcessByPort,
|
|
cleanupTempDir,
|
|
killMeteorProcess,
|
|
createMeteorApp,
|
|
runMeteorApp,
|
|
waitForMeteorOutput, waitForPlaywrightConsole
|
|
} from "./helpers";
|
|
import { testMeteorBundler, testMeteorRspackBundler } from './test-helpers';
|
|
import fs from 'fs-extra';
|
|
import path from 'path';
|
|
import { assertMeteorReactApp, assertConsoleEval } from "./assertions";
|
|
|
|
describe('React App Bundling /', () => {
|
|
|
|
// TODO: Create one test aside for all skeletons
|
|
describe.skip('Meteor Creator /', () => {
|
|
const PORT = 3100;
|
|
|
|
beforeAll(async () => {
|
|
// Ensure any process on the port is killed
|
|
await killProcessByPort(PORT);
|
|
});
|
|
|
|
test('"meteor create" / should create a new Meteor react app', async () => {
|
|
// Create a new Meteor app with --react example
|
|
const result = await createMeteorApp('react', 'react');
|
|
const newAppTempDir = result.tempDir;
|
|
const newAppMeteorProcess = result.meteorProcess;
|
|
|
|
// Wait for the process to complete
|
|
await newAppMeteorProcess;
|
|
|
|
// Check if the app directory exists
|
|
const appDirExists = await fs.pathExists(newAppTempDir);
|
|
expect(appDirExists).toBe(true);
|
|
|
|
// Check if package.json exists and contains react
|
|
const packageJsonPath = path.join(newAppTempDir, 'package.json');
|
|
const packageJsonExists = await fs.pathExists(packageJsonPath);
|
|
expect(packageJsonExists).toBe(true);
|
|
|
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
expect(packageJson.dependencies).toHaveProperty('react');
|
|
expect(packageJson.dependencies).toHaveProperty('react-dom');
|
|
|
|
// Run the newly created app
|
|
let runAppProcess = (await runMeteorApp(newAppTempDir, PORT))?.meteorProcess;
|
|
|
|
// Assert that the Meteor React app is running correctly
|
|
await assertMeteorReactApp(PORT);
|
|
|
|
// Kill the meteor processes
|
|
await killMeteorProcess(runAppProcess);
|
|
if (newAppMeteorProcess) {
|
|
await killMeteorProcess(newAppMeteorProcess);
|
|
}
|
|
|
|
// Ensure any process on the port is killed
|
|
await killProcessByPort(PORT);
|
|
|
|
// Clean up the temporary directory
|
|
await cleanupTempDir(newAppTempDir);
|
|
});
|
|
});
|
|
|
|
describe('Meteor+Rspack Bundler /', testMeteorRspackBundler({
|
|
appName: 'react',
|
|
port: 3102,
|
|
filePaths: {
|
|
client: 'client/main.jsx',
|
|
server: 'server/main.js',
|
|
test: 'tests/main.js'
|
|
},
|
|
configFile: 'rspack.config.cjs',
|
|
customAssertions: {
|
|
afterRun: async ({ result }) => {
|
|
await waitForReactEnvs(result.outputLines, { isJsxEnabled: true });
|
|
|
|
// Check if images exist and return 200 status code
|
|
await assertImagesExistAndLoad();
|
|
},
|
|
afterRunRebuildClient: async ({ allConsoleLogs }) => {
|
|
// Check for HMR output as enabled by default
|
|
await waitForMeteorOutput(allConsoleLogs, /.*HMR.*Updated modules:.*/);
|
|
},
|
|
afterRunProduction: async ({ result }) => {
|
|
await waitForReactEnvs(result.outputLines, { isJsxEnabled: true });
|
|
|
|
// Check if images exist and return 200 status code
|
|
await assertImagesExistAndLoad();
|
|
},
|
|
afterRunProductionRebuildClient: async ({ allConsoleLogs }) => {
|
|
// Check for HMR to not be enabled in production-like mode
|
|
await waitForMeteorOutput(allConsoleLogs, /.*HMR.*Updated modules:*/, { negate: true });
|
|
},
|
|
afterTest: async ({ result }) => {
|
|
await waitForReactEnvs(result.outputLines);
|
|
},
|
|
afterTestOnce: async ({ result }) => {
|
|
await waitForReactEnvs(result.outputLines);
|
|
},
|
|
afterBuild: async ({ result }) => {
|
|
await waitForReactEnvs(result.outputLines, { isJsxEnabled: true });
|
|
},
|
|
}
|
|
}));
|
|
});
|
|
|
|
/**
|
|
* Helper function to wait for React environment output from both Rspack Client and Server
|
|
* @param {string[]} outputLines - Array that will be populated with output lines
|
|
* @param {Object} options - Options for waiting
|
|
* @param {number} options.timeout - Maximum time to wait in milliseconds
|
|
* @param {number} options.checkInterval - Interval between checks in milliseconds
|
|
* @returns {Promise<void>} - A promise that resolves when react envs are enabled
|
|
*/
|
|
export async function waitForReactEnvs(outputLines, options = {}) {
|
|
await waitForMeteorOutput(
|
|
outputLines,
|
|
/.*isReactEnabled:.*true.*/,
|
|
options
|
|
);
|
|
if (options.isJsxEnabled) {
|
|
await waitForMeteorOutput(
|
|
outputLines,
|
|
/.*isJsxEnabled:.*true.*/,
|
|
options
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to assert that images exist in the DOM and return 200 status code when fetched
|
|
* @returns {Promise<void>} - A promise that resolves when images are verified
|
|
*/
|
|
export async function assertImagesExistAndLoad() {
|
|
await assertConsoleEval(`
|
|
(async () => {
|
|
// Get the image elements
|
|
const imageGenerated = document.getElementById('image-generated');
|
|
const imagePublic = document.getElementById('image-public');
|
|
|
|
// Check if images exist
|
|
if (!imageGenerated || !imagePublic) {
|
|
return { success: false, error: 'Images not found in the DOM' };
|
|
}
|
|
|
|
// Function to check if an image URL returns 200
|
|
const checkImageStatus = async (url) => {
|
|
try {
|
|
const response = await fetch(url);
|
|
return {
|
|
url,
|
|
status: response.status,
|
|
ok: response.ok
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
url,
|
|
status: 0,
|
|
ok: false,
|
|
error: error.message
|
|
};
|
|
}
|
|
};
|
|
|
|
// Function to extract URL from background-image CSS property
|
|
const extractUrlFromBackgroundImage = (backgroundImage) => {
|
|
// Extract the URL from the background-image property (format: url("..."))
|
|
const urlMatch = backgroundImage.match(/url\\(['"]?([^'"\\)]+)['"]?\\)/);
|
|
return urlMatch ? urlMatch[1] : null;
|
|
};
|
|
|
|
// Get body's background-image
|
|
const bodyStyle = getComputedStyle(document.body);
|
|
const backgroundImage = bodyStyle.backgroundImage;
|
|
const backgroundImageUrl = extractUrlFromBackgroundImage(backgroundImage);
|
|
|
|
// Check both images and background image
|
|
const generatedResult = await checkImageStatus(imageGenerated.src);
|
|
const publicResult = await checkImageStatus(imagePublic.src);
|
|
|
|
let backgroundResult = { ok: true };
|
|
if (backgroundImageUrl) {
|
|
backgroundResult = await checkImageStatus(backgroundImageUrl);
|
|
} else {
|
|
backgroundResult = {
|
|
ok: false,
|
|
error: 'No background image URL found on body element'
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: generatedResult.ok && publicResult.ok && backgroundResult.ok,
|
|
};
|
|
})()
|
|
`, { success: true }, { exactMatch: false });
|
|
}
|