1import { vol } from 'memfs';
2
3import { CreateFileMiddleware } from '../CreateFileMiddleware';
4import { ServerRequest, ServerResponse } from '../server.types';
5
6const asReq = (req: Partial<ServerRequest>) => req as ServerRequest;
7
8afterEach(() => {
9  vol.reset();
10});
11
12function createMiddleware() {
13  vol.fromJSON({}, '/');
14
15  const middleware = new CreateFileMiddleware('/');
16  middleware['parseRawBody'] = jest.fn((req) => JSON.parse((req as any).body));
17  return { middleware };
18}
19
20function createMockResponse() {
21  return {
22    setHeader: jest.fn(),
23    end: jest.fn(),
24    statusCode: 200,
25  } as unknown as ServerResponse;
26}
27
28describe('_shouldHandleRequest', () => {
29  const { middleware } = createMiddleware();
30
31  it(`returns false when the middleware should not handle`, () => {
32    for (const req of [
33      asReq({}),
34      asReq({ url: 'http://localhost:8081' }),
35      asReq({ url: 'http://localhost:8081/' }),
36    ]) {
37      expect(middleware._shouldHandleRequest(req)).toBe(false);
38    }
39  });
40  it(`returns true when the middleware should handle`, () => {
41    for (const req of [asReq({ url: 'http://localhost:8081/_expo/touch' })]) {
42      expect(middleware._shouldHandleRequest(req)).toBe(true);
43    }
44  });
45});
46
47describe('handleRequestAsync', () => {
48  it('refuses non-POST', async () => {
49    const { middleware } = createMiddleware();
50
51    const response = createMockResponse();
52    await middleware.handleRequestAsync(
53      asReq({
54        url: 'http://localhost:8081/_expo/touch',
55      }),
56      response
57    );
58    expect(response.statusCode).toBe(405);
59    expect(response.end).toBeCalledWith('Method Not Allowed');
60  });
61  it('creates a basic file', async () => {
62    const { middleware } = createMiddleware();
63
64    const response = createMockResponse();
65    await middleware.handleRequestAsync(
66      asReq({
67        url: 'http://localhost:8081/_expo/touch',
68        method: 'POST',
69        body: JSON.stringify({
70          contents: 'hello world',
71          path: '/hello.txt',
72        }),
73      }),
74      response
75    );
76    expect(response.statusCode).toBe(200);
77    expect(response.end).toBeCalledWith('OK');
78    expect(vol.readFileSync('/hello.txt', 'utf8')).toBe('hello world');
79  });
80  it('creates a TypeScript file when added to a project with a tsconfig', async () => {
81    vol.writeFileSync('/tsconfig.json', JSON.stringify({ compilerOptions: {} }));
82
83    const { middleware } = createMiddleware();
84
85    const response = createMockResponse();
86    await middleware.handleRequestAsync(
87      asReq({
88        url: 'http://localhost:8081/_expo/touch',
89        method: 'POST',
90        body: JSON.stringify({
91          contents: 'hello world',
92          path: '/hello.js',
93        }),
94      }),
95      response
96    );
97    expect(response.statusCode).toBe(200);
98    expect(response.end).toBeCalledWith('OK');
99    expect(vol.readFileSync('/hello.tsx', 'utf8')).toBe('hello world');
100  });
101  it('creates a basic JavaScript file', async () => {
102    const { middleware } = createMiddleware();
103
104    const response = createMockResponse();
105    await middleware.handleRequestAsync(
106      asReq({
107        url: 'http://localhost:8081/_expo/touch',
108        method: 'POST',
109        body: JSON.stringify({
110          contents: 'hello world',
111          path: '/hello.js',
112        }),
113      }),
114      response
115    );
116    expect(response.statusCode).toBe(200);
117    expect(response.end).toBeCalledWith('OK');
118    expect(vol.readFileSync('/hello.js', 'utf8')).toBe('hello world');
119  });
120});
121