Coverage for test\test_cors.py: 100%

67 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-21 20:31 +0100

1# test_cors_with_app.py 

2import pytest 

3from nexios import get_application 

4from nexios.testing import Client 

5from nexios.config import MakeConfig 

6from nexios.middlewares.cors import CORSMiddleware 

7 

8 

9@pytest.fixture 

10async def cors_app(): 

11 # Create app with CORS configuration 

12 config = MakeConfig( 

13 { 

14 "cors": { 

15 "allow_origins": ["http://example.com", "https://example.org"], 

16 "allow_methods": ["GET", "POST"], 

17 "allow_headers": ["X-Custom-Header"], 

18 "allow_credentials": True, 

19 "expose_headers": ["X-Exposed-Header"], 

20 "debug": True, 

21 } 

22 } 

23 ) 

24 app = get_application(config) 

25 

26 # Add test route 

27 @app.get("/test") 

28 async def test_route(req, res): 

29 return res.text("OK") 

30 

31 # Add CORS middleware 

32 app.add_middleware(CORSMiddleware()) 

33 

34 return app 

35 

36 

37@pytest.fixture 

38async def client(cors_app): 

39 async with Client(cors_app) as c: 

40 yield c 

41 

42 

43async def test_simple_request_allowed_origin(client): 

44 # Test simple GET request with allowed origin 

45 response = await client.get("/test", headers={"Origin": "http://example.com"}) 

46 

47 assert response.status_code == 200 

48 assert response.text == "OK" 

49 assert response.headers["Access-Control-Allow-Origin"] == "http://example.com" 

50 assert response.headers["Access-Control-Allow-Credentials"] == "true" 

51 assert response.headers["Access-Control-Expose-Headers"] == "X-Exposed-Header" 

52 

53 

54async def test_simple_request_disallowed_origin(client): 

55 # Test simple GET request with disallowed origin 

56 response = await client.get("/test", headers={"Origin": "http://disallowed.com"}) 

57 

58 assert response.status_code == 200 

59 assert response.text == "OK" 

60 # Should not have CORS headers for disallowed origin 

61 assert "Access-Control-Allow-Origin" not in response.headers 

62 

63 

64async def test_preflight_request_success(client): 

65 # Test successful OPTIONS preflight request 

66 response = await client.options( 

67 "/test", 

68 headers={ 

69 "Origin": "http://example.com", 

70 "Access-Control-Request-Method": "GET", 

71 "Access-Control-Request-Headers": "X-Custom-Header", 

72 }, 

73 ) 

74 

75 assert response.status_code == 201 # Custom status from our middleware 

76 assert response.headers["Access-Control-Allow-Origin"] == "http://example.com" 

77 assert response.headers["Access-Control-Allow-Methods"] == "GET, POST" 

78 assert response.headers["Access-Control-Allow-Headers"] == "X-Custom-Header" 

79 assert response.headers["Access-Control-Allow-Credentials"] == "true" 

80 assert response.headers["Access-Control-Max-Age"] == "600" # Default value 

81 

82 

83async def test_preflight_request_disallowed_method(client): 

84 # Test OPTIONS request with disallowed method 

85 response = await client.options( 

86 "/test", 

87 headers={ 

88 "Origin": "http://example.com", 

89 "Access-Control-Request-Method": "PUT", 

90 }, 

91 ) 

92 

93 # assert response.status_code == 400 # Default error status 

94 assert "PUT" not in response.headers.get("Access-Control-Allow-Methods", "") 

95 

96 

97async def test_preflight_request_disallowed_header(client): 

98 # Test OPTIONS request with disallowed header 

99 response = await client.options( 

100 "/test", 

101 headers={ 

102 "Origin": "http://example.com", 

103 "Access-Control-Request-Method": "GET", 

104 "Access-Control-Request-Headers": "X-Disallowed-Header", 

105 }, 

106 ) 

107 

108 assert response.status_code == 400 

109 assert "X-Disallowed-Header" not in response.headers.get( 

110 "Access-Control-Allow-Headers", "" 

111 ) 

112 

113 

114async def test_wildcard_origin(): 

115 # Test app with wildcard origin 

116 config = MakeConfig({"cors": {"allow_origins": ["*"], "allow_methods": ["*"]}}) 

117 app = get_application(config) 

118 

119 @app.get("/wildcard") 

120 async def wildcard_route(req, res): 

121 return res.text("OK") 

122 

123 app.add_middleware(CORSMiddleware()) 

124 

125 async with Client(app) as client: 

126 response = await client.get( 

127 "/wildcard", headers={"Origin": "http://any-origin.com"} 

128 ) 

129 

130 assert response.status_code == 200 

131 assert ( 

132 response.headers["Access-Control-Allow-Origin"] == "http://any-origin.com" 

133 ) 

134 

135 

136async def test_no_cors_headers_without_origin(): 

137 # Test that CORS headers aren't added when no Origin header is present 

138 config = MakeConfig( 

139 {"cors": {"allow_origins": ["http://example.com"], "allow_methods": ["GET"]}} 

140 ) 

141 app = get_application(config) 

142 

143 @app.get("/no-origin") 

144 async def no_origin_route(req, res): 

145 return res.text("OK") 

146 

147 app.add_middleware(CORSMiddleware()) 

148 

149 async with Client(app) as client: 

150 response = await client.get("/no-origin") 

151 

152 assert response.status_code == 200 

153 assert "Access-Control-Allow-Origin" not in response.headers