Coverage for mindsdb / integrations / handlers / shopify_handler / tests / test_shopify_handler.py: 0%

444 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1import unittest 

2from unittest.mock import MagicMock, patch 

3import sys 

4 

5from mindsdb.integrations.libs.response import HandlerStatusResponse as StatusResponse 

6from mindsdb.integrations.libs.api_handler_exceptions import ( 

7 MissingConnectionParams, 

8 ConnectionFailed, 

9 InvalidNativeQuery, 

10) 

11 

12# Mock shopify and requests modules before importing the handler 

13if "shopify" not in sys.modules: 

14 sys.modules["shopify"] = MagicMock() 

15 sys.modules["shopify.ShopifyResource"] = MagicMock() 

16 sys.modules["shopify.Session"] = MagicMock() 

17 sys.modules["shopify.Shop"] = MagicMock() 

18 

19if "requests" not in sys.modules: 

20 sys.modules["requests"] = MagicMock() 

21 

22from mindsdb.integrations.handlers.shopify_handler.shopify_handler import ShopifyHandler 

23 

24 

25class BaseShopifyHandlerTest(unittest.TestCase): 

26 """Base test class with common setup and helper methods.""" 

27 

28 # Test constants 

29 TEST_SHOP_URL = "test-shop.myshopify.com" 

30 TEST_CLIENT_ID = "test_client_id" 

31 TEST_CLIENT_SECRET = "test_client_secret" 

32 TEST_HANDLER_NAME = "test_shopify_handler" 

33 

34 def setUp(self): 

35 """Set up test fixtures.""" 

36 self.connection_data = { 

37 "shop_url": self.TEST_SHOP_URL, 

38 "client_id": self.TEST_CLIENT_ID, 

39 "client_secret": self.TEST_CLIENT_SECRET, 

40 } 

41 

42 def tearDown(self): 

43 """Clean up after tests.""" 

44 pass 

45 

46 

47class TestShopifyHandlerInitialization(BaseShopifyHandlerTest): 

48 """Test suite for Shopify Handler initialization.""" 

49 

50 def test_handler_initialization_success(self): 

51 """Test successful handler initialization with all required parameters.""" 

52 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

53 

54 self.assertEqual(handler.name, self.TEST_HANDLER_NAME) 

55 self.assertEqual(handler.connection_data, self.connection_data) 

56 self.assertFalse(handler.is_connected) 

57 self.assertIsNone(handler.connection) 

58 

59 def test_handler_initialization_without_connection_data(self): 

60 """Test handler initialization fails when connection_data is missing.""" 

61 with self.assertRaises(MissingConnectionParams) as context: 

62 ShopifyHandler(self.TEST_HANDLER_NAME) 

63 

64 self.assertIn("Incomplete parameters", str(context.exception)) 

65 

66 def test_handler_initialization_missing_shop_url(self): 

67 """Test handler initialization fails when shop_url is missing.""" 

68 incomplete_data = { 

69 "client_id": self.TEST_CLIENT_ID, 

70 "client_secret": self.TEST_CLIENT_SECRET, 

71 } 

72 

73 with self.assertRaises(MissingConnectionParams) as context: 

74 ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=incomplete_data) 

75 

76 self.assertIn("shop_url", str(context.exception)) 

77 

78 def test_handler_initialization_missing_client_id(self): 

79 """Test handler initialization fails when client_id is missing.""" 

80 incomplete_data = { 

81 "shop_url": self.TEST_SHOP_URL, 

82 "client_secret": self.TEST_CLIENT_SECRET, 

83 } 

84 

85 with self.assertRaises(MissingConnectionParams) as context: 

86 ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=incomplete_data) 

87 

88 self.assertIn("client_id", str(context.exception)) 

89 

90 def test_handler_initialization_missing_client_secret(self): 

91 """Test handler initialization fails when client_secret is missing.""" 

92 incomplete_data = { 

93 "shop_url": self.TEST_SHOP_URL, 

94 "client_id": self.TEST_CLIENT_ID, 

95 } 

96 

97 with self.assertRaises(MissingConnectionParams) as context: 

98 ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=incomplete_data) 

99 

100 self.assertIn("client_secret", str(context.exception)) 

101 

102 def test_handler_tables_registered(self): 

103 """Test that all required tables are registered during initialization.""" 

104 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

105 

106 expected_tables = [ 

107 "products", 

108 "customers", 

109 "orders", 

110 "product_variants", 

111 "marketing_events", 

112 "inventory_items", 

113 "staff_members", 

114 "gift_cards", 

115 ] 

116 

117 for table_name in expected_tables: 

118 self.assertIn(table_name, handler._tables) 

119 

120 

121class TestShopifyHandlerConnection(BaseShopifyHandlerTest): 

122 """Test suite for Shopify Handler connection management.""" 

123 

124 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

125 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

126 def test_connect_success(self, mock_shopify, mock_requests): 

127 """Test successful connection to Shopify API.""" 

128 # Mock the OAuth response 

129 mock_response = MagicMock() 

130 mock_response.json.return_value = {"access_token": "test_access_token"} 

131 mock_requests.post.return_value = mock_response 

132 

133 # Mock the Session 

134 mock_session = MagicMock() 

135 mock_shopify.Session.return_value = mock_session 

136 

137 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

138 result = handler.connect() 

139 

140 # Verify OAuth request was made 

141 mock_requests.post.assert_called_once() 

142 call_args = mock_requests.post.call_args 

143 self.assertIn(self.TEST_SHOP_URL, call_args[0][0]) 

144 self.assertEqual(call_args[1]["data"]["client_id"], self.TEST_CLIENT_ID) 

145 self.assertEqual(call_args[1]["data"]["client_secret"], self.TEST_CLIENT_SECRET) 

146 

147 # Verify session was created 

148 mock_shopify.Session.assert_called_once_with(self.TEST_SHOP_URL, "2025-10", "test_access_token") 

149 

150 self.assertTrue(handler.is_connected) 

151 self.assertEqual(result, mock_session) 

152 

153 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

154 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

155 def test_connect_when_already_connected(self, mock_shopify, mock_requests): 

156 """Test that connect returns existing connection when already connected.""" 

157 mock_session = MagicMock() 

158 

159 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

160 handler.connection = mock_session 

161 handler.is_connected = True 

162 

163 result = handler.connect() 

164 

165 # Should not make new OAuth request 

166 mock_requests.post.assert_not_called() 

167 mock_shopify.Session.assert_not_called() 

168 

169 self.assertEqual(result, mock_session) 

170 

171 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

172 def test_connect_oauth_failure(self, mock_requests): 

173 """Test connection failure when OAuth request fails.""" 

174 error_msg = "Invalid credentials" 

175 mock_requests.post.side_effect = Exception(error_msg) 

176 

177 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

178 

179 with self.assertRaises(Exception) as context: 

180 handler.connect() 

181 

182 self.assertIn(error_msg, str(context.exception)) 

183 self.assertFalse(handler.is_connected) 

184 

185 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

186 def test_connect_missing_access_token(self, mock_requests): 

187 """Test connection failure when access token is missing from response.""" 

188 mock_response = MagicMock() 

189 mock_response.json.return_value = {} # No access_token 

190 mock_requests.post.return_value = mock_response 

191 

192 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

193 

194 with self.assertRaises(ConnectionFailed) as context: 

195 handler.connect() 

196 

197 self.assertIn("Unable to get an access token", str(context.exception)) 

198 self.assertFalse(handler.is_connected) 

199 

200 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

201 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

202 def test_check_connection_success(self, mock_shopify, mock_requests): 

203 """Test successful connection check.""" 

204 # Mock OAuth response 

205 mock_response = MagicMock() 

206 mock_response.json.return_value = {"access_token": "test_access_token"} 

207 mock_requests.post.return_value = mock_response 

208 

209 # Mock session and shop 

210 mock_session = MagicMock() 

211 mock_shopify.Session.return_value = mock_session 

212 mock_shopify.ShopifyResource.activate_session = MagicMock() 

213 mock_shopify.Shop.current.return_value = MagicMock() 

214 

215 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

216 result = handler.check_connection() 

217 

218 self.assertIsInstance(result, StatusResponse) 

219 self.assertTrue(result.success) 

220 self.assertTrue(handler.is_connected) 

221 

222 # Verify session was activated and Shop.current was called 

223 mock_shopify.ShopifyResource.activate_session.assert_called_once_with(mock_session) 

224 mock_shopify.Shop.current.assert_called_once() 

225 

226 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

227 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

228 def test_check_connection_failure(self, mock_shopify, mock_requests): 

229 """Test connection check failure.""" 

230 # Mock OAuth response 

231 mock_response = MagicMock() 

232 mock_response.json.return_value = {"access_token": "test_access_token"} 

233 mock_requests.post.return_value = mock_response 

234 

235 # Mock session 

236 mock_session = MagicMock() 

237 mock_shopify.Session.return_value = mock_session 

238 mock_shopify.ShopifyResource.activate_session = MagicMock() 

239 

240 # Make Shop.current fail 

241 error_message = "Invalid shop" 

242 mock_shopify.Shop.current.side_effect = Exception(error_message) 

243 

244 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

245 

246 with self.assertRaises(ConnectionFailed): 

247 handler.check_connection() 

248 

249 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

250 def test_check_connection_oauth_failure(self, mock_requests): 

251 """Test connection check failure during OAuth.""" 

252 error_message = "OAuth failed" 

253 mock_requests.post.side_effect = Exception(error_message) 

254 

255 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

256 

257 with self.assertRaises(ConnectionFailed): 

258 handler.check_connection() 

259 

260 

261class TestShopifyHandlerQueries(BaseShopifyHandlerTest): 

262 """Test suite for Shopify Handler query execution.""" 

263 

264 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

265 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

266 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.parse_sql") 

267 def test_native_query_success(self, mock_parse_sql, mock_shopify, mock_requests): 

268 """Test successful native query execution.""" 

269 # Mock OAuth response 

270 mock_response = MagicMock() 

271 mock_response.json.return_value = {"access_token": "test_access_token"} 

272 mock_requests.post.return_value = mock_response 

273 

274 # Mock session 

275 mock_session = MagicMock() 

276 mock_shopify.Session.return_value = mock_session 

277 

278 # Mock parse_sql 

279 mock_ast = MagicMock() 

280 mock_parse_sql.return_value = mock_ast 

281 

282 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

283 

284 # Mock the query method to return a success response 

285 handler.query = MagicMock() 

286 mock_query_response = MagicMock() 

287 handler.query.return_value = mock_query_response 

288 

289 query = "SELECT * FROM products" 

290 result = handler.native_query(query) 

291 

292 mock_parse_sql.assert_called_once_with(query) 

293 handler.query.assert_called_once_with(mock_ast) 

294 self.assertEqual(result, mock_query_response) 

295 

296 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.parse_sql") 

297 def test_native_query_invalid_sql(self, mock_parse_sql): 

298 """Test native query with invalid SQL.""" 

299 mock_parse_sql.side_effect = Exception("Invalid SQL") 

300 

301 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

302 

303 query = "INVALID SQL QUERY" 

304 with self.assertRaises(InvalidNativeQuery) as context: 

305 handler.native_query(query) 

306 

307 self.assertIn("invalid", str(context.exception).lower()) 

308 

309 

310class TestShopifyHandlerConnectionArgs(BaseShopifyHandlerTest): 

311 """Test suite for Shopify Handler connection arguments validation.""" 

312 

313 def test_connection_args_structure(self): 

314 """Test that connection_args has the correct structure.""" 

315 from mindsdb.integrations.handlers.shopify_handler.connection_args import connection_args 

316 

317 required_fields = ["type", "description", "required", "label"] 

318 

319 # Check shop_url 

320 self.assertIn("shop_url", connection_args) 

321 for field in required_fields: 

322 self.assertIn(field, connection_args["shop_url"]) 

323 self.assertTrue(connection_args["shop_url"]["required"]) 

324 

325 # Check client_id 

326 self.assertIn("client_id", connection_args) 

327 for field in required_fields: 

328 self.assertIn(field, connection_args["client_id"]) 

329 self.assertTrue(connection_args["client_id"]["required"]) 

330 

331 # Check client_secret 

332 self.assertIn("client_secret", connection_args) 

333 for field in required_fields: 

334 self.assertIn(field, connection_args["client_secret"]) 

335 self.assertTrue(connection_args["client_secret"]["required"]) 

336 self.assertTrue(connection_args["client_secret"].get("secret", False)) 

337 

338 def test_connection_args_example_structure(self): 

339 """Test that connection_args_example has the correct structure.""" 

340 from mindsdb.integrations.handlers.shopify_handler.connection_args import ( 

341 connection_args_example, 

342 ) 

343 

344 self.assertIn("shop_url", connection_args_example) 

345 self.assertIn("client_id", connection_args_example) 

346 self.assertIn("client_secret", connection_args_example) 

347 

348 self.assertIsInstance(connection_args_example["shop_url"], str) 

349 self.assertIsInstance(connection_args_example["client_id"], str) 

350 self.assertIsInstance(connection_args_example["client_secret"], str) 

351 

352 

353class TestShopifyHandlerEdgeCases(BaseShopifyHandlerTest): 

354 """Test suite for Shopify Handler edge cases.""" 

355 

356 def test_handler_name_attribute(self): 

357 """Test that handler has correct name attribute.""" 

358 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

359 self.assertEqual(handler.name, self.TEST_HANDLER_NAME) 

360 

361 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

362 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

363 def test_multiple_connections(self, mock_shopify, mock_requests): 

364 """Test multiple connection attempts.""" 

365 # Mock OAuth response 

366 mock_response = MagicMock() 

367 mock_response.json.return_value = {"access_token": "test_access_token"} 

368 mock_requests.post.return_value = mock_response 

369 

370 # Mock session 

371 mock_session = MagicMock() 

372 mock_shopify.Session.return_value = mock_session 

373 

374 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

375 

376 # First connection 

377 result1 = handler.connect() 

378 self.assertTrue(handler.is_connected) 

379 

380 # Second connection (should return existing) 

381 result2 = handler.connect() 

382 self.assertEqual(result1, result2) 

383 

384 # Should only call OAuth once 

385 self.assertEqual(mock_requests.post.call_count, 1) 

386 

387 def test_connection_data_preserved(self): 

388 """Test that connection data is preserved after initialization.""" 

389 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

390 

391 self.assertEqual(handler.connection_data["shop_url"], self.TEST_SHOP_URL) 

392 self.assertEqual(handler.connection_data["client_id"], self.TEST_CLIENT_ID) 

393 self.assertEqual(handler.connection_data["client_secret"], self.TEST_CLIENT_SECRET) 

394 

395 def test_empty_connection_data(self): 

396 """Test handler initialization with empty connection_data.""" 

397 with self.assertRaises(MissingConnectionParams): 

398 ShopifyHandler(self.TEST_HANDLER_NAME, connection_data={}) 

399 

400 def test_partial_connection_data(self): 

401 """Test handler initialization with partial connection_data.""" 

402 partial_data = {"shop_url": self.TEST_SHOP_URL} 

403 

404 with self.assertRaises(MissingConnectionParams) as context: 

405 ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=partial_data) 

406 

407 # Should mention the missing parameters 

408 error_message = str(context.exception) 

409 self.assertTrue("client_id" in error_message or "client_secret" in error_message) 

410 

411 

412class TestShopifyHandlerIntegration(BaseShopifyHandlerTest): 

413 """Test suite for Shopify Handler integration scenarios.""" 

414 

415 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.requests") 

416 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_handler.shopify") 

417 def test_connection_and_check(self, mock_shopify, mock_requests): 

418 """Test connection followed by check_connection.""" 

419 # Mock OAuth response 

420 mock_response = MagicMock() 

421 mock_response.json.return_value = {"access_token": "test_access_token"} 

422 mock_requests.post.return_value = mock_response 

423 

424 # Mock session 

425 mock_session = MagicMock() 

426 mock_shopify.Session.return_value = mock_session 

427 mock_shopify.ShopifyResource.activate_session = MagicMock() 

428 mock_shopify.Shop.current.return_value = MagicMock() 

429 

430 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

431 

432 # First connect 

433 handler.connect() 

434 self.assertTrue(handler.is_connected) 

435 

436 # Then check connection 

437 result = handler.check_connection() 

438 self.assertTrue(result.success) 

439 

440 def test_handler_with_extra_kwargs(self): 

441 """Test handler initialization with extra keyword arguments.""" 

442 extra_kwargs = { 

443 "connection_data": self.connection_data, 

444 "extra_param": "extra_value", 

445 } 

446 

447 handler = ShopifyHandler(self.TEST_HANDLER_NAME, **extra_kwargs) 

448 self.assertEqual(handler.name, self.TEST_HANDLER_NAME) 

449 self.assertTrue(handler.is_connected is False) 

450 

451 

452class TestShopifyHandlerTableMetadata(BaseShopifyHandlerTest): 

453 """Test suite for Shopify Handler table metadata methods.""" 

454 

455 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_tables.query_graphql") 

456 def test_products_table_meta_get_tables(self, mock_query_graphql): 

457 """Test meta_get_tables method for products table.""" 

458 mock_query_graphql.return_value = {"productsCount": {"count": 100}} 

459 

460 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

461 products_table = handler._tables["products"] 

462 

463 result = products_table.meta_get_tables() 

464 

465 self.assertIsInstance(result, dict) 

466 self.assertEqual(result["table_name"], "products") 

467 self.assertEqual(result["table_type"], "BASE TABLE") 

468 self.assertIn("table_description", result) 

469 self.assertEqual(result["row_count"], 100) 

470 

471 def test_products_table_meta_get_primary_keys(self): 

472 """Test meta_get_primary_keys method for products table.""" 

473 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

474 products_table = handler._tables["products"] 

475 

476 result = products_table.meta_get_primary_keys("products") 

477 

478 self.assertIsInstance(result, list) 

479 self.assertEqual(len(result), 1) 

480 self.assertEqual(result[0]["table_name"], "products") 

481 self.assertEqual(result[0]["column_name"], "id") 

482 

483 def test_products_table_meta_get_foreign_keys(self): 

484 """Test meta_get_foreign_keys method for products table.""" 

485 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

486 products_table = handler._tables["products"] 

487 

488 result = products_table.meta_get_foreign_keys("products", ["products", "orders"]) 

489 

490 self.assertIsInstance(result, list) 

491 # Products table should have no foreign keys 

492 self.assertEqual(len(result), 0) 

493 

494 def test_products_table_get_columns(self): 

495 """Test get_columns method for products table.""" 

496 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

497 products_table = handler._tables["products"] 

498 

499 result = products_table.get_columns() 

500 

501 self.assertIsInstance(result, list) 

502 self.assertGreater(len(result), 0) 

503 # Check that some expected columns are present 

504 self.assertIn("id", result) 

505 self.assertIn("title", result) 

506 # All items should be strings 

507 for column_name in result: 

508 self.assertIsInstance(column_name, str) 

509 

510 def test_products_table_meta_get_columns(self): 

511 """Test meta_get_columns method for products table.""" 

512 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

513 products_table = handler._tables["products"] 

514 

515 result = products_table.meta_get_columns() 

516 

517 self.assertIsInstance(result, list) 

518 self.assertGreater(len(result), 0) 

519 # Each column should be a dictionary with metadata 

520 for column in result: 

521 self.assertIsInstance(column, dict) 

522 self.assertIn("COLUMN_NAME", column) 

523 

524 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_tables.query_graphql") 

525 def test_product_variants_table_meta_get_tables(self, mock_query_graphql): 

526 """Test meta_get_tables method for product_variants table.""" 

527 mock_query_graphql.return_value = {"productVariantsCount": {"count": 250}} 

528 

529 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

530 variants_table = handler._tables["product_variants"] 

531 

532 result = variants_table.meta_get_tables() 

533 

534 self.assertIsInstance(result, dict) 

535 self.assertEqual(result["table_name"], "product_variants") 

536 self.assertEqual(result["table_type"], "BASE TABLE") 

537 self.assertIn("table_description", result) 

538 self.assertEqual(result["row_count"], 250) 

539 

540 def test_product_variants_table_meta_get_primary_keys(self): 

541 """Test meta_get_primary_keys method for product_variants table.""" 

542 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

543 variants_table = handler._tables["product_variants"] 

544 

545 result = variants_table.meta_get_primary_keys("product_variants") 

546 

547 self.assertIsInstance(result, list) 

548 self.assertEqual(len(result), 1) 

549 self.assertEqual(result[0]["table_name"], "product_variants") 

550 self.assertEqual(result[0]["column_name"], "id") 

551 

552 def test_product_variants_table_meta_get_foreign_keys(self): 

553 """Test meta_get_foreign_keys method for product_variants table.""" 

554 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

555 variants_table = handler._tables["product_variants"] 

556 

557 result = variants_table.meta_get_foreign_keys("product_variants", ["products", "product_variants"]) 

558 

559 self.assertIsInstance(result, list) 

560 # Product variants should have a foreign key to products 

561 self.assertGreater(len(result), 0) 

562 self.assertEqual(result[0]["PARENT_TABLE_NAME"], "product_variants") 

563 self.assertEqual(result[0]["PARENT_COLUMN_NAME"], "productId") 

564 self.assertEqual(result[0]["CHILD_TABLE_NAME"], "products") 

565 self.assertEqual(result[0]["CHILD_COLUMN_NAME"], "id") 

566 

567 def test_product_variants_table_get_columns(self): 

568 """Test get_columns method for product_variants table.""" 

569 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

570 variants_table = handler._tables["product_variants"] 

571 

572 result = variants_table.get_columns() 

573 

574 self.assertIsInstance(result, list) 

575 self.assertGreater(len(result), 0) 

576 # Check that some expected columns are present 

577 self.assertIn("id", result) 

578 self.assertIn("productId", result) 

579 

580 def test_product_variants_table_meta_get_columns(self): 

581 """Test meta_get_columns method for product_variants table.""" 

582 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

583 variants_table = handler._tables["product_variants"] 

584 

585 result = variants_table.meta_get_columns() 

586 

587 self.assertIsInstance(result, list) 

588 self.assertGreater(len(result), 0) 

589 for column in result: 

590 self.assertIsInstance(column, dict) 

591 self.assertIn("COLUMN_NAME", column) 

592 

593 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_tables.query_graphql") 

594 def test_customers_table_meta_get_tables(self, mock_query_graphql): 

595 """Test meta_get_tables method for customers table.""" 

596 mock_query_graphql.return_value = {"customersCount": {"count": 500}} 

597 

598 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

599 customers_table = handler._tables["customers"] 

600 

601 result = customers_table.meta_get_tables() 

602 

603 self.assertIsInstance(result, dict) 

604 self.assertEqual(result["table_name"], "customers") 

605 self.assertEqual(result["table_type"], "BASE TABLE") 

606 self.assertIn("table_description", result) 

607 self.assertEqual(result["row_count"], 500) 

608 

609 def test_customers_table_meta_get_primary_keys(self): 

610 """Test meta_get_primary_keys method for customers table.""" 

611 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

612 customers_table = handler._tables["customers"] 

613 

614 result = customers_table.meta_get_primary_keys("customers") 

615 

616 self.assertIsInstance(result, list) 

617 self.assertEqual(len(result), 1) 

618 self.assertEqual(result[0]["table_name"], "customers") 

619 self.assertEqual(result[0]["column_name"], "id") 

620 

621 def test_customers_table_meta_get_foreign_keys(self): 

622 """Test meta_get_foreign_keys method for customers table.""" 

623 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

624 customers_table = handler._tables["customers"] 

625 

626 result = customers_table.meta_get_foreign_keys("customers", ["customers", "orders"]) 

627 

628 self.assertIsInstance(result, list) 

629 # Customers table should have no foreign keys 

630 self.assertEqual(len(result), 0) 

631 

632 def test_customers_table_get_columns(self): 

633 """Test get_columns method for customers table.""" 

634 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

635 customers_table = handler._tables["customers"] 

636 

637 result = customers_table.get_columns() 

638 

639 self.assertIsInstance(result, list) 

640 self.assertGreater(len(result), 0) 

641 # Check that some expected columns are present 

642 self.assertIn("id", result) 

643 self.assertIn("emailAddress", result) 

644 

645 def test_customers_table_meta_get_columns(self): 

646 """Test meta_get_columns method for customers table.""" 

647 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

648 customers_table = handler._tables["customers"] 

649 

650 result = customers_table.meta_get_columns() 

651 

652 self.assertIsInstance(result, list) 

653 self.assertGreater(len(result), 0) 

654 for column in result: 

655 self.assertIsInstance(column, dict) 

656 self.assertIn("COLUMN_NAME", column) 

657 

658 @patch("mindsdb.integrations.handlers.shopify_handler.shopify_tables.query_graphql") 

659 def test_orders_table_meta_get_tables(self, mock_query_graphql): 

660 """Test meta_get_tables method for orders table.""" 

661 mock_query_graphql.return_value = {"ordersCount": {"count": 1000}} 

662 

663 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

664 orders_table = handler._tables["orders"] 

665 

666 result = orders_table.meta_get_tables() 

667 

668 self.assertIsInstance(result, dict) 

669 self.assertEqual(result["table_name"], "orders") 

670 self.assertEqual(result["table_type"], "BASE TABLE") 

671 self.assertIn("table_description", result) 

672 self.assertEqual(result["row_count"], 1000) 

673 

674 def test_orders_table_meta_get_primary_keys(self): 

675 """Test meta_get_primary_keys method for orders table.""" 

676 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

677 orders_table = handler._tables["orders"] 

678 

679 result = orders_table.meta_get_primary_keys("orders") 

680 

681 self.assertIsInstance(result, list) 

682 self.assertEqual(len(result), 1) 

683 self.assertEqual(result[0]["table_name"], "orders") 

684 self.assertEqual(result[0]["column_name"], "id") 

685 

686 def test_orders_table_meta_get_foreign_keys(self): 

687 """Test meta_get_foreign_keys method for orders table.""" 

688 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

689 orders_table = handler._tables["orders"] 

690 

691 # Test with customers in the table list 

692 result = orders_table.meta_get_foreign_keys("orders", ["customers", "orders"]) 

693 

694 self.assertIsInstance(result, list) 

695 # Orders table should have a foreign key to customers 

696 self.assertGreater(len(result), 0) 

697 self.assertEqual(result[0]["PARENT_TABLE_NAME"], "orders") 

698 self.assertEqual(result[0]["PARENT_COLUMN_NAME"], "customerId") 

699 self.assertEqual(result[0]["CHILD_TABLE_NAME"], "customers") 

700 self.assertEqual(result[0]["CHILD_COLUMN_NAME"], "id") 

701 

702 def test_orders_table_get_columns(self): 

703 """Test get_columns method for orders table.""" 

704 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

705 orders_table = handler._tables["orders"] 

706 

707 result = orders_table.get_columns() 

708 

709 self.assertIsInstance(result, list) 

710 self.assertGreater(len(result), 0) 

711 # Check that some expected columns are present 

712 self.assertIn("id", result) 

713 self.assertIn("customerId", result) 

714 

715 def test_orders_table_meta_get_columns(self): 

716 """Test meta_get_columns method for orders table.""" 

717 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

718 orders_table = handler._tables["orders"] 

719 

720 result = orders_table.meta_get_columns() 

721 

722 self.assertIsInstance(result, list) 

723 self.assertGreater(len(result), 0) 

724 for column in result: 

725 self.assertIsInstance(column, dict) 

726 self.assertIn("COLUMN_NAME", column) 

727 

728 def test_all_tables_have_metadata_methods(self): 

729 """Test that all registered tables have required metadata methods.""" 

730 handler = ShopifyHandler(self.TEST_HANDLER_NAME, connection_data=self.connection_data) 

731 

732 expected_tables = [ 

733 "products", 

734 "customers", 

735 "orders", 

736 "product_variants", 

737 "marketing_events", 

738 "inventory_items", 

739 "staff_members", 

740 "gift_cards", 

741 ] 

742 

743 for table_name in expected_tables: 

744 with self.subTest(table=table_name): 

745 table = handler._tables[table_name] 

746 

747 # Check that all required methods exist 

748 self.assertTrue(hasattr(table, "meta_get_tables")) 

749 self.assertTrue(hasattr(table, "meta_get_primary_keys")) 

750 self.assertTrue(hasattr(table, "meta_get_foreign_keys")) 

751 self.assertTrue(hasattr(table, "get_columns")) 

752 self.assertTrue(hasattr(table, "meta_get_columns")) 

753 

754 # Check that methods are callable 

755 self.assertTrue(callable(table.meta_get_tables)) 

756 self.assertTrue(callable(table.meta_get_primary_keys)) 

757 self.assertTrue(callable(table.meta_get_foreign_keys)) 

758 self.assertTrue(callable(table.get_columns)) 

759 self.assertTrue(callable(table.meta_get_columns)) 

760 

761 

762if __name__ == "__main__": 

763 unittest.main()