Merge branch 'release-3.1.0' into leonado/changelog

This commit is contained in:
Leonardo Venturini
2024-11-11 18:35:26 -04:00
committed by GitHub
11 changed files with 2952 additions and 2047 deletions

4
.envrc
View File

@@ -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
}
}

View File

@@ -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:

View File

@@ -1 +0,0 @@
node_modules

View File

@@ -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.

View File

@@ -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");

View File

@@ -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)

View File

@@ -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;
}
);

View File

@@ -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

View File

@@ -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++;

View File

@@ -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