Source: tests/search/book-info.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 a fake account for testing
 * 
 * @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()
        });
}

/**
 * Saves an image from a URL to a temporary file
 * 
 * @param {string} url
 * @returns {Promise<string>}
 */
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;
}

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 retrieving book info", () => {
    beforeAll(() => {
        return initializeTestDB();
    });

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

    test("Successful info retrieved (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) => {
                                expect(response.statusCode).toBe(200);
                                
                                return request(app)
                                    .get("/v1/book")
                                    .query({ isbn })
                                    .set('Authorization', token)
                                    .then((response) => {
                                        expect(response.statusCode).toBe(200);

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

            });
    }, 30 * 1000);

    test("Invalid token (401)", () => {
        return request(app)
            .get("/v1/book")
            .query({ isbn: randomValidISBN() })
            .set('Authorization', faker.string.alphanumeric(32))
            .then((response) => {
                expect(response.statusCode).toBe(401);
            });
    });

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

                return request(app)
                    .get("/v1/book")
                    .set('Authorization', token)
                    .then((response) => {
                        expect(response.statusCode).toBe(400);
                    });
            });
    });

    test("Book not found (404)", () => {
        return createAccount()
            .then((response) => {
                const token = response.body.token;

                return request(app)
                    .get("/v1/book")
                    .query({ isbn: faker.commerce.isbn() })
                    .set('Authorization', token)
                    .then((response) => {
                        expect(response.statusCode).toBe(404);
                    });
            });
    });
});