diff --git a/packages/components/package-lock.json b/packages/components/package-lock.json index b39e1db101..331fe1a0e4 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.39.1", + "version": "7.39.2-fb-dropCrossFolder.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.39.1", + "version": "7.39.2-fb-dropCrossFolder.0", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@hello-pangea/dnd": "18.0.1", diff --git a/packages/components/package.json b/packages/components/package.json index 19c7ba1c93..9495416777 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.39.1", + "version": "7.39.2-fb-dropCrossFolder.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index dd13b772d3..483f1e657c 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -1,6 +1,10 @@ # @labkey/components Components, models, actions, and utility functions for LabKey applications and pages +### version 7.X +*Released*: X May 2026 +- GitHub Issue 903: Remove Cross-Container Sample and Data Class Import Feature + ### version TBD *Released*: TBD - Misc. accessibility improvements diff --git a/packages/components/src/internal/components/entities/models.ts b/packages/components/src/internal/components/entities/models.ts index fc52e63d17..9907edd40d 100644 --- a/packages/components/src/internal/components/entities/models.ts +++ b/packages/components/src/internal/components/entities/models.ts @@ -479,7 +479,6 @@ export interface EntityDataType { ancestorColumnName?: string; appUrlPrefixParts?: string[]; containerFilter?: Query.ContainerFilter; - crossFolderImportForbidden?: boolean; deleteHelpLinkTopic: string; dependencyText: Function | string; descriptionPlural: string; diff --git a/packages/test/config/integration.setup.js b/packages/test/config/integration.setup.js index 1040aec6a4..9ee23fb843 100644 --- a/packages/test/config/integration.setup.js +++ b/packages/test/config/integration.setup.js @@ -139,3 +139,11 @@ process.env.INTEGRATION_SERVER = `${protocol}://${server}:${port}`; process.env.INTEGRATION_CONTEXT_PATH = contextPath; process.env.INTEGRATION_AUTH_USER = user; process.env.INTEGRATION_AUTH_PASS = pass; + +// Seed configuration for reproducible random test data. +// Each Jest worker inherits TEST_SEED from the environment; if absent, generate +// from Date.now() and write back so utils.ts (loaded after setupFiles) sees it. +if (!process.env.TEST_SEED) { + process.env.TEST_SEED = String(Date.now() >>> 0); +} +console.log(`[LabKey Test] Random seed: ${process.env.TEST_SEED} (rerun with: TEST_SEED=${process.env.TEST_SEED})`); diff --git a/packages/test/package-lock.json b/packages/test/package-lock.json index 0e40fe84a8..22727588f2 100644 --- a/packages/test/package-lock.json +++ b/packages/test/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/test", - "version": "1.13.2", + "version": "1.14.0-fb-dropCrossFolder.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/test", - "version": "1.13.2", + "version": "1.14.0-fb-dropCrossFolder.1", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "properties-reader": "3.0.1", diff --git a/packages/test/package.json b/packages/test/package.json index ffb437d268..d6e10fa063 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/test", - "version": "1.13.2", + "version": "1.14.0-fb-dropCrossFolder.1", "description": "Configurations and utilities for JavaScript-based testing", "main": "dist/test.js", "module": "dist/test.js", diff --git a/packages/test/src/ExperimentCrudUtils.ts b/packages/test/src/ExperimentCrudUtils.ts index 900f5fb2a5..2512905c63 100644 --- a/packages/test/src/ExperimentCrudUtils.ts +++ b/packages/test/src/ExperimentCrudUtils.ts @@ -107,7 +107,7 @@ export async function importData(server, importText: string, queryName: string, let errorResp = null; const response = await server.request('experiment', isSamples ? 'importSamples' : 'importData', (agent, url) => { return agent - .post(url + '?auditBehavior=DETAILED&crossFolderImport=true') + .post(url + '?auditBehavior=DETAILED') .type('form') .send({ schemaName: isSamples ? 'samples' : 'exp.data', @@ -210,7 +210,7 @@ export async function importCrossTypeData( isSamples ? 'importSamples' : 'importData', (agent, url) => { return agent - .post(url + '?auditBehavior=DETAILED&crossFolderImport=true&crossTypeImport=true') + .post(url + '?auditBehavior=DETAILED&crossTypeImport=true') .type('form') .send({ schemaName: undefined, diff --git a/packages/test/src/index.ts b/packages/test/src/index.ts index 58f2bcaa77..d8f9f71a33 100644 --- a/packages/test/src/index.ts +++ b/packages/test/src/index.ts @@ -22,6 +22,8 @@ import { } from './integrationUtils'; import { sleep, + random, + testSeed, shuffleArray, selectRandomN, generateDomainName, @@ -83,6 +85,8 @@ export { IntegrationTestServer, RequestOptions, sleep, + random, + testSeed, successfulResponse, TestUser, ExperimentCRUDUtils, diff --git a/packages/test/src/utils.ts b/packages/test/src/utils.ts index 546ca182db..448937f4c1 100644 --- a/packages/test/src/utils.ts +++ b/packages/test/src/utils.ts @@ -18,6 +18,36 @@ * @param ms number of milliseconds to sleep. */ +// Seeded PRNG (mulberry32). Reads TEST_SEED at module load time; +// falls back to Date.now() if not set. +function _mulberry32(seed: number): () => number { + return function () { + seed |= 0; + seed = seed + 0x6D2B79F5 | 0; + let t = Math.imul(seed ^ (seed >>> 15), 1 | seed); + t = t + Math.imul(t ^ (t >>> 7), 61 | t) ^ t; + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +const _seedStr = typeof process !== 'undefined' ? process.env?.TEST_SEED : undefined; +const _seed = _seedStr !== undefined ? (parseInt(_seedStr, 10) >>> 0) : (Date.now() >>> 0); + +/** Seeded drop-in for Math.random(). Use in tests instead of Math.random() + * so runs are reproducible via the TEST_SEED environment variable. + * + * Note: this is a module-level singleton — all test files loaded in the same Jest worker share + * one sequence. With --maxWorkers 1 (the default for integration tests) this means full + * reproducibility: the same seed always produces the same sequence regardless of which file + * calls random() and in what order. If --maxWorkers is increased, each worker gets its own + * copy of this module initialized from the same TEST_SEED, so files on different workers draw + * from independent sequences — a multi-worker run may not reproduce identically under + * --maxWorkers 1 even with the same seed. */ +export const random = _mulberry32(_seed); + +/** The seed used for this test run. Log it so failures can be reproduced with TEST_SEED=. */ +export const testSeed = _seed; + const QUERY_KEY_CHARSET = '$/&}~,.'; const ALPHA = 'ABCDabcvxyz'; const NUMERIC = '0123456789'; @@ -38,7 +68,7 @@ export const sleep = (ms = 0): Promise => { export function shuffleArray(original: T[]) : T[] { const array = [...original]; for (let i = array.length - 1; i >= 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); + const j = Math.floor(random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; @@ -56,7 +86,7 @@ export function generateRandomStr(length: number = 8, charset: string = STRING_C const charsetLength = charset.length; while (result.length < length) { - const randomIndex = Math.floor(Math.random() * charsetLength); + const randomIndex = Math.floor(random() * charsetLength); const select = charset[randomIndex]; if (!excluded || excluded.indexOf(select) === -1) result += charset[randomIndex];