mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 09:37:17 +00:00
496 lines
11 KiB
TypeScript
496 lines
11 KiB
TypeScript
import { knex } from "../../db";
|
|
import SkinModel from "../../data/SkinModel";
|
|
import * as S3 from "../../s3";
|
|
import { processUserUploads } from "../processUserUploads";
|
|
import UserContext from "../../data/UserContext";
|
|
import { client } from "../../algolia";
|
|
import { createYogaInstance } from "../../app/graphql/yoga";
|
|
import { YogaServerInstance } from "graphql-yoga";
|
|
jest.mock("../../s3");
|
|
jest.mock("../../algolia");
|
|
jest.mock("../processUserUploads");
|
|
jest.mock("../auth");
|
|
|
|
let yoga: YogaServerInstance<any, any>;
|
|
const handler = jest.fn();
|
|
const log = jest.fn();
|
|
const logError = jest.fn();
|
|
|
|
let username: string | undefined;
|
|
|
|
beforeEach(async () => {
|
|
jest.clearAllMocks();
|
|
username = "<MOCKED>";
|
|
yoga = createYogaInstance({
|
|
eventHandler: handler,
|
|
getUserContext: () => new UserContext(username),
|
|
logger: { log, logError },
|
|
});
|
|
await knex.migrate.latest();
|
|
await knex.seed.run();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await knex.destroy();
|
|
});
|
|
|
|
function gql(templateString: TemplateStringsArray): string {
|
|
return templateString[0];
|
|
}
|
|
|
|
async function graphQLRequest(query: string, variables?: any) {
|
|
const response = await yoga.fetch("/graphql", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ query, variables }),
|
|
});
|
|
const body = await response.json();
|
|
if (body.errors && body.errors.length) {
|
|
for (const err of body.errors) {
|
|
console.warn(err.message);
|
|
console.warn("Stack", err.stack);
|
|
}
|
|
}
|
|
|
|
return body;
|
|
}
|
|
|
|
test(".node", async () => {
|
|
const { data } = await graphQLRequest(gql`
|
|
query {
|
|
skins(first: 1) {
|
|
nodes {
|
|
id
|
|
md5
|
|
}
|
|
}
|
|
}
|
|
`);
|
|
const skin = data.skins.nodes[0];
|
|
expect(skin.id).toEqual("Q2xhc3NpY1NraW5fX2FfZmFrZV9tZDU=");
|
|
|
|
const { data: data2 } = await graphQLRequest(
|
|
gql`
|
|
query MyQuery($id: ID!) {
|
|
node(id: $id) {
|
|
... on Skin {
|
|
md5
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{ id: skin.id }
|
|
);
|
|
expect(data2.node).toEqual({ md5: skin.md5 });
|
|
});
|
|
|
|
describe(".me", () => {
|
|
test("logged in ", async () => {
|
|
const { data } = await graphQLRequest(gql`
|
|
query {
|
|
me {
|
|
username
|
|
}
|
|
}
|
|
`);
|
|
expect(data).toEqual({ me: { username: "<MOCKED>" } });
|
|
});
|
|
test("not logged in", async () => {
|
|
username = undefined;
|
|
const { data } = await graphQLRequest(gql`
|
|
query {
|
|
me {
|
|
username
|
|
}
|
|
}
|
|
`);
|
|
expect(data).toEqual({ me: { username: null } });
|
|
});
|
|
});
|
|
|
|
describe("Query.skins", () => {
|
|
test("no query params", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
query {
|
|
skins(sort: MUSEUM) {
|
|
count
|
|
nodes {
|
|
... on ClassicSkin {
|
|
md5
|
|
filename
|
|
nsfw
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`
|
|
);
|
|
expect(data.skins).toMatchInlineSnapshot(`
|
|
{
|
|
"count": 6,
|
|
"nodes": [
|
|
{
|
|
"filename": "tweeted.wsz",
|
|
"md5": "a_tweeted_md5",
|
|
"nsfw": false,
|
|
},
|
|
{
|
|
"filename": "Zelda_Amp_3.wsz",
|
|
"md5": "48bbdbbeb03d347e59b1eebda4d352d0",
|
|
"nsfw": false,
|
|
},
|
|
{
|
|
"filename": "path.wsz",
|
|
"md5": "a_fake_md5",
|
|
"nsfw": false,
|
|
},
|
|
{
|
|
"filename": "approved.wsz",
|
|
"md5": "an_approved_md5",
|
|
"nsfw": false,
|
|
},
|
|
{
|
|
"filename": "rejected.wsz",
|
|
"md5": "a_rejected_md5",
|
|
"nsfw": false,
|
|
},
|
|
{
|
|
"filename": "nsfw.wsz",
|
|
"md5": "a_nsfw_md5",
|
|
"nsfw": true,
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
test("first and offset", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
query MyQuery($first: Int, $offset: Int) {
|
|
skins(first: $first, offset: $offset, sort: MUSEUM) {
|
|
count
|
|
nodes {
|
|
... on ClassicSkin {
|
|
md5
|
|
filename
|
|
nsfw
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{ first: 2, offset: 1 }
|
|
);
|
|
expect(data.skins).toMatchInlineSnapshot(`
|
|
{
|
|
"count": 6,
|
|
"nodes": [
|
|
{
|
|
"filename": "Zelda_Amp_3.wsz",
|
|
"md5": "48bbdbbeb03d347e59b1eebda4d352d0",
|
|
"nsfw": false,
|
|
},
|
|
{
|
|
"filename": "path.wsz",
|
|
"md5": "a_fake_md5",
|
|
"nsfw": false,
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
});
|
|
|
|
// TODO: Upgrade Grats
|
|
test("Query.fetch_skin_by_md5 (debug data)", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
query MyQuery($md5: String!) {
|
|
fetch_skin_by_md5(md5: $md5) {
|
|
... on ClassicSkin {
|
|
id
|
|
md5
|
|
museum_url
|
|
webamp_url
|
|
screenshot_url
|
|
download_url
|
|
filename
|
|
readme_text
|
|
nsfw
|
|
average_color
|
|
tweeted
|
|
tweets {
|
|
url
|
|
}
|
|
archive_files {
|
|
filename
|
|
url
|
|
date
|
|
file_md5
|
|
size
|
|
text_content
|
|
is_directory
|
|
skin {
|
|
md5
|
|
}
|
|
}
|
|
filename
|
|
internet_archive_item {
|
|
identifier
|
|
url
|
|
metadata_url
|
|
raw_metadata_json
|
|
skin {
|
|
md5
|
|
}
|
|
}
|
|
reviews {
|
|
skin {
|
|
md5
|
|
}
|
|
reviewer
|
|
rating
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{ md5: "a_fake_md5" }
|
|
);
|
|
expect(data).toMatchSnapshot();
|
|
});
|
|
|
|
test("Mutation.request_nsfw_review_for_skin", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
mutation ($md5: String!) {
|
|
request_nsfw_review_for_skin(md5: $md5)
|
|
}
|
|
`,
|
|
{ md5: "a_fake_md5" }
|
|
);
|
|
expect(handler).toHaveBeenCalledWith({
|
|
type: "REVIEW_REQUESTED",
|
|
md5: "a_fake_md5",
|
|
});
|
|
expect(data).toEqual({ request_nsfw_review_for_skin: true });
|
|
});
|
|
|
|
test("Mutation.approve_skin", async () => {
|
|
const ctx = new UserContext();
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
mutation ($md5: String!) {
|
|
approve_skin(md5: $md5)
|
|
}
|
|
`,
|
|
{ md5: "a_fake_md5" }
|
|
);
|
|
expect(handler).toHaveBeenCalledWith({
|
|
type: "APPROVED_SKIN",
|
|
md5: "a_fake_md5",
|
|
});
|
|
expect(data).toEqual({ approve_skin: true });
|
|
const skin = await SkinModel.fromMd5(ctx, "a_fake_md5");
|
|
|
|
expect(await skin?.getTweetStatus()).toEqual("APPROVED");
|
|
});
|
|
|
|
test("Mutation.reject_skin", async () => {
|
|
const ctx = new UserContext();
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
mutation ($md5: String!) {
|
|
reject_skin(md5: $md5)
|
|
}
|
|
`,
|
|
{ md5: "a_fake_md5" }
|
|
);
|
|
expect(handler).toHaveBeenCalledWith({
|
|
type: "REJECTED_SKIN",
|
|
md5: "a_fake_md5",
|
|
});
|
|
expect(data).toEqual({ reject_skin: true });
|
|
const skin = await SkinModel.fromMd5(ctx, "a_fake_md5");
|
|
|
|
expect(await skin?.getTweetStatus()).toEqual("REJECTED");
|
|
});
|
|
|
|
test("Mutation.mark_skin_nsfw", async () => {
|
|
const ctx = new UserContext();
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
mutation ($md5: String!) {
|
|
mark_skin_nsfw(md5: $md5)
|
|
}
|
|
`,
|
|
{ md5: "a_fake_md5" }
|
|
);
|
|
expect(handler).toHaveBeenCalledWith({
|
|
type: "MARKED_SKIN_NSFW",
|
|
md5: "a_fake_md5",
|
|
});
|
|
expect(client.partialUpdateObjects).toHaveBeenCalledWith({
|
|
indexName: "test-index",
|
|
objects: [{ nsfw: true, objectID: "a_fake_md5" }],
|
|
});
|
|
expect(data).toEqual({ mark_skin_nsfw: true });
|
|
const skin = await SkinModel.fromMd5(ctx, "a_fake_md5");
|
|
|
|
expect(await skin?.getTweetStatus()).toEqual("NSFW");
|
|
});
|
|
|
|
describe("Query.skin_to_review", () => {
|
|
test("logged in ", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
query {
|
|
skin_to_review {
|
|
md5
|
|
filename
|
|
}
|
|
}
|
|
`
|
|
);
|
|
|
|
expect(data).toEqual({
|
|
skin_to_review: {
|
|
filename: expect.any(String),
|
|
md5: expect.any(String),
|
|
},
|
|
});
|
|
});
|
|
test("not logged in ", async () => {
|
|
username = undefined;
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
query {
|
|
skin_to_review {
|
|
md5
|
|
filename
|
|
}
|
|
}
|
|
`
|
|
);
|
|
expect(data).toEqual({ skin_to_review: null });
|
|
});
|
|
});
|
|
|
|
// TODO: Actually upload some skins?
|
|
test("Query.upload_statuses_by_md5", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
query ($md5s: [String!]!) {
|
|
upload_statuses_by_md5(md5s: $md5s) {
|
|
id
|
|
status
|
|
upload_md5
|
|
}
|
|
}
|
|
`,
|
|
{ md5s: ["a_fake_md5", "a_missing_md5"] }
|
|
);
|
|
expect(data.upload_statuses_by_md5).toEqual([]);
|
|
});
|
|
|
|
test("Mutation.upload.get_upload_urls", async () => {
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
mutation ($files: [UploadUrlRequest!]!) {
|
|
upload {
|
|
get_upload_urls(files: $files) {
|
|
id
|
|
url
|
|
md5
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{
|
|
files: [
|
|
{
|
|
md5: "3b73bcd43c30b85d4cad3083e8ac9695",
|
|
filename: "a_fake_new_file.wsz",
|
|
},
|
|
{
|
|
md5: "48bbdbbeb03d347e59b1eebda4d352d0",
|
|
filename: "a_new_name_for_a_file_that_exists.wsz",
|
|
},
|
|
],
|
|
}
|
|
);
|
|
|
|
expect(S3.getSkinUploadUrl).toHaveBeenCalledWith(
|
|
"3b73bcd43c30b85d4cad3083e8ac9695",
|
|
expect.any(Number)
|
|
);
|
|
|
|
expect(data.upload.get_upload_urls).toEqual([
|
|
{
|
|
md5: "3b73bcd43c30b85d4cad3083e8ac9695",
|
|
id: expect.any(String),
|
|
url: "<MOCK_S3_UPLOAD_URL>",
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("An Upload Flow", async () => {
|
|
// Request an upload URL
|
|
const md5 = "3b73bcd43c30b85d4cad3083e8ac9695";
|
|
const filename = "a_fake_new_file.wsz";
|
|
const { data } = await graphQLRequest(
|
|
gql`
|
|
mutation ($files: [UploadUrlRequest!]!) {
|
|
upload {
|
|
get_upload_urls(files: $files) {
|
|
id
|
|
url
|
|
md5
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{ files: [{ md5, filename }] }
|
|
);
|
|
|
|
expect(data.upload.get_upload_urls).toEqual([
|
|
{
|
|
md5,
|
|
id: expect.any(String),
|
|
url: "<MOCK_S3_UPLOAD_URL>",
|
|
},
|
|
]);
|
|
|
|
const id = data.upload.get_upload_urls[0].id;
|
|
|
|
const requestedUpload = await knex("skin_uploads").where({ id }).first();
|
|
expect(requestedUpload).toEqual({
|
|
filename,
|
|
id: Number(id),
|
|
skin_md5: md5,
|
|
status: "URL_REQUESTED",
|
|
});
|
|
|
|
// Report that we've uploaded the skin to S3 (we lie)
|
|
const { data: uploadReportData } = await graphQLRequest(
|
|
gql`
|
|
mutation ($id: String!, $md5: String!) {
|
|
upload {
|
|
report_skin_uploaded(id: $id, md5: $md5)
|
|
}
|
|
}
|
|
`,
|
|
{ md5, id }
|
|
);
|
|
expect(uploadReportData.upload.report_skin_uploaded).toEqual(true);
|
|
expect(processUserUploads).toHaveBeenCalled();
|
|
|
|
const reportedUpload = await knex("skin_uploads").where({ id }).first();
|
|
expect(reportedUpload).toEqual({
|
|
filename,
|
|
id: Number(id),
|
|
skin_md5: md5,
|
|
status: "UPLOAD_REPORTED",
|
|
});
|
|
});
|