mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'release-3.1.0' into leonado/changelog
This commit is contained in:
4
.envrc
4
.envrc
@@ -20,7 +20,7 @@ function @get-ready {
|
||||
}
|
||||
|
||||
function @test-packages {
|
||||
TINYTEST_FILTER="$1" @meteor test-packages --exclude-archs=web.browser.legacy,web.cordova --exclude=roles
|
||||
TINYTEST_FILTER="$1" @meteor test-packages --exclude-archs=web.browser.legacy,web.cordova
|
||||
}
|
||||
|
||||
function @test-self {
|
||||
@@ -74,4 +74,4 @@ function @packages-bumped {
|
||||
echo "- $pkg_name@$version_in_red"
|
||||
fi
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ dist: jammy
|
||||
sudo: required
|
||||
services: xvfb
|
||||
node_js:
|
||||
- "20.15.1"
|
||||
- "22.11.0"
|
||||
cache:
|
||||
directories:
|
||||
- ".meteor"
|
||||
@@ -16,7 +16,7 @@ env:
|
||||
- CXX=g++-12
|
||||
- phantom=false
|
||||
- PUPPETEER_DOWNLOAD_PATH=~/.npm/chromium
|
||||
- TEST_PACKAGES_EXCLUDE=roles,stylus
|
||||
- TEST_PACKAGES_EXCLUDE=stylus
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
node_modules
|
||||
@@ -1,7 +0,0 @@
|
||||
This directory and the files immediately inside it are automatically generated
|
||||
when you change this package's NPM dependencies. Commit the files in this
|
||||
directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
|
||||
so that others run the same versions of sub-dependencies.
|
||||
|
||||
You should NOT check in the node_modules directory that Meteor automatically
|
||||
creates; if you are using git, the .gitignore file tells git to ignore it.
|
||||
@@ -27,18 +27,14 @@ Package.onUse(function (api) {
|
||||
});
|
||||
|
||||
Package.onTest(function (api) {
|
||||
// Add code coverage
|
||||
api.use([
|
||||
"lmieulet:meteor-legacy-coverage",
|
||||
"lmieulet:meteor-coverage@4.1.0 || 5.0.0",
|
||||
"meteortesting:mocha@2.1.0 || 3.2.0",
|
||||
]);
|
||||
|
||||
const both = ["client", "server"];
|
||||
|
||||
// `accounts-password` is included so `Meteor.users` exists
|
||||
|
||||
api.use(["ecmascript", "alanning:roles", "mongo"], both);
|
||||
api.use([
|
||||
"tinytest",
|
||||
"ecmascript",
|
||||
"mongo",
|
||||
"roles"
|
||||
], both);
|
||||
|
||||
api.addFiles("tests/serverAsync.js", "server");
|
||||
api.addFiles("tests/client.js", "client");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RolesCollection, RoleAssignmentCollection } from 'packages/roles/roles_common_async'
|
||||
import { RolesCollection, RoleAssignmentCollection } from './roles_common_async';
|
||||
|
||||
const indexFnAssignment = RoleAssignmentCollection.createIndexAsync.bind(RoleAssignmentCollection)
|
||||
const indexFnRoles = RolesCollection.createIndexAsync.bind(RolesCollection)
|
||||
|
||||
@@ -1,138 +1,152 @@
|
||||
/* eslint-env mocha */
|
||||
/* global Roles */
|
||||
|
||||
import { Meteor } from 'meteor/meteor'
|
||||
import { assert } from 'chai'
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import { Tinytest } from "meteor/tinytest";
|
||||
|
||||
// To ensure that the files are loaded for coverage
|
||||
import 'packages/roles/roles_client'
|
||||
import "../roles_client";
|
||||
|
||||
const safeInsert = (collection, data) => {
|
||||
try {
|
||||
collection.insert(data)
|
||||
collection.insert(data);
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
const roles = ["admin", "editor", "user"];
|
||||
const users = {
|
||||
eve: {
|
||||
_id: "eve",
|
||||
},
|
||||
bob: {
|
||||
_id: "bob",
|
||||
},
|
||||
joe: {
|
||||
_id: "joe",
|
||||
},
|
||||
};
|
||||
|
||||
function testUser(test, username, expectedRoles, scope) {
|
||||
const user = users[username];
|
||||
|
||||
// test using user object rather than userId to avoid mocking
|
||||
for (const role of roles) {
|
||||
const expected = expectedRoles.includes(role);
|
||||
const msg =
|
||||
username + " expected to have '" + role + "' permission but does not";
|
||||
const nmsg = username + " had un-expected permission " + role;
|
||||
|
||||
if (expected) {
|
||||
test.isTrue(Roles.userIsInRole(user, role, scope), msg);
|
||||
} else {
|
||||
test.isFalse(Roles.userIsInRole(user, role, scope), nmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('roles', function () {
|
||||
const roles = ['admin', 'editor', 'user']
|
||||
const users = {
|
||||
eve: {
|
||||
_id: 'eve'
|
||||
},
|
||||
bob: {
|
||||
_id: 'bob'
|
||||
},
|
||||
joe: {
|
||||
_id: 'joe'
|
||||
}
|
||||
}
|
||||
function setupRoles() {
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: "admin" },
|
||||
inheritedRoles: [{ _id: "admin" }],
|
||||
});
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: "editor" },
|
||||
inheritedRoles: [{ _id: "editor" }],
|
||||
});
|
||||
|
||||
function testUser (username, expectedRoles, scope) {
|
||||
const user = users[username]
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: "user" },
|
||||
inheritedRoles: [{ _id: "user" }],
|
||||
scope: "group1",
|
||||
});
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: "editor" },
|
||||
inheritedRoles: [{ _id: "editor" }],
|
||||
scope: "group2",
|
||||
});
|
||||
|
||||
// test using user object rather than userId to avoid mocking
|
||||
for (const role of roles) {
|
||||
const expected = expectedRoles.includes(role)
|
||||
const msg = username + ' expected to have \'' + role + '\' permission but does not'
|
||||
const nmsg = username + ' had un-expected permission ' + role
|
||||
|
||||
if (expected) {
|
||||
assert.isTrue(Roles.userIsInRole(user, role, scope), msg)
|
||||
} else {
|
||||
assert.isFalse(Roles.userIsInRole(user, role, scope), nmsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let meteorUserMethod
|
||||
before(() => {
|
||||
meteorUserMethod = Meteor.user
|
||||
// Mock Meteor.user() for isInRole handlebars helper testing
|
||||
Meteor.user = function () {
|
||||
return users.eve
|
||||
}
|
||||
})
|
||||
|
||||
after(() => {
|
||||
Meteor.user = meteorUserMethod
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: 'admin' },
|
||||
inheritedRoles: [{ _id: 'admin' }]
|
||||
})
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: 'editor' },
|
||||
inheritedRoles: [{ _id: 'editor' }]
|
||||
})
|
||||
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: 'user' },
|
||||
inheritedRoles: [{ _id: 'user' }],
|
||||
scope: 'group1'
|
||||
})
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: 'editor' },
|
||||
inheritedRoles: [{ _id: 'editor' }],
|
||||
scope: 'group2'
|
||||
})
|
||||
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: 'admin' },
|
||||
inheritedRoles: [{ _id: 'admin' }]
|
||||
})
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: 'editor' },
|
||||
inheritedRoles: [{ _id: 'editor' }],
|
||||
scope: 'group1'
|
||||
})
|
||||
})
|
||||
|
||||
it('can check current users roles via template helper', function () {
|
||||
let expected
|
||||
let actual
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: "admin" },
|
||||
inheritedRoles: [{ _id: "admin" }],
|
||||
});
|
||||
safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: "editor" },
|
||||
inheritedRoles: [{ _id: "editor" }],
|
||||
scope: "group1",
|
||||
});
|
||||
}
|
||||
|
||||
Tinytest.add(
|
||||
"roles - can check current users roles via template helper",
|
||||
(test) => {
|
||||
if (!Roles._handlebarsHelpers) {
|
||||
// probably running package tests outside of a Meteor app.
|
||||
// skip this test.
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const isInRole = Roles._handlebarsHelpers.isInRole
|
||||
assert.equal(typeof isInRole, 'function', "'isInRole' helper not registered")
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
|
||||
expected = true
|
||||
actual = isInRole('admin, editor')
|
||||
assert.equal(actual, expected)
|
||||
setupRoles();
|
||||
|
||||
expected = true
|
||||
actual = isInRole('admin')
|
||||
assert.equal(actual, expected)
|
||||
const isInRole = Roles._handlebarsHelpers.isInRole;
|
||||
test.equal(typeof isInRole, "function", "'isInRole' helper not registered");
|
||||
|
||||
expected = false
|
||||
actual = isInRole('unknown')
|
||||
assert.equal(actual, expected)
|
||||
})
|
||||
test.equal(isInRole("admin, editor"), true);
|
||||
test.equal(isInRole("admin"), true);
|
||||
test.equal(isInRole("unknown"), false);
|
||||
|
||||
it('can check if user is in role', function () {
|
||||
testUser('eve', ['admin', 'editor'])
|
||||
})
|
||||
Meteor.user = meteorUserMethod;
|
||||
}
|
||||
);
|
||||
|
||||
it('can check if user is in role by group', function () {
|
||||
testUser('bob', ['user'], 'group1')
|
||||
testUser('bob', ['editor'], 'group2')
|
||||
})
|
||||
Tinytest.add("roles - can check if user is in role", (test) => {
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
|
||||
it('can check if user is in role with Roles.GLOBAL_GROUP', function () {
|
||||
testUser('joe', ['admin'])
|
||||
testUser('joe', ['admin'], Roles.GLOBAL_GROUP)
|
||||
testUser('joe', ['admin', 'editor'], 'group1')
|
||||
})
|
||||
})
|
||||
setupRoles();
|
||||
testUser(test, "eve", ["admin", "editor"]);
|
||||
|
||||
Meteor.user = meteorUserMethod;
|
||||
});
|
||||
|
||||
Tinytest.add("roles - can check if user is in role by group", (test) => {
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
|
||||
setupRoles();
|
||||
testUser(test, "bob", ["user"], "group1");
|
||||
testUser(test, "bob", ["editor"], "group2");
|
||||
|
||||
Meteor.user = meteorUserMethod;
|
||||
});
|
||||
|
||||
Tinytest.add(
|
||||
"roles - can check if user is in role with Roles.GLOBAL_GROUP",
|
||||
(test) => {
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
|
||||
setupRoles();
|
||||
testUser(test, "joe", ["admin"]);
|
||||
testUser(test, "joe", ["admin"], Roles.GLOBAL_GROUP);
|
||||
testUser(test, "joe", ["admin", "editor"], "group1");
|
||||
|
||||
Meteor.user = meteorUserMethod;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,142 +1,159 @@
|
||||
/* eslint-env mocha */
|
||||
/* global Roles */
|
||||
|
||||
import { Meteor } from 'meteor/meteor'
|
||||
import chai, { assert } from 'chai'
|
||||
import chaiAsPromised from 'chai-as-promised'
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import { Tinytest } from "meteor/tinytest";
|
||||
|
||||
// To ensure that the files are loaded for coverage
|
||||
import 'packages/roles/roles_client'
|
||||
import 'packages/roles/roles_common_async'
|
||||
|
||||
chai.use(chaiAsPromised)
|
||||
import "../roles_client";
|
||||
import "../roles_common_async";
|
||||
|
||||
const safeInsert = async (collection, data) => {
|
||||
return await collection.insertAsync(data).catch(e => console.error(e))
|
||||
return await collection.insertAsync(data).catch((e) => console.error(e));
|
||||
};
|
||||
|
||||
const roles = ["admin", "editor", "user"];
|
||||
const users = {
|
||||
eve: {
|
||||
_id: "eve",
|
||||
},
|
||||
bob: {
|
||||
_id: "bob",
|
||||
},
|
||||
joe: {
|
||||
_id: "joe",
|
||||
},
|
||||
};
|
||||
|
||||
async function testUser(test, username, expectedRoles, scope) {
|
||||
const user = users[username];
|
||||
|
||||
// test using user object rather than userId to avoid mocking
|
||||
for (const role of roles) {
|
||||
const expected = expectedRoles.includes(role);
|
||||
const msg =
|
||||
username + " expected to have '" + role + "' permission but does not";
|
||||
const nmsg = username + " had un-expected permission " + role;
|
||||
|
||||
const result = await Roles.userIsInRoleAsync(user._id, role, scope);
|
||||
if (expected) {
|
||||
test.isTrue(result, msg);
|
||||
} else {
|
||||
test.isFalse(result, nmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('roles async', function () {
|
||||
const roles = ['admin', 'editor', 'user']
|
||||
const users = {
|
||||
eve: {
|
||||
_id: 'eve'
|
||||
},
|
||||
bob: {
|
||||
_id: 'bob'
|
||||
},
|
||||
joe: {
|
||||
_id: 'joe'
|
||||
}
|
||||
}
|
||||
async function setupRoles() {
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: "admin" },
|
||||
inheritedRoles: [{ _id: "admin" }],
|
||||
});
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: "editor" },
|
||||
inheritedRoles: [{ _id: "editor" }],
|
||||
});
|
||||
|
||||
async function testUser (username, expectedRoles, scope) {
|
||||
const user = users[username]
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: "user" },
|
||||
inheritedRoles: [{ _id: "user" }],
|
||||
scope: "group1",
|
||||
});
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: "editor" },
|
||||
inheritedRoles: [{ _id: "editor" }],
|
||||
scope: "group2",
|
||||
});
|
||||
|
||||
// test using user object rather than userId to avoid mocking
|
||||
for (const role of roles) {
|
||||
const expected = expectedRoles.includes(role)
|
||||
const msg = username + ' expected to have \'' + role + '\' permission but does not'
|
||||
const nmsg = username + ' had un-expected permission ' + role
|
||||
|
||||
const result = await Roles.userIsInRoleAsync(user._id, role, scope)
|
||||
if (expected) {
|
||||
assert.isTrue(result, msg)
|
||||
} else {
|
||||
assert.isFalse(result, nmsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let meteorUserMethod
|
||||
before(() => {
|
||||
meteorUserMethod = Meteor.user
|
||||
// Mock Meteor.user() for isInRole handlebars helper testing
|
||||
Meteor.user = function () {
|
||||
return users.eve
|
||||
}
|
||||
Meteor.subscribe('client_assignments')
|
||||
})
|
||||
|
||||
after(() => {
|
||||
Meteor.user = meteorUserMethod
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: 'admin' },
|
||||
inheritedRoles: [{ _id: 'admin' }]
|
||||
})
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.eve,
|
||||
role: { _id: 'editor' },
|
||||
inheritedRoles: [{ _id: 'editor' }]
|
||||
})
|
||||
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: 'user' },
|
||||
inheritedRoles: [{ _id: 'user' }],
|
||||
scope: 'group1'
|
||||
})
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.bob,
|
||||
role: { _id: 'editor' },
|
||||
inheritedRoles: [{ _id: 'editor' }],
|
||||
scope: 'group2'
|
||||
})
|
||||
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: 'admin' },
|
||||
inheritedRoles: [{ _id: 'admin' }]
|
||||
})
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: 'editor' },
|
||||
inheritedRoles: [{ _id: 'editor' }],
|
||||
scope: 'group1'
|
||||
})
|
||||
})
|
||||
|
||||
it('can check current users roles via template helper', function () {
|
||||
let expected
|
||||
let actual
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: "admin" },
|
||||
inheritedRoles: [{ _id: "admin" }],
|
||||
});
|
||||
await safeInsert(Meteor.roleAssignment, {
|
||||
user: users.joe,
|
||||
role: { _id: "editor" },
|
||||
inheritedRoles: [{ _id: "editor" }],
|
||||
scope: "group1",
|
||||
});
|
||||
}
|
||||
|
||||
Tinytest.addAsync(
|
||||
"roles async - can check current users roles via template helper",
|
||||
async (test) => {
|
||||
if (!Roles._handlebarsHelpers) {
|
||||
// probably running package tests outside of a Meteor app.
|
||||
// skip this test.
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const isInRole = Roles._handlebarsHelpers.isInRole
|
||||
assert.equal(typeof isInRole, 'function', "'isInRole' helper not registered")
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
Meteor.subscribe("client_assignments");
|
||||
|
||||
expected = true
|
||||
actual = isInRole('admin, editor')
|
||||
assert.equal(actual, expected)
|
||||
await setupRoles();
|
||||
|
||||
expected = true
|
||||
actual = isInRole('admin')
|
||||
assert.equal(actual, expected)
|
||||
const isInRole = Roles._handlebarsHelpers.isInRole;
|
||||
test.equal(typeof isInRole, "function", "'isInRole' helper not registered");
|
||||
|
||||
expected = false
|
||||
actual = isInRole('unknown')
|
||||
assert.equal(actual, expected)
|
||||
})
|
||||
test.equal(isInRole("admin, editor"), true);
|
||||
test.equal(isInRole("admin"), true);
|
||||
test.equal(isInRole("unknown"), false);
|
||||
|
||||
it('can check if user is in role', async function () {
|
||||
await testUser('eve', ['admin', 'editor'])
|
||||
})
|
||||
Meteor.user = meteorUserMethod;
|
||||
}
|
||||
);
|
||||
|
||||
it('can check if user is in role by group', async function () {
|
||||
await testUser('bob', ['user'], 'group1')
|
||||
await testUser('bob', ['editor'], 'group2')
|
||||
})
|
||||
Tinytest.addAsync(
|
||||
"roles async - can check if user is in role",
|
||||
async (test) => {
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
Meteor.subscribe("client_assignments");
|
||||
|
||||
it('can check if user is in role with Roles.GLOBAL_GROUP', async function () {
|
||||
await testUser('joe', ['admin'])
|
||||
await testUser('joe', ['admin'], Roles.GLOBAL_GROUP)
|
||||
await testUser('joe', ['admin', 'editor'], 'group1')
|
||||
})
|
||||
})
|
||||
await setupRoles();
|
||||
await testUser(test, "eve", ["admin", "editor"]);
|
||||
|
||||
Meteor.user = meteorUserMethod;
|
||||
}
|
||||
);
|
||||
|
||||
Tinytest.addAsync(
|
||||
"roles async - can check if user is in role by group",
|
||||
async (test) => {
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
Meteor.subscribe("client_assignments");
|
||||
|
||||
await setupRoles();
|
||||
await testUser(test, "bob", ["user"], "group1");
|
||||
await testUser(test, "bob", ["editor"], "group2");
|
||||
|
||||
Meteor.user = meteorUserMethod;
|
||||
}
|
||||
);
|
||||
|
||||
Tinytest.addAsync(
|
||||
"roles async - can check if user is in role with Roles.GLOBAL_GROUP",
|
||||
async (test) => {
|
||||
const meteorUserMethod = Meteor.user;
|
||||
Meteor.user = function () {
|
||||
return users.eve;
|
||||
};
|
||||
Meteor.subscribe("client_assignments");
|
||||
|
||||
await setupRoles();
|
||||
await testUser(test, "joe", ["admin"]);
|
||||
await testUser(test, "joe", ["admin"], Roles.GLOBAL_GROUP);
|
||||
await testUser(test, "joe", ["admin", "editor"], "group1");
|
||||
|
||||
Meteor.user = meteorUserMethod;
|
||||
}
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,10 @@ async function runNextUrl(browser) {
|
||||
page.on('console', async msg => {
|
||||
// this is a way to make sure the travis does not timeout
|
||||
// if the test is running for too long without any output to the console (10 minutes)
|
||||
const text = msg.text();
|
||||
if (text.includes('Permissions policy violation')) {
|
||||
return;
|
||||
}
|
||||
if (msg._text !== undefined) console.log(msg._text);
|
||||
else {
|
||||
testNumber++;
|
||||
|
||||
@@ -9,7 +9,7 @@ cd $(dirname $0)/../..
|
||||
export METEOR_HOME=`pwd`
|
||||
|
||||
# Installs into dev_bundle/lib/node_modules/puppeteer.
|
||||
./meteor npm install -g puppeteer@20.4.0
|
||||
./meteor npm install -g puppeteer@23.6.0
|
||||
|
||||
export PATH=$METEOR_HOME:$PATH
|
||||
|
||||
|
||||
Reference in New Issue
Block a user