chore: More flakey test improvements (#5801)
This commit is contained in:
@@ -94,7 +94,7 @@ jobs:
|
|||||||
name: test
|
name: test
|
||||||
command: |
|
command: |
|
||||||
TESTFILES=$(circleci tests glob "server/**/*.test.ts" | circleci tests split)
|
TESTFILES=$(circleci tests glob "server/**/*.test.ts" | circleci tests split)
|
||||||
yarn test $TESTFILES
|
yarn test --maxWorkers=2 $TESTFILES
|
||||||
bundle-size:
|
bundle-size:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"workerIdleMemoryLimit": "0.75",
|
"workerIdleMemoryLimit": "0.75",
|
||||||
"maxWorkers": 2,
|
"maxWorkers": "50%",
|
||||||
"maxConcurrency": 1,
|
|
||||||
"projects": [
|
"projects": [
|
||||||
{
|
{
|
||||||
"displayName": "server",
|
"displayName": "server",
|
||||||
|
|||||||
@@ -3,13 +3,11 @@ import SigninEmail from "@server/emails/templates/SigninEmail";
|
|||||||
import WelcomeEmail from "@server/emails/templates/WelcomeEmail";
|
import WelcomeEmail from "@server/emails/templates/WelcomeEmail";
|
||||||
import { AuthenticationProvider } from "@server/models";
|
import { AuthenticationProvider } from "@server/models";
|
||||||
import { buildUser, buildGuestUser, buildTeam } from "@server/test/factories";
|
import { buildUser, buildGuestUser, buildTeam } from "@server/test/factories";
|
||||||
import { getTestServer, setCloudHosted } from "@server/test/support";
|
import { getTestServer } from "@server/test/support";
|
||||||
|
|
||||||
const server = getTestServer();
|
const server = getTestServer();
|
||||||
|
|
||||||
describe("email", () => {
|
describe("email", () => {
|
||||||
beforeEach(setCloudHosted);
|
|
||||||
|
|
||||||
it("should require email param", async () => {
|
it("should require email param", async () => {
|
||||||
const res = await server.post("/auth/email", {
|
const res = await server.post("/auth/email", {
|
||||||
body: {},
|
body: {},
|
||||||
@@ -49,11 +47,11 @@ describe("email", () => {
|
|||||||
// Disable all the auth providers
|
// Disable all the auth providers
|
||||||
await AuthenticationProvider.update(
|
await AuthenticationProvider.update(
|
||||||
{
|
{
|
||||||
teamId: team.id,
|
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
where: {
|
where: {
|
||||||
|
teamId: team.id,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import randomstring from "randomstring";
|
||||||
import { IntegrationService } from "@shared/types";
|
import { IntegrationService } from "@shared/types";
|
||||||
import env from "@server/env";
|
import env from "@server/env";
|
||||||
import { IntegrationAuthentication, SearchQuery } from "@server/models";
|
import { IntegrationAuthentication, SearchQuery } from "@server/models";
|
||||||
@@ -17,7 +18,7 @@ jest.mock("../slack", () => ({
|
|||||||
const server = getTestServer();
|
const server = getTestServer();
|
||||||
|
|
||||||
describe("#hooks.unfurl", () => {
|
describe("#hooks.unfurl", () => {
|
||||||
it("should return documents", async () => {
|
it("should return documents with matching SSO user", async () => {
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const document = await buildDocument({
|
const document = await buildDocument({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
@@ -28,18 +29,19 @@ describe("#hooks.unfurl", () => {
|
|||||||
service: IntegrationService.Slack,
|
service: IntegrationService.Slack,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
teamId: user.teamId,
|
teamId: user.teamId,
|
||||||
token: "",
|
token: randomstring.generate(32),
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await server.post("/api/hooks.unfurl", {
|
const res = await server.post("/api/hooks.unfurl", {
|
||||||
body: {
|
body: {
|
||||||
token: env.SLACK_VERIFICATION_TOKEN,
|
token: env.SLACK_VERIFICATION_TOKEN,
|
||||||
team_id: "TXXXXXXXX",
|
team_id: `T${randomstring.generate(8)}`,
|
||||||
api_app_id: "AXXXXXXXXX",
|
api_app_id: `A${randomstring.generate(8)}`,
|
||||||
event: {
|
event: {
|
||||||
type: "link_shared",
|
type: "link_shared",
|
||||||
channel: "Cxxxxxx",
|
channel: `C${randomstring.generate(8)}`,
|
||||||
user: user.authentications[0].providerId,
|
user: user.authentications[0].providerId,
|
||||||
message_ts: "123456789.9875",
|
message_ts: randomstring.generate(12),
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
domain: "getoutline.com",
|
domain: "getoutline.com",
|
||||||
|
|||||||
@@ -70,20 +70,31 @@ router.post(
|
|||||||
model: UserAuthentication,
|
model: UserAuthentication,
|
||||||
as: "authentications",
|
as: "authentications",
|
||||||
required: true,
|
required: true,
|
||||||
separate: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
Logger.debug("plugins", "No user found for Slack user ID", {
|
||||||
|
providerId: event.user,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auth = await IntegrationAuthentication.findOne({
|
const auth = await IntegrationAuthentication.findOne({
|
||||||
where: {
|
where: {
|
||||||
service: IntegrationService.Slack,
|
service: IntegrationService.Slack,
|
||||||
teamId: user.teamId,
|
teamId: user.teamId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
|
Logger.debug(
|
||||||
|
"plugins",
|
||||||
|
"No Slack integration authentication found for team",
|
||||||
|
{
|
||||||
|
teamId: user.teamId,
|
||||||
|
}
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get content for unfurled links
|
// get content for unfurled links
|
||||||
|
|||||||
@@ -5,18 +5,16 @@ import { TeamDomain } from "@server/models";
|
|||||||
import Collection from "@server/models/Collection";
|
import Collection from "@server/models/Collection";
|
||||||
import UserAuthentication from "@server/models/UserAuthentication";
|
import UserAuthentication from "@server/models/UserAuthentication";
|
||||||
import { buildUser, buildTeam, buildAdmin } from "@server/test/factories";
|
import { buildUser, buildTeam, buildAdmin } from "@server/test/factories";
|
||||||
import { setCloudHosted, setSelfHosted } from "@server/test/support";
|
import { setSelfHosted } from "@server/test/support";
|
||||||
import accountProvisioner from "./accountProvisioner";
|
import accountProvisioner from "./accountProvisioner";
|
||||||
|
|
||||||
describe("accountProvisioner", () => {
|
describe("accountProvisioner", () => {
|
||||||
const ip = "127.0.0.1";
|
const ip = "127.0.0.1";
|
||||||
|
|
||||||
describe("hosted", () => {
|
describe("hosted", () => {
|
||||||
beforeEach(setCloudHosted);
|
|
||||||
|
|
||||||
it("should create a new user and team", async () => {
|
it("should create a new user and team", async () => {
|
||||||
const spy = jest.spyOn(WelcomeEmail.prototype, "schedule");
|
const spy = jest.spyOn(WelcomeEmail.prototype, "schedule");
|
||||||
const email = faker.internet.email();
|
const email = faker.internet.email().toLowerCase();
|
||||||
const { user, team, isNewTeam, isNewUser } = await accountProvisioner({
|
const { user, team, isNewTeam, isNewUser } = await accountProvisioner({
|
||||||
ip,
|
ip,
|
||||||
user: {
|
user: {
|
||||||
@@ -69,7 +67,7 @@ describe("accountProvisioner", () => {
|
|||||||
});
|
});
|
||||||
const authentications = await existing.$get("authentications");
|
const authentications = await existing.$get("authentications");
|
||||||
const authentication = authentications[0];
|
const authentication = authentications[0];
|
||||||
const newEmail = faker.internet.email();
|
const newEmail = faker.internet.email().toLowerCase();
|
||||||
const { user, isNewUser, isNewTeam } = await accountProvisioner({
|
const { user, isNewUser, isNewTeam } = await accountProvisioner({
|
||||||
ip,
|
ip,
|
||||||
user: {
|
user: {
|
||||||
@@ -104,14 +102,15 @@ describe("accountProvisioner", () => {
|
|||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip("should allow authentication by email matching", async () => {
|
it("should allow authentication by email matching", async () => {
|
||||||
const subdomain = faker.internet.domainWord();
|
const subdomain = faker.internet.domainWord();
|
||||||
const existingTeam = await buildTeam({
|
const existingTeam = await buildTeam({
|
||||||
subdomain,
|
subdomain,
|
||||||
});
|
});
|
||||||
|
|
||||||
const providers = await existingTeam.$get("authenticationProviders");
|
const providers = await existingTeam.$get("authenticationProviders");
|
||||||
const authenticationProvider = providers[0];
|
const authenticationProvider = providers[0];
|
||||||
const email = faker.internet.email();
|
const email = faker.internet.email().toLowerCase();
|
||||||
const userWithoutAuth = await buildUser({
|
const userWithoutAuth = await buildUser({
|
||||||
email,
|
email,
|
||||||
teamId: existingTeam.id,
|
teamId: existingTeam.id,
|
||||||
@@ -196,7 +195,7 @@ describe("accountProvisioner", () => {
|
|||||||
const admin = await buildAdmin({ teamId: existingTeam.id });
|
const admin = await buildAdmin({ teamId: existingTeam.id });
|
||||||
const providers = await existingTeam.$get("authenticationProviders");
|
const providers = await existingTeam.$get("authenticationProviders");
|
||||||
const authenticationProvider = providers[0];
|
const authenticationProvider = providers[0];
|
||||||
const email = faker.internet.email();
|
const email = faker.internet.email().toLowerCase();
|
||||||
|
|
||||||
await TeamDomain.create({
|
await TeamDomain.create({
|
||||||
teamId: existingTeam.id,
|
teamId: existingTeam.id,
|
||||||
@@ -299,7 +298,7 @@ describe("accountProvisioner", () => {
|
|||||||
"authenticationProviders"
|
"authenticationProviders"
|
||||||
);
|
);
|
||||||
const authenticationProvider = authenticationProviders[0];
|
const authenticationProvider = authenticationProviders[0];
|
||||||
const email = faker.internet.email();
|
const email = faker.internet.email().toLowerCase();
|
||||||
const { user, isNewUser } = await accountProvisioner({
|
const { user, isNewUser } = await accountProvisioner({
|
||||||
ip,
|
ip,
|
||||||
user: {
|
user: {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { Event } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import commentCreator from "./commentCreator";
|
import commentCreator from "./commentCreator";
|
||||||
|
|
||||||
describe("commentCreator", () => {
|
describe("commentCreator", () => {
|
||||||
@@ -32,7 +32,9 @@ describe("commentCreator", () => {
|
|||||||
ip,
|
ip,
|
||||||
});
|
});
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(comment.documentId).toEqual(document.id);
|
expect(comment.documentId).toEqual(document.id);
|
||||||
expect(comment.createdById).toEqual(user.id);
|
expect(comment.createdById).toEqual(user.id);
|
||||||
expect(event!.name).toEqual("comments.create");
|
expect(event!.name).toEqual("comments.create");
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Comment } from "@server/models";
|
import { Comment, Event } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import commentDestroyer from "./commentDestroyer";
|
import commentDestroyer from "./commentDestroyer";
|
||||||
|
|
||||||
describe("commentDestroyer", () => {
|
describe("commentDestroyer", () => {
|
||||||
@@ -46,7 +45,9 @@ describe("commentDestroyer", () => {
|
|||||||
});
|
});
|
||||||
expect(count).toEqual(0);
|
expect(count).toEqual(0);
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(event!.name).toEqual("comments.delete");
|
expect(event!.name).toEqual("comments.delete");
|
||||||
expect(event!.modelId).toEqual(comment.id);
|
expect(event!.modelId).toEqual(comment.id);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Event } from "@server/models";
|
||||||
import { sequelize } from "@server/storage/database";
|
import { sequelize } from "@server/storage/database";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import documentUpdater from "./documentUpdater";
|
import documentUpdater from "./documentUpdater";
|
||||||
|
|
||||||
describe("documentUpdater", () => {
|
describe("documentUpdater", () => {
|
||||||
@@ -22,7 +22,9 @@ describe("documentUpdater", () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(document.lastModifiedById).toEqual(user.id);
|
expect(document.lastModifiedById).toEqual(user.id);
|
||||||
expect(event!.name).toEqual("documents.update");
|
expect(event!.name).toEqual("documents.update");
|
||||||
expect(event!.documentId).toEqual(document.id);
|
expect(event!.documentId).toEqual(document.id);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { NotificationEventType } from "@shared/types";
|
import { NotificationEventType } from "@shared/types";
|
||||||
|
import { Event } from "@server/models";
|
||||||
import { sequelize } from "@server/storage/database";
|
import { sequelize } from "@server/storage/database";
|
||||||
import {
|
import {
|
||||||
buildUser,
|
buildUser,
|
||||||
@@ -6,7 +7,6 @@ import {
|
|||||||
buildDocument,
|
buildDocument,
|
||||||
buildCollection,
|
buildCollection,
|
||||||
} from "@server/test/factories";
|
} from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import notificationUpdater from "./notificationUpdater";
|
import notificationUpdater from "./notificationUpdater";
|
||||||
|
|
||||||
describe("notificationUpdater", () => {
|
describe("notificationUpdater", () => {
|
||||||
@@ -46,7 +46,9 @@ describe("notificationUpdater", () => {
|
|||||||
transaction,
|
transaction,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(notification.viewedAt).not.toBe(null);
|
expect(notification.viewedAt).not.toBe(null);
|
||||||
expect(notification.archivedAt).toBe(null);
|
expect(notification.archivedAt).toBe(null);
|
||||||
@@ -89,7 +91,9 @@ describe("notificationUpdater", () => {
|
|||||||
transaction,
|
transaction,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(notification.viewedAt).toBe(null);
|
expect(notification.viewedAt).toBe(null);
|
||||||
expect(notification.archivedAt).toBe(null);
|
expect(notification.archivedAt).toBe(null);
|
||||||
@@ -131,7 +135,9 @@ describe("notificationUpdater", () => {
|
|||||||
transaction,
|
transaction,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(notification.viewedAt).toBe(null);
|
expect(notification.viewedAt).toBe(null);
|
||||||
expect(notification.archivedAt).not.toBe(null);
|
expect(notification.archivedAt).not.toBe(null);
|
||||||
@@ -174,7 +180,9 @@ describe("notificationUpdater", () => {
|
|||||||
transaction,
|
transaction,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(notification.viewedAt).toBe(null);
|
expect(notification.viewedAt).toBe(null);
|
||||||
expect(notification.archivedAt).toBeNull();
|
expect(notification.archivedAt).toBeNull();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { Event } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import pinCreator from "./pinCreator";
|
import pinCreator from "./pinCreator";
|
||||||
|
|
||||||
describe("pinCreator", () => {
|
describe("pinCreator", () => {
|
||||||
@@ -18,7 +18,9 @@ describe("pinCreator", () => {
|
|||||||
ip,
|
ip,
|
||||||
});
|
});
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(pin.documentId).toEqual(document.id);
|
expect(pin.documentId).toEqual(document.id);
|
||||||
expect(pin.collectionId).toEqual(null);
|
expect(pin.collectionId).toEqual(null);
|
||||||
expect(pin.createdById).toEqual(user.id);
|
expect(pin.createdById).toEqual(user.id);
|
||||||
@@ -41,7 +43,9 @@ describe("pinCreator", () => {
|
|||||||
ip,
|
ip,
|
||||||
});
|
});
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(pin.documentId).toEqual(document.id);
|
expect(pin.documentId).toEqual(document.id);
|
||||||
expect(pin.collectionId).toEqual(document.collectionId);
|
expect(pin.collectionId).toEqual(document.collectionId);
|
||||||
expect(pin.createdById).toEqual(user.id);
|
expect(pin.createdById).toEqual(user.id);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Pin } from "@server/models";
|
import { Event, Pin } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import pinDestroyer from "./pinDestroyer";
|
import pinDestroyer from "./pinDestroyer";
|
||||||
|
|
||||||
describe("pinCreator", () => {
|
describe("pinCreator", () => {
|
||||||
@@ -34,7 +33,9 @@ describe("pinCreator", () => {
|
|||||||
});
|
});
|
||||||
expect(count).toEqual(0);
|
expect(count).toEqual(0);
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(event!.name).toEqual("pins.delete");
|
expect(event!.name).toEqual("pins.delete");
|
||||||
expect(event!.modelId).toEqual(pin.id);
|
expect(event!.modelId).toEqual(pin.id);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { Event } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import revisionCreator from "./revisionCreator";
|
import revisionCreator from "./revisionCreator";
|
||||||
|
|
||||||
describe("revisionCreator", () => {
|
describe("revisionCreator", () => {
|
||||||
@@ -16,7 +16,7 @@ describe("revisionCreator", () => {
|
|||||||
user,
|
user,
|
||||||
ip,
|
ip,
|
||||||
});
|
});
|
||||||
const event = await findLatestEvent({
|
const event = await Event.findLatest({
|
||||||
teamId: user.teamId,
|
teamId: user.teamId,
|
||||||
});
|
});
|
||||||
expect(revision.documentId).toEqual(document.id);
|
expect(revision.documentId).toEqual(document.id);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Star, Event } from "@server/models";
|
import { Star, Event } from "@server/models";
|
||||||
import { sequelize } from "@server/storage/database";
|
import { sequelize } from "@server/storage/database";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import starCreator from "./starCreator";
|
import starCreator from "./starCreator";
|
||||||
|
|
||||||
describe("starCreator", () => {
|
describe("starCreator", () => {
|
||||||
@@ -23,7 +22,9 @@ describe("starCreator", () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(star.documentId).toEqual(document.id);
|
expect(star.documentId).toEqual(document.id);
|
||||||
expect(star.userId).toEqual(user.id);
|
expect(star.userId).toEqual(user.id);
|
||||||
expect(star.index).toEqual("P");
|
expect(star.index).toEqual("P");
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Star } from "@server/models";
|
import { Event, Star } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import starDestroyer from "./starDestroyer";
|
import starDestroyer from "./starDestroyer";
|
||||||
|
|
||||||
describe("starDestroyer", () => {
|
describe("starDestroyer", () => {
|
||||||
@@ -34,7 +33,9 @@ describe("starDestroyer", () => {
|
|||||||
});
|
});
|
||||||
expect(count).toEqual(0);
|
expect(count).toEqual(0);
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(event!.name).toEqual("stars.delete");
|
expect(event!.name).toEqual("stars.delete");
|
||||||
expect(event!.modelId).toEqual(star.id);
|
expect(event!.modelId).toEqual(star.id);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Star } from "@server/models";
|
import { Event, Star } from "@server/models";
|
||||||
import { buildDocument, buildUser } from "@server/test/factories";
|
import { buildDocument, buildUser } from "@server/test/factories";
|
||||||
import { findLatestEvent } from "@server/test/support";
|
|
||||||
import starUpdater from "./starUpdater";
|
import starUpdater from "./starUpdater";
|
||||||
|
|
||||||
describe("starUpdater", () => {
|
describe("starUpdater", () => {
|
||||||
@@ -28,7 +27,9 @@ describe("starUpdater", () => {
|
|||||||
ip,
|
ip,
|
||||||
});
|
});
|
||||||
|
|
||||||
const event = await findLatestEvent();
|
const event = await Event.findLatest({
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
expect(star.documentId).toEqual(document.id);
|
expect(star.documentId).toEqual(document.id);
|
||||||
expect(star.userId).toEqual(user.id);
|
expect(star.userId).toEqual(user.id);
|
||||||
expect(star.index).toEqual("h");
|
expect(star.index).toEqual("h");
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
import { faker } from "@faker-js/faker";
|
import { faker } from "@faker-js/faker";
|
||||||
import TeamDomain from "@server/models/TeamDomain";
|
import TeamDomain from "@server/models/TeamDomain";
|
||||||
import { buildTeam, buildUser } from "@server/test/factories";
|
import { buildTeam, buildUser } from "@server/test/factories";
|
||||||
import { setCloudHosted, setSelfHosted } from "@server/test/support";
|
import { setSelfHosted } from "@server/test/support";
|
||||||
import teamProvisioner from "./teamProvisioner";
|
import teamProvisioner from "./teamProvisioner";
|
||||||
|
|
||||||
describe("teamProvisioner", () => {
|
describe("teamProvisioner", () => {
|
||||||
const ip = "127.0.0.1";
|
const ip = "127.0.0.1";
|
||||||
|
|
||||||
describe("hosted", () => {
|
describe("hosted", () => {
|
||||||
beforeEach(setCloudHosted);
|
|
||||||
|
|
||||||
it("should create team and authentication provider", async () => {
|
it("should create team and authentication provider", async () => {
|
||||||
const subdomain = faker.internet.domainWord();
|
const subdomain = faker.internet.domainWord();
|
||||||
const result = await teamProvisioner({
|
const result = await teamProvisioner({
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ type LogCategory =
|
|||||||
| "queue"
|
| "queue"
|
||||||
| "websockets"
|
| "websockets"
|
||||||
| "database"
|
| "database"
|
||||||
| "utils";
|
| "utils"
|
||||||
|
| "plugins";
|
||||||
type Extra = Record<string, any>;
|
type Extra = Record<string, any>;
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { SaveOptions } from "sequelize";
|
import type { SaveOptions, WhereOptions } from "sequelize";
|
||||||
import {
|
import {
|
||||||
ForeignKey,
|
ForeignKey,
|
||||||
AfterSave,
|
AfterSave,
|
||||||
@@ -111,6 +111,19 @@ class Event extends IdModel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the latest event matching the where clause
|
||||||
|
*
|
||||||
|
* @param where The options to match against
|
||||||
|
* @returns A promise resolving to the latest event or null
|
||||||
|
*/
|
||||||
|
static findLatest(where: WhereOptions) {
|
||||||
|
return this.findOne({
|
||||||
|
where,
|
||||||
|
order: [["createdAt", "DESC"]],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static ACTIVITY_EVENTS: TEvent["name"][] = [
|
static ACTIVITY_EVENTS: TEvent["name"][] = [
|
||||||
"collections.create",
|
"collections.create",
|
||||||
"collections.delete",
|
"collections.delete",
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { buildAdmin, buildTeam } from "@server/test/factories";
|
import { buildAdmin, buildTeam } from "@server/test/factories";
|
||||||
import { setCloudHosted } from "@server/test/support";
|
|
||||||
import TeamDomain from "./TeamDomain";
|
import TeamDomain from "./TeamDomain";
|
||||||
|
|
||||||
describe("team domain model", () => {
|
describe("team domain model", () => {
|
||||||
beforeEach(setCloudHosted);
|
|
||||||
|
|
||||||
describe("create", () => {
|
describe("create", () => {
|
||||||
it("should allow creation of domains", async () => {
|
it("should allow creation of domains", async () => {
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { faker } from "@faker-js/faker";
|
||||||
import { CollectionPermission } from "@shared/types";
|
import { CollectionPermission } from "@shared/types";
|
||||||
import { buildUser, buildTeam, buildCollection } from "@server/test/factories";
|
import { buildUser, buildTeam, buildCollection } from "@server/test/factories";
|
||||||
import CollectionUser from "./CollectionUser";
|
import CollectionUser from "./CollectionUser";
|
||||||
@@ -42,10 +43,11 @@ describe("user model", () => {
|
|||||||
|
|
||||||
describe("availableTeams", () => {
|
describe("availableTeams", () => {
|
||||||
it("should return teams where another user with the same email exists", async () => {
|
it("should return teams where another user with the same email exists", async () => {
|
||||||
|
const email = faker.internet.email().toLowerCase();
|
||||||
const user = await buildUser({
|
const user = await buildUser({
|
||||||
email: "user-available-teams@example.com",
|
email,
|
||||||
});
|
});
|
||||||
const anotherUser = await buildUser({ email: user.email });
|
const anotherUser = await buildUser({ email });
|
||||||
|
|
||||||
const response = await user.availableTeams();
|
const response = await user.availableTeams();
|
||||||
expect(response.length).toEqual(2);
|
expect(response.length).toEqual(2);
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
import { buildUser, buildTeam, buildAdmin } from "@server/test/factories";
|
import { buildUser, buildTeam, buildAdmin } from "@server/test/factories";
|
||||||
import { setCloudHosted, setSelfHosted } from "@server/test/support";
|
import { setSelfHosted } from "@server/test/support";
|
||||||
import { serialize } from "./index";
|
import { serialize } from "./index";
|
||||||
|
|
||||||
it.skip("should allow reading only", async () => {
|
describe.skip("policies/team", () => {
|
||||||
await setSelfHosted();
|
it("should allow reading only", async () => {
|
||||||
|
setSelfHosted();
|
||||||
|
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const user = await buildUser({
|
const user = await buildUser({
|
||||||
teamId: team.id,
|
teamId: team.id,
|
||||||
|
});
|
||||||
|
const abilities = serialize(user, team);
|
||||||
|
expect(abilities.read).toEqual(true);
|
||||||
|
expect(abilities.createTeam).toEqual(false);
|
||||||
|
expect(abilities.createAttachment).toEqual(true);
|
||||||
|
expect(abilities.createCollection).toEqual(true);
|
||||||
|
expect(abilities.createDocument).toEqual(true);
|
||||||
|
expect(abilities.createGroup).toEqual(false);
|
||||||
|
expect(abilities.createIntegration).toEqual(false);
|
||||||
});
|
});
|
||||||
const abilities = serialize(user, team);
|
|
||||||
expect(abilities.read).toEqual(true);
|
|
||||||
expect(abilities.createTeam).toEqual(false);
|
|
||||||
expect(abilities.createAttachment).toEqual(true);
|
|
||||||
expect(abilities.createCollection).toEqual(true);
|
|
||||||
expect(abilities.createDocument).toEqual(true);
|
|
||||||
expect(abilities.createGroup).toEqual(false);
|
|
||||||
expect(abilities.createIntegration).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip("should allow admins to manage", async () => {
|
it("should allow admins to manage", async () => {
|
||||||
await setSelfHosted();
|
setSelfHosted();
|
||||||
|
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const admin = await buildAdmin({
|
const admin = await buildAdmin({
|
||||||
teamId: team.id,
|
teamId: team.id,
|
||||||
|
});
|
||||||
|
const abilities = serialize(admin, team);
|
||||||
|
expect(abilities.read).toEqual(true);
|
||||||
|
expect(abilities.createTeam).toEqual(false);
|
||||||
|
expect(abilities.createAttachment).toEqual(true);
|
||||||
|
expect(abilities.createCollection).toEqual(true);
|
||||||
|
expect(abilities.createDocument).toEqual(true);
|
||||||
|
expect(abilities.createGroup).toEqual(true);
|
||||||
|
expect(abilities.createIntegration).toEqual(true);
|
||||||
});
|
});
|
||||||
const abilities = serialize(admin, team);
|
|
||||||
expect(abilities.read).toEqual(true);
|
|
||||||
expect(abilities.createTeam).toEqual(false);
|
|
||||||
expect(abilities.createAttachment).toEqual(true);
|
|
||||||
expect(abilities.createCollection).toEqual(true);
|
|
||||||
expect(abilities.createDocument).toEqual(true);
|
|
||||||
expect(abilities.createGroup).toEqual(true);
|
|
||||||
expect(abilities.createIntegration).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should allow creation on hosted envs", async () => {
|
it("should allow creation on hosted envs", async () => {
|
||||||
setCloudHosted();
|
const team = await buildTeam();
|
||||||
|
const admin = await buildAdmin({
|
||||||
const team = await buildTeam();
|
teamId: team.id,
|
||||||
const admin = await buildAdmin({
|
});
|
||||||
teamId: team.id,
|
const abilities = serialize(admin, team);
|
||||||
|
expect(abilities.read).toEqual(true);
|
||||||
|
expect(abilities.createTeam).toEqual(true);
|
||||||
|
expect(abilities.createAttachment).toEqual(true);
|
||||||
|
expect(abilities.createCollection).toEqual(true);
|
||||||
|
expect(abilities.createDocument).toEqual(true);
|
||||||
|
expect(abilities.createGroup).toEqual(true);
|
||||||
|
expect(abilities.createIntegration).toEqual(true);
|
||||||
});
|
});
|
||||||
const abilities = serialize(admin, team);
|
|
||||||
expect(abilities.read).toEqual(true);
|
|
||||||
expect(abilities.createTeam).toEqual(true);
|
|
||||||
expect(abilities.createAttachment).toEqual(true);
|
|
||||||
expect(abilities.createCollection).toEqual(true);
|
|
||||||
expect(abilities.createDocument).toEqual(true);
|
|
||||||
expect(abilities.createGroup).toEqual(true);
|
|
||||||
expect(abilities.createIntegration).toEqual(true);
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ allow(User, "share", Team, (user, team) => {
|
|||||||
|
|
||||||
allow(User, "createTeam", Team, () => {
|
allow(User, "createTeam", Team, () => {
|
||||||
if (!env.isCloudHosted) {
|
if (!env.isCloudHosted) {
|
||||||
throw IncorrectEditionError("Functionality is only available on cloud");
|
throw IncorrectEditionError(
|
||||||
|
"Functionality is not available in this edition"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -28,7 +30,9 @@ allow(User, "update", Team, (user, team) => {
|
|||||||
|
|
||||||
allow(User, ["delete", "audit"], Team, (user, team) => {
|
allow(User, ["delete", "audit"], Team, (user, team) => {
|
||||||
if (!env.isCloudHosted) {
|
if (!env.isCloudHosted) {
|
||||||
throw IncorrectEditionError("Functionality is only available on cloud");
|
throw IncorrectEditionError(
|
||||||
|
"Functionality is not available in this edition"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!team || user.isViewer || user.teamId !== team.id) {
|
if (!team || user.isViewer || user.teamId !== team.id) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("ImportMarkdownZipTask", () => {
|
|||||||
expect(response.collections.size).toEqual(1);
|
expect(response.collections.size).toEqual(1);
|
||||||
expect(response.documents.size).toEqual(8);
|
expect(response.documents.size).toEqual(8);
|
||||||
expect(response.attachments.size).toEqual(6);
|
expect(response.attachments.size).toEqual(6);
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it("should throw an error with corrupt zip", async () => {
|
it("should throw an error with corrupt zip", async () => {
|
||||||
const fileOperation = await buildFileOperation();
|
const fileOperation = await buildFileOperation();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { buildInvite } from "@server/test/factories";
|
|||||||
import InviteReminderTask from "./InviteReminderTask";
|
import InviteReminderTask from "./InviteReminderTask";
|
||||||
|
|
||||||
describe("InviteReminderTask", () => {
|
describe("InviteReminderTask", () => {
|
||||||
it("should not destroy documents not deleted", async () => {
|
it("should send reminder emails", async () => {
|
||||||
const spy = jest.spyOn(InviteReminderEmail.prototype, "schedule");
|
const spy = jest.spyOn(InviteReminderEmail.prototype, "schedule");
|
||||||
|
|
||||||
// too old
|
// too old
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ describe("#attachments.create", () => {
|
|||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
|
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
const attachment = await Attachment.findByPk(body.data.attachment.id);
|
const attachment = await Attachment.findByPk(body.data.attachment.id, {
|
||||||
expect(attachment!.expiresAt).toBeNull();
|
rejectOnEmpty: true,
|
||||||
|
});
|
||||||
|
expect(attachment.expiresAt).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow attachment creation for documents", async () => {
|
it("should allow attachment creation for documents", async () => {
|
||||||
@@ -71,8 +73,10 @@ describe("#attachments.create", () => {
|
|||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
|
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
const attachment = await Attachment.findByPk(body.data.attachment.id);
|
const attachment = await Attachment.findByPk(body.data.attachment.id, {
|
||||||
expect(attachment!.expiresAt).toBeTruthy();
|
rejectOnEmpty: true,
|
||||||
|
});
|
||||||
|
expect(attachment.expiresAt).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not allow attachment creation for other documents", async () => {
|
it("should not allow attachment creation for other documents", async () => {
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import { faker } from "@faker-js/faker";
|
import { faker } from "@faker-js/faker";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { buildUser, buildTeam } from "@server/test/factories";
|
import { buildUser, buildTeam } from "@server/test/factories";
|
||||||
import {
|
import { getTestServer, setSelfHosted } from "@server/test/support";
|
||||||
getTestServer,
|
|
||||||
setCloudHosted,
|
|
||||||
setSelfHosted,
|
|
||||||
} from "@server/test/support";
|
|
||||||
|
|
||||||
const mockTeamInSessionId = uuidv4();
|
const mockTeamInSessionId = uuidv4();
|
||||||
|
|
||||||
@@ -18,8 +14,6 @@ jest.mock("@server/utils/authentication", () => ({
|
|||||||
const server = getTestServer();
|
const server = getTestServer();
|
||||||
|
|
||||||
describe("#auth.info", () => {
|
describe("#auth.info", () => {
|
||||||
beforeEach(setCloudHosted);
|
|
||||||
|
|
||||||
it("should return current authentication", async () => {
|
it("should return current authentication", async () => {
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const team2 = await buildTeam();
|
const team2 = await buildTeam();
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ router.post("auth.config", async (ctx: APIContext<T.AuthConfigReq>) => {
|
|||||||
// brand for the knowledge base and it's guest signin option is used for the
|
// brand for the knowledge base and it's guest signin option is used for the
|
||||||
// root login page.
|
// root login page.
|
||||||
if (!env.isCloudHosted) {
|
if (!env.isCloudHosted) {
|
||||||
const team = await Team.scope("withAuthenticationProviders").findOne();
|
const team = await Team.scope("withAuthenticationProviders").findOne({
|
||||||
|
order: [["createdAt", "DESC"]],
|
||||||
|
});
|
||||||
|
|
||||||
if (team) {
|
if (team) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ import {
|
|||||||
buildEvent,
|
buildEvent,
|
||||||
buildUser,
|
buildUser,
|
||||||
} from "@server/test/factories";
|
} from "@server/test/factories";
|
||||||
import { getTestServer, setCloudHosted } from "@server/test/support";
|
import { getTestServer } from "@server/test/support";
|
||||||
|
|
||||||
const server = getTestServer();
|
const server = getTestServer();
|
||||||
|
|
||||||
describe("#events.list", () => {
|
describe("#events.list", () => {
|
||||||
beforeEach(setCloudHosted);
|
|
||||||
|
|
||||||
it("should only return activity events", async () => {
|
it("should only return activity events", async () => {
|
||||||
const user = await buildUser();
|
const user = await buildUser();
|
||||||
const admin = await buildAdmin({ teamId: user.teamId });
|
const admin = await buildAdmin({ teamId: user.teamId });
|
||||||
|
|||||||
@@ -6,34 +6,28 @@ import {
|
|||||||
buildTeam,
|
buildTeam,
|
||||||
buildUser,
|
buildUser,
|
||||||
} from "@server/test/factories";
|
} from "@server/test/factories";
|
||||||
import {
|
import { getTestServer, setSelfHosted } from "@server/test/support";
|
||||||
getTestServer,
|
|
||||||
setCloudHosted,
|
|
||||||
setSelfHosted,
|
|
||||||
} from "@server/test/support";
|
|
||||||
|
|
||||||
const server = getTestServer();
|
const server = getTestServer();
|
||||||
|
|
||||||
describe("teams.create", () => {
|
describe("teams.create", () => {
|
||||||
it("creates a team", async () => {
|
it("creates a team", async () => {
|
||||||
setCloudHosted();
|
|
||||||
|
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const user = await buildAdmin({ teamId: team.id });
|
const user = await buildAdmin({ teamId: team.id });
|
||||||
|
const name = faker.company.name();
|
||||||
const res = await server.post("/api/teams.create", {
|
const res = await server.post("/api/teams.create", {
|
||||||
body: {
|
body: {
|
||||||
token: user.getJwtToken(),
|
token: user.getJwtToken(),
|
||||||
name: "factory inc",
|
name,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(body.data.team.name).toEqual("factory inc");
|
expect(body.data.team.name).toEqual(name);
|
||||||
expect(body.data.team.subdomain).toEqual("factory-inc");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("requires a cloud hosted deployment", async () => {
|
it.skip("requires a cloud hosted deployment", async () => {
|
||||||
await setSelfHosted();
|
setSelfHosted();
|
||||||
|
|
||||||
const team = await buildTeam();
|
const team = await buildTeam();
|
||||||
const user = await buildAdmin({ teamId: team.id });
|
const user = await buildAdmin({ teamId: team.id });
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ import { buildDocument, buildUser } from "@server/test/factories";
|
|||||||
import { getTestServer } from "@server/test/support";
|
import { getTestServer } from "@server/test/support";
|
||||||
import resolvers from "@server/utils/unfurl";
|
import resolvers from "@server/utils/unfurl";
|
||||||
|
|
||||||
jest.mock("@server/utils/unfurl", () => ({
|
jest
|
||||||
Iframely: {
|
.spyOn(resolvers.Iframely, "unfurl")
|
||||||
unfurl: jest.fn(),
|
.mockImplementation(async (_: string) => false);
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const server = getTestServer();
|
const server = getTestServer();
|
||||||
|
|
||||||
@@ -166,6 +164,7 @@ describe("#urls.unfurl", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200);
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
|
|
||||||
expect(resolvers.Iframely.unfurl).toHaveBeenCalledWith(
|
expect(resolvers.Iframely.unfurl).toHaveBeenCalledWith(
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ env.OIDC_USERINFO_URI = "http://localhost/userinfo";
|
|||||||
|
|
||||||
env.RATE_LIMITER_ENABLED = false;
|
env.RATE_LIMITER_ENABLED = false;
|
||||||
|
|
||||||
|
env.IFRAMELY_API_KEY = "123";
|
||||||
|
|
||||||
if (process.env.DATABASE_URL_TEST) {
|
if (process.env.DATABASE_URL_TEST) {
|
||||||
env.DATABASE_URL = process.env.DATABASE_URL_TEST;
|
env.DATABASE_URL = process.env.DATABASE_URL_TEST;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { faker } from "@faker-js/faker";
|
import { faker } from "@faker-js/faker";
|
||||||
import isNil from "lodash/isNil";
|
import isNil from "lodash/isNil";
|
||||||
import isNull from "lodash/isNull";
|
import isNull from "lodash/isNull";
|
||||||
|
import randomstring from "randomstring";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import {
|
import {
|
||||||
CollectionPermission,
|
CollectionPermission,
|
||||||
@@ -23,7 +24,6 @@ import {
|
|||||||
Attachment,
|
Attachment,
|
||||||
IntegrationAuthentication,
|
IntegrationAuthentication,
|
||||||
Integration,
|
Integration,
|
||||||
AuthenticationProvider,
|
|
||||||
FileOperation,
|
FileOperation,
|
||||||
WebhookSubscription,
|
WebhookSubscription,
|
||||||
WebhookDelivery,
|
WebhookDelivery,
|
||||||
@@ -77,7 +77,9 @@ export async function buildStar(overrides: Partial<Star> = {}) {
|
|||||||
let user;
|
let user;
|
||||||
|
|
||||||
if (overrides.userId) {
|
if (overrides.userId) {
|
||||||
user = await User.findByPk(overrides.userId);
|
user = await User.findByPk(overrides.userId, {
|
||||||
|
rejectOnEmpty: true,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
user = await buildUser();
|
user = await buildUser();
|
||||||
overrides.userId = user.id;
|
overrides.userId = user.id;
|
||||||
@@ -86,7 +88,7 @@ export async function buildStar(overrides: Partial<Star> = {}) {
|
|||||||
if (!overrides.documentId) {
|
if (!overrides.documentId) {
|
||||||
const document = await buildDocument({
|
const document = await buildDocument({
|
||||||
createdById: overrides.userId,
|
createdById: overrides.userId,
|
||||||
teamId: user?.teamId,
|
teamId: user.teamId,
|
||||||
});
|
});
|
||||||
overrides.documentId = document.id;
|
overrides.documentId = document.id;
|
||||||
}
|
}
|
||||||
@@ -101,7 +103,9 @@ export async function buildSubscription(overrides: Partial<Subscription> = {}) {
|
|||||||
let user;
|
let user;
|
||||||
|
|
||||||
if (overrides.userId) {
|
if (overrides.userId) {
|
||||||
user = await User.findByPk(overrides.userId);
|
user = await User.findByPk(overrides.userId, {
|
||||||
|
rejectOnEmpty: true,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
user = await buildUser();
|
user = await buildUser();
|
||||||
overrides.userId = user.id;
|
overrides.userId = user.id;
|
||||||
@@ -110,7 +114,7 @@ export async function buildSubscription(overrides: Partial<Subscription> = {}) {
|
|||||||
if (!overrides.documentId) {
|
if (!overrides.documentId) {
|
||||||
const document = await buildDocument({
|
const document = await buildDocument({
|
||||||
createdById: overrides.userId,
|
createdById: overrides.userId,
|
||||||
teamId: user?.teamId,
|
teamId: user.teamId,
|
||||||
});
|
});
|
||||||
overrides.documentId = document.id;
|
overrides.documentId = document.id;
|
||||||
}
|
}
|
||||||
@@ -129,7 +133,7 @@ export function buildTeam(overrides: Record<string, any> = {}) {
|
|||||||
authenticationProviders: [
|
authenticationProviders: [
|
||||||
{
|
{
|
||||||
name: "slack",
|
name: "slack",
|
||||||
providerId: uuidv4().replace(/-/g, ""),
|
providerId: randomstring.generate(32),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
...overrides,
|
...overrides,
|
||||||
@@ -170,14 +174,14 @@ export async function buildUser(overrides: Partial<User> = {}) {
|
|||||||
team = await buildTeam();
|
team = await buildTeam();
|
||||||
overrides.teamId = team.id;
|
overrides.teamId = team.id;
|
||||||
} else {
|
} else {
|
||||||
team = await Team.findByPk(overrides.teamId);
|
team = await Team.findByPk(overrides.teamId, {
|
||||||
|
include: "authenticationProviders",
|
||||||
|
rejectOnEmpty: true,
|
||||||
|
paranoid: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const authenticationProvider = await AuthenticationProvider.findOne({
|
const authenticationProvider = team.authenticationProviders[0];
|
||||||
where: {
|
|
||||||
teamId: overrides.teamId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const user = await User.create(
|
const user = await User.create(
|
||||||
{
|
{
|
||||||
email: faker.internet.email().toLowerCase(),
|
email: faker.internet.email().toLowerCase(),
|
||||||
@@ -185,12 +189,14 @@ export async function buildUser(overrides: Partial<User> = {}) {
|
|||||||
createdAt: new Date("2018-01-01T00:00:00.000Z"),
|
createdAt: new Date("2018-01-01T00:00:00.000Z"),
|
||||||
updatedAt: new Date("2018-01-02T00:00:00.000Z"),
|
updatedAt: new Date("2018-01-02T00:00:00.000Z"),
|
||||||
lastActiveAt: new Date("2018-01-03T00:00:00.000Z"),
|
lastActiveAt: new Date("2018-01-03T00:00:00.000Z"),
|
||||||
authentications: [
|
authentications: authenticationProvider
|
||||||
{
|
? [
|
||||||
authenticationProviderId: authenticationProvider!.id,
|
{
|
||||||
providerId: uuidv4().replace(/-/g, ""),
|
authenticationProviderId: authenticationProvider.id,
|
||||||
},
|
providerId: randomstring.generate(32),
|
||||||
],
|
},
|
||||||
|
]
|
||||||
|
: [],
|
||||||
...overrides,
|
...overrides,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -244,7 +250,7 @@ export async function buildIntegration(overrides: Partial<Integration> = {}) {
|
|||||||
service: IntegrationService.Slack,
|
service: IntegrationService.Slack,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
teamId: user.teamId,
|
teamId: user.teamId,
|
||||||
token: "fake-access-token",
|
token: randomstring.generate(32),
|
||||||
scopes: ["example", "scopes", "here"],
|
scopes: ["example", "scopes", "here"],
|
||||||
});
|
});
|
||||||
return Integration.create({
|
return Integration.create({
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import sharedEnv from "@shared/env";
|
||||||
|
import env from "@server/env";
|
||||||
import Redis from "@server/storage/redis";
|
import Redis from "@server/storage/redis";
|
||||||
|
|
||||||
require("@server/storage/database");
|
require("@server/storage/database");
|
||||||
@@ -22,3 +24,7 @@ jest.mock("aws-sdk", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => Redis.defaultClient.disconnect());
|
afterAll(() => Redis.defaultClient.disconnect());
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
env.URL = sharedEnv.URL = "https://app.outline.dev";
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
|
import { faker } from "@faker-js/faker";
|
||||||
import TestServer from "fetch-test-server";
|
import TestServer from "fetch-test-server";
|
||||||
import { WhereOptions } from "sequelize";
|
|
||||||
import sharedEnv from "@shared/env";
|
import sharedEnv from "@shared/env";
|
||||||
import env from "@server/env";
|
import env from "@server/env";
|
||||||
import { Event, Team } from "@server/models";
|
|
||||||
import onerror from "@server/onerror";
|
import onerror from "@server/onerror";
|
||||||
import webService from "@server/services/web";
|
import webService from "@server/services/web";
|
||||||
import { sequelize } from "@server/storage/database";
|
import { sequelize } from "@server/storage/database";
|
||||||
@@ -18,32 +17,13 @@ export function getTestServer() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
afterAll(server.disconnect);
|
afterAll(server.disconnect);
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return server;
|
||||||
* Set the environment to be cloud hosted.
|
|
||||||
*/
|
|
||||||
export function setCloudHosted() {
|
|
||||||
return (env.URL = sharedEnv.URL = "https://app.outline.dev");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the environment to be self hosted.
|
* Set the environment to be self hosted.
|
||||||
*/
|
*/
|
||||||
export async function setSelfHosted() {
|
export function setSelfHosted() {
|
||||||
env.URL = sharedEnv.URL = "https://wiki.example.com";
|
env.URL = sharedEnv.URL = `https://${faker.internet.domainName()}`;
|
||||||
|
|
||||||
// Self hosted deployments only have one team, to ensure behavior is correct
|
|
||||||
// we need to delete all teams before running tests
|
|
||||||
return Team.destroy({
|
|
||||||
truncate: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function findLatestEvent(where: WhereOptions<Event> = {}) {
|
|
||||||
return Event.findOne({
|
|
||||||
where,
|
|
||||||
order: [["createdAt", "DESC"]],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,11 @@ export async function getTeamFromContext(ctx: Context) {
|
|||||||
|
|
||||||
let team;
|
let team;
|
||||||
if (!env.isCloudHosted) {
|
if (!env.isCloudHosted) {
|
||||||
team = await Team.findOne();
|
if (env.ENVIRONMENT === "test") {
|
||||||
|
team = await Team.findOne({ where: { domain: env.URL } });
|
||||||
|
} else {
|
||||||
|
team = await Team.findOne();
|
||||||
|
}
|
||||||
} else if (domain.custom) {
|
} else if (domain.custom) {
|
||||||
team = await Team.findOne({ where: { domain: domain.host } });
|
team = await Team.findOne({ where: { domain: domain.host } });
|
||||||
} else if (domain.teamSubdomain) {
|
} else if (domain.teamSubdomain) {
|
||||||
|
|||||||
@@ -1,41 +1,42 @@
|
|||||||
import { existsSync } from "fs";
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import glob from "glob";
|
import glob from "glob";
|
||||||
import startCase from "lodash/startCase";
|
|
||||||
import env from "@server/env";
|
import env from "@server/env";
|
||||||
import Logger from "@server/logging/Logger";
|
import Logger from "@server/logging/Logger";
|
||||||
import { UnfurlResolver } from "@server/types";
|
import { UnfurlResolver } from "@server/types";
|
||||||
|
|
||||||
const rootDir = env.ENVIRONMENT === "test" ? "" : "build";
|
const rootDir = env.ENVIRONMENT === "test" ? "" : "build";
|
||||||
|
|
||||||
const hasResolver = (plugin: string) => {
|
const plugins = glob.sync(path.join(rootDir, "plugins/*/server/unfurl.[jt]s"));
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
const resolvers: Record<string, UnfurlResolver> = plugins.reduce(
|
||||||
const config = require(path.join(process.cwd(), plugin, "plugin.json"));
|
(resolvers, filePath) => {
|
||||||
|
|
||||||
return (
|
|
||||||
existsSync(resolverPath(plugin)) &&
|
|
||||||
(config.requiredEnvVars ?? []).every((name: string) => !!env[name])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const resolverPath = (plugin: string) =>
|
|
||||||
path.join(plugin, "server", "unfurl.js");
|
|
||||||
|
|
||||||
const plugins = glob.sync(path.join(rootDir, "plugins/*"));
|
|
||||||
const resolvers: Record<string, UnfurlResolver> = plugins
|
|
||||||
.filter(hasResolver)
|
|
||||||
.map(resolverPath)
|
|
||||||
.reduce((resolvers, resolverPath) => {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const resolver: UnfurlResolver = require(path.join(
|
const resolver: UnfurlResolver = require(path.join(
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
resolverPath
|
filePath
|
||||||
));
|
));
|
||||||
const name = startCase(resolverPath.split("/")[2]);
|
const id = filePath.replace("build/", "").split("/")[1];
|
||||||
resolvers[name] = resolver;
|
const config = require(path.join(
|
||||||
Logger.debug("utils", `Registered unfurl resolver ${resolverPath}`);
|
process.cwd(),
|
||||||
|
rootDir,
|
||||||
|
"plugins",
|
||||||
|
id,
|
||||||
|
"plugin.json"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Test the all required env vars are set for the resolver
|
||||||
|
const enabled = (config.requiredEnvVars ?? []).every(
|
||||||
|
(name: string) => !!env[name]
|
||||||
|
);
|
||||||
|
if (!enabled) {
|
||||||
|
return resolvers;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvers[config.name] = resolver;
|
||||||
|
Logger.debug("utils", `Registered unfurl resolver ${filePath}`);
|
||||||
|
|
||||||
return resolvers;
|
return resolvers;
|
||||||
}, {});
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
export default resolvers;
|
export default resolvers;
|
||||||
|
|||||||
Reference in New Issue
Block a user