Source: tests/contributing/add-edition.test.js

/** @module test */

const request = require("supertest");
const { faker } = require('@faker-js/faker');
const app = require("../../app");
const { initializeTestDB, closeTestDB } = require("../mysql-test");
const fs = require('fs');

/**
 * Creates an account in the database
 * @returns {request.SuperTestStatic.Test}
 */
function createAccount() {
    return request(app)
        .post("/v1/user/register")
        .send({
            method: 'email',
            email: faker.internet.email(),
            password: faker.internet.password(),
            name: faker.person.fullName()
        });
}

/**
 * Downloads an image from a URL and saves it to a temporary file
 * @param {string} url
 * @returns {string} pathToTempFile
 */
async function saveImageFromUrl(url) {
    if (!fs.existsSync(process.env.STORAGE_PATH + '/temp')) {
        fs.mkdirSync(process.env.STORAGE_PATH + '/temp', { recursive: true });
    }
    const filepath = process.env.STORAGE_PATH + '/temp/' + new Date().getTime() + '.jpg';

    const response = await fetch(url, { redirect: 'follow' });
    const buffer = await response.arrayBuffer();
    fs.writeFileSync(filepath, Buffer.from(buffer));
    return filepath;
}

/** Array containing some existing ISBN numbers for use in testing */
const isbns = [
    '9781603093491',
    '978-1-60309-384-2',
    '978-1-891830-91-4',
    '9781603090452',
    '1-60309-507-1',
    '1603095322'
];

/**
 * Generates a random valid ISBN
 * 
 * @returns {string}
 */
function randomValidISBN() {
    return isbns[Math.floor(Math.random() * isbns.length)];
}

describe("Test adding editions", () => {
    beforeAll(() => {
        return initializeTestDB();
    });

    afterAll(() => {
        return closeTestDB();
    });

    test("Successful edition addition (200)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;
                const imageUrl = faker.image.url();

                return saveImageFromUrl(imageUrl)
                    .then((filepath) => {
                        return request(app)
                            .post("/v1/contribute/edition/add")
                            .query({ isbn: randomValidISBN() })
                            .set('Authorization', token)
                            .attach('file', filepath)
                            .then((response) => {
                                expect(response.statusCode).toBe(200);

                                fs.unlinkSync(filepath);
                            });
                    });

            });
    }, 60 * 1000);

    test("Invalid token (401)", () => {
        return request(app)
            .post("/v1/contribute/edition/add")
            .query({ isbn: randomValidISBN() })
            .set('Authorization', faker.string.alphanumeric(32))
            .then((response) => {
                expect(response.statusCode).toBe(401);
            });
    }, 60 * 1000);

    test("Missing ISBN (400)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;

                return request(app)
                    .post("/v1/contribute/edition/add")
                    .set('Authorization', token)
                    .then((response) => {
                        expect(response.statusCode).toBe(400);
                    });
            });
    }, 60 * 1000);

    test("Invalid ISBN with letters (400)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;

                return request(app)
                    .post("/v1/contribute/edition/add")
                    .query({ isbn: faker.string.alphanumeric(10) })
                    .set('Authorization', token)
                    .then((response) => {
                        expect(response.statusCode).toBe(400);
                    });
            });
    }, 60 * 1000);

    test("Invalid ISBN with wrong length (400)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;

                return request(app)
                    .post("/v1/contribute/edition/add")
                    .query({ isbn: faker.string.numeric(9) })
                    .set('Authorization', token)
                    .then((response) => {
                        expect(response.statusCode).toBe(400);
                    });
            });
    }, 60 * 1000);

    test("Add image to existing edition (200)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;
                const imageUrl = faker.image.url();
                const isbn = randomValidISBN();

                return saveImageFromUrl(imageUrl)
                    .then((filepath) => {
                        return request(app)
                            .post("/v1/contribute/edition/add")
                            .query({ isbn })
                            .set('Authorization', token)
                            .attach('file', filepath)
                            .then((response) => {
                                return request(app)
                                    .post("/v1/contribute/edition/add")
                                    .query({ isbn })
                                    .set('Authorization', token)
                                    .attach('file', filepath)
                                    .then((response) => {
                                        expect(response.statusCode).toBe(200);

                                        fs.unlinkSync(filepath);
                                    });
                            });
                    });

            });
    }, 60 * 1000);

    test("Missing spine image (400)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;

                return request(app)
                    .post("/v1/contribute/edition/add")
                    .query({ isbn: randomValidISBN() })
                    .set('Authorization', token)
                    .then((response) => {
                        expect(response.statusCode).toBe(400);
                    });
            });
    }, 60 * 1000);
});